Skip to main content

feanor_math/
local.rs

1use crate::algorithms::int_bisect;
2use crate::pid::{EuclideanRing, EuclideanRingStore};
3use crate::divisibility::*;
4use crate::primitive_int::StaticRing;
5use crate::ring::*;
6
7///
8/// Trait for principal ideal rings that additionally are local rings, i.e. have a unique
9/// maximal ideal.
10/// 
11/// Note that in this case, the unique maximal ideal is clearly generated by a single element.
12/// Such an element can be accessed via [`PrincipalLocalRing::max_ideal_gen()`]. Equivalently,
13/// a principal local ring can be characterized by the property that for any elements `x, y`,
14/// either `x | y` or `y | x`.
15/// 
16/// Principal local rings are also valuation rings, i.e. have a function `val: R -> ZZ_>0 u {∞}`
17/// that satisfies `val(xy) = val(x) + val(y)`, `val(x + y) >= min(val(x), val(y))` and if `val(x) >= val(y)`
18/// then `y | x`. This can be accessed using [`PrincipalLocalRing::valuation()`].
19/// 
20#[stability::unstable(feature = "enable")]
21pub trait PrincipalLocalRing: EuclideanRing {
22
23    ///
24    /// Returns a generator `p` or the unique maximal ideal `(p)` of this ring.
25    /// 
26    /// In other words, for each element `x` we have either that `p | x` or `x | 1`. 
27    /// 
28    fn max_ideal_gen(&self) -> &Self::Element;
29
30    ///
31    /// Returns the smallest nonnegative integer `e` such that `p^e = 0` where `p` is 
32    /// the generator of the maximal ideal.
33    /// 
34    fn nilpotent_power(&self) -> Option<usize>;
35
36    ///
37    /// Returns the largest nonnegative integer `e` such that `p^e | x` where `p` is 
38    /// the generator of the maximal ideal.
39    /// 
40    fn valuation(&self, x: &Self::Element) -> Option<usize> {
41        assert!(self.is_noetherian());
42        if self.is_zero(x) {
43            return None;
44        }
45        let ring = RingRef::new(self);
46        return Some(int_bisect::find_root_floor(&StaticRing::<i64>::RING, 0, |e| {
47            if *e < 0 || ring.checked_div(x, &ring.pow(ring.clone_el(ring.max_ideal_gen()), *e as usize)).is_some() {
48                -1
49            } else {
50                1
51            }
52        }) as usize)
53    }
54}
55
56///
57/// [`RingStore`] for [`PrincipalLocalRing`]
58/// 
59#[stability::unstable(feature = "enable")]
60pub trait PrincipalLocalRingStore: EuclideanRingStore
61    where Self::Type: PrincipalLocalRing
62{
63    delegate!{ PrincipalLocalRing, fn max_ideal_gen(&self) -> &El<Self> }
64    delegate!{ PrincipalLocalRing, fn valuation(&self, x: &El<Self>) -> Option<usize> }
65    delegate!{ PrincipalLocalRing, fn nilpotent_power(&self) -> Option<usize> }
66}
67
68impl<R> PrincipalLocalRingStore for R
69    where R: RingStore,
70        R::Type: PrincipalLocalRing {}