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]
136 pub const fn conditional_set_max(&mut self, choice: Choice) {
137 let mut i = 0;
138 while i < self.nlimbs() {
139 self.limbs[i] = Limb::select(self.limbs[i], Limb::MAX, choice);
140 i += 1;
141 }
142 }
143
144 #[must_use]
146 pub const fn to_uint_resize<const LIMBS: usize>(&self) -> Uint<LIMBS> {
147 let mut out = Uint::ZERO;
148 let len = if self.nlimbs() > LIMBS {
149 LIMBS
150 } else {
151 self.nlimbs()
152 };
153 let mut i = 0;
154 while i < len {
155 out.limbs[i] = self.limbs[i];
156 i += 1;
157 }
158 out
159 }
160
161 #[inline]
163 #[must_use]
164 pub const fn as_nz_vartime(&self) -> Option<&NonZero<Self>> {
165 if self.is_zero_vartime() {
166 return None;
167 }
168 Some(self.as_nz_unchecked())
169 }
170
171 #[inline]
180 #[must_use]
181 #[allow(unsafe_code)]
182 pub(crate) const fn as_nz_unchecked(&self) -> &NonZero<Self> {
183 unsafe { &*(ptr::from_ref(self) as *const NonZero<Self>) }
185 }
186
187 #[inline]
189 #[must_use]
190 pub const fn as_odd_vartime(&self) -> Option<&Odd<Self>> {
191 if !self.is_odd().to_bool_vartime() {
192 return None;
193 }
194 Some(self.as_odd_unchecked())
195 }
196
197 #[inline]
206 #[must_use]
207 #[allow(unsafe_code)]
208 pub(crate) const fn as_odd_unchecked(&self) -> &Odd<Self> {
209 unsafe { &*(ptr::from_ref(self) as *const Odd<Self>) }
211 }
212
213 cpubits::cpubits! {
214 32 => {
215 #[inline(always)]
217 pub(crate) const fn lowest_u64(&self) -> u64 {
218 debug_assert!(self.nlimbs() >= 1);
219 let mut ret = self.limbs[0].0 as u64;
220
221 if self.nlimbs() >= 2 {
222 ret |= (self.limbs[1].0 as u64) << 32;
223 }
224
225 ret
226 }
227 }
228 64 => {
229 #[inline(always)]
231 pub(crate) const fn lowest_u64(&self) -> u64 {
232 self.limbs[0].0
233 }
234 }
235 }
236
237 #[cfg(feature = "alloc")]
241 #[inline(always)]
242 pub(crate) fn fold_limbs<F>(&mut self, lhs: &Self, rhs: &Self, mut carry: Limb, f: F) -> Limb
243 where
244 F: Fn(Limb, Limb, Limb) -> (Limb, Limb),
245 {
246 for i in 0..self.nlimbs() {
247 let &a = lhs.limbs.get(i).unwrap_or(&Limb::ZERO);
248 let &b = rhs.limbs.get(i).unwrap_or(&Limb::ZERO);
249 (self.limbs[i], carry) = f(a, b, carry);
250 }
251
252 carry
253 }
254
255 #[cfg(feature = "alloc")]
259 #[inline(always)]
260 pub(crate) fn fold_limbs_assign<F>(&mut self, rhs: &UintRef, mut carry: Limb, f: F) -> Limb
261 where
262 F: Fn(Limb, Limb, Limb) -> (Limb, Limb),
263 {
264 for i in 0..self.nlimbs() {
265 let &b = rhs.limbs.get(i).unwrap_or(&Limb::ZERO);
266 (self.limbs[i], carry) = f(self.limbs[i], b, carry);
267 }
268
269 carry
270 }
271}
272
273impl AsRef<[Limb]> for UintRef {
274 #[inline]
275 fn as_ref(&self) -> &[Limb] {
276 self.as_limbs()
277 }
278}
279
280impl AsRef<UintRef> for UintRef {
281 #[inline]
282 fn as_ref(&self) -> &Self {
283 self
284 }
285}
286
287impl AsMut<[Limb]> for UintRef {
288 #[inline]
289 fn as_mut(&mut self) -> &mut [Limb] {
290 self.as_mut_limbs()
291 }
292}
293
294impl AsMut<UintRef> for UintRef {
295 #[inline]
296 fn as_mut(&mut self) -> &mut Self {
297 self
298 }
299}
300
301impl Index<usize> for UintRef {
302 type Output = Limb;
303
304 #[inline]
305 fn index(&self, index: usize) -> &Limb {
306 self.limbs.index(index)
307 }
308}
309
310impl IndexMut<usize> for UintRef {
311 #[inline]
312 fn index_mut(&mut self, index: usize) -> &mut Limb {
313 self.limbs.index_mut(index)
314 }
315}
316
317#[cfg(feature = "alloc")]
318impl ToOwned for UintRef {
319 type Owned = BoxedUint;
320
321 fn to_owned(&self) -> BoxedUint {
322 BoxedUint::from(self)
323 }
324}
325
326#[cfg(feature = "alloc")]
327impl ToUnsigned for UintRef {
328 type Unsigned = BoxedUint;
329
330 fn to_unsigned(&self) -> Self::Unsigned {
331 BoxedUint::from(self)
332 }
333
334 fn to_unsigned_zero(&self) -> Self::Unsigned {
335 BoxedUint::zero_with_precision(self.bits_precision())
336 }
337}
338
339impl fmt::Debug for UintRef {
340 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
341 write!(f, "UintRef(0x{self:X})")
342 }
343}
344
345impl fmt::Binary for UintRef {
346 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
347 if f.alternate() {
348 write!(f, "0b")?;
349 }
350
351 for limb in self.iter().rev() {
352 write!(f, "{:0width$b}", &limb.0, width = Limb::BITS as usize)?;
353 }
354 Ok(())
355 }
356}
357
358impl fmt::Display for UintRef {
359 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
360 fmt::UpperHex::fmt(self, f)
361 }
362}
363
364impl fmt::LowerHex for UintRef {
365 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
366 if f.alternate() {
367 write!(f, "0x")?;
368 }
369 for limb in self.iter().rev() {
370 write!(f, "{:0width$x}", &limb.0, width = Limb::BYTES * 2)?;
371 }
372 Ok(())
373 }
374}
375
376impl fmt::UpperHex for UintRef {
377 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
378 if f.alternate() {
379 write!(f, "0x")?;
380 }
381 for limb in self.iter().rev() {
382 write!(f, "{:0width$X}", &limb.0, width = Limb::BYTES * 2)?;
383 }
384 Ok(())
385 }
386}