| ... | @@ -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. |
| 407 | pub fn rotr(comptime T: type, x: T, r: anytype) T { | 407 | pub 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 | } |
| 423 | | 432 | |
| 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. |
| 426 | pub fn rotl(comptime T: type, x: T, r: anytype) T { | 435 | pub 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 | } |
| 442 | | 460 | |
| 443 | pub fn Log2Int(comptime T: type) type { | 461 | pub 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 | | | |