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
13pub mod factorization;
14
15/// The simplex algorithm is defined over the ordered fields.
16///
17/// All methods containing algorithmic logic should be defined to work an ordered field (or a field,
18/// if they don't need the ordering). All methods representing a matrix should be defined over a
19/// field, because they don't need the additional ordering.
20pub trait OrderedField: Ord + NonZeroSigned + Field + Sized {}
21impl<T: Ord + NonZeroSigned + Field + Sized> OrderedField for T {}
22
23/// A reference to an ordered field.
24pub trait OrderedFieldRef<Deref>: Ord + FieldRef<Deref> {}
25impl<Deref, T: Ord + FieldRef<Deref>> OrderedFieldRef<Deref> for T {}
26
27/// Basic field operations with Self and with references to Self.
28pub trait Field:
29    PartialEq + // Equivalence relation
30    Eq +
31    PartialOrd +
32    num_traits::Zero + // Additive identity
33    Neg<Output=Self> + // Additive inverse
34    num_traits::One + // Multiplicative identity
35    // First operation
36    Add<Self, Output=Self> +
37    for<'r> Add<&'r Self, Output=Self> +
38    AddAssign<Self> +
39    for<'r> AddAssign<&'r Self> +
40    Sum +
41    // First operation inverse
42    Sub<Self, Output=Self> +
43    for<'r> Sub<&'r Self, Output=Self> +
44    SubAssign<Self> +
45    for<'r> SubAssign<&'r Self> +
46    // Second operation
47    Mul<Self, Output=Self> +
48    for<'r> Mul<&'r Self, Output=Self> +
49    MulAssign<Self> +
50    for<'r> MulAssign<&'r Self> +
51    // Second operation inverse
52    Div<Self, Output=Self> +
53    for<'r> Div<&'r Self, Output=Self> +
54    DivAssign<Self> +
55    for<'r> DivAssign<&'r Self> +
56    // TODO: MulAdd should be possible. Only in specialization?
57    //  + MulAdd
58
59    // Practicalities
60    Clone +
61    Display +
62    ToString +
63    Debug +
64{}
65impl<T> Field for T where T:
66    PartialEq + // Equivalence relation
67    Eq +
68    PartialOrd +
69    num_traits::Zero + // Additive identity
70    Neg<Output=Self> + // Additive inverse
71    num_traits::One + // Multiplicative identity
72    // First operation
73    Add<Self, Output=Self> +
74    for<'r> Add<&'r Self, Output=Self> +
75    AddAssign<Self> +
76    for<'r> AddAssign<&'r Self> +
77    Sum +
78    // First operation inverse
79    Sub<Self, Output=Self> +
80    for<'r> Sub<&'r Self, Output=Self> +
81    SubAssign<Self> +
82    for<'r> SubAssign<&'r Self> +
83    // Second operation
84    Mul<Self, Output=Self> +
85    for<'r> Mul<&'r Self, Output=Self> +
86    MulAssign<Self> +
87    for<'r> MulAssign<&'r Self> +
88    // Second operation inverse
89    Div<Self, Output=Self> +
90    for<'r> Div<&'r Self, Output=Self> +
91    DivAssign<Self> +
92    for<'r> DivAssign<&'r Self> +
93    // TODO: MulAdd should be possible. Only in specialization?
94    //  + MulAdd
95
96    // Practicalities
97    Clone +
98    Display +
99    ToString +
100    Debug +
101{}
102
103/// A reference to a variable that is in a `Field`.
104///
105/// TODO: Can less HRTB be used? Can the be written down less often? Can this trait be integrated
106///  with the `Field` trait?
107pub trait FieldRef<Deref>:
108    // Equivalence relation
109    PartialEq<Self> +
110    Neg<Output=Deref> +  // Additive inverse
111    // First operation
112    Add<Deref, Output=Deref> +
113    Add<Output=Deref> +
114    // First operation inverse
115    Sub<Deref, Output=Deref> +
116    Sub<Output=Deref> +
117    // Second operation
118    Mul<Deref, Output=Deref> +
119    Mul<Output=Deref> +
120    // Second operation inverse
121    Div<Deref, Output=Deref> +
122    Div<Output=Deref> +
123    // TODO: MulAdd should be possible. Only in specialization?
124    //  + MulAdd
125
126    // Practicalities
127    Copy +
128    Clone +
129    Display +
130    Debug +
131    // Necessary for the Add, Sub, Mul and Div traits. References are sized anyways.
132    Sized +
133{}
134impl<Deref, T> FieldRef<Deref> for T where T:
135    // Equivalence relation
136    PartialEq<Self> +
137    Neg<Output=Deref> +  // Additive inverse
138    // First operation
139    Add<Deref, Output=Deref> +
140    Add<Output=Deref> +
141    // First operation inverse
142    Sub<Deref, Output=Deref> +
143    Sub<Output=Deref> +
144    // Second operation
145    Mul<Deref, Output=Deref> +
146    Mul<Output=Deref> +
147    // Second operation inverse
148    Div<Deref, Output=Deref> +
149    Div<Output=Deref> +
150    // TODO: MulAdd should be possible. Only in specialization?
151    //  + MulAdd
152
153    // Practicalities
154    Copy +
155    Clone +
156    Display +
157    Debug +
158    // Necessary for the Add, Sub, Mul and Div traits. References are sized anyways.
159    Sized +
160{}
161
162/// Absolute value of a number.
163///
164/// Automatically implemented for all types satisfying the trait's bounds.
165pub trait Abs: Neg<Output=Self> + Ord + num_traits::Zero {
166    /// The absolute value of a number.
167    ///
168    /// Compute the additive inverse if the number is smaller than the additive identity.
169    fn abs(self) -> Self {
170        if self < Self::zero() {
171            -self
172        } else {
173            self
174        }
175    }
176}
177impl<T: Neg<Output=Self> + Ord + num_traits::Zero> Abs for T {
178}
179
180/// Helper macro for tests.
181#[macro_export]
182macro_rules! F {
183    ($value:expr) => {
184        {
185            <F as $crate::FromPrimitive>::from_f64($value as f64).unwrap()
186        }
187    };
188}