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