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