Skip to main content

adic/math/normed/
valuation.rs

1use std::{
2    cmp::Ordering,
3    fmt::{Debug, Display, Formatter, Result as fmtResult},
4    hash::Hash,
5    ops,
6};
7use num::Zero;
8use super::ValuationRing;
9
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
12#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
13/// Represents valuations of ultrametric numbers
14///
15/// In the digital representation,
16///  this is the number of digits between decimal point and first nonzero digit,
17///  possibly negative.
18/// This struct can also be used to represent certainty.
19/// E.g.
20///
21/// ```
22/// # use adic::{normed::{UltraNormed, Valuation}, traits::{AdicPrimitive, HasApproximateDigits}, QAdic, UAdic, ZAdic};
23/// let z = ZAdic::new_approx(5, 6, vec![0, 0, 3, 1, 2, 4]);
24/// assert_eq!(Valuation::Finite(2), z.valuation());
25/// assert_eq!(Valuation::Finite(6), z.certainty());
26/// assert_eq!(Valuation::Finite(0), ZAdic::empty(5).valuation());
27/// assert_eq!(Valuation::Finite(0), ZAdic::empty(5).certainty());
28/// assert_eq!(Valuation::PosInf, UAdic::new(5, vec![]).valuation());
29/// assert_eq!(Valuation::PosInf, UAdic::new(5, vec![]).certainty());
30/// assert_eq!(Valuation::Finite(0), QAdic::new(UAdic::new(5, vec![1, 2]), 0).valuation());
31/// assert_eq!(Valuation::Finite(2), QAdic::new(UAdic::new(5, vec![1, 2]), 2).valuation());
32/// assert_eq!(Valuation::Finite(-2), QAdic::new(UAdic::new(5, vec![1, 2]), -2).valuation());
33/// assert_eq!(Valuation::Finite(-1), QAdic::new(UAdic::new(5, vec![0, 2]), -2).valuation());
34/// assert_eq!(Valuation::PosInf, QAdic::new(UAdic::zero(5), -2).valuation());
35/// ```
36pub enum Valuation<F>
37where F: ValuationRing {
38    /// Positive infinity, e.g. for the size of zero
39    PosInf,
40    /// Finite valuation
41    Finite(F),
42}
43
44impl<F> Valuation<F>
45where F: ValuationRing {
46
47    /// Return finite value if `Finite` and `None` if `PosInf`
48    pub fn finite(&self) -> Option<F> {
49        if let Self::Finite(v) = self {
50            Some(*v)
51        } else {
52            None
53        }
54    }
55
56    /// Is the valuation finite
57    pub fn is_finite(&self) -> bool {
58        matches!(self, Self::Finite(_))
59    }
60
61    /// Convert from one valuation to another
62    ///
63    /// # Errors
64    /// Error if the conversion attempt fails
65    pub fn convert<G>(self) -> Result<Valuation<G>, G::Error>
66    where G: ValuationRing + TryFrom<F> {
67        match self {
68            Valuation::PosInf => Ok(Valuation::PosInf),
69            Valuation::Finite(fval) => Ok(Valuation::Finite(fval.try_into()?)),
70        }
71    }
72
73}
74
75
76impl<F> From<F> for Valuation<F>
77where F: ValuationRing {
78    fn from(value: F) -> Self {
79        Valuation::Finite(value)
80    }
81}
82
83
84impl<F> Zero for Valuation<F>
85where F: ValuationRing {
86    fn zero() -> Self {
87        Self::Finite(F::zero())
88    }
89    fn is_zero(&self) -> bool {
90        *self == Self::Finite(F::zero())
91    }
92}
93
94
95impl<F> Ord for Valuation<F>
96where F: ValuationRing {
97    fn cmp(&self, other: &Self) -> Ordering {
98        match (self, other) {
99            (Self::PosInf, Self::PosInf) => Ordering::Equal,
100            (Self::PosInf, Self::Finite(_)) => Ordering::Greater,
101            (Self::Finite(_), Self::PosInf) => Ordering::Less,
102            (Self::Finite(sv), Self::Finite(ov)) => {
103                sv.cmp(ov)
104            },
105        }
106    }
107}
108
109impl<F> PartialOrd for Valuation<F>
110where F: ValuationRing {
111    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
112        Some(self.cmp(other))
113    }
114}
115
116
117impl<F> Display for Valuation<F>
118where F: ValuationRing + Display {
119    fn fmt(&self, f: &mut Formatter) -> fmtResult {
120        match self {
121            Self::PosInf => write!(f, "inf"),
122            Self::Finite(v) => write!(f, "{v}")
123        }
124    }
125}
126
127
128impl<F> Default for Valuation<F>
129where F: ValuationRing + Default {
130    fn default() -> Self {
131        Self::Finite(F::default())
132    }
133}
134
135
136impl<F> ops::Add for Valuation<F>
137where F: ValuationRing {
138    type Output = Self;
139    fn add(self, rhs: Self) -> Self::Output {
140        if let (Self::Finite(sv), Self::Finite(rv)) = (self, rhs) {
141            Self::Finite(sv + rv)
142        } else {
143            Self::PosInf
144        }
145    }
146}
147
148impl<F> ops::Mul for Valuation<F>
149where F: ValuationRing {
150    type Output = Self;
151    fn mul(self, rhs: Self) -> Self::Output {
152        if let (Self::Finite(sv), Self::Finite(rv)) = (self, rhs) {
153            Self::Finite(sv * rv)
154        } else {
155            Self::PosInf
156        }
157    }
158}
159
160impl<F> ops::Neg for Valuation<F>
161where F: ValuationRing + ops::Neg<Output=F> {
162    type Output = Option<Self>;
163    fn neg(self) -> Self::Output {
164        if let Self::Finite(v) = self {
165            Some(Self::Finite(-v))
166        } else {
167            None
168        }
169    }
170}
171
172impl<F> ops::Sub for Valuation<F>
173where F: ValuationRing + ops::Sub<Output=F> {
174    type Output = Option<Self>;
175    fn sub(self, rhs: Self) -> Self::Output {
176        match (self, rhs) {
177            (Self::Finite(sv), Self::Finite(rv)) => Some(Self::Finite(sv - rv)),
178            (Self::PosInf, Self::Finite(_)) => Some(Self::PosInf),
179            _ => None,
180        }
181    }
182}
183
184impl<F> ops::Div for Valuation<F>
185where F: ValuationRing + ops::Div<Output=F> {
186    type Output = Option<Self>;
187    fn div(self, rhs: Self) -> Self::Output {
188        match (self, rhs) {
189            (Self::Finite(sv), Self::Finite(rv)) => Some(Self::Finite(sv / rv)),
190            (Self::PosInf, Self::Finite(rv)) if Self::Finite(rv) > Self::zero() => Some(Self::PosInf),
191            _ => None,
192        }
193    }
194}