fracints_internals/traits.rs
1use core::{
2 fmt,
3 iter::{Product, Sum},
4 ops::*,
5 str::FromStr,
6};
7
8// TODO decide on how `to_string_general` should work
9
10/// A common trait for a special case of fixed point numbers in the form of all
11/// fractional bits.
12pub trait Fracint:
13 Sized
14 + Clone
15 + Copy
16 + Default
17 + PartialEq
18 + Eq
19 + PartialOrd
20 + Ord
21 + core::hash::Hash
22 + fmt::Display
23 + fmt::Debug
24 + FromStr
25 + Neg<Output = Self>
26 + Add<Output = Self>
27 + AddAssign
28 + Sub<Output = Self>
29 + SubAssign
30 + Mul<Output = Self>
31 + MulAssign
32 + Div<Output = Self>
33 + DivAssign
34 + Shl<usize, Output = Self>
35 + ShlAssign<usize>
36 + Shr<usize, Output = Self>
37 + ShrAssign<usize>
38 + Not<Output = Self>
39 + BitOr<Output = Self>
40 + BitOrAssign
41 + BitAnd<Output = Self>
42 + BitAndAssign
43 + BitXor<Output = Self>
44 + BitXorAssign
45 + Sum
46 + Product
47{
48 /// This is only for workarounds, to make this better we would need a
49 /// refined trait for normal integers.
50 type Int: Sized
51 + Clone
52 + Copy
53 + TryInto<u128, Error: fmt::Debug>
54 + TryFrom<u128, Error: fmt::Debug>
55 + fmt::Debug;
56
57 /// The number of bits in this type
58 const BITS: usize;
59 /// The maximum value representable by `Self`
60 const MAX: Self;
61 /// The minimum value representable by `Self`
62 const MIN: Self;
63 /// For `fiN`, `ONE` and `MAX` are the same. Prefer to use `MAX` when
64 /// wanting to emphasize the true numeric bounds or ordered maximum,
65 /// and instead use `ONE` for numeric values.
66 const ONE: Self;
67 /// A numerical value of negative one.
68 ///
69 /// Note that `NEG_ONE` is not equal to `MIN`, but to `MIN + ULP`.
70 /// The purpose of `NEG_ONE` in contrast to `MIN` is preventing
71 /// certain overflows, such as `fiN::MIN.wrapping_mul(fiN::MIN)` or
72 /// `fiN::wrapping_abs(fiN::MIN)`.
73 const NEG_ONE: Self;
74 /// One positive Unit in the Last Place
75 const ULP: Self;
76 /// Zero.
77 const ZERO: Self;
78 /// If this type is signed
79 const SIGNED: bool;
80
81 /// Casts from the `Self::Int` type
82 fn from_int(x: Self::Int) -> Self;
83 /// Casts to the `Self::Int` type
84 fn as_int(self) -> Self::Int;
85
86 fn is_zero(self) -> bool {
87 self == Self::ZERO
88 }
89 fn is_negative(self) -> bool {
90 self < Self::ZERO
91 }
92 fn is_positive(self) -> bool {
93 self >= Self::ZERO
94 }
95
96 /// Returns a value representing the sign of `self`.
97 ///
98 /// - `fiN::NEG_ONE` if the value is negative
99 /// - `fiN::ZERO` if the value is zero
100 /// - `fiN::ONE` if the value is positive
101 fn signum(self) -> Self {
102 if self < Self::ZERO {
103 Self::NEG_ONE
104 } else if self == Self::ZERO {
105 Self::ZERO
106 } else {
107 Self::ONE
108 }
109 }
110
111 /// Wrapping absolute value of `self`.
112 ///
113 /// # Overflow behavior
114 ///
115 /// `Self::MIN.abs()` -> `Self::MIN`
116 fn wrapping_abs(self) -> Self {
117 if self.is_negative() {
118 self.wrapping_neg()
119 } else {
120 self
121 }
122 }
123
124 /// Returns a tuple of `self.wrapping_abs()` along with a boolean indicating
125 /// whether an overflow happened.
126 fn overflowing_abs(self) -> (Self, bool);
127
128 /// Same as `overflowing_abs` except it returns `None` on overflow
129 fn checked_abs(self) -> Option<Self> {
130 match self.overflowing_abs() {
131 (x, false) => Some(x),
132 (_, true) => None,
133 }
134 }
135
136 /// Saturating absolute value of `self`. It behaves the same way as
137 /// `wrapping_abs` except `Self::MIN.saturating_abs()` -> `Self::ONE`
138 fn saturating_abs(self) -> Self {
139 self.checked_abs().unwrap_or(Self::ONE)
140 }
141
142 /// Wrapping negation of `self`.
143 ///
144 /// # Overflow behavior
145 ///
146 /// `Self::MIN.wrapping_neg()` -> `Self::MIN`
147 fn wrapping_neg(self) -> Self;
148
149 /// Returns a tuple of `self.wrapping_neg()` along with a boolean indicating
150 /// whether an overflow happened.
151 fn overflowing_neg(self) -> (Self, bool);
152
153 /// Same as `overflowing_neg` except it returns `None` on overflow
154 fn checked_neg(self) -> Option<Self> {
155 match self.overflowing_neg() {
156 (x, false) => Some(x),
157 (_, true) => None,
158 }
159 }
160
161 /// Saturating negation of `self`. It behaves the same way as `wrapping_neg`
162 /// except `Self::MIN.saturating_neg()` -> `Self::ONE`
163 fn saturating_neg(self) -> Self;
164
165 /// Saturating inversion of `self`. It has the special cases
166 ///
167 /// - `fiN::MIN` => `-1`
168 /// - `fiN::ZERO` => `iX::MAX`
169 ///
170 /// Note that it does not panic on zero.
171 fn saturating_inv(self) -> Self::Int;
172
173 /// Wrapping (modular) addition.
174 ///
175 /// # Overflow behavior
176 ///
177 /// If the numeric value of `self` added to `rhs` is more than `fiN::MAX`
178 /// or less than `fiN::MIN` (if `fiN::MIN` should be avoided, use
179 /// `fiN::NEG_ONE` as the minimum value instead), modular overflow will
180 /// happen.
181 fn wrapping_add(self, rhs: Self) -> Self;
182
183 /// Returns a tuple of `self.wrapping_add(rhs)` along with a boolean
184 /// indicating whether an overflow happened.
185 /// Note that if `self.wrapping_add(rhs) == fiN::MIN`, it is counted as
186 /// overflow.
187 fn overflowing_add(self, rhs: Self) -> (Self, bool);
188
189 /// Same as `overflowing_add` except it returns `None` on overflow
190 fn checked_add(self, rhs: Self) -> Option<Self> {
191 match self.overflowing_add(rhs) {
192 (v, false) => Some(v),
193 (_, true) => None,
194 }
195 }
196
197 /// Saturating addition. Saturates at the numeric bounds `fiN::NEG_ONE` and
198 /// `fiN::ONE` instead of overflowing.
199 fn saturating_add(self, rhs: Self) -> Self;
200
201 /// Wrapping (modular) subtraction.
202 ///
203 /// # Overflow behavior
204 ///
205 /// If the numeric value of `self` subtracted by `rhs` is more than
206 /// `fiN::MAX` or less than `fiN::MIN` (if `fiN::MIN` should be avoided,
207 /// use `fiN::NEG_ONE` as the minimum value instead), modular overflow
208 /// will happen.
209 fn wrapping_sub(self, rhs: Self) -> Self;
210
211 /// Returns a tuple of `self.wrapping_sub(rhs)` along with a boolean
212 /// indicating whether an overflow happened.
213 /// Note that if `self.wrapping_sub(rhs) == fiN::MIN`, it is counted as
214 /// overflow.
215 fn overflowing_sub(self, rhs: Self) -> (Self, bool);
216
217 /// Same as `overflowing_sub` except it returns `None` on overflow
218 fn checked_sub(self, rhs: Self) -> Option<Self> {
219 match self.overflowing_sub(rhs) {
220 (v, false) => Some(v),
221 (_, true) => None,
222 }
223 }
224
225 /// Saturating subtraction. Saturates at the numeric bounds `fiN::NEG_ONE`
226 /// and `fiN::ONE` instead of overflowing.
227 fn saturating_sub(self, rhs: Self) -> Self;
228
229 /// Wrapping fracint multiplication.
230 ///
231 /// # Overflow Behavior
232 ///
233 /// There is only one case where overflow can occur:
234 /// `fiN::MIN.wrapping_mul(fiN::MIN)` -> `fiN::MIN`.
235 fn wrapping_mul(self, rhs: Self) -> Self;
236
237 /// Returns a tuple of `self.wrapping_mul(rhs)` along with a boolean
238 /// indicating whether an overflow happened.
239 ///
240 /// Note that only the overflow possible is the corner case
241 /// `fiN::MIN.wrapping_mul(fiN::MIN)` -> `fiN::MIN`.
242 fn overflowing_mul(self, rhs: Self) -> (Self, bool);
243
244 /// Same as `overflowing_mul` except it returns `None` on overflow
245 fn checked_mul(self, rhs: Self) -> Option<Self> {
246 match self.overflowing_mul(rhs) {
247 (v, false) => Some(v),
248 (_, true) => None,
249 }
250 }
251
252 /// Saturating fracint multiplication. Saturates at the numeric bounds
253 /// `fiN::NEG_ONE` and `fiN::ONE` instead of overflowing.
254 fn saturating_mul(self, rhs: Self) -> Self;
255
256 /// Saturating fracint multiplication with an integer. Saturates at the
257 /// numeric bounds `fiN::NEG_ONE` and `fiN::ONE` instead of overflowing.
258 fn saturating_mul_int(self, rhs: Self::Int) -> Self;
259
260 /// Saturating fracint division. Saturates at the numeric bounds
261 /// `fiN::NEG_ONE` and `fiN::ONE` instead of overflowing.
262 ///
263 /// Panics are prevented and saturation handled in this way:
264 /// - if `rhs == fiN::ZERO`, `self.signum()` is returned
265 /// - else if `self.saturating_abs() >= rhs.saturating_abs()`, it will
266 /// return `fiN::NEG_ONE` if their signs are not equal, `fiN::ONE`
267 /// otherwise (except for `rhs == fiN::ZERO` as shown above)
268 ///
269 /// Note that it does not panic on zero
270 fn saturating_div(self, rhs: Self) -> Self;
271
272 /// Saturating fracint division with an integer. Saturates at the numeric
273 /// bounds `fiN::NEG_ONE` and `fiN::ONE` instead of overflowing.
274 ///
275 /// Panics are prevented and saturation handled in this way:
276 /// - if `rhs == fiN::ZERO`, `self.signum()` is returned
277 /// - if `self == fiN::MIN` and `rhs == -1`, `Self::ONE` is returned
278 fn saturating_div_int(self, rhs: Self::Int) -> Self;
279
280 #[cfg(feature = "rand_support")]
281 fn rand<R: rand_core::Rng + ?Sized>(rng: &mut R) -> Self;
282
283 /// Converts from an `f32` to `Self`. Returns `None` if the absolute value
284 /// is greater than 1.0.
285 fn from_f32(f: f32) -> Option<Self>;
286
287 /// Converts from an `f64` to `Self`. Returns `None` if the absolute value
288 /// is greater than 1.0.
289 fn from_f64(f: f64) -> Option<Self>;
290
291 /// Converts to an `f32`
292 fn to_f32(self) -> f32;
293
294 /// Converts to an `f64`
295 fn to_f64(self) -> f64;
296
297 /// Slow way of calculating the truncated square root using bisection. This
298 /// will always underestimate the square root, with about as much bit error
299 /// as the number of leading zero bits.
300 fn sqrt_simple_bisection(self) -> Self {
301 let mut set_bit = if Self::SIGNED {
302 Self::ULP << (Self::BITS - 2)
303 } else {
304 Self::ULP << (Self::BITS - 1)
305 };
306 let mut res = Self::ZERO;
307 let mut prev_sqr = Self::ZERO;
308 loop {
309 if set_bit.is_zero() {
310 break res
311 }
312 let test = res | set_bit;
313 let sqr = test.saturating_mul(test);
314 if sqr <= self {
315 res = test;
316 if sqr == self {
317 break res
318 }
319 }
320 if sqr == prev_sqr {
321 // we have reached a point where the set bit no longer contributes
322 break res
323 }
324 prev_sqr = sqr;
325 set_bit >>= 1;
326 }
327 }
328
329 /// Fast way of calculating the square root to within a few ULPs of the true
330 /// value.
331 fn sqrt_fast(self) -> Self;
332}
333
334pub trait FracintDouble: Fracint {
335 /// The double-sized version of `Self`
336 type Double: Fracint + FracintHalf<Half = Self>;
337
338 /// Widens `self` by extending with zero bits
339 fn widen(self) -> Self::Double;
340
341 /// Saturating widening multiplication of `self` and `other`. All inputs
342 /// result in numerically _exact_ outputs, except for
343 /// `fiN::MIN.full_mul(fiN::MIN)` which has to be saturated to `fiM::ONE`.
344 ///
345 /// # Examples
346 ///
347 /// ```
348 /// use fracints::*;
349 ///
350 /// // note: `from_str` and `to_string` sometimes have small
351 /// // round-to-even errors when converting and displaying, but
352 /// // the `full_mul` between those functions is truly exact
353 /// // (except for the corner case).
354 /// assert_eq!(
355 /// fi32!(0.123456789)
356 /// .saturating_widening_mul(fi32!(0.123456789))
357 /// .to_string(),
358 /// "0.0152415787947921023"
359 /// );
360 ///
361 /// // the only overflow corner case
362 /// assert_eq!(fi32::MIN.saturating_widening_mul(fi32::MIN), fi64::ONE);
363 /// ```
364 fn saturating_widening_mul(self, rhs: Self) -> Self::Double;
365
366 /// This calculates a nearly exact truncated square root using bisection
367 /// with a larger type
368 fn sqrt_slow(self) -> Self {
369 self.widen().sqrt_simple_bisection().truncate()
370 }
371}
372
373pub trait FracintHalf: Fracint + From<Self::Half> {
374 /// The half-sized version of `Self`
375 type Half: Fracint + FracintDouble<Double = Self>;
376
377 /// Returns half sized low and high parts. The high part is effectively a
378 /// truncated version of `self`, and the low part is the remainder.
379 fn split(self) -> (Self::Half, Self::Half);
380
381 /// Truncates `self` down to a half sized type with the same value except
382 /// with less than 1 ULP of error.
383 fn truncate(self) -> Self::Half;
384}