authorgravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2020-10-29 10:08:50+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-10-29 14:17:46-04:00
logbb3dfd2708067a0fd11d50b667361fb410fc1e2b
treed40cad8dcea7359e6a90f3eef883bd56a0fd7ca9
parentb3314a8be6c902c4da3ccef4b29f2ca3ae22061c

std/math: add support for vectors to rotl()/rotr()


1 files changed, 20 insertions(+), 3 deletions(-)

lib/std/math.zig+20-3
...@@ -405,7 +405,14 @@ test "math.shr" {...@@ -405,7 +405,14 @@ test "math.shr" {
405/// Rotates right. Only unsigned values can be rotated.405/// Rotates right. Only unsigned values can be rotated.
406/// Negative shift values results in shift modulo the bit count.406/// Negative shift values results in shift modulo the bit count.
407pub fn rotr(comptime T: type, x: T, r: anytype) T {407pub fn rotr(comptime T: type, x: T, r: anytype) T {
408 if (@typeInfo(T).Int.is_signed) {408 if (@typeInfo(T) == .Vector) {
409 const C = @typeInfo(T).Vector.child;
410 if (@typeInfo(C).Int.is_signed) {
411 @compileError("cannot rotate signed integers");
412 }
413 const ar = @intCast(Log2Int(C), @mod(r, @typeInfo(C).Int.bits));
414 return (x >> @splat(@typeInfo(T).Vector.len, ar)) | (x << @splat(@typeInfo(T).Vector.len, 1 + ~ar));
415 } else if (@typeInfo(T).Int.is_signed) {
409 @compileError("cannot rotate signed integer");416 @compileError("cannot rotate signed integer");
410 } else {417 } else {
411 const ar = @mod(r, @typeInfo(T).Int.bits);418 const ar = @mod(r, @typeInfo(T).Int.bits);
...@@ -419,12 +426,21 @@ test "math.rotr" {...@@ -419,12 +426,21 @@ test "math.rotr" {
419 testing.expect(rotr(u8, 0b00000001, @as(usize, 8)) == 0b00000001);426 testing.expect(rotr(u8, 0b00000001, @as(usize, 8)) == 0b00000001);
420 testing.expect(rotr(u8, 0b00000001, @as(usize, 4)) == 0b00010000);427 testing.expect(rotr(u8, 0b00000001, @as(usize, 4)) == 0b00010000);
421 testing.expect(rotr(u8, 0b00000001, @as(isize, -1)) == 0b00000010);428 testing.expect(rotr(u8, 0b00000001, @as(isize, -1)) == 0b00000010);
429 testing.expect(rotr(std.meta.Vector(1, u32), std.meta.Vector(1, u32){1}, @as(usize, 1))[0] == @as(u32, 1) << 31);
430 testing.expect(rotr(std.meta.Vector(1, u32), std.meta.Vector(1, u32){1}, @as(isize, -1))[0] == @as(u32, 1) << 1);
422}431}
423432
424/// Rotates left. Only unsigned values can be rotated.433/// Rotates left. Only unsigned values can be rotated.
425/// Negative shift values results in shift modulo the bit count.434/// Negative shift values results in shift modulo the bit count.
426pub fn rotl(comptime T: type, x: T, r: anytype) T {435pub fn rotl(comptime T: type, x: T, r: anytype) T {
427 if (@typeInfo(T).Int.is_signed) {436 if (@typeInfo(T) == .Vector) {
437 const C = @typeInfo(T).Vector.child;
438 if (@typeInfo(C).Int.is_signed) {
439 @compileError("cannot rotate signed integers");
440 }
441 const ar = @intCast(Log2Int(C), @mod(r, @typeInfo(C).Int.bits));
442 return (x << @splat(@typeInfo(T).Vector.len, ar)) | (x >> @splat(@typeInfo(T).Vector.len, 1 +% ~ar));
443 } else if (@typeInfo(T).Int.is_signed) {
428 @compileError("cannot rotate signed integer");444 @compileError("cannot rotate signed integer");
429 } else {445 } else {
430 const ar = @mod(r, @typeInfo(T).Int.bits);446 const ar = @mod(r, @typeInfo(T).Int.bits);
...@@ -438,6 +454,8 @@ test "math.rotl" {...@@ -438,6 +454,8 @@ test "math.rotl" {
438 testing.expect(rotl(u8, 0b00000001, @as(usize, 8)) == 0b00000001);454 testing.expect(rotl(u8, 0b00000001, @as(usize, 8)) == 0b00000001);
439 testing.expect(rotl(u8, 0b00000001, @as(usize, 4)) == 0b00010000);455 testing.expect(rotl(u8, 0b00000001, @as(usize, 4)) == 0b00010000);
440 testing.expect(rotl(u8, 0b00000001, @as(isize, -1)) == 0b10000000);456 testing.expect(rotl(u8, 0b00000001, @as(isize, -1)) == 0b10000000);
457 testing.expect(rotl(std.meta.Vector(1, u32), std.meta.Vector(1, u32){1 << 31}, @as(usize, 1))[0] == 1);
458 testing.expect(rotl(std.meta.Vector(1, u32), std.meta.Vector(1, u32){1 << 31}, @as(isize, -1))[0] == @as(u32, 1) << 30);
441}459}
442460
443pub fn Log2Int(comptime T: type) type {461pub fn Log2Int(comptime T: type) type {
...@@ -1141,4 +1159,3 @@ test "math.comptime" {...@@ -1141,4 +1159,3 @@ test "math.comptime" {
1141 comptime const v = sin(@as(f32, 1)) + ln(@as(f32, 5));1159 comptime const v = sin(@as(f32, 1)) + ln(@as(f32, 5));
1142 testing.expect(v == sin(@as(f32, 1)) + ln(@as(f32, 5)));1160 testing.expect(v == sin(@as(f32, 1)) + ln(@as(f32, 5)));
1143}1161}
1144