| ... | ... | @@ -552,21 +552,29 @@ pub const Mutable = struct { |
| 552 | 552 | r.positive = a.positive; |
| 553 | 553 | } |
| 554 | 554 | |
| 555 | | /// r = a | b |
| 555 | /// r = a | b under 2s complement semantics. |
| 556 | 556 | /// r may alias with a or b. |
| 557 | 557 | /// |
| 558 | 558 | /// a and b are zero-extended to the longer of a or b. |
| 559 | 559 | /// |
| 560 | 560 | /// Asserts that r has enough limbs to store the result. Upper bound is `math.max(a.limbs.len, b.limbs.len)`. |
| 561 | 561 | pub fn bitOr(r: *Mutable, a: Const, b: Const) void { |
| 562 | | if (a.limbs.len > b.limbs.len) { |
| 563 | | llor(r.limbs[0..], a.limbs[0..a.limbs.len], b.limbs[0..b.limbs.len]); |
| 564 | | r.len = a.limbs.len; |
| 562 | // Trivial cases, llsignedor does not support zero. |
| 563 | if (a.eqZero()) { |
| 564 | r.copy(b); |
| 565 | return; |
| 566 | } else if (b.eqZero()) { |
| 567 | r.copy(a); |
| 568 | return; |
| 569 | } |
| 570 | |
| 571 | if (a.limbs.len >= b.limbs.len) { |
| 572 | r.positive = llsignedor(r.limbs, a.limbs, a.positive, b.limbs, b.positive); |
| 573 | r.normalize(a.limbs.len); |
| 565 | 574 | } else { |
| 566 | | llor(r.limbs[0..], b.limbs[0..b.limbs.len], a.limbs[0..a.limbs.len]); |
| 567 | | r.len = b.limbs.len; |
| 575 | r.positive = llsignedor(r.limbs, b.limbs, b.positive, a.limbs, a.positive); |
| 576 | r.normalize(b.limbs.len); |
| 568 | 577 | } |
| 569 | | r.positive = a.positive or b.positive; |
| 570 | 578 | } |
| 571 | 579 | |
| 572 | 580 | /// r = a & b |
| ... | ... | @@ -2236,17 +2244,119 @@ fn llshr(r: []Limb, a: []const Limb, shift: usize) void { |
| 2236 | 2244 | } |
| 2237 | 2245 | } |
| 2238 | 2246 | |
| 2239 | | fn llor(r: []Limb, a: []const Limb, b: []const Limb) void { |
| 2247 | fn llsignedor(r: []Limb, a: []const Limb, a_positive: bool, b: []const Limb, b_positive: bool) bool { |
| 2240 | 2248 | @setRuntimeSafety(debug_safety); |
| 2241 | 2249 | assert(r.len >= a.len); |
| 2242 | 2250 | assert(a.len >= b.len); |
| 2243 | 2251 | |
| 2244 | | var i: usize = 0; |
| 2245 | | while (i < b.len) : (i += 1) { |
| 2246 | | r[i] = a[i] | b[i]; |
| 2247 | | } |
| 2248 | | while (i < a.len) : (i += 1) { |
| 2249 | | r[i] = a[i]; |
| 2252 | if (a_positive and b_positive) { |
| 2253 | // Trivial case, result is positive., |
| 2254 | var i: usize = 0; |
| 2255 | while (i < b.len) : (i += 1) { |
| 2256 | r[i] = a[i] | b[i]; |
| 2257 | } |
| 2258 | while (i < a.len) : (i += 1) { |
| 2259 | r[i] = a[i]; |
| 2260 | } |
| 2261 | |
| 2262 | return true; |
| 2263 | } else if (!a_positive and b_positive) { |
| 2264 | // r = (--a) | b |
| 2265 | // = ~(-a - 1) | b |
| 2266 | // = ~(-a - 1) | ~~b |
| 2267 | // = ~((-a - 1) & ~b) |
| 2268 | // = -(((-a - 1) & ~b) + 1) |
| 2269 | // result is negative. |
| 2270 | |
| 2271 | var i: usize = 0; |
| 2272 | var a_borrow: u1 = 1; |
| 2273 | var r_carry: u1 = 1; |
| 2274 | |
| 2275 | while (i < b.len) : (i += 1) { |
| 2276 | var a_limb: Limb = undefined; |
| 2277 | a_borrow = @boolToInt(@subWithOverflow(Limb, a[i], a_borrow, &a_limb)); |
| 2278 | |
| 2279 | r[i] = a_limb & ~b[i]; |
| 2280 | r_carry = @boolToInt(@addWithOverflow(Limb, r[i], r_carry, &r[i])); |
| 2281 | } |
| 2282 | |
| 2283 | // With b = 0, we get (-a - 1) & ~0 = -a - 1. |
| 2284 | while (i < a.len) : (i += 1) { |
| 2285 | a_borrow = @boolToInt(@subWithOverflow(Limb, a[i], a_borrow, &r[i])); |
| 2286 | r_carry = @boolToInt(@addWithOverflow(Limb, r[i], r_carry, &r[i])); |
| 2287 | } |
| 2288 | |
| 2289 | assert(a_borrow == 0); // a was 0. |
| 2290 | |
| 2291 | // Can never overflow because a_borrow would need to equal 1. |
| 2292 | assert(r_carry == 0); |
| 2293 | |
| 2294 | return false; |
| 2295 | } else if (a_positive and !b_positive) { |
| 2296 | // r = a | (--b) |
| 2297 | // = a | ~(-b - 1) |
| 2298 | // = ~~a | ~(-b - 1) |
| 2299 | // = ~(~a & (-b - 1)) |
| 2300 | // = -((~a & (-b - 1)) + 1) |
| 2301 | // result is negative. |
| 2302 | |
| 2303 | var i: usize = 0; |
| 2304 | var b_borrow: u1 = 1; |
| 2305 | var r_carry: u1 = 1; |
| 2306 | |
| 2307 | while (i < b.len) : (i += 1) { |
| 2308 | var b_limb: Limb = undefined; |
| 2309 | b_borrow = @boolToInt(@subWithOverflow(Limb, b[i], b_borrow, &b_limb)); |
| 2310 | |
| 2311 | r[i] = ~a[i] & b_limb; |
| 2312 | r_carry = @boolToInt(@addWithOverflow(Limb, r[i], r_carry, &r[i])); |
| 2313 | } |
| 2314 | |
| 2315 | // b is at least 1, so this should never underflow. |
| 2316 | assert(b_borrow == 0); // b was 0 |
| 2317 | |
| 2318 | // Can never overflow because in order for b_limb to be maxInt(Limb), |
| 2319 | // b_borrow would need to equal 1. |
| 2320 | assert(r_carry == 0); |
| 2321 | |
| 2322 | // With b = 0 and b_borrow = 0, we get ~a & (-0 - 0) = ~a & 0 = 0. |
| 2323 | mem.set(Limb, r[i..a.len], 0); |
| 2324 | |
| 2325 | return false; |
| 2326 | } else { |
| 2327 | // r = (--a) | (--b) |
| 2328 | // = ~(-a - 1) | ~(-b - 1) |
| 2329 | // = ~((-a - 1) & (-b - 1)) |
| 2330 | // = -(~(~((-a - 1) & (-b - 1))) + 1) |
| 2331 | // = -((-a - 1) & (-b - 1) + 1) |
| 2332 | // result is negative. |
| 2333 | |
| 2334 | var i: usize = 0; |
| 2335 | var a_borrow: u1 = 1; |
| 2336 | var b_borrow: u1 = 1; |
| 2337 | var r_carry: u1 = 1; |
| 2338 | |
| 2339 | while (i < b.len) : (i += 1) { |
| 2340 | var a_limb: Limb = undefined; |
| 2341 | a_borrow = @boolToInt(@subWithOverflow(Limb, a[i], a_borrow, &a_limb)); |
| 2342 | |
| 2343 | var b_limb: Limb = undefined; |
| 2344 | b_borrow = @boolToInt(@subWithOverflow(Limb, b[i], b_borrow, &b_limb)); |
| 2345 | |
| 2346 | r[i] = a_limb & b_limb; |
| 2347 | r_carry = @boolToInt(@addWithOverflow(Limb, r[i], r_carry, &r[i])); |
| 2348 | } |
| 2349 | |
| 2350 | // b is at least 1, so this should never underflow. |
| 2351 | assert(b_borrow == 0); // b was 0 |
| 2352 | |
| 2353 | // Can never overflow because in order for b_limb to be maxInt(Limb), |
| 2354 | // b_borrow would need to equal 1. |
| 2355 | assert(r_carry == 0); |
| 2356 | |
| 2357 | // With b = 0 and b_borrow = 0 we get (-a - 1) & (-0 - 0) = (-a - 1) & 0 = 0. |
| 2358 | mem.set(Limb, r[i..a.len], 0); |
| 2359 | return false; |
| 2250 | 2360 | } |
| 2251 | 2361 | } |
| 2252 | 2362 | |