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" {
405405/// Rotates right. Only unsigned values can be rotated.
406406/// Negative shift values results in shift modulo the bit count.
407407pub 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) {
409416 @compileError("cannot rotate signed integer");
410417 } else {
411418 const ar = @mod(r, @typeInfo(T).Int.bits);
......@@ -419,12 +426,21 @@ test "math.rotr" {
419426 testing.expect(rotr(u8, 0b00000001, @as(usize, 8)) == 0b00000001);
420427 testing.expect(rotr(u8, 0b00000001, @as(usize, 4)) == 0b00010000);
421428 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);
422431}
423432
424433/// Rotates left. Only unsigned values can be rotated.
425434/// Negative shift values results in shift modulo the bit count.
426435pub 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) {
428444 @compileError("cannot rotate signed integer");
429445 } else {
430446 const ar = @mod(r, @typeInfo(T).Int.bits);
......@@ -438,6 +454,8 @@ test "math.rotl" {
438454 testing.expect(rotl(u8, 0b00000001, @as(usize, 8)) == 0b00000001);
439455 testing.expect(rotl(u8, 0b00000001, @as(usize, 4)) == 0b00010000);
440456 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);
441459}
442460
443461pub fn Log2Int(comptime T: type) type {
......@@ -1141,4 +1159,3 @@ test "math.comptime" {
11411159 comptime const v = sin(@as(f32, 1)) + ln(@as(f32, 5));
11421160 testing.expect(v == sin(@as(f32, 1)) + ln(@as(f32, 5)));
11431161}
1144