1
1
//! Reciprocal, shared across Uint and BoxedUint
2
- use crate :: { ConstChoice , Limb , NonZero , WideWord , Word } ;
2
+ use crate :: { ConstChoice , Limb , NonZero , Word , primitives } ;
3
3
use subtle:: { Choice , ConditionallySelectable } ;
4
4
5
5
/// Calculates the reciprocal of the given 32-bit divisor with the highmost bit set.
@@ -49,17 +49,17 @@ pub const fn reciprocal(d: Word) -> Word {
49
49
let v2 = ( v1 << 13 ) + ( ( v1 * ( ( 1 << 60 ) - v1 * d40) ) >> 47 ) ;
50
50
51
51
// Checks that the expression for `e` can be simplified in the way we did below.
52
- debug_assert ! ( mulhilo( v2, d63) . 0 == ( 1 << 32 ) - 1 ) ;
52
+ debug_assert ! ( primitives :: mulhilo( v2, d63) . 0 == ( 1 << 32 ) - 1 ) ;
53
53
let e = Word :: MAX - v2. wrapping_mul ( d63) + 1 + ( v2 >> 1 ) * d0;
54
54
55
- let ( hi, _lo) = mulhilo ( v2, e) ;
55
+ let ( hi, _lo) = primitives :: mulhilo ( v2, e) ;
56
56
let v3 = ( v2 << 31 ) . wrapping_add ( hi >> 1 ) ;
57
57
58
58
// The paper has `(v3 + 1) * d / 2^64` (there's another 2^64, but it's accounted for later).
59
59
// If `v3 == 2^64-1` this should give `d`, but we can't achieve this in our wrapping arithmetic.
60
60
// Hence the `ct_select()`.
61
61
let x = v3. wrapping_add ( 1 ) ;
62
- let ( hi, _lo) = mulhilo ( x, d) ;
62
+ let ( hi, _lo) = primitives :: mulhilo ( x, d) ;
63
63
let hi = ConstChoice :: from_word_nonzero ( x) . select_word ( d, hi) ;
64
64
65
65
v3. wrapping_sub ( hi) . wrapping_sub ( d)
@@ -108,23 +108,6 @@ const fn short_div(dividend: u32, dividend_bits: u32, divisor: u32, divisor_bits
108
108
quotient
109
109
}
110
110
111
- /// Multiplies `x` and `y`, returning the most significant
112
- /// and the least significant words as `(hi, lo)`.
113
- #[ inline( always) ]
114
- const fn mulhilo ( x : Word , y : Word ) -> ( Word , Word ) {
115
- let res = ( x as WideWord ) * ( y as WideWord ) ;
116
- ( ( res >> Word :: BITS ) as Word , res as Word )
117
- }
118
-
119
- /// Adds wide numbers represented by pairs of (most significant word, least significant word)
120
- /// and returns the result in the same format `(hi, lo)`.
121
- #[ inline( always) ]
122
- const fn addhilo ( x_hi : Word , x_lo : Word , y_hi : Word , y_lo : Word ) -> ( Word , Word ) {
123
- let res = ( ( ( x_hi as WideWord ) << Word :: BITS ) | ( x_lo as WideWord ) )
124
- + ( ( ( y_hi as WideWord ) << Word :: BITS ) | ( y_lo as WideWord ) ) ;
125
- ( ( res >> Word :: BITS ) as Word , res as Word )
126
- }
127
-
128
111
/// Calculate the quotient and the remainder of the division of a wide word
129
112
/// (supplied as high and low words) by `d`, with a precalculated reciprocal `v`.
130
113
#[ inline( always) ]
@@ -134,8 +117,8 @@ pub(crate) const fn div2by1(u1: Word, u0: Word, reciprocal: &Reciprocal) -> (Wor
134
117
debug_assert ! ( d >= ( 1 << ( Word :: BITS - 1 ) ) ) ;
135
118
debug_assert ! ( u1 < d) ;
136
119
137
- let ( q1, q0) = mulhilo ( reciprocal. reciprocal , u1) ;
138
- let ( q1, q0) = addhilo ( q1, q0, u1, u0) ;
120
+ let ( q1, q0) = primitives :: mulhilo ( reciprocal. reciprocal , u1) ;
121
+ let ( q1, q0) = primitives :: addhilo ( q1, q0, u1, u0) ;
139
122
let q1 = q1. wrapping_add ( 1 ) ;
140
123
let r = u0. wrapping_sub ( q1. wrapping_mul ( d) ) ;
141
124
0 commit comments