1use crate::primitives::{bitle, bitlt, 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 Self::from_u8_lsb(bitlt!(x, y, u8::BITS))
127 }
128
129 #[inline]
131 #[must_use]
132 pub const fn from_u8_nz(value: u8) -> Self {
133 Self::from_u8_lsb(bitnz!(value, u8::BITS))
134 }
135
136 #[inline]
140 #[must_use]
141 pub const fn from_u16_eq(x: u16, y: u16) -> Self {
142 Self::from_u16_nz(x ^ y).not()
143 }
144
145 #[inline]
147 #[must_use]
148 pub const fn from_u16_le(x: u16, y: u16) -> Self {
149 Self::from_u16_lsb(bitle!(x, y, u16::BITS))
150 }
151
152 #[inline]
154 #[must_use]
155 pub const fn from_u16_lsb(value: u16) -> Self {
156 Self((value & 0x1) as u8)
157 }
158
159 #[inline]
161 #[must_use]
162 pub const fn from_u16_lt(x: u16, y: u16) -> Self {
163 Self::from_u16_lsb(bitlt!(x, y, u16::BITS))
164 }
165
166 #[inline]
168 #[must_use]
169 pub const fn from_u16_nz(value: u16) -> Self {
170 Self::from_u16_lsb(bitnz!(value, u16::BITS))
171 }
172
173 #[inline]
177 #[must_use]
178 pub const fn from_u32_eq(x: u32, y: u32) -> Self {
179 Self::from_u32_nz(x ^ y).not()
180 }
181
182 #[inline]
184 #[must_use]
185 pub const fn from_u32_le(x: u32, y: u32) -> Self {
186 crate::primitives::le_u32(x, y)
187 }
188
189 #[inline]
191 #[must_use]
192 pub const fn from_u32_lsb(value: u32) -> Self {
193 Self((value & 0x1) as u8)
194 }
195
196 #[inline]
198 #[must_use]
199 pub const fn from_u32_lt(x: u32, y: u32) -> Self {
200 crate::primitives::lt_u32(x, y)
201 }
202
203 #[inline]
205 #[must_use]
206 pub const fn from_u32_nz(value: u32) -> Self {
207 crate::primitives::nz_u32(value)
208 }
209
210 #[inline]
214 #[must_use]
215 pub const fn from_u64_eq(x: u64, y: u64) -> Self {
216 Self::from_u64_nz(x ^ y).not()
217 }
218
219 #[inline]
221 #[must_use]
222 pub const fn from_u64_le(x: u64, y: u64) -> Self {
223 crate::primitives::le_u64(x, y)
224 }
225
226 #[inline]
228 #[must_use]
229 pub const fn from_u64_lsb(value: u64) -> Self {
230 Self((value & 0x1) as u8)
231 }
232
233 #[inline]
235 #[must_use]
236 pub const fn from_u64_lt(x: u64, y: u64) -> Self {
237 crate::primitives::lt_u64(x, y)
238 }
239
240 #[inline]
242 #[must_use]
243 pub const fn from_u64_nz(value: u64) -> Self {
244 crate::primitives::nz_u64(value)
245 }
246
247 #[inline]
251 #[must_use]
252 pub const fn from_u128_eq(x: u128, y: u128) -> Self {
253 Self::from_u128_nz(x ^ y).not()
254 }
255
256 #[inline]
258 #[must_use]
259 pub const fn from_u128_le(x: u128, y: u128) -> Self {
260 #[cfg(target_pointer_width = "32")]
261 {
262 Self::from_u128_lt(y, x).not()
263 }
264 #[cfg(not(target_pointer_width = "32"))]
265 {
266 Self::from_u128_lsb(bitle!(x, y, u128::BITS))
267 }
268 }
269
270 #[inline]
272 #[must_use]
273 pub const fn from_u128_lsb(value: u128) -> Self {
274 Self((value & 1) as u8)
275 }
276
277 #[inline]
279 #[must_use]
280 pub const fn from_u128_lt(x: u128, y: u128) -> Self {
281 #[cfg(target_pointer_width = "32")]
282 {
283 Self::from_u128_lt_halves(x, y)
284 }
285 #[cfg(not(target_pointer_width = "32"))]
286 {
287 Self::from_u128_lsb(bitlt!(x, y, u128::BITS))
288 }
289 }
290
291 #[cfg(any(target_pointer_width = "32", test))]
292 #[inline]
293 #[allow(clippy::cast_possible_truncation)]
294 const fn from_u128_lt_halves(x: u128, y: u128) -> Self {
295 let x_hi = (x >> 64) as u64;
299 let y_hi = (y >> 64) as u64;
300 let hi_lt = Self::from_u64_lt(x_hi, y_hi).to_u8();
301 let hi_eq = Self::from_u64_eq(x_hi, y_hi).to_u8();
302 let lo_lt = Self::from_u64_lt(x as u64, y as u64).to_u8();
303 Self::from_u8_lsb(hi_lt | (hi_eq & lo_lt))
304 }
305
306 #[inline]
308 #[must_use]
309 pub const fn from_u128_nz(value: u128) -> Self {
310 Self::from_u128_lsb(bitnz!(value, u128::BITS))
311 }
312
313 #[inline]
322 #[must_use]
323 pub const fn select_i64(self, a: i64, b: i64) -> i64 {
324 self.select_u64(a.cast_unsigned(), b.cast_unsigned())
325 .cast_signed()
326 }
327
328 #[inline]
333 #[must_use]
334 pub const fn select_u8(self, a: u8, b: u8) -> u8 {
335 a ^ (self.to_u8_mask() & (a ^ b))
336 }
337
338 #[inline]
343 #[must_use]
344 pub const fn select_u16(self, a: u16, b: u16) -> u16 {
345 a ^ (self.to_u16_mask() & (a ^ b))
346 }
347
348 #[inline]
353 #[must_use]
354 pub const fn select_u32(self, a: u32, b: u32) -> u32 {
355 a ^ (self.to_u32_mask() & (a ^ b))
356 }
357
358 #[inline]
363 #[must_use]
364 pub const fn select_u64(self, a: u64, b: u64) -> u64 {
365 a ^ (self.to_u64_mask() & (a ^ b))
366 }
367
368 #[inline]
373 #[must_use]
374 pub const fn select_u128(self, a: u128, b: u128) -> u128 {
375 a ^ (self.to_u128_mask() & (a ^ b))
376 }
377
378 #[must_use]
400 pub const fn to_bool(self) -> bool {
401 self.to_u8() != 0
402 }
403
404 #[must_use]
406 pub const fn to_u8(self) -> u8 {
407 core::hint::black_box(self.0)
411 }
412
413 #[deprecated(since = "0.4.3", note = "use `Choice::to_bool` instead")]
423 #[must_use]
424 pub const fn to_bool_vartime(self) -> bool {
425 self.to_bool()
426 }
427
428 #[deprecated(since = "0.4.3", note = "use `Choice::to_u8` instead")]
432 #[must_use]
433 pub const fn to_u8_vartime(self) -> u8 {
434 self.to_u8()
435 }
436
437 #[inline]
443 #[must_use]
444 pub const fn to_u8_mask(self) -> u8 {
445 self.to_u8().wrapping_neg()
446 }
447
448 #[inline]
454 #[must_use]
455 pub const fn to_u16_mask(self) -> u16 {
456 (self.to_u8() as u16).wrapping_neg()
457 }
458
459 #[inline]
465 #[must_use]
466 pub const fn to_u32_mask(self) -> u32 {
467 (self.to_u8() as u32).wrapping_neg()
468 }
469
470 #[inline]
476 #[must_use]
477 pub const fn to_u64_mask(self) -> u64 {
478 (self.to_u8() as u64).wrapping_neg()
479 }
480
481 #[inline]
487 #[must_use]
488 pub const fn to_u128_mask(self) -> u128 {
489 (self.to_u8() as u128).wrapping_neg()
490 }
491}
492
493impl BitAnd for Choice {
494 type Output = Choice;
495
496 #[inline]
497 fn bitand(self, rhs: Choice) -> Choice {
498 self.and(rhs)
499 }
500}
501
502impl BitAndAssign for Choice {
503 #[inline]
504 fn bitand_assign(&mut self, rhs: Choice) {
505 *self = *self & rhs;
506 }
507}
508
509impl BitOr for Choice {
510 type Output = Choice;
511
512 #[inline]
513 fn bitor(self, rhs: Choice) -> Choice {
514 self.or(rhs)
515 }
516}
517
518impl BitOrAssign for Choice {
519 #[inline]
520 fn bitor_assign(&mut self, rhs: Choice) {
521 *self = *self | rhs;
522 }
523}
524
525impl BitXor for Choice {
526 type Output = Choice;
527
528 #[inline]
529 fn bitxor(self, rhs: Choice) -> Choice {
530 Choice(self.0 ^ rhs.0)
531 }
532}
533
534impl BitXorAssign for Choice {
535 #[inline]
536 fn bitxor_assign(&mut self, rhs: Choice) {
537 *self = *self ^ rhs;
538 }
539}
540
541impl CtAssign for Choice {
542 #[inline]
543 fn ct_assign(&mut self, other: &Self, choice: Choice) {
544 self.0.ct_assign(&other.0, choice);
545 }
546}
547impl CtAssignSlice for Choice {}
548impl CtSelectUsingCtAssign for Choice {}
549
550impl CtEq for Choice {
551 #[inline]
552 fn ct_eq(&self, other: &Self) -> Self {
553 self.0.ct_eq(&other.0)
554 }
555}
556impl CtEqSlice for Choice {}
557
558impl From<u8> for Choice {
567 fn from(value: u8) -> Self {
568 Choice::from_u8_lsb(value)
569 }
570}
571
572impl From<Choice> for u8 {
573 fn from(choice: Choice) -> u8 {
574 choice.to_u8()
575 }
576}
577
578impl From<Choice> for bool {
589 fn from(choice: Choice) -> bool {
590 choice.to_bool()
591 }
592}
593
594impl Not for Choice {
595 type Output = Choice;
596
597 #[inline]
598 fn not(self) -> Choice {
599 self.not()
600 }
601}
602
603#[cfg(feature = "subtle")]
604impl From<subtle::Choice> for Choice {
605 #[inline]
606 fn from(choice: subtle::Choice) -> Choice {
607 Choice(choice.unwrap_u8())
608 }
609}
610
611#[cfg(feature = "subtle")]
612impl From<Choice> for subtle::Choice {
613 #[inline]
614 fn from(choice: Choice) -> subtle::Choice {
615 subtle::Choice::from(choice.0)
616 }
617}
618
619#[cfg(feature = "subtle")]
620impl subtle::ConditionallySelectable for Choice {
621 #[inline]
622 fn conditional_select(a: &Self, b: &Self, choice: subtle::Choice) -> Self {
623 CtSelect::ct_select(a, b, choice.into())
624 }
625}
626
627#[cfg(feature = "subtle")]
628impl subtle::ConstantTimeEq for Choice {
629 #[inline]
630 fn ct_eq(&self, other: &Self) -> subtle::Choice {
631 CtEq::ct_eq(self, other).into()
632 }
633}
634
635#[cfg(test)]
636mod tests {
637 use super::Choice;
638 use crate::{CtEq, CtGt, CtLt, CtSelect};
639
640 #[test]
641 fn ct_eq() {
642 let a = Choice::TRUE;
643 let b = Choice::TRUE;
644 let c = Choice::FALSE;
645
646 assert!(a.ct_eq(&b).to_bool());
647 assert!(!a.ct_eq(&c).to_bool());
648 assert!(!b.ct_eq(&c).to_bool());
649
650 assert!(!a.ct_ne(&b).to_bool());
651 assert!(a.ct_ne(&c).to_bool());
652 assert!(b.ct_ne(&c).to_bool());
653 }
654
655 #[test]
656 fn ct_select() {
657 let a = Choice::FALSE;
658 let b = Choice::TRUE;
659 assert_eq!(a.ct_select(&b, Choice::FALSE).to_bool(), a.to_bool());
660 assert_eq!(a.ct_select(&b, Choice::TRUE).to_bool(), b.to_bool());
661 }
662
663 #[test]
664 fn and() {
665 assert_eq!((Choice::FALSE & Choice::FALSE).to_u8(), 0);
666 assert_eq!((Choice::TRUE & Choice::FALSE).to_u8(), 0);
667 assert_eq!((Choice::FALSE & Choice::TRUE).to_u8(), 0);
668 assert_eq!((Choice::TRUE & Choice::TRUE).to_u8(), 1);
669 }
670
671 #[test]
672 fn or() {
673 assert_eq!((Choice::FALSE | Choice::FALSE).to_u8(), 0);
674 assert_eq!((Choice::TRUE | Choice::FALSE).to_u8(), 1);
675 assert_eq!((Choice::FALSE | Choice::TRUE).to_u8(), 1);
676 assert_eq!((Choice::TRUE | Choice::TRUE).to_u8(), 1);
677 }
678
679 #[test]
680 fn xor() {
681 assert_eq!((Choice::FALSE ^ Choice::FALSE).to_u8(), 0);
682 assert_eq!((Choice::TRUE ^ Choice::FALSE).to_u8(), 1);
683 assert_eq!((Choice::FALSE ^ Choice::TRUE).to_u8(), 1);
684 assert_eq!((Choice::TRUE ^ Choice::TRUE).to_u8(), 0);
685 }
686
687 #[test]
688 fn not() {
689 assert_eq!(Choice::FALSE.not().to_u8(), 1);
690 assert_eq!(Choice::TRUE.not().to_u8(), 0);
691 }
692
693 #[test]
694 fn from_i64_eq() {
695 assert!(Choice::from_i64_eq(0, 1).eq(Choice::FALSE).to_bool());
696 assert!(Choice::from_i64_eq(1, 1).eq(Choice::TRUE).to_bool());
697 }
698
699 #[test]
700 fn from_u8_eq() {
701 assert!(Choice::from_u8_eq(0, 1).eq(Choice::FALSE).to_bool());
702 assert!(Choice::from_u8_eq(1, 1).eq(Choice::TRUE).to_bool());
703 }
704
705 #[test]
706 fn from_u8_le() {
707 assert!(Choice::from_u8_le(0, 0).eq(Choice::TRUE).to_bool());
708 assert!(Choice::from_u8_le(1, 0).eq(Choice::FALSE).to_bool());
709 assert!(Choice::from_u8_le(1, 1).eq(Choice::TRUE).to_bool());
710 assert!(Choice::from_u8_le(1, 2).eq(Choice::TRUE).to_bool());
711 }
712
713 #[test]
714 fn from_u8_lsb() {
715 assert!(Choice::from_u8_lsb(0).eq(Choice::FALSE).to_bool());
716 assert!(Choice::from_u8_lsb(1).eq(Choice::TRUE).to_bool());
717 assert!(Choice::from_u8_lsb(2).eq(Choice::FALSE).to_bool());
718 assert!(Choice::from_u8_lsb(3).eq(Choice::TRUE).to_bool());
719 }
720
721 #[test]
722 fn from_u8_lt() {
723 assert!(Choice::from_u8_lt(0, 0).eq(Choice::FALSE).to_bool());
724 assert!(Choice::from_u8_lt(1, 0).eq(Choice::FALSE).to_bool());
725 assert!(Choice::from_u8_lt(1, 1).eq(Choice::FALSE).to_bool());
726 assert!(Choice::from_u8_lt(1, 2).eq(Choice::TRUE).to_bool());
727 }
728
729 #[test]
730 fn from_u8_nz() {
731 assert!(Choice::from_u8_nz(0).eq(Choice::FALSE).to_bool());
732 assert!(Choice::from_u8_nz(1).eq(Choice::TRUE).to_bool());
733 assert!(Choice::from_u8_nz(2).eq(Choice::TRUE).to_bool());
734 }
735
736 #[test]
737 fn from_u16_eq() {
738 assert!(Choice::from_u16_eq(0, 1).eq(Choice::FALSE).to_bool());
739 assert!(Choice::from_u16_eq(1, 1).eq(Choice::TRUE).to_bool());
740 }
741
742 #[test]
743 fn from_u16_le() {
744 assert!(Choice::from_u16_le(0, 0).eq(Choice::TRUE).to_bool());
745 assert!(Choice::from_u16_le(1, 0).eq(Choice::FALSE).to_bool());
746 assert!(Choice::from_u16_le(1, 1).eq(Choice::TRUE).to_bool());
747 assert!(Choice::from_u16_le(1, 2).eq(Choice::TRUE).to_bool());
748 }
749
750 #[test]
751 fn from_u16_lsb() {
752 assert!(Choice::from_u16_lsb(0).eq(Choice::FALSE).to_bool());
753 assert!(Choice::from_u16_lsb(1).eq(Choice::TRUE).to_bool());
754 assert!(Choice::from_u16_lsb(2).eq(Choice::FALSE).to_bool());
755 assert!(Choice::from_u16_lsb(3).eq(Choice::TRUE).to_bool());
756 }
757
758 #[test]
759 fn from_u16_lt() {
760 assert!(Choice::from_u16_lt(0, 0).eq(Choice::FALSE).to_bool());
761 assert!(Choice::from_u16_lt(1, 0).eq(Choice::FALSE).to_bool());
762 assert!(Choice::from_u16_lt(1, 1).eq(Choice::FALSE).to_bool());
763 assert!(Choice::from_u16_lt(1, 2).eq(Choice::TRUE).to_bool());
764 }
765
766 #[test]
767 fn from_u16_nz() {
768 assert!(Choice::from_u16_nz(0).eq(Choice::FALSE).to_bool());
769 assert!(Choice::from_u16_nz(1).eq(Choice::TRUE).to_bool());
770 assert!(Choice::from_u16_nz(2).eq(Choice::TRUE).to_bool());
771 }
772
773 #[test]
774 fn from_u32_eq() {
775 assert!(Choice::from_u32_eq(0, 1).eq(Choice::FALSE).to_bool());
776 assert!(Choice::from_u32_eq(1, 1).eq(Choice::TRUE).to_bool());
777 }
778
779 #[test]
780 fn from_u32_le() {
781 assert!(Choice::from_u32_le(0, 0).eq(Choice::TRUE).to_bool());
782 assert!(Choice::from_u32_le(1, 0).eq(Choice::FALSE).to_bool());
783 assert!(Choice::from_u32_le(1, 1).eq(Choice::TRUE).to_bool());
784 assert!(Choice::from_u32_le(1, 2).eq(Choice::TRUE).to_bool());
785 }
786
787 #[test]
788 fn from_u32_lsb() {
789 assert!(Choice::from_u32_lsb(0).eq(Choice::FALSE).to_bool());
790 assert!(Choice::from_u32_lsb(1).eq(Choice::TRUE).to_bool());
791 assert!(Choice::from_u32_lsb(2).eq(Choice::FALSE).to_bool());
792 assert!(Choice::from_u32_lsb(3).eq(Choice::TRUE).to_bool());
793 }
794
795 #[test]
796 fn from_u32_lt() {
797 assert!(Choice::from_u32_lt(0, 0).eq(Choice::FALSE).to_bool());
798 assert!(Choice::from_u32_lt(1, 0).eq(Choice::FALSE).to_bool());
799 assert!(Choice::from_u32_lt(1, 1).eq(Choice::FALSE).to_bool());
800 assert!(Choice::from_u32_lt(1, 2).eq(Choice::TRUE).to_bool());
801 }
802
803 #[test]
804 fn from_u32_nz() {
805 assert!(Choice::from_u32_nz(0).eq(Choice::FALSE).to_bool());
806 assert!(Choice::from_u32_nz(1).eq(Choice::TRUE).to_bool());
807 assert!(Choice::from_u32_nz(2).eq(Choice::TRUE).to_bool());
808 }
809
810 #[test]
811 fn from_u64_eq() {
812 assert!(Choice::from_u64_eq(0, 1).eq(Choice::FALSE).to_bool());
813 assert!(Choice::from_u64_eq(1, 1).eq(Choice::TRUE).to_bool());
814 }
815
816 #[test]
817 fn from_u64_le() {
818 assert!(Choice::from_u64_le(0, 0).eq(Choice::TRUE).to_bool());
819 assert!(Choice::from_u64_le(1, 0).eq(Choice::FALSE).to_bool());
820 assert!(Choice::from_u64_le(1, 1).eq(Choice::TRUE).to_bool());
821 assert!(Choice::from_u64_le(1, 2).eq(Choice::TRUE).to_bool());
822 }
823
824 #[test]
825 fn from_u64_lsb() {
826 assert!(Choice::from_u64_lsb(0).eq(Choice::FALSE).to_bool());
827 assert!(Choice::from_u64_lsb(1).eq(Choice::TRUE).to_bool());
828 }
829
830 #[test]
831 fn from_u64_lt() {
832 assert!(Choice::from_u64_lt(0, 0).eq(Choice::FALSE).to_bool());
833 assert!(Choice::from_u64_lt(1, 0).eq(Choice::FALSE).to_bool());
834 assert!(Choice::from_u64_lt(1, 1).eq(Choice::FALSE).to_bool());
835 assert!(Choice::from_u64_lt(1, 2).eq(Choice::TRUE).to_bool());
836 }
837
838 #[test]
839 fn from_u64_nz() {
840 assert!(Choice::from_u64_nz(0).eq(Choice::FALSE).to_bool());
841 assert!(Choice::from_u64_nz(1).eq(Choice::TRUE).to_bool());
842 assert!(Choice::from_u64_nz(2).eq(Choice::TRUE).to_bool());
843 }
844
845 #[test]
846 fn from_u128_eq() {
847 assert!(Choice::from_u128_eq(0, 1).eq(Choice::FALSE).to_bool());
848 assert!(Choice::from_u128_eq(1, 1).eq(Choice::TRUE).to_bool());
849 }
850
851 #[test]
852 fn from_u128_le() {
853 assert!(Choice::from_u128_le(0, 0).eq(Choice::TRUE).to_bool());
854 assert!(Choice::from_u128_le(1, 0).eq(Choice::FALSE).to_bool());
855 assert!(Choice::from_u128_le(1, 1).eq(Choice::TRUE).to_bool());
856 assert!(Choice::from_u128_le(1, 2).eq(Choice::TRUE).to_bool());
857 }
858
859 #[test]
860 fn from_u128_lsb() {
861 assert!(Choice::from_u128_lsb(0).eq(Choice::FALSE).to_bool());
862 assert!(Choice::from_u128_lsb(1).eq(Choice::TRUE).to_bool());
863 }
864
865 #[test]
866 fn from_u128_lt() {
867 assert!(Choice::from_u128_lt(0, 0).eq(Choice::FALSE).to_bool());
868 assert!(Choice::from_u128_lt(1, 0).eq(Choice::FALSE).to_bool());
869 assert!(Choice::from_u128_lt(1, 1).eq(Choice::FALSE).to_bool());
870 assert!(Choice::from_u128_lt(1, 2).eq(Choice::TRUE).to_bool());
871 }
872
873 #[test]
874 fn from_u128_comparison_boundaries() {
875 const LT: Choice = Choice::from_u128_lt_halves((1 << 96) - 1, 1 << 96);
876 const LE: Choice = Choice::from_u128_le(1 << 64, 1 << 64);
877 assert!(LT.to_bool());
878 assert!(LE.to_bool());
879
880 let values = [
881 0,
882 1,
883 (1 << 32) - 1,
884 1 << 32,
885 (1 << 64) - 1,
886 1 << 64,
887 (1 << 64) + 1,
888 (1 << 96) - 1,
889 1 << 96,
890 u128::MAX - 1,
891 u128::MAX,
892 ];
893
894 for x in values {
895 for y in values {
896 assert_eq!(x < y, Choice::from_u128_lt_halves(x, y).to_bool());
897 assert_eq!(x < y, Choice::from_u128_lt(x, y).to_bool());
898 assert_eq!(x <= y, Choice::from_u128_le(x, y).to_bool());
899 assert_eq!(x < y, x.ct_lt(&y).to_bool());
900 assert_eq!(x > y, x.ct_gt(&y).to_bool());
901 }
902 }
903 }
904
905 #[test]
906 fn from_u128_nz() {
907 assert!(Choice::from_u128_nz(0).eq(Choice::FALSE).to_bool());
908 assert!(Choice::from_u128_nz(1).eq(Choice::TRUE).to_bool());
909 assert!(Choice::from_u128_nz(2).eq(Choice::TRUE).to_bool());
910 }
911
912 #[test]
913 fn select_i64() {
914 let a: i64 = 1;
915 let b: i64 = 2;
916 assert_eq!(Choice::TRUE.select_i64(a, b), b);
917 assert_eq!(Choice::FALSE.select_i64(a, b), a);
918 }
919
920 #[test]
921 fn select_u8() {
922 let a: u8 = 1;
923 let b: u8 = 2;
924 assert_eq!(Choice::TRUE.select_u8(a, b), b);
925 assert_eq!(Choice::FALSE.select_u8(a, b), a);
926 }
927
928 #[test]
929 fn select_u16() {
930 let a: u16 = 1;
931 let b: u16 = 2;
932 assert_eq!(Choice::TRUE.select_u16(a, b), b);
933 assert_eq!(Choice::FALSE.select_u16(a, b), a);
934 }
935
936 #[test]
937 fn select_u32() {
938 let a: u32 = 1;
939 let b: u32 = 2;
940 assert_eq!(Choice::TRUE.select_u32(a, b), b);
941 assert_eq!(Choice::FALSE.select_u32(a, b), a);
942 }
943
944 #[test]
945 fn select_u64() {
946 let a: u64 = 1;
947 let b: u64 = 2;
948 assert_eq!(Choice::TRUE.select_u64(a, b), b);
949 assert_eq!(Choice::FALSE.select_u64(a, b), a);
950 }
951
952 #[test]
953 fn select_u128() {
954 let a: u128 = 1;
955 let b: u128 = 2;
956 assert_eq!(Choice::TRUE.select_u128(a, b), b);
957 assert_eq!(Choice::FALSE.select_u128(a, b), a);
958 }
959
960 #[test]
961 fn to_bool() {
962 assert!(!Choice::FALSE.to_bool());
963 assert!(Choice::TRUE.to_bool());
964 }
965
966 #[test]
967 fn to_u8() {
968 assert_eq!(Choice::FALSE.to_u8(), 0);
969 assert_eq!(Choice::TRUE.to_u8(), 1);
970 }
971
972 #[test]
973 fn to_u8_mask() {
974 assert_eq!(Choice::FALSE.to_u8_mask(), 0);
975 assert_eq!(Choice::TRUE.to_u8_mask(), u8::MAX);
976 }
977
978 #[test]
979 fn to_u16_mask() {
980 assert_eq!(Choice::FALSE.to_u16_mask(), 0);
981 assert_eq!(Choice::TRUE.to_u16_mask(), u16::MAX);
982 }
983
984 #[test]
985 fn to_u32_mask() {
986 assert_eq!(Choice::FALSE.to_u32_mask(), 0);
987 assert_eq!(Choice::TRUE.to_u32_mask(), u32::MAX);
988 }
989
990 #[test]
991 fn to_u64_mask() {
992 assert_eq!(Choice::FALSE.to_u64_mask(), 0);
993 assert_eq!(Choice::TRUE.to_u64_mask(), u64::MAX);
994 }
995
996 #[test]
997 fn to_u128_mask() {
998 assert_eq!(Choice::FALSE.to_u128_mask(), 0);
999 assert_eq!(Choice::TRUE.to_u128_mask(), u128::MAX);
1000 }
1001}