add count_leading_zeros, count_trailing_zeros, and count_ones implementations
[vector-math.git] / src / prim.rs
1 #[cfg(not(feature = "std"))]
2 use crate::scalar::{Scalar, Value};
3 use crate::{
4 f16::F16,
5 traits::{ConvertFrom, ConvertTo},
6 };
7 use core::{fmt, hash, ops};
8
9 mod sealed {
10 use crate::f16::F16;
11
12 pub trait Sealed {}
13 impl Sealed for F16 {}
14 impl Sealed for f32 {}
15 impl Sealed for f64 {}
16 impl Sealed for u8 {}
17 impl Sealed for u16 {}
18 impl Sealed for u32 {}
19 impl Sealed for u64 {}
20 impl Sealed for i8 {}
21 impl Sealed for i16 {}
22 impl Sealed for i32 {}
23 impl Sealed for i64 {}
24 }
25
26 pub trait PrimBase:
27 sealed::Sealed
28 + Copy
29 + 'static
30 + Send
31 + Sync
32 + PartialOrd
33 + fmt::Debug
34 + fmt::Display
35 + ops::Add<Output = Self>
36 + ops::Sub<Output = Self>
37 + ops::Mul<Output = Self>
38 + ops::Div<Output = Self>
39 + ops::Rem<Output = Self>
40 + ops::AddAssign
41 + ops::SubAssign
42 + ops::MulAssign
43 + ops::DivAssign
44 + ops::RemAssign
45 + ConvertFrom<i8>
46 + ConvertFrom<u8>
47 + ConvertFrom<i16>
48 + ConvertFrom<u16>
49 + ConvertFrom<F16>
50 + ConvertFrom<i32>
51 + ConvertFrom<u32>
52 + ConvertFrom<f32>
53 + ConvertFrom<i64>
54 + ConvertFrom<u64>
55 + ConvertFrom<f64>
56 + ConvertTo<i8>
57 + ConvertTo<u8>
58 + ConvertTo<i16>
59 + ConvertTo<u16>
60 + ConvertTo<F16>
61 + ConvertTo<i32>
62 + ConvertTo<u32>
63 + ConvertTo<f32>
64 + ConvertTo<i64>
65 + ConvertTo<u64>
66 + ConvertTo<f64>
67 {
68 }
69
70 pub trait PrimInt:
71 PrimBase
72 + Ord
73 + hash::Hash
74 + fmt::Binary
75 + fmt::LowerHex
76 + fmt::Octal
77 + fmt::UpperHex
78 + ops::BitAnd<Output = Self>
79 + ops::BitOr<Output = Self>
80 + ops::BitXor<Output = Self>
81 + ops::Shl<Output = Self>
82 + ops::Shr<Output = Self>
83 + ops::Not<Output = Self>
84 + ops::BitAndAssign
85 + ops::BitOrAssign
86 + ops::BitXorAssign
87 + ops::ShlAssign
88 + ops::ShrAssign
89 {
90 const ZERO: Self;
91 const ONE: Self;
92 const MIN: Self;
93 const MAX: Self;
94 const BITS: Self;
95 }
96
97 pub trait PrimUInt: PrimInt + ConvertFrom<Self::SignedType> {
98 type SignedType: PrimSInt<UnsignedType = Self> + ConvertFrom<Self>;
99 }
100
101 pub trait PrimSInt: PrimInt + ops::Neg<Output = Self> + ConvertFrom<Self::UnsignedType> {
102 type UnsignedType: PrimUInt<SignedType = Self> + ConvertFrom<Self>;
103 }
104
105 macro_rules! impl_int {
106 ($uint:ident, $sint:ident) => {
107 impl PrimBase for $uint {}
108 impl PrimBase for $sint {}
109 impl PrimInt for $uint {
110 const ZERO: Self = 0;
111 const ONE: Self = 1;
112 const MIN: Self = 0;
113 const MAX: Self = !0;
114 const BITS: Self = (0 as $uint).count_zeros() as $uint;
115 }
116 impl PrimInt for $sint {
117 const ZERO: Self = 0;
118 const ONE: Self = 1;
119 const MIN: Self = $sint::MIN;
120 const MAX: Self = $sint::MAX;
121 const BITS: Self = (0 as $sint).count_zeros() as $sint;
122 }
123 impl PrimUInt for $uint {
124 type SignedType = $sint;
125 }
126 impl PrimSInt for $sint {
127 type UnsignedType = $uint;
128 }
129 };
130 }
131
132 impl_int!(u8, i8);
133 impl_int!(u16, i16);
134 impl_int!(u32, i32);
135 impl_int!(u64, i64);
136
137 pub trait PrimFloat:
138 PrimBase + ops::Neg<Output = Self> + ConvertFrom<Self::BitsType> + ConvertFrom<Self::SignedBitsType>
139 {
140 type BitsType: PrimUInt<SignedType = Self::SignedBitsType> + ConvertFrom<Self>;
141 type SignedBitsType: PrimSInt<UnsignedType = Self::BitsType> + ConvertFrom<Self>;
142 const EXPONENT_BIAS_UNSIGNED: Self::BitsType;
143 const EXPONENT_BIAS_SIGNED: Self::SignedBitsType;
144 const SIGN_FIELD_WIDTH: Self::BitsType;
145 const EXPONENT_FIELD_WIDTH: Self::BitsType;
146 const MANTISSA_FIELD_WIDTH: Self::BitsType;
147 const SIGN_FIELD_SHIFT: Self::BitsType;
148 const EXPONENT_FIELD_SHIFT: Self::BitsType;
149 const MANTISSA_FIELD_SHIFT: Self::BitsType;
150 const SIGN_FIELD_MASK: Self::BitsType;
151 const EXPONENT_FIELD_MASK: Self::BitsType;
152 const MANTISSA_FIELD_MASK: Self::BitsType;
153 const IMPLICIT_MANTISSA_BIT: Self::BitsType;
154 const ZERO_SUBNORMAL_EXPONENT: Self::BitsType;
155 const NAN_INFINITY_EXPONENT: Self::BitsType;
156 const INFINITY_BITS: Self::BitsType;
157 const NAN_BITS: Self::BitsType;
158 fn is_nan(self) -> bool;
159 fn from_bits(bits: Self::BitsType) -> Self;
160 fn to_bits(self) -> Self::BitsType;
161 fn abs(self) -> Self;
162 fn max_contiguous_integer() -> Self {
163 (Self::BitsType::cvt_from(1) << (Self::MANTISSA_FIELD_WIDTH + 1.to())).to()
164 }
165 fn is_finite(self) -> bool;
166 fn trunc(self) -> Self;
167 /// round to nearest, ties to unspecified
168 fn round(self) -> Self;
169 fn floor(self) -> Self;
170 fn ceil(self) -> Self;
171 fn copy_sign(self, sign: Self) -> Self;
172 }
173
174 macro_rules! impl_float {
175 (
176 impl PrimFloat for $float:ident {
177 type BitsType = $bits_type:ident;
178 type SignedBitsType = $signed_bits_type:ident;
179 const EXPONENT_FIELD_WIDTH: u32 = $exponent_field_width:literal;
180 const MANTISSA_FIELD_WIDTH: u32 = $mantissa_field_width:literal;
181 }
182 ) => {
183 impl PrimBase for $float {}
184
185 impl PrimFloat for $float {
186 type BitsType = $bits_type;
187 type SignedBitsType = $signed_bits_type;
188 const EXPONENT_BIAS_UNSIGNED: Self::BitsType =
189 (1 << (Self::EXPONENT_FIELD_WIDTH - 1)) - 1;
190 const EXPONENT_BIAS_SIGNED: Self::SignedBitsType = Self::EXPONENT_BIAS_UNSIGNED as _;
191 const SIGN_FIELD_WIDTH: Self::BitsType = 1;
192 const EXPONENT_FIELD_WIDTH: Self::BitsType = $exponent_field_width;
193 const MANTISSA_FIELD_WIDTH: Self::BitsType = $mantissa_field_width;
194 const SIGN_FIELD_SHIFT: Self::BitsType =
195 Self::EXPONENT_FIELD_SHIFT + Self::EXPONENT_FIELD_WIDTH;
196 const EXPONENT_FIELD_SHIFT: Self::BitsType = Self::MANTISSA_FIELD_WIDTH;
197 const MANTISSA_FIELD_SHIFT: Self::BitsType = 0;
198 const SIGN_FIELD_MASK: Self::BitsType = 1 << Self::SIGN_FIELD_SHIFT;
199 const EXPONENT_FIELD_MASK: Self::BitsType =
200 ((1 << Self::EXPONENT_FIELD_WIDTH) - 1) << Self::EXPONENT_FIELD_SHIFT;
201 const MANTISSA_FIELD_MASK: Self::BitsType = (1 << Self::MANTISSA_FIELD_WIDTH) - 1;
202 const IMPLICIT_MANTISSA_BIT: Self::BitsType = 1 << Self::MANTISSA_FIELD_WIDTH;
203 const ZERO_SUBNORMAL_EXPONENT: Self::BitsType = 0;
204 const NAN_INFINITY_EXPONENT: Self::BitsType = (1 << Self::EXPONENT_FIELD_WIDTH) - 1;
205 const INFINITY_BITS: Self::BitsType =
206 Self::NAN_INFINITY_EXPONENT << Self::EXPONENT_FIELD_SHIFT;
207 const NAN_BITS: Self::BitsType =
208 Self::INFINITY_BITS | (1 << (Self::MANTISSA_FIELD_WIDTH - 1));
209 fn is_nan(self) -> bool {
210 $float::is_nan(self)
211 }
212 fn from_bits(bits: Self::BitsType) -> Self {
213 $float::from_bits(bits)
214 }
215 fn to_bits(self) -> Self::BitsType {
216 self.to_bits()
217 }
218 fn abs(self) -> Self {
219 #[cfg(feature = "std")]
220 return $float::abs(self);
221 #[cfg(not(feature = "std"))]
222 return crate::algorithms::base::abs(Scalar, Value(self)).0;
223 }
224 fn is_finite(self) -> bool {
225 $float::is_finite(self)
226 }
227 fn trunc(self) -> Self {
228 #[cfg(feature = "std")]
229 return $float::trunc(self);
230 #[cfg(not(feature = "std"))]
231 return crate::algorithms::base::trunc(Scalar, Value(self)).0;
232 }
233 fn round(self) -> Self {
234 #[cfg(feature = "std")]
235 return $float::round(self);
236 #[cfg(not(feature = "std"))]
237 return crate::algorithms::base::round_to_nearest_ties_to_even(Scalar, Value(self))
238 .0;
239 }
240 fn floor(self) -> Self {
241 #[cfg(feature = "std")]
242 return $float::floor(self);
243 #[cfg(not(feature = "std"))]
244 return crate::algorithms::base::floor(Scalar, Value(self)).0;
245 }
246 fn ceil(self) -> Self {
247 #[cfg(feature = "std")]
248 return $float::ceil(self);
249 #[cfg(not(feature = "std"))]
250 return crate::algorithms::base::ceil(Scalar, Value(self)).0;
251 }
252 fn copy_sign(self, sign: Self) -> Self {
253 #[cfg(feature = "std")]
254 return $float::copysign(self, sign);
255 #[cfg(not(feature = "std"))]
256 return crate::algorithms::base::copy_sign(Scalar, Value(self), Value(sign)).0;
257 }
258 }
259 };
260 }
261
262 impl_float! {
263 impl PrimFloat for F16 {
264 type BitsType = u16;
265 type SignedBitsType = i16;
266 const EXPONENT_FIELD_WIDTH: u32 = 5;
267 const MANTISSA_FIELD_WIDTH: u32 = 10;
268 }
269 }
270
271 impl_float! {
272 impl PrimFloat for f32 {
273 type BitsType = u32;
274 type SignedBitsType = i32;
275 const EXPONENT_FIELD_WIDTH: u32 = 8;
276 const MANTISSA_FIELD_WIDTH: u32 = 23;
277 }
278 }
279
280 impl_float! {
281 impl PrimFloat for f64 {
282 type BitsType = u64;
283 type SignedBitsType = i64;
284 const EXPONENT_FIELD_WIDTH: u32 = 11;
285 const MANTISSA_FIELD_WIDTH: u32 = 52;
286 }
287 }