1use crate::primitives::{bitle, bitnz};
2use crate::{CtAssign, CtAssignSlice, CtEq, CtEqSlice, CtSelectUsingCtAssign};
3use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not};
4
5#[cfg(feature = "subtle")]
6use crate::CtSelect;
7
8#[derive(Copy, Clone, Debug)]
18pub struct Choice(pub(crate) u8);
19
20impl Choice {
21 pub const FALSE: Self = Self(0);
23
24 pub const TRUE: Self = Self(1);
26
27 #[inline]
33 #[must_use]
34 pub const fn and(self, rhs: Choice) -> Choice {
35 #[cfg(all(target_arch = "arm", not(target_has_atomic = "ptr")))]
36 {
37 Self(self.to_u8() & rhs.to_u8())
39 }
40 #[cfg(not(all(target_arch = "arm", not(target_has_atomic = "ptr"))))]
41 {
42 Self(self.0 & rhs.0)
43 }
44 }
45
46 #[inline]
48 #[must_use]
49 pub const fn or(self, rhs: Choice) -> Choice {
50 Self(self.0 | rhs.0)
51 }
52
53 #[inline]
55 #[must_use]
56 pub const fn xor(self, rhs: Choice) -> Choice {
57 Self(self.0 ^ rhs.0)
58 }
59
60 #[inline]
62 #[must_use]
63 pub const fn not(self) -> Choice {
64 Self(self.0 ^ 1)
66 }
67
68 #[inline]
74 #[must_use]
75 pub const fn eq(self, other: Self) -> Self {
76 Self::ne(self, other).not()
77 }
78
79 #[inline]
81 #[must_use]
82 pub const fn ne(self, other: Self) -> Self {
83 Self::xor(self, other)
84 }
85
86 #[inline]
94 #[must_use]
95 pub const fn from_i64_eq(x: i64, y: i64) -> Self {
96 Self::from_u64_nz(x.cast_unsigned() ^ y.cast_unsigned()).not()
97 }
98
99 #[inline]
103 #[must_use]
104 pub const fn from_u8_eq(x: u8, y: u8) -> Self {
105 Self::from_u8_nz(x ^ y).not()
106 }
107
108 #[inline]
110 #[must_use]
111 pub const fn from_u8_le(x: u8, y: u8) -> Self {
112 Self::from_u8_lsb(bitle!(x, y, u8::BITS))
113 }
114
115 #[inline]
117 #[must_use]
118 pub const fn from_u8_lsb(value: u8) -> Self {
119 Self(value & 0x1)
120 }
121
122 #[inline]
124 #[must_use]
125 pub const fn from_u8_lt(x: u8, y: u8) -> Self {
126 #[cfg(all(target_arch = "arm", not(target_has_atomic = "ptr")))]
128 {
129 Self::from_u32_lt(x as u32, y as u32)
130 }
131 #[cfg(not(all(target_arch = "arm", not(target_has_atomic = "ptr"))))]
132 {
133 Self::from_u8_lsb(crate::primitives::bitlt!(x, y, u8::BITS))
134 }
135 }
136
137 #[inline]
139 #[must_use]
140 pub const fn from_u8_nz(value: u8) -> Self {
141 Self::from_u8_lsb(bitnz!(value, u8::BITS))
142 }
143
144 #[inline]
148 #[must_use]
149 pub const fn from_u16_eq(x: u16, y: u16) -> Self {
150 Self::from_u16_nz(x ^ y).not()
151 }
152
153 #[inline]
155 #[must_use]
156 pub const fn from_u16_le(x: u16, y: u16) -> Self {
157 Self::from_u16_lsb(bitle!(x, y, u16::BITS))
158 }
159
160 #[inline]
162 #[must_use]
163 pub const fn from_u16_lsb(value: u16) -> Self {
164 Self((value & 0x1) as u8)
165 }
166
167 #[inline]
169 #[must_use]
170 pub const fn from_u16_lt(x: u16, y: u16) -> Self {
171 #[cfg(all(target_arch = "arm", not(target_has_atomic = "ptr")))]
173 {
174 Self::from_u32_lt(x as u32, y as u32)
175 }
176 #[cfg(not(all(target_arch = "arm", not(target_has_atomic = "ptr"))))]
177 {
178 Self::from_u16_lsb(crate::primitives::bitlt!(x, y, u16::BITS))
179 }
180 }
181
182 #[inline]
184 #[must_use]
185 pub const fn from_u16_nz(value: u16) -> Self {
186 Self::from_u16_lsb(bitnz!(value, u16::BITS))
187 }
188
189 #[inline]
193 #[must_use]
194 pub const fn from_u32_eq(x: u32, y: u32) -> Self {
195 Self::from_u32_nz(x ^ y).not()
196 }
197
198 #[inline]
200 #[must_use]
201 pub const fn from_u32_le(x: u32, y: u32) -> Self {
202 crate::primitives::le_u32(x, y)
203 }
204
205 #[inline]
207 #[must_use]
208 pub const fn from_u32_lsb(value: u32) -> Self {
209 Self((value & 0x1) as u8)
210 }
211
212 #[inline]
214 #[must_use]
215 pub const fn from_u32_lt(x: u32, y: u32) -> Self {
216 crate::primitives::lt_u32(x, y)
217 }
218
219 #[inline]
221 #[must_use]
222 pub const fn from_u32_nz(value: u32) -> Self {
223 crate::primitives::nz_u32(value)
224 }
225
226 #[inline]
230 #[must_use]
231 pub const fn from_u64_eq(x: u64, y: u64) -> Self {
232 Self::from_u64_nz(x ^ y).not()
233 }
234
235 #[inline]
237 #[must_use]
238 pub const fn from_u64_le(x: u64, y: u64) -> Self {
239 crate::primitives::le_u64(x, y)
240 }
241
242 #[inline]
244 #[must_use]
245 pub const fn from_u64_lsb(value: u64) -> Self {
246 Self((value & 0x1) as u8)
247 }
248
249 #[inline]
251 #[must_use]
252 pub const fn from_u64_lt(x: u64, y: u64) -> Self {
253 crate::primitives::lt_u64(x, y)
254 }
255
256 #[inline]
258 #[must_use]
259 pub const fn from_u64_nz(value: u64) -> Self {
260 crate::primitives::nz_u64(value)
261 }
262
263 #[inline]
267 #[must_use]
268 pub const fn from_u128_eq(x: u128, y: u128) -> Self {
269 Self::from_u128_nz(x ^ y).not()
270 }
271
272 #[inline]
274 #[must_use]
275 pub const fn from_u128_le(x: u128, y: u128) -> Self {
276 #[cfg(target_pointer_width = "32")]
277 {
278 Self::from_u128_lt(y, x).not()
279 }
280 #[cfg(not(target_pointer_width = "32"))]
281 {
282 Self::from_u128_lsb(bitle!(x, y, u128::BITS))
283 }
284 }
285
286 #[inline]
288 #[must_use]
289 pub const fn from_u128_lsb(value: u128) -> Self {
290 Self((value & 1) as u8)
291 }
292
293 #[inline]
295 #[must_use]
296 pub const fn from_u128_lt(x: u128, y: u128) -> Self {
297 #[cfg(target_pointer_width = "32")]
298 {
299 Self::from_u128_lt_halves(x, y)
300 }
301 #[cfg(not(target_pointer_width = "32"))]
302 {
303 Self::from_u128_lsb(crate::primitives::bitlt!(x, y, u128::BITS))
304 }
305 }
306
307 #[cfg(any(target_pointer_width = "32", test))]
308 #[inline]
309 #[allow(clippy::cast_possible_truncation)]
310 const fn from_u128_lt_halves(x: u128, y: u128) -> Self {
311 let x_hi = (x >> 64) as u64;
315 let y_hi = (y >> 64) as u64;
316 let hi_lt = Self::from_u64_lt(x_hi, y_hi).to_u8();
317 let hi_eq = Self::from_u64_eq(x_hi, y_hi).to_u8();
318 let lo_lt = Self::from_u64_lt(x as u64, y as u64).to_u8();
319 Self::from_u8_lsb(hi_lt | (hi_eq & lo_lt))
320 }
321
322 #[inline]
324 #[must_use]
325 pub const fn from_u128_nz(value: u128) -> Self {
326 Self::from_u128_lsb(bitnz!(value, u128::BITS))
327 }
328
329 #[inline]
338 #[must_use]
339 pub const fn select_i64(self, a: i64, b: i64) -> i64 {
340 self.select_u64(a.cast_unsigned(), b.cast_unsigned())
341 .cast_signed()
342 }
343
344 #[inline]
349 #[must_use]
350 pub const fn select_u8(self, a: u8, b: u8) -> u8 {
351 a ^ (self.to_u8_mask() & (a ^ b))
352 }
353
354 #[inline]
359 #[must_use]
360 pub const fn select_u16(self, a: u16, b: u16) -> u16 {
361 a ^ (self.to_u16_mask() & (a ^ b))
362 }
363
364 #[inline]
369 #[must_use]
370 pub const fn select_u32(self, a: u32, b: u32) -> u32 {
371 a ^ (self.to_u32_mask() & (a ^ b))
372 }
373
374 #[inline]
379 #[must_use]
380 pub const fn select_u64(self, a: u64, b: u64) -> u64 {
381 a ^ (self.to_u64_mask() & (a ^ b))
382 }
383
384 #[inline]
389 #[must_use]
390 pub const fn select_u128(self, a: u128, b: u128) -> u128 {
391 a ^ (self.to_u128_mask() & (a ^ b))
392 }
393
394 #[must_use]
416 pub const fn to_bool(self) -> bool {
417 self.to_u8() != 0
418 }
419
420 #[must_use]
422 pub const fn to_u8(self) -> u8 {
423 core::hint::black_box(self.0)
427 }
428
429 #[deprecated(since = "0.4.3", note = "use `Choice::to_bool` instead")]
439 #[must_use]
440 pub const fn to_bool_vartime(self) -> bool {
441 self.to_bool()
442 }
443
444 #[deprecated(since = "0.4.3", note = "use `Choice::to_u8` instead")]
448 #[must_use]
449 pub const fn to_u8_vartime(self) -> u8 {
450 self.to_u8()
451 }
452
453 #[inline]
459 #[must_use]
460 pub const fn to_u8_mask(self) -> u8 {
461 self.to_u8().wrapping_neg()
462 }
463
464 #[inline]
470 #[must_use]
471 pub const fn to_u16_mask(self) -> u16 {
472 (self.to_u8() as u16).wrapping_neg()
473 }
474
475 #[inline]
481 #[must_use]
482 pub const fn to_u32_mask(self) -> u32 {
483 (self.to_u8() as u32).wrapping_neg()
484 }
485
486 #[inline]
492 #[must_use]
493 pub const fn to_u64_mask(self) -> u64 {
494 (self.to_u8() as u64).wrapping_neg()
495 }
496
497 #[inline]
503 #[must_use]
504 pub const fn to_u128_mask(self) -> u128 {
505 (self.to_u8() as u128).wrapping_neg()
506 }
507}
508
509impl BitAnd for Choice {
510 type Output = Choice;
511
512 #[inline]
513 fn bitand(self, rhs: Choice) -> Choice {
514 self.and(rhs)
515 }
516}
517
518impl BitAndAssign for Choice {
519 #[inline]
520 fn bitand_assign(&mut self, rhs: Choice) {
521 *self = *self & rhs;
522 }
523}
524
525impl BitOr for Choice {
526 type Output = Choice;
527
528 #[inline]
529 fn bitor(self, rhs: Choice) -> Choice {
530 self.or(rhs)
531 }
532}
533
534impl BitOrAssign for Choice {
535 #[inline]
536 fn bitor_assign(&mut self, rhs: Choice) {
537 *self = *self | rhs;
538 }
539}
540
541impl BitXor for Choice {
542 type Output = Choice;
543
544 #[inline]
545 fn bitxor(self, rhs: Choice) -> Choice {
546 Choice(self.0 ^ rhs.0)
547 }
548}
549
550impl BitXorAssign for Choice {
551 #[inline]
552 fn bitxor_assign(&mut self, rhs: Choice) {
553 *self = *self ^ rhs;
554 }
555}
556
557impl CtAssign for Choice {
558 #[inline]
559 fn ct_assign(&mut self, other: &Self, choice: Choice) {
560 self.0.ct_assign(&other.0, choice);
561 }
562}
563impl CtAssignSlice for Choice {}
564impl CtSelectUsingCtAssign for Choice {}
565
566impl CtEq for Choice {
567 #[inline]
568 fn ct_eq(&self, other: &Self) -> Self {
569 self.0.ct_eq(&other.0)
570 }
571}
572impl CtEqSlice for Choice {}
573
574impl From<u8> for Choice {
583 fn from(value: u8) -> Self {
584 Choice::from_u8_lsb(value)
585 }
586}
587
588impl From<Choice> for u8 {
589 fn from(choice: Choice) -> u8 {
590 choice.to_u8()
591 }
592}
593
594impl From<Choice> for bool {
605 fn from(choice: Choice) -> bool {
606 choice.to_bool()
607 }
608}
609
610impl Not for Choice {
611 type Output = Choice;
612
613 #[inline]
614 fn not(self) -> Choice {
615 self.not()
616 }
617}
618
619#[cfg(feature = "subtle")]
620impl From<subtle::Choice> for Choice {
621 #[inline]
622 fn from(choice: subtle::Choice) -> Choice {
623 Choice(choice.unwrap_u8())
624 }
625}
626
627#[cfg(feature = "subtle")]
628impl From<Choice> for subtle::Choice {
629 #[inline]
630 fn from(choice: Choice) -> subtle::Choice {
631 subtle::Choice::from(choice.0)
632 }
633}
634
635#[cfg(feature = "subtle")]
636impl subtle::ConditionallySelectable for Choice {
637 #[inline]
638 fn conditional_select(a: &Self, b: &Self, choice: subtle::Choice) -> Self {
639 CtSelect::ct_select(a, b, choice.into())
640 }
641}
642
643#[cfg(feature = "subtle")]
644impl subtle::ConstantTimeEq for Choice {
645 #[inline]
646 fn ct_eq(&self, other: &Self) -> subtle::Choice {
647 CtEq::ct_eq(self, other).into()
648 }
649}
650
651#[cfg(test)]
652mod tests {
653 use super::Choice;
654 use crate::{CtEq, CtGt, CtLt, CtSelect};
655
656 #[test]
657 fn ct_eq() {
658 let a = Choice::TRUE;
659 let b = Choice::TRUE;
660 let c = Choice::FALSE;
661
662 assert!(a.ct_eq(&b).to_bool());
663 assert!(!a.ct_eq(&c).to_bool());
664 assert!(!b.ct_eq(&c).to_bool());
665
666 assert!(!a.ct_ne(&b).to_bool());
667 assert!(a.ct_ne(&c).to_bool());
668 assert!(b.ct_ne(&c).to_bool());
669 }
670
671 #[test]
672 fn ct_select() {
673 let a = Choice::FALSE;
674 let b = Choice::TRUE;
675 assert_eq!(a.ct_select(&b, Choice::FALSE).to_bool(), a.to_bool());
676 assert_eq!(a.ct_select(&b, Choice::TRUE).to_bool(), b.to_bool());
677 }
678
679 #[test]
680 fn and() {
681 assert_eq!((Choice::FALSE & Choice::FALSE).to_u8(), 0);
682 assert_eq!((Choice::TRUE & Choice::FALSE).to_u8(), 0);
683 assert_eq!((Choice::FALSE & Choice::TRUE).to_u8(), 0);
684 assert_eq!((Choice::TRUE & Choice::TRUE).to_u8(), 1);
685 }
686
687 #[test]
688 fn or() {
689 assert_eq!((Choice::FALSE | Choice::FALSE).to_u8(), 0);
690 assert_eq!((Choice::TRUE | Choice::FALSE).to_u8(), 1);
691 assert_eq!((Choice::FALSE | Choice::TRUE).to_u8(), 1);
692 assert_eq!((Choice::TRUE | Choice::TRUE).to_u8(), 1);
693 }
694
695 #[test]
696 fn xor() {
697 assert_eq!((Choice::FALSE ^ Choice::FALSE).to_u8(), 0);
698 assert_eq!((Choice::TRUE ^ Choice::FALSE).to_u8(), 1);
699 assert_eq!((Choice::FALSE ^ Choice::TRUE).to_u8(), 1);
700 assert_eq!((Choice::TRUE ^ Choice::TRUE).to_u8(), 0);
701 }
702
703 #[test]
704 fn not() {
705 assert_eq!(Choice::FALSE.not().to_u8(), 1);
706 assert_eq!(Choice::TRUE.not().to_u8(), 0);
707 }
708
709 #[test]
710 fn from_i64_eq() {
711 assert!(Choice::from_i64_eq(0, 1).eq(Choice::FALSE).to_bool());
712 assert!(Choice::from_i64_eq(1, 1).eq(Choice::TRUE).to_bool());
713 }
714
715 #[test]
716 fn from_u8_eq() {
717 assert!(Choice::from_u8_eq(0, 1).eq(Choice::FALSE).to_bool());
718 assert!(Choice::from_u8_eq(1, 1).eq(Choice::TRUE).to_bool());
719 }
720
721 #[test]
722 fn from_u8_le() {
723 assert!(Choice::from_u8_le(0, 0).eq(Choice::TRUE).to_bool());
724 assert!(Choice::from_u8_le(1, 0).eq(Choice::FALSE).to_bool());
725 assert!(Choice::from_u8_le(1, 1).eq(Choice::TRUE).to_bool());
726 assert!(Choice::from_u8_le(1, 2).eq(Choice::TRUE).to_bool());
727 }
728
729 #[test]
730 fn from_u8_lsb() {
731 assert!(Choice::from_u8_lsb(0).eq(Choice::FALSE).to_bool());
732 assert!(Choice::from_u8_lsb(1).eq(Choice::TRUE).to_bool());
733 assert!(Choice::from_u8_lsb(2).eq(Choice::FALSE).to_bool());
734 assert!(Choice::from_u8_lsb(3).eq(Choice::TRUE).to_bool());
735 }
736
737 #[test]
738 fn from_u8_lt() {
739 assert!(Choice::from_u8_lt(0, 0).eq(Choice::FALSE).to_bool());
740 assert!(Choice::from_u8_lt(1, 0).eq(Choice::FALSE).to_bool());
741 assert!(Choice::from_u8_lt(1, 1).eq(Choice::FALSE).to_bool());
742 assert!(Choice::from_u8_lt(1, 2).eq(Choice::TRUE).to_bool());
743 }
744
745 #[test]
746 fn from_u8_nz() {
747 assert!(Choice::from_u8_nz(0).eq(Choice::FALSE).to_bool());
748 assert!(Choice::from_u8_nz(1).eq(Choice::TRUE).to_bool());
749 assert!(Choice::from_u8_nz(2).eq(Choice::TRUE).to_bool());
750 }
751
752 #[test]
753 fn from_u16_eq() {
754 assert!(Choice::from_u16_eq(0, 1).eq(Choice::FALSE).to_bool());
755 assert!(Choice::from_u16_eq(1, 1).eq(Choice::TRUE).to_bool());
756 }
757
758 #[test]
759 fn from_u16_le() {
760 assert!(Choice::from_u16_le(0, 0).eq(Choice::TRUE).to_bool());
761 assert!(Choice::from_u16_le(1, 0).eq(Choice::FALSE).to_bool());
762 assert!(Choice::from_u16_le(1, 1).eq(Choice::TRUE).to_bool());
763 assert!(Choice::from_u16_le(1, 2).eq(Choice::TRUE).to_bool());
764 }
765
766 #[test]
767 fn from_u16_lsb() {
768 assert!(Choice::from_u16_lsb(0).eq(Choice::FALSE).to_bool());
769 assert!(Choice::from_u16_lsb(1).eq(Choice::TRUE).to_bool());
770 assert!(Choice::from_u16_lsb(2).eq(Choice::FALSE).to_bool());
771 assert!(Choice::from_u16_lsb(3).eq(Choice::TRUE).to_bool());
772 }
773
774 #[test]
775 fn from_u16_lt() {
776 assert!(Choice::from_u16_lt(0, 0).eq(Choice::FALSE).to_bool());
777 assert!(Choice::from_u16_lt(1, 0).eq(Choice::FALSE).to_bool());
778 assert!(Choice::from_u16_lt(1, 1).eq(Choice::FALSE).to_bool());
779 assert!(Choice::from_u16_lt(1, 2).eq(Choice::TRUE).to_bool());
780 }
781
782 #[test]
783 fn from_u16_nz() {
784 assert!(Choice::from_u16_nz(0).eq(Choice::FALSE).to_bool());
785 assert!(Choice::from_u16_nz(1).eq(Choice::TRUE).to_bool());
786 assert!(Choice::from_u16_nz(2).eq(Choice::TRUE).to_bool());
787 }
788
789 #[test]
790 fn from_u32_eq() {
791 assert!(Choice::from_u32_eq(0, 1).eq(Choice::FALSE).to_bool());
792 assert!(Choice::from_u32_eq(1, 1).eq(Choice::TRUE).to_bool());
793 }
794
795 #[test]
796 fn from_u32_le() {
797 assert!(Choice::from_u32_le(0, 0).eq(Choice::TRUE).to_bool());
798 assert!(Choice::from_u32_le(1, 0).eq(Choice::FALSE).to_bool());
799 assert!(Choice::from_u32_le(1, 1).eq(Choice::TRUE).to_bool());
800 assert!(Choice::from_u32_le(1, 2).eq(Choice::TRUE).to_bool());
801 }
802
803 #[test]
804 fn from_u32_lsb() {
805 assert!(Choice::from_u32_lsb(0).eq(Choice::FALSE).to_bool());
806 assert!(Choice::from_u32_lsb(1).eq(Choice::TRUE).to_bool());
807 assert!(Choice::from_u32_lsb(2).eq(Choice::FALSE).to_bool());
808 assert!(Choice::from_u32_lsb(3).eq(Choice::TRUE).to_bool());
809 }
810
811 #[test]
812 fn from_u32_lt() {
813 assert!(Choice::from_u32_lt(0, 0).eq(Choice::FALSE).to_bool());
814 assert!(Choice::from_u32_lt(1, 0).eq(Choice::FALSE).to_bool());
815 assert!(Choice::from_u32_lt(1, 1).eq(Choice::FALSE).to_bool());
816 assert!(Choice::from_u32_lt(1, 2).eq(Choice::TRUE).to_bool());
817 }
818
819 #[test]
820 fn from_u32_nz() {
821 assert!(Choice::from_u32_nz(0).eq(Choice::FALSE).to_bool());
822 assert!(Choice::from_u32_nz(1).eq(Choice::TRUE).to_bool());
823 assert!(Choice::from_u32_nz(2).eq(Choice::TRUE).to_bool());
824 }
825
826 #[test]
827 fn from_u64_eq() {
828 assert!(Choice::from_u64_eq(0, 1).eq(Choice::FALSE).to_bool());
829 assert!(Choice::from_u64_eq(1, 1).eq(Choice::TRUE).to_bool());
830 }
831
832 #[test]
833 fn from_u64_le() {
834 assert!(Choice::from_u64_le(0, 0).eq(Choice::TRUE).to_bool());
835 assert!(Choice::from_u64_le(1, 0).eq(Choice::FALSE).to_bool());
836 assert!(Choice::from_u64_le(1, 1).eq(Choice::TRUE).to_bool());
837 assert!(Choice::from_u64_le(1, 2).eq(Choice::TRUE).to_bool());
838 }
839
840 #[test]
841 fn from_u64_lsb() {
842 assert!(Choice::from_u64_lsb(0).eq(Choice::FALSE).to_bool());
843 assert!(Choice::from_u64_lsb(1).eq(Choice::TRUE).to_bool());
844 }
845
846 #[test]
847 fn from_u64_lt() {
848 assert!(Choice::from_u64_lt(0, 0).eq(Choice::FALSE).to_bool());
849 assert!(Choice::from_u64_lt(1, 0).eq(Choice::FALSE).to_bool());
850 assert!(Choice::from_u64_lt(1, 1).eq(Choice::FALSE).to_bool());
851 assert!(Choice::from_u64_lt(1, 2).eq(Choice::TRUE).to_bool());
852 }
853
854 #[test]
855 fn from_u64_nz() {
856 assert!(Choice::from_u64_nz(0).eq(Choice::FALSE).to_bool());
857 assert!(Choice::from_u64_nz(1).eq(Choice::TRUE).to_bool());
858 assert!(Choice::from_u64_nz(2).eq(Choice::TRUE).to_bool());
859 }
860
861 #[test]
862 fn from_u128_eq() {
863 assert!(Choice::from_u128_eq(0, 1).eq(Choice::FALSE).to_bool());
864 assert!(Choice::from_u128_eq(1, 1).eq(Choice::TRUE).to_bool());
865 }
866
867 #[test]
868 fn from_u128_le() {
869 assert!(Choice::from_u128_le(0, 0).eq(Choice::TRUE).to_bool());
870 assert!(Choice::from_u128_le(1, 0).eq(Choice::FALSE).to_bool());
871 assert!(Choice::from_u128_le(1, 1).eq(Choice::TRUE).to_bool());
872 assert!(Choice::from_u128_le(1, 2).eq(Choice::TRUE).to_bool());
873 }
874
875 #[test]
876 fn from_u128_lsb() {
877 assert!(Choice::from_u128_lsb(0).eq(Choice::FALSE).to_bool());
878 assert!(Choice::from_u128_lsb(1).eq(Choice::TRUE).to_bool());
879 }
880
881 #[test]
882 fn from_u128_lt() {
883 assert!(Choice::from_u128_lt(0, 0).eq(Choice::FALSE).to_bool());
884 assert!(Choice::from_u128_lt(1, 0).eq(Choice::FALSE).to_bool());
885 assert!(Choice::from_u128_lt(1, 1).eq(Choice::FALSE).to_bool());
886 assert!(Choice::from_u128_lt(1, 2).eq(Choice::TRUE).to_bool());
887 }
888
889 #[test]
890 fn from_u128_comparison_boundaries() {
891 const LT: Choice = Choice::from_u128_lt_halves((1 << 96) - 1, 1 << 96);
892 const LE: Choice = Choice::from_u128_le(1 << 64, 1 << 64);
893 assert!(LT.to_bool());
894 assert!(LE.to_bool());
895
896 let values = [
897 0,
898 1,
899 (1 << 32) - 1,
900 1 << 32,
901 (1 << 64) - 1,
902 1 << 64,
903 (1 << 64) + 1,
904 (1 << 96) - 1,
905 1 << 96,
906 u128::MAX - 1,
907 u128::MAX,
908 ];
909
910 for x in values {
911 for y in values {
912 assert_eq!(x < y, Choice::from_u128_lt_halves(x, y).to_bool());
913 assert_eq!(x < y, Choice::from_u128_lt(x, y).to_bool());
914 assert_eq!(x <= y, Choice::from_u128_le(x, y).to_bool());
915 assert_eq!(x < y, x.ct_lt(&y).to_bool());
916 assert_eq!(x > y, x.ct_gt(&y).to_bool());
917 }
918 }
919 }
920
921 #[test]
922 fn from_u128_nz() {
923 assert!(Choice::from_u128_nz(0).eq(Choice::FALSE).to_bool());
924 assert!(Choice::from_u128_nz(1).eq(Choice::TRUE).to_bool());
925 assert!(Choice::from_u128_nz(2).eq(Choice::TRUE).to_bool());
926 }
927
928 #[test]
929 fn select_i64() {
930 let a: i64 = 1;
931 let b: i64 = 2;
932 assert_eq!(Choice::TRUE.select_i64(a, b), b);
933 assert_eq!(Choice::FALSE.select_i64(a, b), a);
934 }
935
936 #[test]
937 fn select_u8() {
938 let a: u8 = 1;
939 let b: u8 = 2;
940 assert_eq!(Choice::TRUE.select_u8(a, b), b);
941 assert_eq!(Choice::FALSE.select_u8(a, b), a);
942 }
943
944 #[test]
945 fn select_u16() {
946 let a: u16 = 1;
947 let b: u16 = 2;
948 assert_eq!(Choice::TRUE.select_u16(a, b), b);
949 assert_eq!(Choice::FALSE.select_u16(a, b), a);
950 }
951
952 #[test]
953 fn select_u32() {
954 let a: u32 = 1;
955 let b: u32 = 2;
956 assert_eq!(Choice::TRUE.select_u32(a, b), b);
957 assert_eq!(Choice::FALSE.select_u32(a, b), a);
958 }
959
960 #[test]
961 fn select_u64() {
962 let a: u64 = 1;
963 let b: u64 = 2;
964 assert_eq!(Choice::TRUE.select_u64(a, b), b);
965 assert_eq!(Choice::FALSE.select_u64(a, b), a);
966 }
967
968 #[test]
969 fn select_u128() {
970 let a: u128 = 1;
971 let b: u128 = 2;
972 assert_eq!(Choice::TRUE.select_u128(a, b), b);
973 assert_eq!(Choice::FALSE.select_u128(a, b), a);
974 }
975
976 #[test]
977 fn to_bool() {
978 assert!(!Choice::FALSE.to_bool());
979 assert!(Choice::TRUE.to_bool());
980 }
981
982 #[test]
983 fn to_u8() {
984 assert_eq!(Choice::FALSE.to_u8(), 0);
985 assert_eq!(Choice::TRUE.to_u8(), 1);
986 }
987
988 #[test]
989 fn to_u8_mask() {
990 assert_eq!(Choice::FALSE.to_u8_mask(), 0);
991 assert_eq!(Choice::TRUE.to_u8_mask(), u8::MAX);
992 }
993
994 #[test]
995 fn to_u16_mask() {
996 assert_eq!(Choice::FALSE.to_u16_mask(), 0);
997 assert_eq!(Choice::TRUE.to_u16_mask(), u16::MAX);
998 }
999
1000 #[test]
1001 fn to_u32_mask() {
1002 assert_eq!(Choice::FALSE.to_u32_mask(), 0);
1003 assert_eq!(Choice::TRUE.to_u32_mask(), u32::MAX);
1004 }
1005
1006 #[test]
1007 fn to_u64_mask() {
1008 assert_eq!(Choice::FALSE.to_u64_mask(), 0);
1009 assert_eq!(Choice::TRUE.to_u64_mask(), u64::MAX);
1010 }
1011
1012 #[test]
1013 fn to_u128_mask() {
1014 assert_eq!(Choice::FALSE.to_u128_mask(), 0);
1015 assert_eq!(Choice::TRUE.to_u128_mask(), u128::MAX);
1016 }
1017}