| ... | ... | @@ -542,6 +542,36 @@ pub const Mutable = struct { |
| 542 | 542 | rma.positive = (a.positive == b.positive); |
| 543 | 543 | } |
| 544 | 544 | |
| 545 | pub fn mulNoAliasWrap( |
| 546 | rma: *Mutable, |
| 547 | a: Const, |
| 548 | b: Const, |
| 549 | signedness: std.builtin.Signedness, |
| 550 | bit_count: usize, |
| 551 | ) void { |
| 552 | assert(rma.limbs.ptr != a.limbs.ptr); // illegal aliasing |
| 553 | assert(rma.limbs.ptr != b.limbs.ptr); // illegal aliasing |
| 554 | |
| 555 | const req_limbs = calcTwosCompLimbCount(bit_count); |
| 556 | |
| 557 | // We can ignore the upper bits here, those results will be discarded anyway. |
| 558 | const a_limbs = a.limbs[0..math.min(req_limbs, a.limbs.len)]; |
| 559 | const b_limbs = b.limbs[0..math.min(req_limbs, b.limbs.len)]; |
| 560 | |
| 561 | mem.set(Limb, rma.limbs[0..req_limbs], 0); |
| 562 | |
| 563 | if (a_limbs.len >= b_limbs.len) { |
| 564 | llmulacc_lo(rma.limbs, a_limbs, b_limbs); |
| 565 | } else { |
| 566 | llmulacc_lo(rma.limbs, b_limbs, a_limbs); |
| 567 | } |
| 568 | |
| 569 | rma.normalize(math.min(req_limbs, a.limbs.len + b.limbs.len)); |
| 570 | rma.positive = (a.positive == b.positive); |
| 571 | |
| 572 | rma.truncate(rma.toConst(), signedness, bit_count); |
| 573 | } |
| 574 | |
| 545 | 575 | /// rma = a * a |
| 546 | 576 | /// |
| 547 | 577 | /// `rma` may not alias with `a`. |
| ... | ... | @@ -2156,6 +2186,19 @@ pub const Managed = struct { |
| 2156 | 2186 | } |
| 2157 | 2187 | }; |
| 2158 | 2188 | |
| 2189 | /// r = a * b, ignoring overflow |
| 2190 | fn llmulacc_lo(r: []Limb, a: []const Limb, b: []const Limb) void { |
| 2191 | assert(r.len >= a.len); |
| 2192 | assert(a.len >= b.len); |
| 2193 | |
| 2194 | // TODO: Improve performance. |
| 2195 | |
| 2196 | var i: usize = 0; |
| 2197 | while (i < b.len) : (i += 1) { |
| 2198 | llmulDigit(r[i..], a, b[i]); |
| 2199 | } |
| 2200 | } |
| 2201 | |
| 2159 | 2202 | /// Knuth 4.3.1, Algorithm M. |
| 2160 | 2203 | /// |
| 2161 | 2204 | /// r MUST NOT alias any of a or b. |