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