14
14
#include " src/__support/CPP/limits.h"
15
15
#include " src/__support/CPP/optional.h"
16
16
#include " src/__support/CPP/type_traits.h"
17
- #include " src/__support/integer_utils.h"
18
17
#include " src/__support/macros/attributes.h" // LIBC_INLINE
19
18
#include " src/__support/macros/optimization.h" // LIBC_UNLIKELY
20
19
#include " src/__support/math_extras.h" // SumCarry, DiffBorrow
@@ -36,6 +35,52 @@ template <> struct half_width<__uint128_t> : cpp::type_identity<uint64_t> {};
36
35
#endif // __SIZEOF_INT128__
37
36
38
37
template <typename T> using half_width_t = typename half_width<T>::type;
38
+
39
+ template <typename T> constexpr NumberPair<T> full_mul (T a, T b) {
40
+ NumberPair<T> pa = split (a);
41
+ NumberPair<T> pb = split (b);
42
+ NumberPair<T> prod;
43
+
44
+ prod.lo = pa.lo * pb.lo ; // exact
45
+ prod.hi = pa.hi * pb.hi ; // exact
46
+ NumberPair<T> lo_hi = split (pa.lo * pb.hi ); // exact
47
+ NumberPair<T> hi_lo = split (pa.hi * pb.lo ); // exact
48
+
49
+ constexpr size_t HALF_BIT_WIDTH = sizeof (T) * CHAR_BIT / 2 ;
50
+
51
+ auto r1 = add_with_carry (prod.lo , lo_hi.lo << HALF_BIT_WIDTH, T (0 ));
52
+ prod.lo = r1.sum ;
53
+ prod.hi = add_with_carry (prod.hi , lo_hi.hi , r1.carry ).sum ;
54
+
55
+ auto r2 = add_with_carry (prod.lo , hi_lo.lo << HALF_BIT_WIDTH, T (0 ));
56
+ prod.lo = r2.sum ;
57
+ prod.hi = add_with_carry (prod.hi , hi_lo.hi , r2.carry ).sum ;
58
+
59
+ return prod;
60
+ }
61
+
62
+ template <>
63
+ LIBC_INLINE constexpr NumberPair<uint32_t > full_mul<uint32_t >(uint32_t a,
64
+ uint32_t b) {
65
+ uint64_t prod = uint64_t (a) * uint64_t (b);
66
+ NumberPair<uint32_t > result;
67
+ result.lo = uint32_t (prod);
68
+ result.hi = uint32_t (prod >> 32 );
69
+ return result;
70
+ }
71
+
72
+ #ifdef __SIZEOF_INT128__
73
+ template <>
74
+ LIBC_INLINE constexpr NumberPair<uint64_t > full_mul<uint64_t >(uint64_t a,
75
+ uint64_t b) {
76
+ __uint128_t prod = __uint128_t (a) * __uint128_t (b);
77
+ NumberPair<uint64_t > result;
78
+ result.lo = uint64_t (prod);
79
+ result.hi = uint64_t (prod >> 64 );
80
+ return result;
81
+ }
82
+ #endif // __SIZEOF_INT128__
83
+
39
84
} // namespace internal
40
85
41
86
template <size_t Bits, bool Signed, typename WordType = uint64_t >
@@ -263,7 +308,7 @@ struct BigInt {
263
308
LIBC_INLINE constexpr WordType mul (WordType x) {
264
309
BigInt<2 * WORD_SIZE, Signed, WordType> partial_sum (0 );
265
310
for (size_t i = 0 ; i < WORD_COUNT; ++i) {
266
- NumberPair<WordType> prod = full_mul (val[i], x);
311
+ NumberPair<WordType> prod = internal:: full_mul (val[i], x);
267
312
BigInt<2 * WORD_SIZE, Signed, WordType> tmp ({prod.lo , prod.hi });
268
313
const WordType carry = partial_sum.add (tmp);
269
314
val[i] = partial_sum.val [0 ];
@@ -296,7 +341,8 @@ struct BigInt {
296
341
WordType carry = 0 ;
297
342
for (size_t i = 0 ; i < WORD_COUNT; ++i) {
298
343
for (size_t j = 0 ; j <= i; j++) {
299
- NumberPair<WordType> prod = full_mul (val[j], other.val [i - j]);
344
+ NumberPair<WordType> prod =
345
+ internal::full_mul (val[j], other.val [i - j]);
300
346
BigInt<2 * WORD_SIZE, Signed, WordType> tmp ({prod.lo , prod.hi });
301
347
carry += partial_sum.add (tmp);
302
348
}
@@ -324,7 +370,8 @@ struct BigInt {
324
370
i < OTHER_WORDCOUNT ? 0 : i - OTHER_WORDCOUNT + 1 ;
325
371
const size_t upper_idx = i < WORD_COUNT ? i : WORD_COUNT - 1 ;
326
372
for (size_t j = lower_idx; j <= upper_idx; ++j) {
327
- NumberPair<WordType> prod = full_mul (val[j], other.val [i - j]);
373
+ NumberPair<WordType> prod =
374
+ internal::full_mul (val[j], other.val [i - j]);
328
375
BigInt<2 * WORD_SIZE, Signed, WordType> tmp ({prod.lo , prod.hi });
329
376
carry += partial_sum.add (tmp);
330
377
}
@@ -366,7 +413,7 @@ struct BigInt {
366
413
// product.
367
414
for (size_t i = 0 ; i < WORD_COUNT; ++i) {
368
415
NumberPair<WordType> prod =
369
- full_mul (val[i], other.val [WORD_COUNT - 1 - i]);
416
+ internal:: full_mul (val[i], other.val [WORD_COUNT - 1 - i]);
370
417
BigInt<2 * WORD_SIZE, Signed, WordType> tmp ({prod.lo , prod.hi });
371
418
carry += partial_sum.add (tmp);
372
419
}
@@ -375,7 +422,8 @@ struct BigInt {
375
422
partial_sum.val [1 ] = carry;
376
423
carry = 0 ;
377
424
for (size_t j = i - WORD_COUNT + 1 ; j < WORD_COUNT; ++j) {
378
- NumberPair<WordType> prod = full_mul (val[j], other.val [i - j]);
425
+ NumberPair<WordType> prod =
426
+ internal::full_mul (val[j], other.val [i - j]);
379
427
BigInt<2 * WORD_SIZE, Signed, WordType> tmp ({prod.lo , prod.hi });
380
428
carry += partial_sum.add (tmp);
381
429
}
0 commit comments