crypto_bigint/uint/
ref_type.rs1mod add;
4mod bits;
5mod cmp;
6mod ct;
7mod div;
8mod invert_mod;
9mod mul;
10mod shl;
11mod shr;
12mod slice;
13mod sub;
14
15use crate::{Choice, Limb, NonZero, Odd, Uint, Word};
16use core::{
17 fmt,
18 ops::{Index, IndexMut},
19 ptr,
20};
21
22#[cfg(feature = "alloc")]
23use {
24 crate::{BoxedUint, ToUnsigned},
25 alloc::borrow::ToOwned,
26};
27
28#[repr(transparent)]
33#[derive(PartialEq, Eq)]
34pub struct UintRef {
35 pub(crate) limbs: [Limb],
38}
39
40impl UintRef {
41 #[inline]
43 #[must_use]
44 pub const fn new(limbs: &[Limb]) -> &Self {
45 #[allow(unsafe_code)]
47 unsafe {
48 &*(ptr::from_ref(limbs) as *const UintRef)
49 }
50 }
51
52 #[inline]
54 pub const fn new_mut(limbs: &mut [Limb]) -> &mut Self {
55 #[allow(unsafe_code)]
57 unsafe {
58 &mut *(ptr::from_mut(limbs) as *mut UintRef)
59 }
60 }
61
62 pub const fn new_flattened_mut<const N: usize>(slice: &mut [[Limb; N]]) -> &mut Self {
64 let len = slice.len() * N;
67
68 #[allow(unsafe_code)]
73 let slice = unsafe { core::slice::from_raw_parts_mut(slice.as_mut_ptr().cast(), len) };
74 Self::new_mut(slice)
75 }
76
77 #[inline]
79 #[must_use]
80 pub const fn as_limbs(&self) -> &[Limb] {
81 &self.limbs
82 }
83
84 #[inline]
86 pub const fn as_mut_limbs(&mut self) -> &mut [Limb] {
87 &mut self.limbs
88 }
89
90 #[inline]
92 #[must_use]
93 pub const fn as_words(&self) -> &[Word] {
94 Limb::slice_as_words(&self.limbs)
95 }
96
97 #[inline]
99 pub const fn as_mut_words(&mut self) -> &mut [Word] {
100 Limb::slice_as_mut_words(&mut self.limbs)
101 }
102
103 #[inline]
105 #[must_use]
106 pub fn iter(&self) -> impl DoubleEndedIterator<Item = &Limb> {
107 self.limbs.iter()
108 }
109
110 #[inline]
112 #[allow(dead_code)] pub fn iter_mut(&mut self) -> impl DoubleEndedIterator<Item = &mut Limb> {
114 self.limbs.iter_mut()
115 }
116
117 #[inline]
119 #[must_use]
120 pub const fn nlimbs(&self) -> usize {
121 self.limbs.len()
122 }
123
124 #[inline(always)]
126 pub const fn conditional_set_zero(&mut self, choice: Choice) {
127 let mut i = 0;
128 while i < self.nlimbs() {
129 self.limbs[i] = Limb::select(self.limbs[i], Limb::ZERO, choice);
130 i += 1;
131 }
132 }
133
134 #[inline(always)]
136 pub const fn conditional_set_one(&mut self, choice: Choice) {
137 self.limbs[0] = Limb::select(self.limbs[0], Limb::ONE, choice);
138 self.trailing_mut(1).conditional_set_zero(choice);
139 }
140
141 #[inline]
143 pub const fn conditional_set_max(&mut self, choice: Choice) {
144 let mut i = 0;
145 while i < self.nlimbs() {
146 self.limbs[i] = Limb::select(self.limbs[i], Limb::MAX, choice);
147 i += 1;
148 }
149 }
150
151 #[must_use]
153 pub const fn to_uint_resize<const LIMBS: usize>(&self) -> Uint<LIMBS> {
154 let mut out = Uint::ZERO;
155 let len = if self.nlimbs() > LIMBS {
156 LIMBS
157 } else {
158 self.nlimbs()
159 };
160 let mut i = 0;
161 while i < len {
162 out.limbs[i] = self.limbs[i];
163 i += 1;
164 }
165 out
166 }
167
168 #[inline]
170 #[must_use]
171 pub const fn as_nz_vartime(&self) -> Option<&NonZero<Self>> {
172 if self.is_zero_vartime() {
173 return None;
174 }
175 Some(NonZero::new_ref_unchecked(self))
176 }
177
178 #[inline]
180 #[must_use]
181 pub const fn as_odd_vartime(&self) -> Option<&Odd<Self>> {
182 if !self.is_odd().to_bool_vartime() {
183 return None;
184 }
185 Some(Odd::new_ref_unchecked(self))
186 }
187
188 cpubits::cpubits! {
189 32 => {
190 #[inline(always)]
192 pub(crate) const fn lowest_u64(&self) -> u64 {
193 debug_assert!(self.nlimbs() >= 1);
194 let mut ret = self.limbs[0].0 as u64;
195
196 if self.nlimbs() >= 2 {
197 ret |= (self.limbs[1].0 as u64) << 32;
198 }
199
200 ret
201 }
202 }
203 64 => {
204 #[inline(always)]
206 pub(crate) const fn lowest_u64(&self) -> u64 {
207 self.limbs[0].0
208 }
209 }
210 }
211
212 #[cfg(feature = "alloc")]
216 #[inline(always)]
217 pub(crate) fn fold_limbs<F>(&mut self, lhs: &Self, rhs: &Self, mut carry: Limb, f: F) -> Limb
218 where
219 F: Fn(Limb, Limb, Limb) -> (Limb, Limb),
220 {
221 for i in 0..self.nlimbs() {
222 let &a = lhs.limbs.get(i).unwrap_or(&Limb::ZERO);
223 let &b = rhs.limbs.get(i).unwrap_or(&Limb::ZERO);
224 (self.limbs[i], carry) = f(a, b, carry);
225 }
226
227 carry
228 }
229
230 #[cfg(feature = "alloc")]
234 #[inline(always)]
235 pub(crate) fn fold_limbs_assign<F>(&mut self, rhs: &UintRef, mut carry: Limb, f: F) -> Limb
236 where
237 F: Fn(Limb, Limb, Limb) -> (Limb, Limb),
238 {
239 for i in 0..self.nlimbs() {
240 let &b = rhs.limbs.get(i).unwrap_or(&Limb::ZERO);
241 (self.limbs[i], carry) = f(self.limbs[i], b, carry);
242 }
243
244 carry
245 }
246}
247
248impl AsRef<[Limb]> for UintRef {
249 #[inline]
250 fn as_ref(&self) -> &[Limb] {
251 self.as_limbs()
252 }
253}
254
255impl AsRef<UintRef> for UintRef {
256 #[inline]
257 fn as_ref(&self) -> &Self {
258 self
259 }
260}
261
262impl AsMut<[Limb]> for UintRef {
263 #[inline]
264 fn as_mut(&mut self) -> &mut [Limb] {
265 self.as_mut_limbs()
266 }
267}
268
269impl AsMut<UintRef> for UintRef {
270 #[inline]
271 fn as_mut(&mut self) -> &mut Self {
272 self
273 }
274}
275
276impl Index<usize> for UintRef {
277 type Output = Limb;
278
279 #[inline]
280 fn index(&self, index: usize) -> &Limb {
281 self.limbs.index(index)
282 }
283}
284
285impl IndexMut<usize> for UintRef {
286 #[inline]
287 fn index_mut(&mut self, index: usize) -> &mut Limb {
288 self.limbs.index_mut(index)
289 }
290}
291
292#[cfg(feature = "alloc")]
293impl ToOwned for UintRef {
294 type Owned = BoxedUint;
295
296 fn to_owned(&self) -> BoxedUint {
297 BoxedUint::from(self)
298 }
299}
300
301#[cfg(feature = "alloc")]
302impl ToUnsigned for UintRef {
303 type Unsigned = BoxedUint;
304
305 fn to_unsigned(&self) -> Self::Unsigned {
306 BoxedUint::from(self)
307 }
308
309 fn to_unsigned_zero(&self) -> Self::Unsigned {
310 BoxedUint::zero_with_precision(self.bits_precision())
311 }
312}
313
314impl fmt::Debug for UintRef {
315 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
316 write!(f, "UintRef(0x{self:X})")
317 }
318}
319
320impl fmt::Binary for UintRef {
321 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
322 if f.alternate() {
323 write!(f, "0b")?;
324 }
325
326 for limb in self.iter().rev() {
327 write!(f, "{:0width$b}", &limb.0, width = Limb::BITS as usize)?;
328 }
329 Ok(())
330 }
331}
332
333impl fmt::Display for UintRef {
334 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
335 fmt::UpperHex::fmt(self, f)
336 }
337}
338
339impl fmt::LowerHex for UintRef {
340 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
341 if f.alternate() {
342 write!(f, "0x")?;
343 }
344 for limb in self.iter().rev() {
345 write!(f, "{:0width$x}", &limb.0, width = Limb::BYTES * 2)?;
346 }
347 Ok(())
348 }
349}
350
351impl fmt::UpperHex for UintRef {
352 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
353 if f.alternate() {
354 write!(f, "0x")?;
355 }
356 for limb in self.iter().rev() {
357 write!(f, "{:0width$X}", &limb.0, width = Limb::BYTES * 2)?;
358 }
359 Ok(())
360 }
361}