1use crate::{
4 Bounded, Choice, ConstOne, CtAssign, CtEq, CtOption, CtSelect, Int, Integer, Limb, Mul,
5 NonZero, One, Uint, UintRef,
6};
7use core::{cmp::Ordering, fmt, ops::Deref};
8use ctutils::{CtAssignSlice, CtEqSlice};
9
10#[cfg(feature = "alloc")]
11use crate::{BoxedUint, Resize};
12
13#[cfg(feature = "rand_core")]
14use crate::{Random, rand_core::TryRng};
15
16#[cfg(all(feature = "alloc", feature = "rand_core"))]
17use crate::RandomBits;
18
19#[cfg(feature = "serde")]
20use crate::Zero;
21#[cfg(feature = "serde")]
22use serdect::serde::{
23 Deserialize, Deserializer, Serialize, Serializer,
24 de::{Error, Unexpected},
25};
26
27pub type OddUint<const LIMBS: usize> = Odd<Uint<LIMBS>>;
29
30pub type OddUintRef = Odd<UintRef>;
32
33pub type OddInt<const LIMBS: usize> = Odd<Int<LIMBS>>;
35
36#[cfg(feature = "alloc")]
38pub type OddBoxedUint = Odd<BoxedUint>;
39
40#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
44#[repr(transparent)]
45pub struct Odd<T: ?Sized>(pub(crate) T);
46
47impl<T> Odd<T> {
48 #[inline]
50 pub fn new(mut n: T) -> CtOption<Self>
51 where
52 T: Integer,
53 {
54 let is_odd = n.is_odd();
55
56 n.ct_assign(&T::one_like(&n), !is_odd);
60 CtOption::new(Self(n), is_odd)
61 }
62
63 #[inline]
65 pub fn get(self) -> T {
66 self.0
67 }
68
69 #[inline]
74 pub const fn get_copy(self) -> T
75 where
76 T: Copy,
77 {
78 self.0
79 }
80}
81
82impl<T: ?Sized> Odd<T> {
83 pub const fn as_ref(&self) -> &T {
85 &self.0
86 }
87
88 pub const fn as_nz_ref(&self) -> &NonZero<T> {
91 #[allow(unsafe_code)]
95 unsafe {
96 &*(&raw const self.0 as *const NonZero<T>)
97 }
98 }
99}
100
101impl<T> Odd<T>
102where
103 T: Bounded + ?Sized,
104{
105 pub const BITS: u32 = T::BITS;
107
108 pub const BYTES: usize = T::BYTES;
110}
111
112impl<const LIMBS: usize> OddUint<LIMBS> {
113 #[must_use]
119 #[track_caller]
120 pub const fn from_be_hex(hex: &str) -> Self {
121 let uint = Uint::<LIMBS>::from_be_hex(hex);
122 assert!(uint.is_odd().to_bool_vartime(), "number must be odd");
123 Odd(uint)
124 }
125
126 #[must_use]
132 #[track_caller]
133 pub const fn from_le_hex(hex: &str) -> Self {
134 let uint = Uint::<LIMBS>::from_le_hex(hex);
135 assert!(uint.is_odd().to_bool_vartime(), "number must be odd");
136 Odd(uint)
137 }
138
139 #[inline]
141 #[must_use]
142 pub const fn as_uint_ref(&self) -> &OddUintRef {
143 self.0.as_uint_ref().as_odd_unchecked()
144 }
145
146 #[must_use]
150 pub const fn resize<const T: usize>(&self) -> Odd<Uint<T>> {
151 Odd(self.0.resize())
152 }
153}
154
155impl<const LIMBS: usize> AsRef<OddUintRef> for OddUint<LIMBS> {
156 fn as_ref(&self) -> &OddUintRef {
157 self.as_uint_ref()
158 }
159}
160
161impl<const LIMBS: usize> Odd<Int<LIMBS>> {
162 #[must_use]
164 pub const fn abs_sign(&self) -> (Odd<Uint<LIMBS>>, Choice) {
165 let (abs, sgn) = Int::abs_sign(self.as_ref());
167 (Odd(abs), sgn)
168 }
169
170 #[must_use]
172 pub const fn abs(&self) -> Odd<Uint<LIMBS>> {
173 self.abs_sign().0
174 }
175}
176
177impl<T: ?Sized> AsRef<T> for Odd<T> {
178 fn as_ref(&self) -> &T {
179 &self.0
180 }
181}
182
183impl<T> AsRef<[Limb]> for Odd<T>
184where
185 T: AsRef<[Limb]>,
186{
187 fn as_ref(&self) -> &[Limb] {
188 self.0.as_ref()
189 }
190}
191
192impl<T: ?Sized> AsRef<NonZero<T>> for Odd<T> {
193 fn as_ref(&self) -> &NonZero<T> {
194 self.as_nz_ref()
195 }
196}
197
198impl<T> CtAssign for Odd<T>
199where
200 T: CtAssign,
201{
202 #[inline]
203 fn ct_assign(&mut self, other: &Self, choice: Choice) {
204 self.0.ct_assign(&other.0, choice);
205 }
206}
207impl<T> CtAssignSlice for Odd<T> where T: CtAssignSlice {}
208
209impl<T> CtEq for Odd<T>
210where
211 T: CtEq + ?Sized,
212{
213 #[inline]
214 fn ct_eq(&self, other: &Self) -> Choice {
215 CtEq::ct_eq(&self.0, &other.0)
216 }
217}
218impl<T> CtEqSlice for Odd<T> where T: CtEq {}
219
220impl<T> CtSelect for Odd<T>
221where
222 T: CtSelect,
223{
224 #[inline]
225 fn ct_select(&self, other: &Self, choice: Choice) -> Self {
226 Self(self.0.ct_select(&other.0, choice))
227 }
228}
229
230impl<T> Default for Odd<T>
231where
232 T: One,
233{
234 #[inline]
235 fn default() -> Self {
236 Odd(T::one())
237 }
238}
239
240impl<T: ?Sized> Deref for Odd<T> {
241 type Target = T;
242
243 fn deref(&self) -> &T {
244 &self.0
245 }
246}
247
248impl<T> ConstOne for Odd<T>
249where
250 T: ConstOne + One,
251{
252 const ONE: Self = Self(T::ONE);
253}
254
255impl<T> One for Odd<T>
256where
257 T: One,
258{
259 #[inline]
260 fn one() -> Self {
261 Self(T::one())
262 }
263}
264
265impl<T> num_traits::One for Odd<T>
266where
267 T: One + Mul<T, Output = T>,
268{
269 #[inline]
270 fn one() -> Self {
271 Self(T::one())
272 }
273
274 fn is_one(&self) -> bool {
275 self.0.is_one().into()
276 }
277}
278
279impl<T> Mul<Self> for Odd<T>
281where
282 T: Mul<T, Output = T>,
283{
284 type Output = Self;
285
286 fn mul(self, rhs: Self) -> Self {
287 Self(self.0 * rhs.0)
288 }
289}
290
291impl<const LIMBS: usize> PartialEq<Odd<Uint<LIMBS>>> for Uint<LIMBS> {
292 fn eq(&self, other: &Odd<Uint<LIMBS>>) -> bool {
293 self.eq(&other.0)
294 }
295}
296
297impl<const LIMBS: usize> PartialOrd<Odd<Uint<LIMBS>>> for Uint<LIMBS> {
298 fn partial_cmp(&self, other: &Odd<Uint<LIMBS>>) -> Option<Ordering> {
299 Some(self.cmp(&other.0))
300 }
301}
302
303impl OddUintRef {
304 #[must_use]
308 pub const fn to_uint_resize<const T: usize>(&self) -> Odd<Uint<T>> {
309 Odd(self.0.to_uint_resize())
310 }
311}
312
313#[cfg(feature = "alloc")]
314impl OddBoxedUint {
315 #[inline]
317 #[must_use]
318 pub const fn as_uint_ref(&self) -> &OddUintRef {
319 self.0.as_uint_ref().as_odd_unchecked()
320 }
321
322 #[cfg(feature = "rand_core")]
324 pub fn random<R: TryRng + ?Sized>(rng: &mut R, bit_length: u32) -> Self {
325 let mut ret = BoxedUint::random_bits(rng, bit_length);
326 ret.limbs[0] |= Limb::ONE;
327 Odd(ret)
328 }
329}
330
331#[cfg(feature = "alloc")]
332impl AsRef<OddUintRef> for OddBoxedUint {
333 fn as_ref(&self) -> &OddUintRef {
334 self.as_uint_ref()
335 }
336}
337
338#[cfg(feature = "alloc")]
339impl PartialEq<OddBoxedUint> for BoxedUint {
340 fn eq(&self, other: &OddBoxedUint) -> bool {
341 self.eq(&other.0)
342 }
343}
344
345#[cfg(feature = "alloc")]
346impl PartialOrd<OddBoxedUint> for BoxedUint {
347 fn partial_cmp(&self, other: &OddBoxedUint) -> Option<Ordering> {
348 Some(self.cmp(&other.0))
349 }
350}
351
352#[cfg(feature = "alloc")]
353impl Resize for OddBoxedUint {
354 type Output = Self;
355
356 fn resize_unchecked(self, at_least_bits_precision: u32) -> Self::Output {
357 Odd(self.0.resize_unchecked(at_least_bits_precision))
358 }
359
360 fn try_resize(self, at_least_bits_precision: u32) -> Option<Self::Output> {
361 self.0.try_resize(at_least_bits_precision).map(Odd)
362 }
363}
364
365#[cfg(feature = "alloc")]
366impl Resize for &OddBoxedUint {
367 type Output = OddBoxedUint;
368
369 fn resize_unchecked(self, at_least_bits_precision: u32) -> Self::Output {
370 Odd((&self.0).resize_unchecked(at_least_bits_precision))
371 }
372
373 fn try_resize(self, at_least_bits_precision: u32) -> Option<Self::Output> {
374 (&self.0).try_resize(at_least_bits_precision).map(Odd)
375 }
376}
377
378#[cfg(feature = "rand_core")]
379impl<const LIMBS: usize> Random for Odd<Uint<LIMBS>> {
380 fn try_random_from_rng<R: TryRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
382 let mut ret = Uint::try_random_from_rng(rng)?;
383 ret.limbs[0] |= Limb::ONE;
384 Ok(Odd(ret))
385 }
386}
387
388impl<T> fmt::Display for Odd<T>
389where
390 T: fmt::Display + ?Sized,
391{
392 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
393 fmt::Display::fmt(&self.0, f)
394 }
395}
396
397impl<T> fmt::Binary for Odd<T>
398where
399 T: fmt::Binary + ?Sized,
400{
401 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
402 fmt::Binary::fmt(&self.0, f)
403 }
404}
405
406impl<T> fmt::Octal for Odd<T>
407where
408 T: fmt::Octal + ?Sized,
409{
410 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
411 fmt::Octal::fmt(&self.0, f)
412 }
413}
414
415impl<T> fmt::LowerHex for Odd<T>
416where
417 T: fmt::LowerHex + ?Sized,
418{
419 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
420 fmt::LowerHex::fmt(&self.0, f)
421 }
422}
423
424impl<T> fmt::UpperHex for Odd<T>
425where
426 T: fmt::UpperHex + ?Sized,
427{
428 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
429 fmt::UpperHex::fmt(&self.0, f)
430 }
431}
432
433#[cfg(feature = "serde")]
434impl<'de, T: Deserialize<'de> + Integer + Zero> Deserialize<'de> for Odd<T> {
435 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
436 where
437 D: Deserializer<'de>,
438 {
439 let value: T = T::deserialize(deserializer)?;
440 Option::<Self>::from(Self::new(value)).ok_or(D::Error::invalid_value(
441 Unexpected::Other("even"),
442 &"a non-zero odd value",
443 ))
444 }
445}
446
447#[cfg(feature = "serde")]
448impl<T: Serialize + Zero> Serialize for Odd<T> {
449 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
450 where
451 S: Serializer,
452 {
453 self.0.serialize(serializer)
454 }
455}
456
457#[cfg(feature = "subtle")]
458impl<T> subtle::ConditionallySelectable for Odd<T>
459where
460 T: Copy,
461 Self: CtSelect,
462{
463 fn conditional_select(a: &Self, b: &Self, choice: subtle::Choice) -> Self {
464 a.ct_select(b, choice.into())
465 }
466}
467
468#[cfg(feature = "subtle")]
469impl<T> subtle::ConstantTimeEq for Odd<T>
470where
471 T: ?Sized,
472 Self: CtEq,
473{
474 fn ct_eq(&self, other: &Self) -> subtle::Choice {
475 CtEq::ct_eq(self, other).into()
476 }
477}
478
479#[cfg(feature = "zeroize")]
480impl<T: zeroize::Zeroize> zeroize::Zeroize for Odd<T> {
481 fn zeroize(&mut self) {
482 self.0.zeroize();
483 }
484}
485
486#[cfg(test)]
487mod tests {
488 use super::Odd;
489 use crate::{ConstOne, U128, Uint};
490
491 #[cfg(feature = "alloc")]
492 use crate::BoxedUint;
493
494 #[test]
495 fn default() {
496 assert!(Odd::<U128>::default().is_odd().to_bool());
497 }
498
499 #[test]
500 fn from_be_hex_when_odd() {
501 assert_eq!(
502 Odd::<U128>::from_be_hex("00000000000000000000000000000001"),
503 Odd::<U128>::ONE
504 );
505 }
506
507 #[test]
508 #[should_panic]
509 fn from_be_hex_when_even() {
510 let _ = Odd::<U128>::from_be_hex("00000000000000000000000000000002");
511 }
512
513 #[test]
514 fn from_le_hex_when_odd() {
515 assert_eq!(
516 Odd::<U128>::from_le_hex("01000000000000000000000000000000"),
517 Odd::<U128>::ONE
518 );
519 }
520
521 #[test]
522 #[should_panic]
523 fn from_le_hex_when_even() {
524 let _ = Odd::<U128>::from_le_hex("20000000000000000000000000000000");
525 }
526
527 #[test]
528 fn not_odd_numbers() {
529 let zero = Odd::new(Uint::<4>::ZERO);
530 assert!(bool::from(zero.is_none()));
531 let two = Odd::new(Uint::<4>::from(2u8));
532 assert!(bool::from(two.is_none()));
533 }
534
535 #[cfg(feature = "alloc")]
536 #[test]
537 fn not_odd_numbers_boxed() {
538 let zero = Odd::new(BoxedUint::zero());
539 assert!(bool::from(zero.is_none()));
540 let two = Odd::new(BoxedUint::from(2u8));
541 assert!(bool::from(two.is_none()));
542 }
543}