| ... | @@ -1173,7 +1173,9 @@ pub const Mutable = struct { | ... | @@ -1173,7 +1173,9 @@ pub const Mutable = struct { |
| 1173 | /// Asserts there is enough memory to fit the result. The upper bound Limb count is | 1173 | /// Asserts there is enough memory to fit the result. The upper bound Limb count is |
| 1174 | /// `a.limbs.len - (shift / (@sizeOf(Limb) * 8))`. | 1174 | /// `a.limbs.len - (shift / (@sizeOf(Limb) * 8))`. |
| 1175 | pub fn shiftRight(r: *Mutable, a: Const, shift: usize) void { | 1175 | pub fn shiftRight(r: *Mutable, a: Const, shift: usize) void { |
| 1176 | if (a.limbs.len <= shift / limb_bits) { | 1176 | const full_limbs_shifted_out = shift / limb_bits; |
| | 1177 | const remaining_bits_shifted_out = shift % limb_bits; |
| | 1178 | if (a.limbs.len <= full_limbs_shifted_out) { |
| 1177 | // Shifting negative numbers converges to -1 instead of 0 | 1179 | // Shifting negative numbers converges to -1 instead of 0 |
| 1178 | if (a.positive) { | 1180 | if (a.positive) { |
| 1179 | r.len = 1; | 1181 | r.len = 1; |
| ... | @@ -1186,14 +1188,29 @@ pub const Mutable = struct { | ... | @@ -1186,14 +1188,29 @@ pub const Mutable = struct { |
| 1186 | } | 1188 | } |
| 1187 | return; | 1189 | return; |
| 1188 | } | 1190 | } |
| | 1191 | const nonzero_negative_shiftout = if (a.positive) false else nonzero: { |
| | 1192 | for (a.limbs[0..full_limbs_shifted_out]) |x| { |
| | 1193 | if (x != 0) |
| | 1194 | break :nonzero true; |
| | 1195 | } |
| | 1196 | if (remaining_bits_shifted_out == 0) |
| | 1197 | break :nonzero false; |
| | 1198 | const not_covered: Log2Limb = @intCast(limb_bits - remaining_bits_shifted_out); |
| | 1199 | break :nonzero a.limbs[full_limbs_shifted_out] << not_covered != 0; |
| | 1200 | }; |
| 1189 | | 1201 | |
| 1190 | llshr(r.limbs[0..], a.limbs[0..a.limbs.len], shift); | 1202 | llshr(r.limbs[0..], a.limbs[0..a.limbs.len], shift); |
| 1191 | r.normalize(a.limbs.len - (shift / limb_bits)); | 1203 | |
| 1192 | r.positive = a.positive; | 1204 | r.len = a.limbs.len - full_limbs_shifted_out; |
| 1193 | // Shifting negative numbers converges to -1 instead of 0 | 1205 | if (nonzero_negative_shiftout) { |
| 1194 | if (!r.positive and r.len == 1 and r.limbs[0] == 0) { | 1206 | if (full_limbs_shifted_out > 0) { |
| 1195 | r.limbs[0] = 1; | 1207 | r.limbs[a.limbs.len - full_limbs_shifted_out] = 0; |
| | 1208 | r.len += 1; |
| | 1209 | } |
| | 1210 | r.addScalar(r.toConst(), -1); |
| 1196 | } | 1211 | } |
| | 1212 | r.normalize(r.len); |
| | 1213 | r.positive = a.positive; |
| 1197 | } | 1214 | } |
| 1198 | | 1215 | |
| 1199 | /// r = ~a under 2s complement wrapping semantics. | 1216 | /// r = ~a under 2s complement wrapping semantics. |