Skip to main content

relp_num/traits/
mod.rs

1//! # Traits
2//!
3//! A hierarchy of number types is defined. The hierarchy is "mathematically exact", but the
4//! implementations aren't. That is, the contracts that these traits define, or their names imply,
5//! may not be kept precisely. This is due to finite representation of these numbers and is a
6//! fundamental problem that cannot be avoided, but perhaps be dealt with differently.
7use std::fmt::{Debug, Display};
8use std::iter::Sum;
9use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
10
11use crate::non_zero::NonZeroSigned;
12
13mod absorb;
14pub use absorb::Absorb;
15pub use absorb::AbsorbAll;
16
17// The other direction across the same boundary as `absorb`, kept beside it.
18mod narrow;
19pub use narrow::Narrow;
20
21mod gcd;
22pub use gcd::Gcd;
23
24mod size;
25pub use size::EncodingSize;
26
27pub mod factorization;
28
29/// The simplex algorithm is defined over the ordered fields.
30///
31/// All methods containing algorithmic logic should be defined to work an ordered field (or a field,
32/// if they don't need the ordering). All methods representing a matrix should be defined over a
33/// field, because they don't need the additional ordering.
34pub trait OrderedField: Ord + NonZeroSigned + Field {}
35impl<T: Ord + NonZeroSigned + Field> OrderedField for T {}
36
37/// A reference to an ordered field.
38pub trait OrderedFieldRef<Deref>: Ord + FieldRef<Deref> {}
39impl<Deref, T: Ord + FieldRef<Deref>> OrderedFieldRef<Deref> for T {}
40
41/// Basic field operations with Self and with references to Self.
42///
43/// This trait is deliberately **not** blanket-implemented over its bounds. The primitive integers
44/// satisfy every one of them, but `i32` is not a field: its division truncates. Because this crate
45/// exists to give the simplex method exact arithmetic, a type that silently rounds must not be
46/// usable where a field is required. Implement it explicitly for types whose four operations are
47/// exact.
48pub trait Field:
49    Eq + // Equivalence relation
50    PartialOrd +
51    num_traits::Zero + // Additive identity
52    Neg<Output=Self> + // Additive inverse
53    num_traits::One + // Multiplicative identity
54    // First operation
55    Add<Self, Output=Self> +
56    for<'r> Add<&'r Self, Output=Self> +
57    AddAssign<Self> +
58    for<'r> AddAssign<&'r Self> +
59    Sum +
60    // First operation inverse
61    Sub<Self, Output=Self> +
62    for<'r> Sub<&'r Self, Output=Self> +
63    SubAssign<Self> +
64    for<'r> SubAssign<&'r Self> +
65    // Second operation
66    Mul<Self, Output=Self> +
67    for<'r> Mul<&'r Self, Output=Self> +
68    MulAssign<Self> +
69    for<'r> MulAssign<&'r Self> +
70    // Second operation inverse
71    Div<Self, Output=Self> +
72    for<'r> Div<&'r Self, Output=Self> +
73    DivAssign<Self> +
74    for<'r> DivAssign<&'r Self> +
75    // A fused multiply-add lives on `Absorb` instead, as `add_mul_narrow`. It belongs with the
76    // mixed-type operations rather than here: what makes fusing worth anything is a narrow factor
77    // that is one, where there is no multiplication to fuse and no intermediate to avoid.
78
79    // Practicalities
80    Clone +
81    Display +
82    Debug +
83{}
84// No blanket impl: see the note on `Field` above.
85
86/// A reference to a variable that is in a `Field`.
87///
88/// # On writing this down less often
89///
90/// Generic code needs `F: Field, for<'r> &'r F: FieldRef<F>`, and the second half is the awkward
91/// one. Moving it onto the definition of `Field`, as `trait Field where for<'r> &'r Self:
92/// FieldRef<Self>`, does not help and makes things worse: a where clause on a type that is not
93/// `Self` is a requirement on implementors, not something a `F: Field` bound implies, so every
94/// caller still has to discharge it, and now has to do so even when it uses no reference
95/// operations at all.
96///
97/// What does work is not having a reference type to bound. [`AbsorbAll`](crate::AbsorbAll) takes
98/// every operand by reference already, so `F: AbsorbAll<F>` is a single bound with no higher
99/// ranked part and gives the same arithmetic through methods rather than operators. This trait
100/// stays for code written against the operators.
101pub trait FieldRef<Deref>:
102    // Equivalence relation
103    PartialEq<Self> +
104    Neg<Output=Deref> +  // Additive inverse
105    // First operation
106    Add<Deref, Output=Deref> +
107    Add<Output=Deref> +
108    // First operation inverse
109    Sub<Deref, Output=Deref> +
110    Sub<Output=Deref> +
111    // Second operation
112    Mul<Deref, Output=Deref> +
113    Mul<Output=Deref> +
114    // Second operation inverse
115    Div<Deref, Output=Deref> +
116    Div<Output=Deref> +
117    // TODO: MulAdd should be possible. Only in specialization?
118    //  + MulAdd
119
120    // Practicalities
121    Copy +
122    Clone +
123    Display +
124    Debug +
125    // Necessary for the Add, Sub, Mul and Div traits. References are sized anyways.
126    Sized +
127{}
128impl<Deref, T> FieldRef<Deref> for T where T:
129    // Equivalence relation
130    PartialEq<Self> +
131    Neg<Output=Deref> +  // Additive inverse
132    // First operation
133    Add<Deref, Output=Deref> +
134    Add<Output=Deref> +
135    // First operation inverse
136    Sub<Deref, Output=Deref> +
137    Sub<Output=Deref> +
138    // Second operation
139    Mul<Deref, Output=Deref> +
140    Mul<Output=Deref> +
141    // Second operation inverse
142    Div<Deref, Output=Deref> +
143    Div<Output=Deref> +
144    // TODO: MulAdd should be possible. Only in specialization?
145    //  + MulAdd
146
147    // Practicalities
148    Copy +
149    Clone +
150    Display +
151    Debug +
152    // Necessary for the Add, Sub, Mul and Div traits. References are sized anyways.
153    Sized +
154{}
155
156/// Absolute value of a number.
157///
158/// The default body compares against the additive identity and negates. Types that carry their
159/// sign separately, such as the crate's rational types, override it with a sign field write
160/// and never touch the magnitude. This trait is deliberately not blanket-implemented: a blanket
161/// impl would make that override impossible.
162pub trait Abs: Neg<Output=Self> + Ord + num_traits::Zero {
163    /// The absolute value of a number.
164    ///
165    /// Compute the additive inverse if the number is smaller than the additive identity.
166    fn abs(self) -> Self {
167        if self < Self::zero() {
168            -self
169        } else {
170            self
171        }
172    }
173}
174
175macro_rules! abs_by_negation {
176    ($($t:ty),+ $(,)?) => {$(
177        impl Abs for $t {
178            /// # Panics
179            ///
180            /// In debug builds, when called on the most negative representable value, whose
181            /// absolute value does not fit in the type.
182            #[inline]
183            fn abs(self) -> Self {
184                <$t>::abs(self)
185            }
186        }
187    )+}
188}
189abs_by_negation!(i8, i16, i32, i64, i128, isize);
190
191impl Abs for crate::fixed::Zero {
192    #[inline]
193    fn abs(self) -> Self {
194        self
195    }
196}
197
198/// Helper macro for tests.
199#[macro_export]
200macro_rules! F {
201    ($value:expr) => {
202        {
203            <F as $crate::FromPrimitive>::from_f64($value as f64).unwrap()
204        }
205    };
206}