Commit 7cc0e6d4cd

Андрей Краевский <75577902+AndrewKraevskii@users.noreply.github.com>
2024-04-13 12:06:23
std: fix big int llshr to respect aliasing (#19612)
1 parent 4fac5bd
Changed files (2)
lib
std
lib/std/math/big/int.zig
@@ -3776,19 +3776,19 @@ fn llshr(r: []Limb, a: []const Limb, shift: usize) void {
     const limb_shift = shift / limb_bits;
     const interior_limb_shift = @as(Log2Limb, @truncate(shift));
 
-    var carry: Limb = 0;
     var i: usize = 0;
     while (i < a.len - limb_shift) : (i += 1) {
-        const src_i = a.len - i - 1;
-        const dst_i = src_i - limb_shift;
+        const dst_i = i;
+        const src_i = dst_i + limb_shift;
 
         const src_digit = a[src_i];
-        r[dst_i] = carry | (src_digit >> interior_limb_shift);
-        carry = @call(.always_inline, math.shl, .{
+        const src_digit_next = if (src_i + 1 < a.len) a[src_i + 1] else 0;
+        const carry = @call(.always_inline, math.shl, .{
             Limb,
-            src_digit,
+            src_digit_next,
             limb_bits - @as(Limb, @intCast(interior_limb_shift)),
         });
+        r[dst_i] = carry | (src_digit >> interior_limb_shift);
     }
 }
 
lib/std/math/big/int_test.zig
@@ -2019,6 +2019,19 @@ test "shift-right multi" {
     try a.shiftRight(&a, 63);
     try a.shiftRight(&a, 2);
     try testing.expect(a.eqlZero());
+
+    try a.set(0xffff0000eeee1111dddd2222cccc3333000000000000000000000);
+    try a.shiftRight(&a, 84);
+    const string = try a.toString(
+        testing.allocator,
+        16,
+        .lower,
+    );
+    defer testing.allocator.free(string);
+    try std.testing.expectEqualStrings(
+        string,
+        "ffff0000eeee1111dddd2222cccc3333",
+    );
 }
 
 test "shift-left single" {