#![allow(dead_code)]
use std::iter::{once, repeat_with};
use num::Zero;
use crate::{
local_num::LocalOne,
normed::{UltraNormed, Valuation, ValuationRing},
};
use super::Sequence;
#[derive(Debug, Clone)]
pub struct PowerSequence<T>
where T: LocalOne + Clone {
coefficient: T,
term: T,
power: u32,
}
impl<T> PowerSequence<T>
where T: LocalOne + Clone {
pub fn new(coefficient: T, term: T, power: u32) -> Self {
Self {coefficient, term, power}
}
}
impl<T> PowerSequence<T>
where T: LocalOne + Clone + UltraNormed {
pub fn critical_valuation_index<V> (&self, valuation: V) -> Option<usize>
where V: Into<Valuation<T::ValuationRing>> {
use Valuation::{Finite, PosInf};
let converted_power = T::ValuationRing::try_from_u32(self.power).expect("Convert u32 to ValuationRing");
match (valuation.into(), self.coefficient.valuation(), self.term.valuation()) {
(PosInf, _ , _) => None,
(Finite(_v), PosInf, _) => Some(0),
(Finite(_v), Finite(_v_coeff), Finite(v_term)) if ( v_term < T::ValuationRing::zero() && !converted_power.is_zero() ) => None,
(Finite(v), Finite(v_coeff), _) if ( v_coeff >= v ) => Some(0),
(Finite(_v), Finite(_v_coeff), Finite(v_term)) if ( v_term.is_zero() || converted_power.is_zero() ) => None,
(Finite(_v), Finite(_v_coeff), PosInf) => Some(1),
(Finite(v), Finite(v_coeff), Finite(v_term)) => {
let v_diff_coeff = (v - v_coeff).try_into_usize().expect("Convert ValuationRing to usize");
let v_term_power = (v_term * converted_power).try_into_usize().expect("Convert ValuationRing to usize");
Some(v_diff_coeff.div_ceil(v_term_power))
},
}
}
pub fn valuation_at(&self, index: usize) -> Valuation<T::ValuationRing> {
let converted_index = T::ValuationRing::try_from_usize(index).expect("Convert usize to ValuationRing").into();
let converted_power = T::ValuationRing::try_from_u32(self.power).expect("Convert u32 to ValuationRing").into();
self.coefficient.valuation() + self.term.valuation() * converted_index * converted_power
}
}
impl<T> Sequence for PowerSequence<T>
where T: LocalOne + Clone {
type Term = T;
fn terms(&self) -> Box<dyn Iterator<Item = Self::Term> + '_> {
let a = (0..self.power).fold(self.term.local_one(), |acc, _| acc * self.term.clone());
let mut prev_term = self.coefficient.clone();
Box::new(once(prev_term.clone()).chain(repeat_with(move || {
prev_term = prev_term.clone() * a.clone();
prev_term.clone()
})))
}
fn approx_num_terms(&self) -> Option<usize> {
None
}
}
#[cfg(test)]
mod test{
use crate::{
normed::Valuation,
traits::PrimedFrom,
EAdic, QAdic,
};
use super::PowerSequence;
#[test]
fn critical_valuation_index() {
let a = PowerSequence::new(EAdic::primed_from(5, 1), EAdic::primed_from(5, 5), 1);
assert_eq!(a.critical_valuation_index(3), Some(3));
assert_eq!(a.critical_valuation_index(Valuation::PosInf), None);
let a = PowerSequence::new(EAdic::primed_from(5, 0), EAdic::primed_from(5, 5), 1);
assert_eq!(a.critical_valuation_index(0), Some(0));
assert_eq!(a.critical_valuation_index(3), Some(0));
let a = PowerSequence::new(EAdic::primed_from(5, 25), EAdic::primed_from(5, 5), 1);
assert_eq!(a.critical_valuation_index(0), Some(0));
assert_eq!(a.critical_valuation_index(1), Some(0));
assert_eq!(a.critical_valuation_index(2), Some(0));
assert_eq!(a.critical_valuation_index(3), Some(1));
assert_eq!(a.critical_valuation_index(4), Some(2));
assert_eq!(a.critical_valuation_index(5), Some(3));
assert_eq!(a.critical_valuation_index(6), Some(4));
let a = PowerSequence::new(EAdic::primed_from(5, 25), EAdic::primed_from(5, 0), 1);
assert_eq!(a.critical_valuation_index(0), Some(0));
assert_eq!(a.critical_valuation_index(1), Some(0));
assert_eq!(a.critical_valuation_index(2), Some(0));
assert_eq!(a.critical_valuation_index(3), Some(1));
assert_eq!(a.critical_valuation_index(4), Some(1));
assert_eq!(a.critical_valuation_index(5), Some(1));
let a = PowerSequence::new(EAdic::primed_from(5, 25), EAdic::primed_from(5, 6), 1);
assert_eq!(a.critical_valuation_index(3), None);
let a = PowerSequence::new(EAdic::primed_from(5, 25), EAdic::primed_from(5, 5), 0);
assert_eq!(a.critical_valuation_index(3), None);
let a = PowerSequence::new(EAdic::primed_from(5, 25), EAdic::primed_from(5, 5), 2);
assert_eq!(a.critical_valuation_index(0), Some(0));
assert_eq!(a.critical_valuation_index(1), Some(0));
assert_eq!(a.critical_valuation_index(2), Some(0));
assert_eq!(a.critical_valuation_index(3), Some(1));
assert_eq!(a.critical_valuation_index(4), Some(1));
assert_eq!(a.critical_valuation_index(5), Some(2));
assert_eq!(a.critical_valuation_index(6), Some(2));
assert_eq!(a.critical_valuation_index(7), Some(3));
assert_eq!(a.critical_valuation_index(8), Some(3));
assert_eq!(a.critical_valuation_index(9), Some(4));
assert_eq!(a.critical_valuation_index(10), Some(4));
assert_eq!(a.critical_valuation_index(11), Some(5));
let zero = QAdic::new(EAdic::primed_from(5, 0), 0);
let one = QAdic::new(EAdic::primed_from(5, 1), 0);
let five = QAdic::new(EAdic::primed_from(5, 1), 1);
let one_fifth = QAdic::new(EAdic::primed_from(5, 1), -1);
let one_twenty_fifth = QAdic::new(EAdic::primed_from(5, 1), -2);
let a = PowerSequence::new(one, one_fifth.clone(), 1);
assert_eq!(a.critical_valuation_index(0), None);
assert_eq!(a.critical_valuation_index(1), None);
assert_eq!(a.critical_valuation_index(2), None);
let a = PowerSequence::new(zero, one_fifth.clone(), 1);
assert_eq!(a.critical_valuation_index(0), Some(0));
let a = PowerSequence::new(five.clone(), one_fifth, 0);
assert_eq!(a.critical_valuation_index(0), Some(0));
assert_eq!(a.critical_valuation_index(1), Some(0));
assert_eq!(a.critical_valuation_index(2), None);
let a = PowerSequence::new(one_twenty_fifth.clone(), five.clone(), 1);
assert_eq!(a.critical_valuation_index(-3), Some(0));
assert_eq!(a.critical_valuation_index(-2), Some(0));
assert_eq!(a.critical_valuation_index(-1), Some(1));
assert_eq!(a.critical_valuation_index(0), Some(2));
assert_eq!(a.critical_valuation_index(1), Some(3));
assert_eq!(a.critical_valuation_index(2), Some(4));
let a = PowerSequence::new(one_twenty_fifth.clone(), five.clone(), 2);
assert_eq!(a.critical_valuation_index(-3), Some(0));
assert_eq!(a.critical_valuation_index(-2), Some(0));
assert_eq!(a.critical_valuation_index(-1), Some(1));
assert_eq!(a.critical_valuation_index(0), Some(1));
assert_eq!(a.critical_valuation_index(1), Some(2));
assert_eq!(a.critical_valuation_index(2), Some(2));
}
}