#![cfg(feature = "padic")]
use puremp::padic::Padic;
use puremp::{Int, Rational};
fn p(v: i64) -> Int {
Int::from_i64(v)
}
fn rat(a: i64, b: i64) -> Rational {
Rational::new(Int::from_i64(a), Int::from_i64(b))
}
#[test]
fn minus_one_in_z2_is_all_ones() {
let n = 8;
let x = Padic::from_int(p(2), n, p(-1));
assert_eq!(x.valuation(), Some(0));
let digits = x.digits();
assert_eq!(digits.len(), n as usize);
for d in &digits {
assert_eq!(*d, Int::ONE);
}
assert_eq!(x.to_rational(), Rational::from_integer(p(255)));
}
#[test]
fn one_third_reciprocal_in_z2() {
let n = 20;
let third = Padic::from_rational(p(2), n, &rat(1, 3));
let three = Padic::from_int(p(2), n, p(3));
assert_eq!(&third * &three, Padic::one(p(2), n));
assert_eq!(third.valuation(), Some(0));
let d = third.digits();
let expect = [1, 1, 0, 1, 0, 1];
for (i, e) in expect.iter().enumerate() {
assert_eq!(d[i], p(*e), "digit {i}");
}
}
#[test]
fn addition_matches_direct_construction() {
let n = 12;
let a = Padic::from_int(p(5), n, p(123456));
let b = Padic::from_int(p(5), n, p(-987654));
let sum_direct = Padic::from_int(p(5), n, p(123456 - 987654));
assert_eq!(&a + &b, sum_direct);
}
#[test]
fn multiplication_matches_direct_construction() {
let n = 12;
let a = Padic::from_int(p(7), n, p(1234));
let b = Padic::from_int(p(7), n, p(5678));
let prod_direct = Padic::from_int(p(7), n, p(1234 * 5678));
assert_eq!(&a * &b, prod_direct);
}
#[test]
fn self_minus_self_is_zero() {
let n = 10;
let a = Padic::from_rational(p(3), n, &rat(7, 4));
let z = &a - &a;
assert!(z.is_zero());
assert_eq!(z, Padic::new(p(3), n));
}
#[test]
fn unit_times_reciprocal_is_one() {
let n = 15;
for val in [2i64, 5, 17, 100] {
let a = Padic::from_int(p(11), n, p(val));
let inv = a.inv();
assert_eq!(&a * &inv, Padic::one(p(11), n));
assert_eq!(&a / &a, Padic::one(p(11), n));
}
}
#[test]
fn valuation_of_p_power_times_unit() {
let n = 10;
for k in 0..5u32 {
let value = p(7).pow(k).mul(&p(6)); let x = Padic::from_int(p(7), n, value);
assert_eq!(x.valuation(), Some(k as i64));
}
}
#[test]
fn negative_valuation_in_qp() {
let n = 8;
let x = Padic::from_rational(p(5), n, &rat(1, 5));
assert_eq!(x.valuation(), Some(-1));
assert_eq!(x.abs_value(), Rational::from_integer(p(5)));
let y = Padic::from_rational(p(5), n, &rat(1, 125));
assert_eq!(y.valuation(), Some(-3));
let five = Padic::from_int(p(5), n, p(5));
assert_eq!(&x * &five, Padic::one(p(5), n));
}
#[test]
fn abs_value_of_zero_and_units() {
let n = 6;
assert_eq!(Padic::new(p(3), n).abs_value(), Rational::ZERO);
let u = Padic::from_int(p(3), n, p(2));
assert_eq!(u.abs_value(), Rational::ONE);
let x = Padic::from_int(p(3), n, p(9));
assert_eq!(x.abs_value(), Rational::new(Int::ONE, p(9)));
}
#[test]
fn sqrt_odd_prime() {
let n = 12;
let two = Padic::from_int(p(7), n, p(2));
let r = two.sqrt().expect("2 is a 7-adic square");
assert_eq!(&r * &r, two);
let three = Padic::from_int(p(7), n, p(3));
assert!(three.sqrt().is_none());
}
#[test]
fn sqrt_two_adic() {
let n = 16;
let x = Padic::from_int(p(2), n, p(17));
let r = x.sqrt().expect("17 is a 2-adic square");
assert_eq!(&r * &r, x);
assert!(Padic::from_int(p(2), n, p(3)).sqrt().is_none());
}
#[test]
fn sqrt_with_even_valuation() {
let n = 10;
let value = p(7).pow(2).mul(&p(2));
let x = Padic::from_int(p(7), n, value);
let r = x.sqrt().expect("even valuation, residue unit");
assert_eq!(r.valuation(), Some(1));
assert_eq!(&r * &r, x);
let odd = Padic::from_int(p(7), n, p(7).mul(&p(2)));
assert!(odd.sqrt().is_none());
}
#[test]
fn display_format() {
let n = 5;
let x = Padic::from_int(p(2), n, p(-1));
assert_eq!(x.to_string(), "1 + 1*2 + 1*2^2 + 1*2^3 + 1*2^4 + O(2^5)");
assert_eq!(Padic::new(p(2), n).to_string(), "O(2^5)");
}
#[test]
fn to_rational_roundtrip() {
let n = 30;
let x = Padic::from_int(p(5), n, p(123));
assert_eq!(x.to_rational(), Rational::from_integer(p(123)));
}