File tree Expand file tree Collapse file tree 3 files changed +73
-10
lines changed Expand file tree Collapse file tree 3 files changed +73
-10
lines changed Original file line number Diff line number Diff line change @@ -197,15 +197,33 @@ impl Scalar29 {
197
197
}
198
198
199
199
// conditionally add l if the difference is negative
200
+ difference. conditional_add_l ( Choice :: from ( ( borrow >> 31 ) as u8 ) ) ;
201
+ difference
202
+ }
203
+
204
+ pub ( crate ) fn conditional_add_l ( & mut self , condition : Choice ) -> u32 {
200
205
let mut carry: u32 = 0 ;
206
+ let mask = ( 1u32 << 29 ) - 1 ;
207
+
201
208
for i in 0 ..9 {
202
- let underflow = Choice :: from ( ( borrow >> 31 ) as u8 ) ;
203
- let addend = u32:: conditional_select ( & 0 , & constants:: L [ i] , underflow) ;
204
- carry = ( carry >> 29 ) + difference[ i] + addend;
205
- difference[ i] = carry & mask;
209
+ let addend = u32:: conditional_select ( & 0 , & constants:: L [ i] , condition) ;
210
+ carry = ( carry >> 29 ) + self [ i] + addend;
211
+ self [ i] = carry & mask;
206
212
}
213
+ carry
214
+ }
207
215
208
- difference
216
+ /// Compute a raw in-place carrying right shift over the limbs.
217
+ #[ inline( always) ]
218
+ pub ( crate ) fn shr1_assign ( & mut self ) -> u32 {
219
+ let mut carry: u32 = 0 ;
220
+ for i in ( 0 ..9 ) . rev ( ) {
221
+ let limb = self [ i] ;
222
+ let next_carry = limb & 1 ;
223
+ self [ i] = ( limb >> 1 ) | ( carry << 28 ) ;
224
+ carry = next_carry;
225
+ }
226
+ carry
209
227
}
210
228
211
229
/// Compute `a * b`.
Original file line number Diff line number Diff line change @@ -186,15 +186,34 @@ impl Scalar52 {
186
186
}
187
187
188
188
// conditionally add l if the difference is negative
189
+ difference. conditional_add_l ( Choice :: from ( ( borrow >> 63 ) as u8 ) ) ;
190
+ difference
191
+ }
192
+
193
+ pub ( crate ) fn conditional_add_l ( & mut self , condition : Choice ) -> u64 {
189
194
let mut carry: u64 = 0 ;
195
+ let mask = ( 1u64 << 52 ) - 1 ;
196
+
190
197
for i in 0 ..5 {
191
- let underflow = Choice :: from ( ( borrow >> 63 ) as u8 ) ;
192
- let addend = u64:: conditional_select ( & 0 , & constants:: L [ i] , underflow) ;
193
- carry = ( carry >> 52 ) + difference[ i] + addend;
194
- difference[ i] = carry & mask;
198
+ let addend = u64:: conditional_select ( & 0 , & constants:: L [ i] , condition) ;
199
+ carry = ( carry >> 52 ) + self [ i] + addend;
200
+ self [ i] = carry & mask;
195
201
}
196
202
197
- difference
203
+ carry
204
+ }
205
+
206
+ /// Compute a raw in-place carrying right shift over the limbs.
207
+ #[ inline( always) ]
208
+ pub ( crate ) fn shr1_assign ( & mut self ) -> u64 {
209
+ let mut carry: u64 = 0 ;
210
+ for i in ( 0 ..5 ) . rev ( ) {
211
+ let limb = self [ i] ;
212
+ let next_carry = limb & 1 ;
213
+ self [ i] = ( limb >> 1 ) | ( carry << 51 ) ;
214
+ carry = next_carry;
215
+ }
216
+ carry
198
217
}
199
218
200
219
/// Compute `a * b`
Original file line number Diff line number Diff line change @@ -831,6 +831,22 @@ impl Scalar {
831
831
ret
832
832
}
833
833
834
+ /// Compute `b` such that `b + b = a mod modulus`.
835
+ pub fn div_by_2 ( & self ) -> Self {
836
+ // We are looking for such `b` that `b + b = a mod modulus`.
837
+ // Two possibilities:
838
+ // - if `a` is even, we can just divide by 2;
839
+ // - if `a` is odd, we divide `(a + modulus)` by 2.
840
+ let is_odd = Choice :: from ( self . as_bytes ( ) [ 0 ] & 1 ) ;
841
+ let mut scalar = self . unpack ( ) ;
842
+ scalar. conditional_add_l ( is_odd) ;
843
+
844
+ // TODO(tarcieri): propagate carry
845
+ let _carry = scalar. shr1_assign ( ) ;
846
+ scalar. pack ( )
847
+ }
848
+
849
+
834
850
/// Get the bits of the scalar, in little-endian order
835
851
pub ( crate ) fn bits_le ( & self ) -> impl DoubleEndedIterator < Item = bool > + ' _ {
836
852
( 0 ..256 ) . map ( |i| {
@@ -1677,6 +1693,16 @@ pub(crate) mod test {
1677
1693
}
1678
1694
}
1679
1695
1696
+ #[ test]
1697
+ fn div_by_2 ( ) {
1698
+ for i in 0u64 ..32 {
1699
+ let scalar = Scalar :: from ( i) ;
1700
+ let double = scalar. double ( ) ;
1701
+ let dividend = double. div_by_2 ( ) ;
1702
+ assert_eq ! ( scalar, dividend) ;
1703
+ }
1704
+ }
1705
+
1680
1706
#[ test]
1681
1707
fn reduce ( ) {
1682
1708
let biggest = Scalar :: from_bytes_mod_order ( [ 0xff ; 32 ] ) ;
You can’t perform that action at this time.
0 commit comments