Skip to main content

fixed_bigint/fixeduint/
prim_int_impl.rs

1use super::{const_leading_zeros, const_trailing_zeros, FixedUInt, MachineWord};
2use crate::const_numtraits::ConstPrimInt;
3use crate::machineword::ConstMachineWord;
4
5use num_traits::One;
6
7c0nst::c0nst! {
8    impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst ConstPrimInt for FixedUInt<T, N> {
9        fn count_ones(self) -> u32 {
10            let mut count = 0u32;
11            let mut i = 0;
12            while i < N {
13                count += self.array[i].count_ones();
14                i += 1;
15            }
16            count
17        }
18        fn count_zeros(self) -> u32 {
19            let mut count = 0u32;
20            let mut i = 0;
21            while i < N {
22                count += self.array[i].count_zeros();
23                i += 1;
24            }
25            count
26        }
27        fn leading_zeros(self) -> u32 {
28            const_leading_zeros(&self.array)
29        }
30        fn trailing_zeros(self) -> u32 {
31            const_trailing_zeros(&self.array)
32        }
33        fn swap_bytes(self) -> Self {
34            let mut ret = <Self as crate::const_numtraits::ConstZero>::zero();
35            let mut i = 0;
36            while i < N {
37                ret.array[i] = self.array[N - 1 - i].swap_bytes();
38                i += 1;
39            }
40            ret
41        }
42        fn rotate_left(self, n: u32) -> Self {
43            let bit_size = Self::BIT_SIZE as u32;
44            if bit_size == 0 {
45                return self;
46            }
47            let shift = n % bit_size;
48            let a = core::ops::Shl::<u32>::shl(self, shift);
49            let b = core::ops::Shr::<u32>::shr(self, bit_size - shift);
50            core::ops::BitOr::bitor(a, b)
51        }
52        fn rotate_right(self, n: u32) -> Self {
53            let bit_size = Self::BIT_SIZE as u32;
54            if bit_size == 0 {
55                return self;
56            }
57            let shift = n % bit_size;
58            let a = core::ops::Shr::<u32>::shr(self, shift);
59            let b = core::ops::Shl::<u32>::shl(self, bit_size - shift);
60            core::ops::BitOr::bitor(a, b)
61        }
62        fn unsigned_shl(self, n: u32) -> Self {
63            core::ops::Shl::<u32>::shl(self, n)
64        }
65        fn unsigned_shr(self, n: u32) -> Self {
66            core::ops::Shr::<u32>::shr(self, n)
67        }
68        fn reverse_bits(self) -> Self {
69            let mut ret = <Self as crate::const_numtraits::ConstZero>::zero();
70            let mut i = 0;
71            while i < N {
72                ret.array[N - 1 - i] = self.array[i].reverse_bits();
73                i += 1;
74            }
75            ret
76        }
77        // TODO: Add big-endian support via #[cfg(target_endian = "big")]
78        fn from_be(x: Self) -> Self {
79            x.swap_bytes()
80        }
81        fn from_le(x: Self) -> Self {
82            x
83        }
84        fn to_be(self) -> Self {
85            self.swap_bytes()
86        }
87        fn to_le(self) -> Self {
88            self
89        }
90        fn pow(self, exp: u32) -> Self {
91            if exp == 0 {
92                return <Self as crate::const_numtraits::ConstOne>::one();
93            }
94            // Exponentiation by squaring: O(log exp) instead of O(exp)
95            let mut result = <Self as crate::const_numtraits::ConstOne>::one();
96            let mut base = self;
97            let mut e = exp;
98            while e > 0 {
99                if (e & 1) == 1 {
100                    result = core::ops::Mul::mul(result, base);
101                }
102                e >>= 1;
103                if e > 0 {
104                    base = core::ops::Mul::mul(base, base);
105                }
106            }
107            result
108        }
109    }
110}
111
112impl<T: MachineWord, const N: usize> num_traits::PrimInt for FixedUInt<T, N> {
113    fn count_ones(self) -> u32 {
114        self.array.iter().map(|&val| val.count_ones()).sum()
115    }
116    fn count_zeros(self) -> u32 {
117        self.array.iter().map(|&val| val.count_zeros()).sum()
118    }
119    fn leading_zeros(self) -> u32 {
120        const_leading_zeros(&self.array)
121    }
122    fn trailing_zeros(self) -> u32 {
123        const_trailing_zeros(&self.array)
124    }
125    fn rotate_left(self, bits: u32) -> Self {
126        let bit_size = Self::BIT_SIZE as u32;
127        if bit_size == 0 {
128            return self;
129        }
130        let shift = bits % bit_size;
131        let a = self << shift;
132        let b = self >> (bit_size - shift);
133        a | b
134    }
135    fn rotate_right(self, bits: u32) -> Self {
136        let bit_size = Self::BIT_SIZE as u32;
137        if bit_size == 0 {
138            return self;
139        }
140        let shift = bits % bit_size;
141        let a = self >> shift;
142        let b = self << (bit_size - shift);
143        a | b
144    }
145    fn signed_shl(self, bits: u32) -> Self {
146        <Self as num_traits::PrimInt>::unsigned_shl(self, bits)
147    }
148    fn signed_shr(self, bits: u32) -> Self {
149        <Self as num_traits::PrimInt>::unsigned_shr(self, bits)
150    }
151    fn unsigned_shl(self, bits: u32) -> Self {
152        self << bits
153    }
154    fn unsigned_shr(self, bits: u32) -> Self {
155        self >> bits
156    }
157    fn swap_bytes(self) -> Self {
158        let mut ret = Self::new();
159        for index in 0..N {
160            ret.array[index] = self.array[N - 1 - index].swap_bytes();
161        }
162
163        ret
164    }
165    // TODO: Add big-endian support via #[cfg(target_endian = "big")]
166    fn from_be(source: Self) -> Self {
167        <Self as num_traits::PrimInt>::swap_bytes(source)
168    }
169    fn from_le(source: Self) -> Self {
170        source
171    }
172    fn to_be(self) -> Self {
173        <Self as num_traits::PrimInt>::swap_bytes(self)
174    }
175    fn to_le(self) -> Self {
176        self
177    }
178    fn pow(self, exp: u32) -> Self {
179        if exp == 0 {
180            return Self::one();
181        }
182        // Exponentiation by squaring: O(log exp) instead of O(exp)
183        let mut result = Self::one();
184        let mut base = self;
185        let mut e = exp;
186        while e > 0 {
187            if (e & 1) == 1 {
188                result *= base;
189            }
190            e >>= 1;
191            if e > 0 {
192                base *= base;
193            }
194        }
195        result
196    }
197}