Skip to main content

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}