fixed_bigint/heapless/
num_traits_bridge.rs1use super::HeaplessBigInt;
10use crate::MachineWord;
11use const_num_traits::{Bounded, CarryingMul, ConstOne, ConstZero, Nct, Personality, Zero};
12
13impl<T: MachineWord, const CAP: usize, P: Personality> num_traits::Zero
14 for HeaplessBigInt<T, CAP, P>
15{
16 fn zero() -> Self {
17 <Self as ConstZero>::ZERO
18 }
19
20 fn is_zero(&self) -> bool {
21 <Self as Zero>::is_zero(self)
22 }
23}
24
25impl<T: MachineWord + CarryingMul<Unsigned = T, Output = T>, const CAP: usize, P: Personality>
29 num_traits::One for HeaplessBigInt<T, CAP, P>
30{
31 fn one() -> Self {
32 <Self as ConstOne>::ONE
33 }
34}
35
36impl<T: MachineWord, const CAP: usize, P: Personality> num_traits::Bounded
37 for HeaplessBigInt<T, CAP, P>
38{
39 fn min_value() -> Self {
40 <Self as Bounded>::min_value()
41 }
42
43 fn max_value() -> Self {
44 <Self as Bounded>::max_value()
45 }
46}
47
48impl<T: MachineWord, const CAP: usize, P: Personality> num_traits::ToPrimitive
49 for HeaplessBigInt<T, CAP, P>
50{
51 fn to_i64(&self) -> Option<i64> {
52 None
54 }
55
56 fn to_u64(&self) -> Option<u64> {
57 let word_size = core::mem::size_of::<T>();
58 let len = self.len as usize;
59 let iter_limit = core::cmp::min(8 / word_size, len);
61 for i in iter_limit..len {
65 if !super::is_zero(&self.limbs[i]) {
66 return None;
67 }
68 }
69 let mut ret: u64 = 0;
70 for (i, word) in self.limbs.iter().take(iter_limit).enumerate() {
71 let bytes = word.to_le_bytes();
72 for (j, &byte) in bytes.as_ref().iter().enumerate() {
73 let bit_shift = (i * word_size + j) * 8;
74 if bit_shift < 64 {
75 ret |= (byte as u64) << bit_shift;
76 }
77 }
78 }
79 Some(ret)
80 }
81}
82
83impl<T: MachineWord, const CAP: usize, P: Personality> num_traits::FromPrimitive
84 for HeaplessBigInt<T, CAP, P>
85{
86 fn from_i64(_: i64) -> Option<Self> {
87 None
88 }
89
90 fn from_u64(input: u64) -> Option<Self> {
91 if let Some(max) =
94 num_traits::ToPrimitive::to_u64(&<Self as num_traits::Bounded>::max_value())
95 {
96 if input > max {
97 return None;
98 }
99 }
100 let bytes = input.to_le_bytes();
105 let mut sig = bytes.len();
106 while sig > 0 && bytes[sig - 1] == 0 {
107 sig -= 1;
108 }
109 Some(Self::from_le_bytes(&bytes[..sig]))
110 }
111}
112
113impl<T: MachineWord, const CAP: usize, P: Personality> num_traits::NumCast
114 for HeaplessBigInt<T, CAP, P>
115{
116 fn from<X: num_traits::ToPrimitive>(arg: X) -> Option<Self> {
117 <Self as num_traits::FromPrimitive>::from_u64(arg.to_u64()?)
118 }
119}
120
121impl<T, const CAP: usize> num_traits::Unsigned for HeaplessBigInt<T, CAP, Nct> where
123 T: MachineWord + CarryingMul<Unsigned = T, Output = T>
124{
125}
126
127#[cfg(test)]
128mod tests {
129 use super::*;
130 use num_traits::{FromPrimitive, ToPrimitive};
131
132 type H32x8 = HeaplessBigInt<u32, 8>; #[test]
139 fn from_u64_is_natural_width() {
140 use const_num_traits::BitsPrecision;
142 let small = H32x8::from_u64(1).unwrap();
143 assert_eq!(small.bits_precision(), 32); }
145
146 #[test]
147 fn wide_value_roundtrip() {
148 for v in [0x1_0000_0000u64, 0x1234_5678_9ABC, 0xFFFF_FFFF_FFFF_FFFF] {
151 assert_eq!(H32x8::from_u64(v).unwrap().to_u64(), Some(v));
152 }
153 assert_eq!(<H32x8 as num_traits::Bounded>::max_value().to_u64(), None);
156 }
157}