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