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 sqrt;
14mod sub;
15
16use crate::{Choice, Limb, NonZero, Odd, Uint, Word};
17use core::{
18 fmt,
19 ops::{Index, IndexMut},
20 ptr,
21};
22
23#[cfg(feature = "alloc")]
24use {
25 crate::{BoxedUint, ToUnsigned},
26 alloc::borrow::ToOwned,
27};
28
29#[repr(transparent)]
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 pub fn iter(&self) -> impl DoubleEndedIterator<Item = &Limb> {
106 self.limbs.iter()
107 }
108
109 #[inline]
111 #[allow(dead_code)] pub fn iter_mut(&mut self) -> impl DoubleEndedIterator<Item = &mut Limb> {
113 self.limbs.iter_mut()
114 }
115
116 #[inline]
118 #[must_use]
119 pub const fn nlimbs(&self) -> usize {
120 self.limbs.len()
121 }
122
123 #[inline(always)]
125 pub const fn conditional_set_zero(&mut self, choice: Choice) {
126 let mut i = 0;
127 while i < self.nlimbs() {
128 self.limbs[i] = Limb::select(self.limbs[i], Limb::ZERO, choice);
129 i += 1;
130 }
131 }
132
133 #[inline(always)]
135 pub const fn conditional_set_one(&mut self, choice: Choice) {
136 self.limbs[0] = Limb::select(self.limbs[0], Limb::ONE, choice);
137 self.trailing_mut(1).conditional_set_zero(choice);
138 }
139
140 #[inline]
142 pub const fn conditional_set_max(&mut self, choice: Choice) {
143 let mut i = 0;
144 while i < self.nlimbs() {
145 self.limbs[i] = Limb::select(self.limbs[i], Limb::MAX, choice);
146 i += 1;
147 }
148 }
149
150 #[must_use]
152 pub const fn to_uint_resize<const LIMBS: usize>(&self) -> Uint<LIMBS> {
153 let mut out = Uint::ZERO;
154 let len = if self.nlimbs() > LIMBS {
155 LIMBS
156 } else {
157 self.nlimbs()
158 };
159 let mut i = 0;
160 while i < len {
161 out.limbs[i] = self.limbs[i];
162 i += 1;
163 }
164 out
165 }
166
167 #[inline]
169 #[must_use]
170 pub const fn as_nz_vartime(&self) -> Option<&NonZero<Self>> {
171 if self.is_zero_vartime() {
172 return None;
173 }
174 Some(NonZero::new_ref_unchecked(self))
175 }
176
177 #[inline]
179 #[must_use]
180 pub const fn as_odd_vartime(&self) -> Option<&Odd<Self>> {
181 if !self.is_odd().to_bool() {
182 return None;
183 }
184 Some(Odd::new_ref_unchecked(self))
185 }
186
187 cpubits::cpubits! {
188 32 => {
189 #[inline(always)]
191 pub(crate) const fn lowest_u64(&self) -> u64 {
192 debug_assert!(self.nlimbs() >= 1);
193 let mut ret = self.limbs[0].0 as u64;
194
195 if self.nlimbs() >= 2 {
196 ret |= (self.limbs[1].0 as u64) << 32;
197 }
198
199 ret
200 }
201 }
202 64 => {
203 #[inline(always)]
205 pub(crate) const fn lowest_u64(&self) -> u64 {
206 self.limbs[0].0
207 }
208 }
209 }
210
211 #[cfg(feature = "alloc")]
215 #[inline(always)]
216 pub(crate) fn fold_limbs<F>(&mut self, lhs: &Self, rhs: &Self, mut carry: Limb, f: F) -> Limb
217 where
218 F: Fn(Limb, Limb, Limb) -> (Limb, Limb),
219 {
220 for i in 0..self.nlimbs() {
221 let &a = lhs.limbs.get(i).unwrap_or(&Limb::ZERO);
222 let &b = rhs.limbs.get(i).unwrap_or(&Limb::ZERO);
223 (self.limbs[i], carry) = f(a, b, carry);
224 }
225
226 carry
227 }
228
229 #[cfg(feature = "alloc")]
233 #[inline(always)]
234 pub(crate) fn fold_limbs_assign<F>(&mut self, rhs: &UintRef, mut carry: Limb, f: F) -> Limb
235 where
236 F: Fn(Limb, Limb, Limb) -> (Limb, Limb),
237 {
238 for i in 0..self.nlimbs() {
239 let &b = rhs.limbs.get(i).unwrap_or(&Limb::ZERO);
240 (self.limbs[i], carry) = f(self.limbs[i], b, carry);
241 }
242
243 carry
244 }
245}
246
247impl AsRef<[Limb]> for UintRef {
248 #[inline]
249 fn as_ref(&self) -> &[Limb] {
250 self.as_limbs()
251 }
252}
253
254impl AsRef<UintRef> for UintRef {
255 #[inline]
256 fn as_ref(&self) -> &Self {
257 self
258 }
259}
260
261impl AsMut<[Limb]> for UintRef {
262 #[inline]
263 fn as_mut(&mut self) -> &mut [Limb] {
264 self.as_mut_limbs()
265 }
266}
267
268impl AsMut<UintRef> for UintRef {
269 #[inline]
270 fn as_mut(&mut self) -> &mut Self {
271 self
272 }
273}
274
275impl Index<usize> for UintRef {
276 type Output = Limb;
277
278 #[inline]
279 fn index(&self, index: usize) -> &Limb {
280 self.limbs.index(index)
281 }
282}
283
284impl IndexMut<usize> for UintRef {
285 #[inline]
286 fn index_mut(&mut self, index: usize) -> &mut Limb {
287 self.limbs.index_mut(index)
288 }
289}
290
291#[cfg(feature = "alloc")]
292impl ToOwned for UintRef {
293 type Owned = BoxedUint;
294
295 fn to_owned(&self) -> BoxedUint {
296 BoxedUint::from(self)
297 }
298}
299
300#[cfg(feature = "alloc")]
301impl ToUnsigned for UintRef {
302 type Unsigned = BoxedUint;
303
304 fn to_unsigned(&self) -> Self::Unsigned {
305 BoxedUint::from(self)
306 }
307
308 fn to_unsigned_zero(&self) -> Self::Unsigned {
309 BoxedUint::zero_with_precision(self.bits_precision())
310 }
311}
312
313impl fmt::Debug for UintRef {
314 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
315 write!(f, "UintRef(0x{self:X})")
316 }
317}
318
319impl fmt::Binary for UintRef {
320 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
321 if f.alternate() {
322 write!(f, "0b")?;
323 }
324
325 for limb in self.iter().rev() {
326 write!(f, "{:0width$b}", &limb.0, width = Limb::BITS as usize)?;
327 }
328 Ok(())
329 }
330}
331
332impl fmt::Display for UintRef {
333 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
334 fmt::UpperHex::fmt(self, f)
335 }
336}
337
338impl fmt::LowerHex for UintRef {
339 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
340 if f.alternate() {
341 write!(f, "0x")?;
342 }
343 for limb in self.iter().rev() {
344 write!(f, "{:0width$x}", &limb.0, width = Limb::BYTES * 2)?;
345 }
346 Ok(())
347 }
348}
349
350impl fmt::UpperHex for UintRef {
351 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
352 if f.alternate() {
353 write!(f, "0x")?;
354 }
355 for limb in self.iter().rev() {
356 write!(f, "{:0width$X}", &limb.0, width = Limb::BYTES * 2)?;
357 }
358 Ok(())
359 }
360}