fixed_bigint/heapless/
identities.rs1use super::{AssertCapFits, HeaplessBigInt, zero};
9use crate::MachineWord;
10use const_num_traits::{Bounded, ConstOne, ConstZero, One, Personality, PersonalityTag, Zero};
11use core::marker::PhantomData;
12
13impl<T: MachineWord, const CAP: usize, P: Personality> Zero for HeaplessBigInt<T, CAP, P> {
16 #[inline]
17 fn zero() -> Self {
18 Self::const_zero()
19 }
20
21 #[inline]
22 fn is_zero(&self) -> bool {
23 let n = self.len as usize;
29 match P::TAG {
30 PersonalityTag::Nct => {
31 let mut i = 0;
32 while i < n {
33 if !super::is_zero(&self.limbs[i]) {
34 return false;
35 }
36 i += 1;
37 }
38 true
39 }
40 PersonalityTag::Ct => {
41 let mut acc = zero::<T>();
42 let mut i = 0;
43 while i < n {
44 acc |= self.limbs[i];
45 i += 1;
46 }
47 super::is_zero(&acc)
48 }
49 }
50 }
51
52 #[inline]
53 fn set_zero(&mut self) {
54 *self = <Self as Zero>::zero();
55 }
56}
57
58impl<T: MachineWord, const CAP: usize, P: Personality> One for HeaplessBigInt<T, CAP, P> {
59 #[inline]
60 fn one() -> Self {
61 let () = <Self as AssertCapFits>::CHECK;
62 Self::const_one()
63 }
64
65 #[inline]
66 fn set_one(&mut self) {
67 *self = <Self as One>::one();
68 }
69
70 #[inline]
71 fn is_one(&self) -> bool {
72 let n = self.len as usize;
76 if n == 0 {
77 return false;
78 }
79 match P::TAG {
80 PersonalityTag::Nct => {
81 if !<T as const_num_traits::One>::is_one(&self.limbs[0]) {
82 return false;
83 }
84 let mut i = 1;
85 while i < n {
86 if !super::is_zero(&self.limbs[i]) {
87 return false;
88 }
89 i += 1;
90 }
91 true
92 }
93 PersonalityTag::Ct => const_is_one_ct(&self.limbs, n),
94 }
95 }
96}
97
98#[inline(never)]
107pub(crate) fn const_is_one_ct<T: MachineWord, const CAP: usize>(
108 limbs: &[T; CAP],
109 n: usize,
110) -> bool {
111 let mut acc = limbs[0] ^ <T as ConstOne>::ONE;
112 let mut i = 1;
113 while i < n {
114 acc |= limbs[i];
115 i += 1;
116 }
117 super::is_zero(&acc)
118}
119
120impl<T: MachineWord, const CAP: usize, P: Personality> Default for HeaplessBigInt<T, CAP, P> {
121 #[inline]
122 fn default() -> Self {
123 <Self as Zero>::zero()
124 }
125}
126
127impl<T: MachineWord, const CAP: usize, P: Personality> HeaplessBigInt<T, CAP, P> {
134 #[inline]
135 const fn const_zero() -> Self {
136 Self {
137 limbs: [<T as ConstZero>::ZERO; CAP],
138 len: 0,
139 _p: PhantomData,
140 }
141 }
142
143 #[inline]
144 const fn const_one() -> Self {
145 assert!(CAP >= 1, "HeaplessBigInt::ONE requires CAP >= 1");
146 let mut limbs = [<T as ConstZero>::ZERO; CAP];
147 limbs[0] = <T as ConstOne>::ONE;
148 Self {
149 limbs,
150 len: 1,
151 _p: PhantomData,
152 }
153 }
154}
155
156impl<T: MachineWord, const CAP: usize, P: Personality> ConstZero for HeaplessBigInt<T, CAP, P> {
157 const ZERO: Self = Self::const_zero();
158}
159
160impl<T: MachineWord, const CAP: usize, P: Personality> ConstOne for HeaplessBigInt<T, CAP, P> {
161 const ONE: Self = Self::const_one();
162}
163
164#[cfg(test)]
165mod tests {
166 use super::*;
167 use const_num_traits::Ct;
168
169 type Hc = HeaplessBigInt<u8, 4, Ct>;
170
171 #[test]
175 fn ct_is_one() {
176 assert!(<Hc as One>::is_one(&<Hc as One>::one()));
177 assert!(!<Hc as One>::is_one(&<Hc as Zero>::zero()));
178 assert!(!<Hc as One>::is_one(&Hc::from_limbs([2, 0, 0, 0], 1)));
179 assert!(!<Hc as One>::is_one(&Hc::from_limbs([0, 1, 0, 0], 2)));
180 }
181}
182
183impl<T: MachineWord, const CAP: usize, P: Personality> Bounded for HeaplessBigInt<T, CAP, P> {
189 #[inline]
190 fn min_value() -> Self {
191 <Self as ConstZero>::ZERO
192 }
193
194 #[inline]
195 fn max_value() -> Self {
196 let () = <Self as AssertCapFits>::CHECK;
199 Self {
200 limbs: [<T as Bounded>::max_value(); CAP],
201 len: CAP as u16,
202 _p: PhantomData,
203 }
204 }
205}