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}