From bb3dfd2708067a0fd11d50b667361fb410fc1e2b Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Thu, 29 Oct 2020 10:08:50 +0100 Subject: std/math: add support for vectors to rotl()/rotr() --- lib/std/math.zig | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) (limited to 'lib/std') diff --git a/lib/std/math.zig b/lib/std/math.zig index f0c4f74d73..ac1ff2b071 100644 --- a/lib/std/math.zig +++ b/lib/std/math.zig @@ -405,7 +405,14 @@ test "math.shr" { /// Rotates right. Only unsigned values can be rotated. /// Negative shift values results in shift modulo the bit count. pub fn rotr(comptime T: type, x: T, r: anytype) T { - if (@typeInfo(T).Int.is_signed) { + if (@typeInfo(T) == .Vector) { + const C = @typeInfo(T).Vector.child; + if (@typeInfo(C).Int.is_signed) { + @compileError("cannot rotate signed integers"); + } + const ar = @intCast(Log2Int(C), @mod(r, @typeInfo(C).Int.bits)); + return (x >> @splat(@typeInfo(T).Vector.len, ar)) | (x << @splat(@typeInfo(T).Vector.len, 1 + ~ar)); + } else if (@typeInfo(T).Int.is_signed) { @compileError("cannot rotate signed integer"); } else { const ar = @mod(r, @typeInfo(T).Int.bits); @@ -419,12 +426,21 @@ test "math.rotr" { testing.expect(rotr(u8, 0b00000001, @as(usize, 8)) == 0b00000001); testing.expect(rotr(u8, 0b00000001, @as(usize, 4)) == 0b00010000); testing.expect(rotr(u8, 0b00000001, @as(isize, -1)) == 0b00000010); + testing.expect(rotr(std.meta.Vector(1, u32), std.meta.Vector(1, u32){1}, @as(usize, 1))[0] == @as(u32, 1) << 31); + testing.expect(rotr(std.meta.Vector(1, u32), std.meta.Vector(1, u32){1}, @as(isize, -1))[0] == @as(u32, 1) << 1); } /// Rotates left. Only unsigned values can be rotated. /// Negative shift values results in shift modulo the bit count. pub fn rotl(comptime T: type, x: T, r: anytype) T { - if (@typeInfo(T).Int.is_signed) { + if (@typeInfo(T) == .Vector) { + const C = @typeInfo(T).Vector.child; + if (@typeInfo(C).Int.is_signed) { + @compileError("cannot rotate signed integers"); + } + const ar = @intCast(Log2Int(C), @mod(r, @typeInfo(C).Int.bits)); + return (x << @splat(@typeInfo(T).Vector.len, ar)) | (x >> @splat(@typeInfo(T).Vector.len, 1 +% ~ar)); + } else if (@typeInfo(T).Int.is_signed) { @compileError("cannot rotate signed integer"); } else { const ar = @mod(r, @typeInfo(T).Int.bits); @@ -438,6 +454,8 @@ test "math.rotl" { testing.expect(rotl(u8, 0b00000001, @as(usize, 8)) == 0b00000001); testing.expect(rotl(u8, 0b00000001, @as(usize, 4)) == 0b00010000); testing.expect(rotl(u8, 0b00000001, @as(isize, -1)) == 0b10000000); + testing.expect(rotl(std.meta.Vector(1, u32), std.meta.Vector(1, u32){1 << 31}, @as(usize, 1))[0] == 1); + testing.expect(rotl(std.meta.Vector(1, u32), std.meta.Vector(1, u32){1 << 31}, @as(isize, -1))[0] == @as(u32, 1) << 30); } pub fn Log2Int(comptime T: type) type { @@ -1141,4 +1159,3 @@ test "math.comptime" { comptime const v = sin(@as(f32, 1)) + ln(@as(f32, 5)); testing.expect(v == sin(@as(f32, 1)) + ln(@as(f32, 5))); } - -- cgit v1.2.3