@@ -20,7 +20,10 @@ impl Choice {
2020 /// Equivalent of [`true`].
2121 pub const TRUE : Self = Self ( 1 ) ;
2222
23- /// Create a new [`Choice`] from the given `u8` value, which should be either `0` or `1`.
23+ /// Create a new [`Choice`] from the given `u8` value, which MUST be either `0` or `1`.
24+ ///
25+ /// # Panics
26+ /// - in `debug` builds, panics if the value is anything other than `0` or `1`.
2427 #[ inline]
2528 pub const fn new ( value : u8 ) -> Self {
2629 // Compare to what should be the non-secret upper bits of the value, which should always be
@@ -165,12 +168,34 @@ impl Choice {
165168 Self :: from_u32_lsb ( ( value | value. wrapping_neg ( ) ) >> ( u32:: BITS - 1 ) )
166169 }
167170
171+ /// Returns the truthy value if `x == y`, and the falsy value otherwise.
172+ #[ inline]
173+ pub const fn from_u64_eq ( x : u64 , y : u64 ) -> Self {
174+ Self :: from_u64_nonzero ( x ^ y) . not ( )
175+ }
176+
177+ /// Returns the truthy value if `x <= y` and the falsy value otherwise.
178+ #[ inline]
179+ pub const fn from_u64_le ( x : u64 , y : u64 ) -> Self {
180+ // See "Hacker's Delight" 2nd ed, section 2-12 (Comparison predicates)
181+ let bit = ( ( ( !x) | y) & ( ( x ^ y) | !y. wrapping_sub ( x) ) ) >> ( u64:: BITS - 1 ) ;
182+ Self :: from_u64_lsb ( bit)
183+ }
184+
168185 /// Initialize from the least significant bit of a `u64`.
169186 #[ inline]
170187 pub const fn from_u64_lsb ( value : u64 ) -> Self {
171188 Self :: new ( ( value & 0x1 ) as u8 )
172189 }
173190
191+ /// Returns the truthy value if `x < y`, and the falsy value otherwise.
192+ #[ inline]
193+ pub const fn from_u64_lt ( x : u64 , y : u64 ) -> Self {
194+ // See "Hacker's Delight" 2nd ed, section 2-12 (Comparison predicates)
195+ let bit = ( ( ( !x) & y) | ( ( ( !x) | y) & x. wrapping_sub ( y) ) ) >> ( u64:: BITS - 1 ) ;
196+ Self :: from_u64_lsb ( bit)
197+ }
198+
174199 /// Returns the truthy value if `value != 0`, and the falsy value otherwise.
175200 #[ inline]
176201 pub const fn from_u64_nonzero ( value : u64 ) -> Self {
@@ -214,8 +239,7 @@ impl Choice {
214239 /// - `0` for `Choice::FALSE`
215240 /// - `u32::MAX` for `Choice::TRUE`
216241 #[ inline]
217- #[ allow( trivial_numeric_casts) ]
218- pub ( crate ) const fn to_u32_mask ( self ) -> u32 {
242+ pub const fn to_u32_mask ( self ) -> u32 {
219243 ( self . 0 as u32 & 1 ) . wrapping_neg ( )
220244 }
221245
@@ -225,8 +249,7 @@ impl Choice {
225249 /// - `0` for `Choice::FALSE`
226250 /// - `u64::MAX` for `Choice::TRUE`
227251 #[ inline]
228- #[ allow( trivial_numeric_casts) ]
229- pub ( crate ) const fn to_u64_mask ( self ) -> u64 {
252+ pub const fn to_u64_mask ( self ) -> u64 {
230253 ( self . 0 as u64 & 1 ) . wrapping_neg ( )
231254 }
232255}
@@ -443,12 +466,34 @@ mod tests {
443466 assert_eq ! ( Choice :: from_u32_nonzero( 2 ) , Choice :: TRUE ) ;
444467 }
445468
469+ #[ test]
470+ fn from_u64_eq ( ) {
471+ assert_eq ! ( Choice :: from_u64_eq( 0 , 1 ) , Choice :: FALSE ) ;
472+ assert_eq ! ( Choice :: from_u64_eq( 1 , 1 ) , Choice :: TRUE ) ;
473+ }
474+
475+ #[ test]
476+ fn from_u64_le ( ) {
477+ assert_eq ! ( Choice :: from_u64_le( 0 , 0 ) , Choice :: TRUE ) ;
478+ assert_eq ! ( Choice :: from_u64_le( 1 , 0 ) , Choice :: FALSE ) ;
479+ assert_eq ! ( Choice :: from_u64_le( 1 , 1 ) , Choice :: TRUE ) ;
480+ assert_eq ! ( Choice :: from_u64_le( 1 , 2 ) , Choice :: TRUE ) ;
481+ }
482+
446483 #[ test]
447484 fn from_u64_lsb ( ) {
448485 assert_eq ! ( Choice :: from_u64_lsb( 0 ) , Choice :: FALSE ) ;
449486 assert_eq ! ( Choice :: from_u64_lsb( 1 ) , Choice :: TRUE ) ;
450487 }
451488
489+ #[ test]
490+ fn from_u64_lt ( ) {
491+ assert_eq ! ( Choice :: from_u64_lt( 0 , 0 ) , Choice :: FALSE ) ;
492+ assert_eq ! ( Choice :: from_u64_lt( 1 , 0 ) , Choice :: FALSE ) ;
493+ assert_eq ! ( Choice :: from_u64_lt( 1 , 1 ) , Choice :: FALSE ) ;
494+ assert_eq ! ( Choice :: from_u64_lt( 1 , 2 ) , Choice :: TRUE ) ;
495+ }
496+
452497 #[ test]
453498 fn from_u64_nonzero ( ) {
454499 assert_eq ! ( Choice :: from_u64_nonzero( 0 ) , Choice :: FALSE ) ;
0 commit comments