use super::functions::*;
use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, Level, Name};
pub struct PAdicValuation {
pub p: u64,
}
impl PAdicValuation {
pub fn new(p: u64) -> Self {
Self { p }
}
pub fn valuation_of(&self, n: i64) -> i64 {
if n == 0 {
return i64::MAX;
}
let mut k = 0i64;
let mut m = n.unsigned_abs();
while m % self.p == 0 {
m /= self.p;
k += 1;
}
k
}
pub fn is_ultrametric(&self) -> bool {
true
}
}
pub struct PolynomialMod {
pub coeffs: Vec<i64>,
pub modulus: u64,
}
impl PolynomialMod {
pub fn new(coeffs: Vec<i64>, modulus: u64) -> Self {
Self { coeffs, modulus }
}
pub fn evaluate(&self, x: i64) -> i64 {
let m = self.modulus as i64;
let mut result = 0i64;
let mut power = 1i64;
for &c in &self.coeffs {
result = (result + c.wrapping_mul(power)) % m;
power = power.wrapping_mul(x) % m;
}
((result % m) + m) % m
}
pub fn derivative(&self) -> Self {
if self.coeffs.is_empty() {
return Self::new(vec![], self.modulus);
}
let d: Vec<i64> = self
.coeffs
.iter()
.enumerate()
.skip(1)
.map(|(i, &c)| c.wrapping_mul(i as i64))
.collect();
Self::new(d, self.modulus)
}
}
pub struct IwasawaAlgebra {
pub p: u64,
pub group_ring: String,
}
impl IwasawaAlgebra {
pub fn new(p: u64) -> Self {
Self {
p,
group_ring: format!("ā¤_{p}[[Ī]]"),
}
}
pub fn is_noetherian(&self) -> bool {
true
}
pub fn krull_dimension(&self) -> usize {
2
}
}
pub struct PAdicNumberV2 {
pub p: u64,
pub digits: Vec<u64>,
pub valuation: i64,
}
impl PAdicNumberV2 {
pub fn new(p: u64, digits: Vec<u64>, valuation: i64) -> Self {
Self {
p,
digits,
valuation,
}
}
pub fn norm(&self) -> f64 {
if self.valuation == i64::MAX {
return 0.0;
}
(self.p as f64).powi(-(self.valuation as i32))
}
pub fn is_unit(&self) -> bool {
self.valuation == 0
}
pub fn is_integer(&self) -> bool {
self.valuation >= 0
}
}
pub struct MahlerExpansion {
pub coefficients: Vec<f64>,
}
impl MahlerExpansion {
pub fn new(coefficients: Vec<f64>) -> Self {
Self { coefficients }
}
pub fn evaluate_at_integer(&self, n: i64) -> f64 {
let mut result = 0.0f64;
for (k, &ak) in self.coefficients.iter().enumerate() {
if k as i64 > n {
break;
}
let binom = binomial_f64(n, k);
result += ak * binom;
}
result
}
}
pub struct PAdicValuationRing {
pub p: u64,
}
impl PAdicValuationRing {
pub fn new(p: u64) -> Self {
Self { p }
}
pub fn contains(&self, x: &PAdicNumber) -> bool {
x.is_integer()
}
}
pub struct LocalField {
pub p: u64,
pub residue_char: u64,
pub degree: usize,
pub ramification_index: usize,
pub inertia_degree: usize,
}
impl LocalField {
pub fn new(p: u64, e: usize, f: usize) -> Self {
Self {
p,
residue_char: p,
degree: e * f,
ramification_index: e,
inertia_degree: f,
}
}
pub fn discriminant_valuation(&self) -> i64 {
let e = self.ramification_index as i64;
let p = self.p as i64;
let mut vp_e = 0i64;
let mut tmp = e;
while tmp % p == 0 {
tmp /= p;
vp_e += 1;
}
(e - 1) + vp_e
}
pub fn is_tamely_ramified(&self) -> bool {
let e = self.ramification_index as u64;
e > 1 && e % self.p != 0
}
pub fn is_wildly_ramified(&self) -> bool {
let e = self.ramification_index as u64;
e % self.p == 0 && e > 1
}
}
pub struct VolkenbornIntegral {
pub p: u64,
}
impl VolkenbornIntegral {
pub fn new(p: u64) -> Self {
Self { p }
}
pub fn finite_sum_approximation(&self, poly: &[f64], precision: u32) -> f64 {
let pn = (self.p as f64).powi(precision as i32);
let n = (self.p as usize).pow(precision);
let sum: f64 = (0..n).map(|j| evaluate_poly(poly, j as f64)).sum();
sum / pn
}
pub fn normalizes_to_one(&self) -> bool {
true
}
pub fn bernoulli_connection_statement(&self) -> String {
format!(
"ā«_{{ā¤_{}}} x^n dx_{} = B_n (the n-th Bernoulli number), \
relating the Volkenborn integral to special values of the Riemann zeta function.",
self.p, self.p
)
}
}
pub struct ProfiniteGroup {
pub name: String,
pub index_list: Vec<u64>,
}
impl ProfiniteGroup {
pub fn new(name: impl Into<String>) -> Self {
Self {
name: name.into(),
index_list: vec![],
}
}
pub fn is_pro_p(&self, p: u64) -> bool {
self.index_list.iter().all(|&idx| {
let mut n = idx;
while n > 1 {
if n % p != 0 {
return false;
}
n /= p;
}
true
})
}
pub fn is_abelian(&self) -> bool {
true
}
}
pub struct PAdicInteger {
pub p: u64,
pub digits: Vec<u64>,
}
impl PAdicInteger {
pub fn new(p: u64, n: i64) -> Self {
assert!(p >= 2, "p must be at least 2");
if n <= 0 {
return Self { p, digits: vec![0] };
}
let mut rem = n as u64;
let mut digits = Vec::new();
while rem > 0 {
digits.push(rem % p);
rem /= p;
}
Self { p, digits }
}
pub fn zero(p: u64) -> Self {
Self { p, digits: vec![0] }
}
pub fn one(p: u64) -> Self {
Self { p, digits: vec![1] }
}
pub fn from_digits(p: u64, digits: Vec<u64>) -> Self {
Self { p, digits }
}
}
pub struct ZpStar {
pub p: u64,
}
impl ZpStar {
pub fn new(p: u64) -> Self {
Self { p }
}
pub fn order(&self) -> Option<u64> {
None
}
pub fn generators(&self) -> Vec<u64> {
if self.p == 2 {
vec![3]
} else {
let primitive_root = (2..self.p)
.find(|&g| {
let mut seen = std::collections::HashSet::new();
let mut x = 1u64;
for _ in 0..self.p - 1 {
x = (x * g) % self.p;
seen.insert(x);
}
seen.len() == (self.p - 1) as usize
})
.unwrap_or(2);
vec![primitive_root, 1 + self.p]
}
}
}
pub struct PAdicBall {
pub center: PAdicNumber,
pub radius: f64,
}
impl PAdicBall {
pub fn new(center: PAdicNumber, radius: f64) -> Self {
Self { center, radius }
}
pub fn contains(&self, x: &PAdicNumber) -> bool {
let diff_val = x.valuation.min(self.center.valuation);
let dist = (x.numerator.p as f64).powi(-diff_val as i32);
dist < self.radius
}
pub fn is_open(&self) -> bool {
true
}
}
pub struct WittVector {
pub p: u64,
pub components: Vec<i64>,
}
impl WittVector {
pub fn new(p: u64, n: usize) -> Self {
Self {
p,
components: vec![0; n],
}
}
pub fn ghost_components(&self) -> Vec<i64> {
let n = self.components.len();
(0..n)
.map(|m| {
self.components
.iter()
.enumerate()
.take(m + 1)
.map(|(k, &x)| {
let pk = (self.p as i64).pow(k as u32);
let exp = (self.p as u32).pow((m - k) as u32);
pk * x.pow(exp)
})
.sum()
})
.collect()
}
pub fn from_integer(p: u64, x: i64) -> Self {
Self {
p,
components: vec![x],
}
}
}
pub struct IntegralExtension {
pub base: String,
pub degree: u64,
}
impl IntegralExtension {
pub fn new(base: String, degree: u64) -> Self {
Self { base, degree }
}
pub fn is_totally_ramified(&self) -> bool {
self.degree > 1
}
pub fn is_unramified(&self) -> bool {
self.degree == 1
}
}
pub struct PAdicDifferentialEquation {
pub p: u64,
pub rank: usize,
}
impl PAdicDifferentialEquation {
pub fn new(p: u64, rank: usize) -> Self {
Self { p, rank }
}
pub fn dworks_theorem_statement(&self) -> String {
format!(
"Dwork's Theorem: A rank-{} p-adic differential equation over the Robba ring \
R_{{p = {}}} is solvable (has a full set of solutions in the Robba ring) \
if and only if its Newton polygon has slopes in ā¤_p.",
self.rank, self.p
)
}
pub fn monodromy_theorem_statement(&self) -> String {
format!(
"p-adic Monodromy Theorem (Berger, 2002): Every de Rham p-adic representation \
of Gal(āĢ_p/ā_p) on a rank-{} Q_{}-vector space is potentially semistable \
(becomes semistable over a finite extension).",
self.rank, self.p
)
}
pub fn frobenius_structure_statement(&self) -> String {
format!(
"A Frobenius structure on a rank-{} differential module over ā_{} is an \
isomorphism Ļ*M ā
M of differential modules, where Ļ is the Frobenius \
endomorphism (x ⦠x^p). Such a structure is unique when it exists.",
self.rank, self.p
)
}
}
pub struct PAdicLogarithm {
pub p: u64,
}
impl PAdicLogarithm {
pub fn new(p: u64) -> Self {
Self { p }
}
pub fn converges_on(&self, x: f64) -> bool {
(1.0 - x).abs() < 1.0
}
pub fn log_p(&self, x: f64) -> f64 {
let u = 1.0 - x;
let mut sum = 0.0f64;
let mut power = u;
for n in 1u32..=50 {
sum -= power / n as f64;
power *= u;
}
sum
}
}
pub struct IwasawaModule {
pub algebra: IwasawaAlgebra,
pub rank: usize,
pub torsion: String,
}
impl IwasawaModule {
pub fn new(algebra: IwasawaAlgebra, rank: usize, torsion: String) -> Self {
Self {
algebra,
rank,
torsion,
}
}
pub fn structural_theorem_statement(&self) -> String {
format!(
"Every finitely generated module M over the Iwasawa algebra Ī = {} is \
pseudo-isomorphic to Ī^r ā (ā Ī/(f_i)) ā (ā Ī/(p^{{n_j}})) where r = {} \
is the rank and the torsion part is described by {}.",
self.algebra.group_ring, self.rank, self.torsion
)
}
}
pub struct PAdicBanachSpace {
pub p: u64,
pub description: String,
pub is_separable: bool,
}
impl PAdicBanachSpace {
pub fn new(p: u64, description: impl Into<String>, is_separable: bool) -> Self {
Self {
p,
description: description.into(),
is_separable,
}
}
pub fn is_complete(&self) -> bool {
true
}
pub fn mahler_basis_orthonormal(&self) -> bool {
true
}
pub fn banach_steinhaus_statement(&self) -> String {
format!(
"Banach-Steinhaus for p-adic Banach spaces: If {{T_n}} is a sequence of \
continuous linear maps on {} that is pointwise bounded, then {{T_n}} is \
equicontinuous (uniformly bounded in operator norm).",
self.description
)
}
}
pub struct OverconvergentFunctions {
pub p: u64,
pub overconvergence_radius: f64,
}
impl OverconvergentFunctions {
pub fn new(p: u64, overconvergence_radius: f64) -> Self {
Self {
p,
overconvergence_radius,
}
}
pub fn is_subspace_of_formal_series(&self) -> bool {
true
}
pub fn robba_ring_statement(&self) -> String {
format!(
"The Robba ring R_p = āŖ_{{r>0}} A_{{p,r}} is the ring of overconvergent \
functions for p = {}: power series convergent on some annulus \
(p^{{-r}} < |x|_p ⤠1). It is the natural setting for p-adic \
differential equations and (Ļ, Ī)-modules.",
self.p
)
}
}
pub struct ColemanPowerSeries {
pub p: u64,
pub series_coefficients: Vec<f64>,
}
impl ColemanPowerSeries {
pub fn new(p: u64, series_coefficients: Vec<f64>) -> Self {
Self {
p,
series_coefficients,
}
}
pub fn colemans_theorem_statement(&self) -> String {
format!(
"Coleman's Theorem (1979): Let (u_n) be a norm-compatible sequence in \
ā¤_{}^Ć (i.e. N_{{K_n/K_{{n-1}}}}(u_n) = u_{{n-1}}). Then there exists a \
unique power series f ā ā¤_{}[[T]]^Ć such that f(ζ_{{p^n}} - 1) = u_n \
for all n, where ζ_{{p^n}} is a primitive p^n-th root of unity.",
self.p, self.p
)
}
pub fn evaluate_at(&self, t: f64) -> f64 {
evaluate_poly(&self.series_coefficients, t)
}
pub fn converges_on_unit_disk(&self) -> bool {
true
}
}
pub struct TeichmullerRepresentative {
pub p: u64,
pub residue: u64,
}
impl TeichmullerRepresentative {
pub fn new(p: u64, residue: u64) -> Self {
assert!(p >= 2, "p must be prime");
assert!(residue > 0 && residue < p, "residue must be in 1..p-1");
Self { p, residue }
}
pub fn is_root_of_unity(&self) -> bool {
true
}
}
pub struct PAdicAbsoluteValue {
pub p: u64,
}
impl PAdicAbsoluteValue {
pub fn new(p: u64) -> Self {
Self { p }
}
pub fn evaluate(&self, n: i64) -> f64 {
if n == 0 {
return 0.0;
}
let mut m = n.unsigned_abs();
let mut val = 0i32;
while m % self.p == 0 {
m /= self.p;
val += 1;
}
(self.p as f64).powi(-val)
}
pub fn ultrametric_inequality(&self) -> bool {
true
}
}
pub struct MahlerTransform {
pub coefficients: Vec<f64>,
pub p: u64,
}
impl MahlerTransform {
pub fn new(p: u64, coefficients: Vec<f64>) -> Self {
Self { coefficients, p }
}
pub fn mahler_coefficient(&self, k: usize) -> f64 {
if k >= self.coefficients.len() {
return 0.0;
}
let mut result = 0.0f64;
for j in 0..=k {
let binom = mahler_binomial(k as i64, j);
let sign = if (k - j) % 2 == 0 { 1.0 } else { -1.0 };
let fj = if j < self.coefficients.len() {
self.coefficients[j]
} else {
0.0
};
result += sign * binom * fj;
}
result
}
pub fn is_bijection_onto_null_sequences(&self) -> bool {
true
}
pub fn characteristic_series_description(&self) -> String {
format!(
"The characteristic series of the Iwasawa module associated to the \
Mahler expansion with {} coefficients: Char_Ī(M) ā Ī.",
self.coefficients.len()
)
}
}
pub struct RigidAnalyticSpace {
pub p: u64,
pub dimension: usize,
pub description: String,
}
impl RigidAnalyticSpace {
pub fn new(p: u64, dimension: usize, description: impl Into<String>) -> Self {
Self {
p,
dimension,
description: description.into(),
}
}
pub fn is_separated(&self) -> bool {
true
}
pub fn gaga_statement(&self) -> String {
format!(
"Rigid GAGA: For a proper rigid analytic space X over ā_{} of dimension {}, \
the categories of coherent algebraic sheaves and coherent analytic sheaves \
are equivalent (Kiehl's theorem).",
self.p, self.dimension
)
}
}
pub struct LocallyAnalyticFunctions {
pub p: u64,
pub target: String,
}
impl LocallyAnalyticFunctions {
pub fn new(p: u64, target: impl Into<String>) -> Self {
Self {
p,
target: target.into(),
}
}
pub fn dense_in_continuous(&self) -> bool {
true
}
pub fn locally_analytic_rep_statement(&self) -> String {
format!(
"A locally analytic representation of G (a p-adic Lie group) on {} \
is a continuous representation such that every orbit map g ⦠Ļ(g)v \
is locally analytic (i.e. locally given by a convergent power series in p-adic coordinates).",
self.target
)
}
}
pub struct PAdicDistributions {
pub p: u64,
}
impl PAdicDistributions {
pub fn new(p: u64) -> Self {
Self { p }
}
pub fn is_locally_convex(&self) -> bool {
true
}
pub fn amice_transform_statement(&self) -> String {
format!(
"The Amice transform A : D(ā¤_{}, ā_{}) ā ā_{}[[T]] sends a distribution μ \
to its generating series A(μ)(T) = ⫠(1+T)^x dμ(x). \
This gives an isomorphism of Ī-modules.",
self.p, self.p, self.p
)
}
}
pub struct KubotaLeopoldt {
pub p: u64,
pub conductor: u64,
}
impl KubotaLeopoldt {
pub fn new(p: u64, conductor: u64) -> Self {
Self { p, conductor }
}
pub fn interpolation_statement(&self) -> String {
format!(
"The Kubota-Leopoldt p-adic L-function L_{}(s, Ļ) for a Dirichlet character Ļ \
of conductor {} satisfies the interpolation formula: \
L_{}(1-n, Ļ) = (1 - ĻĻ^{{-n}}(p)p^{{n-1}}) Ā· L(1-n, ĻĻ^{{-n}}) \
for positive integers n, where Ļ is the Teichmüller character.",
self.p, self.conductor, self.p
)
}
pub fn is_padic_analytic(&self) -> bool {
true
}
}
pub struct LubinTateFormalGroup {
pub p: u64,
pub q: u64,
}
impl LubinTateFormalGroup {
pub fn new(p: u64, q: u64) -> Self {
Self { p, q }
}
pub fn formal_group_law_description(&self) -> String {
format!(
"The Lubin-Tate formal group F associated to uniformizer Ļ (norm q = {}) \
satisfies F(X, Y) ā” X + Y (mod degree 2) and [Ļ]_F(X) ā” ĻX (mod degree 2), \
with [Ļ]_F(X) = X^q + ĻX (the distinguished endomorphism).",
self.q
)
}
pub fn formal_exponential_statement(&self) -> String {
format!(
"The formal exponential exp_F : pā¤_{} ā m_K of the Lubin-Tate formal group \
converges on the maximal ideal and provides an isomorphism of formal groups \
between the additive formal group G_a and F over pā¤_{}.",
self.p, self.p
)
}
pub fn formal_logarithm_statement(&self) -> String {
format!(
"The formal logarithm log_F : m_K ā pā¤_{} of the Lubin-Tate formal group \
is the functional inverse of exp_F. Together they give the p-adic logarithm \
on the group of principal units (1 + m_K) ā
K via the Lubin-Tate theory.",
self.p
)
}
pub fn local_cft_via_lubin_tate(&self) -> String {
format!(
"Lubin-Tate theory: The torsion points F[Ļ^n] of the Lubin-Tate formal group \
generate the totally ramified abelian extensions of K (local field with \
residue characteristic p = {}). The local Artin map sends Ļ to the \
Frobenius in Gal(K^{{ab}}/K).",
self.p
)
}
}
pub struct AffinoidSpace {
pub p: u64,
pub tate_algebra: TateAlgebra,
pub ideal_description: String,
}
impl AffinoidSpace {
pub fn new(p: u64, n: usize, ideal_description: impl Into<String>) -> Self {
Self {
p,
tate_algebra: TateAlgebra::new(p, n),
ideal_description: ideal_description.into(),
}
}
pub fn is_noetherian(&self) -> bool {
true
}
}
pub struct WeierstrausPrepTheorem {
pub p: u64,
pub degree: usize,
}
impl WeierstrausPrepTheorem {
pub fn new(p: u64, degree: usize) -> Self {
Self { p, degree }
}
pub fn factorization_exists(&self) -> bool {
true
}
pub fn statement(&self) -> String {
format!(
"Weierstrass Preparation Theorem: Every f ā ā¤_{}[[T]] not divisible by p \
factors uniquely as f = u Ā· P where u ā ā¤_{}[[T]]^Ć is a unit \
and P is a Weierstrass polynomial of degree {}.",
self.p, self.p, self.degree
)
}
pub fn factorization_is_unique(&self) -> bool {
true
}
}
pub struct PAdicLieGroup {
pub p: u64,
pub dimension: usize,
}
impl PAdicLieGroup {
pub fn new(p: u64, dimension: usize) -> Self {
Self { p, dimension }
}
pub fn is_compact(&self) -> bool {
true
}
pub fn is_abelian(&self) -> bool {
self.dimension <= 1
}
}
pub struct IwasawaInvariants {
pub p: u64,
pub mu_invariant: i64,
pub lambda_invariant: usize,
}
impl IwasawaInvariants {
pub fn new(p: u64, mu: i64, lambda: usize) -> Self {
Self {
p,
mu_invariant: mu,
lambda_invariant: lambda,
}
}
pub fn mu_zero_conjecture_statement(&self) -> String {
format!(
"Iwasawa's μ-conjecture: For p = {} and all primitive Dirichlet characters Ļ, \
the p-adic L-function L_p(s, Ļ) has μ-invariant = 0 (i.e. no factor of p \
in the characteristic power series), and Ī»-invariant = {} (number of zeros).",
self.p, self.lambda_invariant
)
}
}
pub struct TateAlgebra {
pub p: u64,
pub num_vars: usize,
}
impl TateAlgebra {
pub fn new(p: u64, num_vars: usize) -> Self {
Self { p, num_vars }
}
pub fn is_noetherian(&self) -> bool {
true
}
pub fn is_ufd(&self) -> bool {
true
}
pub fn krull_dimension(&self) -> usize {
self.num_vars
}
pub fn polydisk_statement(&self) -> String {
format!(
"The Tate algebra ā_{}āØX_1, ā¦, X_{}ā© consists of power series \
ā_{{ν}} a_ν X^ν that converge on the closed unit polydisk \
{{(x_1, ā¦, x_{}) : |x_i|_p ⤠1}}. It is the ring of analytic \
functions on the closed polydisk.",
self.p, self.num_vars, self.num_vars
)
}
}
pub struct StickelbergerThm {
pub prime: u64,
}
impl StickelbergerThm {
pub fn new(prime: u64) -> Self {
Self { prime }
}
pub fn annihilates_class_group(&self) -> String {
format!(
"The Stickelberger element Īø = ā_{{a=1}}^{{{}ā1}} (a/{}) Ļ_a^{{ā1}} annihilates the class group of ā(ζ_{}) (Stickelberger's theorem).",
self.prime, self.prime, self.prime
)
}
}
pub struct NewtonPolygon {
pub polynomial: PolynomialMod,
pub vertices: Vec<(i64, i64)>,
}
impl NewtonPolygon {
pub fn new(poly: PolynomialMod) -> Self {
let p = poly.modulus;
let vertices: Vec<(i64, i64)> = poly
.coeffs
.iter()
.enumerate()
.filter(|(_, &c)| c != 0)
.map(|(i, &c)| {
let mut val = 0i64;
let mut m = c.unsigned_abs();
while p > 1 && m % p == 0 {
m /= p;
val += 1;
}
(i as i64, val)
})
.collect();
Self {
polynomial: poly,
vertices,
}
}
pub fn slopes(&self) -> Vec<f64> {
if self.vertices.len() < 2 {
return vec![];
}
self.vertices
.windows(2)
.map(|w| {
let (d1, v1) = w[0];
let (d2, v2) = w[1];
let dd = (d2 - d1) as f64;
if dd == 0.0 {
0.0
} else {
(v1 - v2) as f64 / dd
}
})
.collect()
}
}
pub struct PAdicLog {
pub p: u64,
}
impl PAdicLog {
pub fn new(p: u64) -> Self {
Self { p }
}
pub fn evaluate_series(&self, x: f64, terms: u32) -> f64 {
let u = 1.0 - x;
let mut sum = 0.0f64;
let mut power = u;
for n in 1..=terms {
sum -= power / n as f64;
power *= u;
}
sum
}
}
pub struct ContinuousCohomology {
pub group: String,
pub module: String,
pub degree: usize,
}
impl ContinuousCohomology {
pub fn new(group: impl Into<String>, module: impl Into<String>, degree: usize) -> Self {
Self {
group: group.into(),
module: module.into(),
degree,
}
}
pub fn description(&self) -> String {
format!(
"H^{}({}, {}) ā continuous group cohomology of {} with coefficients in {}",
self.degree, self.group, self.module, self.group, self.module
)
}
pub fn vanishes_above_dimension(&self, dim: usize) -> bool {
self.degree > dim
}
pub fn ext_group_statement(&self) -> String {
format!(
"The Ext groups Ext^n_Ī(M, Ī) for the Iwasawa algebra Ī compute the \
Iwasawa cohomology of the module M (the {}-module {}), \
generalizing group cohomology to the Iwasawa algebra setting.",
self.group, self.module
)
}
}
pub struct PAdicNumber {
pub numerator: PAdicInteger,
pub valuation: i64,
}
impl PAdicNumber {
pub fn new(p: u64, n: i64) -> Self {
if n == 0 {
return Self {
numerator: PAdicInteger::zero(p),
valuation: i64::MAX,
};
}
let mut val = 0i64;
let mut m = n.unsigned_abs();
while m % p == 0 {
m /= p;
val += 1;
}
let sign_n = if n < 0 { -(m as i64) } else { m as i64 };
Self {
numerator: PAdicInteger::new(p, sign_n),
valuation: val,
}
}
pub fn p_adic_valuation(&self) -> i64 {
self.valuation
}
pub fn is_integer(&self) -> bool {
self.valuation >= 0
}
pub fn is_unit(&self) -> bool {
self.valuation == 0
}
}
pub struct HenselsLemma {
pub poly: String,
pub prime: u64,
}
impl HenselsLemma {
pub fn new(poly: String, prime: u64) -> Self {
Self { poly, prime }
}
pub fn lifting_applies(&self) -> bool {
true
}
pub fn lift_root(&self, root: i64, precision: u32) -> i64 {
let modulus = (self.prime as i64).pow(precision);
root.rem_euclid(modulus)
}
}
pub struct WittRing {
pub p: u64,
}
impl WittRing {
pub fn new(p: u64) -> Self {
Self { p }
}
pub fn characteristic(&self) -> u64 {
0
}
}
pub struct PAdicExp {
pub p: u64,
pub convergence_radius: f64,
}
impl PAdicExp {
pub fn new(p: u64) -> Self {
let convergence_radius = padic_exp_convergence(p);
Self {
p,
convergence_radius,
}
}
pub fn converges_at(&self, x: &PAdicNumber) -> bool {
if x.valuation == i64::MAX {
return true;
}
let abs_x = (self.p as f64).powi(-(x.valuation as i32));
abs_x < self.convergence_radius
}
pub fn evaluate_series(&self, x: f64, terms: u32) -> f64 {
let mut sum = 0.0f64;
let mut term = 1.0f64;
for n in 1..=terms {
sum += term;
term *= x / n as f64;
}
sum
}
}
pub struct PAdicExponential {
pub p: u64,
}
impl PAdicExponential {
pub fn new(p: u64) -> Self {
Self { p }
}
pub fn radius_of_convergence(&self) -> f64 {
if self.p == 2 {
0.25
} else {
let exp = -1.0 / (self.p as f64 - 1.0);
(self.p as f64).powf(exp)
}
}
pub fn exp_p(&self, x: f64) -> f64 {
let mut sum = 0.0f64;
let mut term = 1.0f64;
for n in 1u32..=50 {
sum += term;
term *= x / n as f64;
}
sum
}
}
pub struct UnramifiedExtension {
pub base_p: u64,
pub degree: usize,
}
impl UnramifiedExtension {
pub fn new(p: u64, f: usize) -> Self {
Self {
base_p: p,
degree: f,
}
}
pub fn residue_field_size(&self) -> u64 {
self.base_p.pow(self.degree as u32)
}
}