@@ -52,24 +52,28 @@ impl<const BITS: usize, const LIMBS: usize> Uint<BITS, LIMBS> {
52
52
/// some pre-computation.
53
53
#[ inline]
54
54
#[ must_use]
55
- #[ cfg( feature = "alloc" ) ] // see comments below
56
55
pub fn mul_mod ( self , rhs : Self , mut modulus : Self ) -> Self {
57
56
if modulus == Self :: ZERO {
58
57
return Self :: ZERO ;
59
58
}
59
+
60
+ // Allocate at least `nlimbs(2 * BITS)` limbs to store the product. This array
61
+ // casting is a workaround for `generic_const_exprs` not being stable.
62
+ let mut product = [ [ 0u64 ; 2 ] ; LIMBS ] ;
63
+ let product_len = crate :: nlimbs ( 2 * BITS ) ;
64
+ debug_assert ! ( 2 * LIMBS >= product_len) ;
65
+ // SAFETY: `[[u64; 2]; LIMBS] == [u64; 2 * LIMBS] >= [u64; nlimbs(2 * BITS)]`.
66
+ let product = unsafe {
67
+ core:: slice:: from_raw_parts_mut ( product. as_mut_ptr ( ) . cast :: < u64 > ( ) , product_len)
68
+ } ;
69
+
60
70
// Compute full product.
61
- // The challenge here is that Rust doesn't allow us to create a
62
- // `Uint<2 * BITS, _>` for the intermediate result. Otherwise
63
- // we could just use a `widening_mul`. So instead we allocate from heap.
64
- // Alternatively we could use `alloca`, but that is blocked on
65
- // See <https://github.com/rust-lang/rust/issues/48055>
66
- let mut product = vec ! [ 0 ; crate :: nlimbs( 2 * BITS ) ] ;
67
- let overflow = algorithms:: addmul ( & mut product, self . as_limbs ( ) , rhs. as_limbs ( ) ) ;
71
+ let overflow = algorithms:: addmul ( product, self . as_limbs ( ) , rhs. as_limbs ( ) ) ;
68
72
debug_assert ! ( !overflow) ;
69
73
70
74
// Compute modulus using `div_rem`.
71
75
// This stores the remainder in the divisor, `modulus`.
72
- algorithms:: div ( & mut product, & mut modulus. limbs ) ;
76
+ algorithms:: div ( product, & mut modulus. limbs ) ;
73
77
74
78
modulus
75
79
}
@@ -79,7 +83,6 @@ impl<const BITS: usize, const LIMBS: usize> Uint<BITS, LIMBS> {
79
83
/// Returns zero if the modulus is zero.
80
84
#[ inline]
81
85
#[ must_use]
82
- #[ cfg( feature = "alloc" ) ] // see comments in mul_mod
83
86
pub fn pow_mod ( mut self , mut exp : Self , modulus : Self ) -> Self {
84
87
if modulus == Self :: ZERO || modulus <= Self :: from ( 1 ) {
85
88
// Also covers Self::BITS == 0
0 commit comments