SetEchoInput(true);

P<x> := PolynomialRing(Integers());

Zp := pAdicRing(7 : Exact);
U := ext<Zp | x^2 + 6*x + 3>;
R := ext<U | x^3 + 7*x^2 + 7*x + 7>;

Qp := FieldOfFractions(Zp);
QU := FieldOfFractions(U);
QR := FieldOfFractions(R);

assert IsWeaklyZero(Evaluate(DefiningPolynomial(R), R.1));
assert IsWeaklyZero(Evaluate(DefiningPolynomial(U), U.1));
assert IsWeaklyZero(Evaluate(DefiningPolynomial(QR), QR.1));
assert IsWeaklyZero(Evaluate(DefiningPolynomial(QU), QU.1));

assert IsWeaklyZero(Evaluate(DefiningPolynomial(R : Exact), R.1));
assert IsWeaklyZero(Evaluate(DefiningPolynomial(U : Exact), U.1));
assert IsWeaklyZero(Evaluate(DefiningPolynomial(QR : Exact), QR.1));
assert IsWeaklyZero(Evaluate(DefiningPolynomial(QU : Exact), QU.1));

assert RamificationDegree(R) eq 3;
assert InertiaDegree(R) eq 1;
assert RamificationDegree(U) eq 1;
assert InertiaDegree(U) eq 2;

assert Valuation(UniformizingElement(R)) eq 1;
assert Valuation(UniformizingElement(U)) eq 1;
assert Valuation(UniformizingElement(QR)) eq 1;
assert Valuation(UniformizingElement(QU)) eq 1;

assert Prime(U) eq Prime(CoefficientRing(U));

rf, rfm := ResidueClassField(U);
assert WeakValuation(rfm(U.1) @@ rfm - U.1) ge 1;

for i in [1 .. 5] do

    r := &+[Random(0, 500)*R.1^i : i in [0 .. 2*Degree(R)]];
    s := &+[Random(0, 300)*R.1^i : i in [0 .. 2*Degree(R)]];

    assert IsWeaklyEqual(r + s, s + r);
    assert WeakValuation(r + s) ge Minimum(WeakValuation(r), WeakValuation(s));
    assert IsWeaklyEqual(r - s, -(s - r));
    assert IsWeaklyEqual(r*s, s*r);
    assert WeakValuation(r*s) eq WeakValuation(r) + WeakValuation(s);
    //assert IsWeaklyEqual(r/s*(s/r), 1);
    //assert RelativePrecision((r/s)*(s/r) - 1) eq 0;//Precision(L);
    assert IsWeaklyEqual(r^4, r*r*r*r);

    assert IsWeaklyZero(r + (-r));

end for;

R!0/5;
QR!0/5;

for i in [1 .. 5] do

    r := &+[Random(0, 500)*QR.1^i : i in [0 .. 2*Degree(QR)]];
    s := &+[Random(0, 300)*QR.1^i : i in [0 .. 2*Degree(QR)]];

    assert IsWeaklyEqual(r + s, s + r);
    assert WeakValuation(r + s) ge Minimum(WeakValuation(r), WeakValuation(s));
    assert IsWeaklyEqual(r - s, -(s - r));
    assert IsWeaklyEqual(r*s, s*r);
    assert WeakValuation(r*s) eq WeakValuation(r) + WeakValuation(s);
    assert IsWeaklyEqual(r div s, 1/(s div r));
    assert RelativePrecision((r/s)*(s/r) - 1) eq 0;//Precision(L);
    assert IsWeaklyEqual(r^4, r*r*r*r);

    assert IsWeaklyZero(r + (-r));
end for;

assert IsWeaklyZero(R!0);
assert IsWeaklyZero(U!0);
assert IsWeaklyZero(QR!0);
assert IsWeaklyZero(QU!0);

assert IsIntegral(U.1);
assert IsIntegral(R.1);
assert IsIntegral(UniformizingElement(R));
assert not IsIntegral(1/UniformizingElement(R));

assert IsIntegral(QU.1);
assert IsIntegral(QR.1);
assert IsIntegral(UniformizingElement(QR));
assert not IsIntegral(1/UniformizingElement(QR));

assert RelativePrecision(Discriminant(DefiningPolynomial(R)) - -3724) eq 0;
assert RelativePrecision(Discriminant(DefiningPolynomial(U)) - 24) eq 0;

URR := ext<R | Polynomial(R, [5, 10, 2, 1])>;
URF := FieldOfFractions(URR);
RRR := ext<URR | Polynomial(URR, [R.1, 5*R.1^20, 1])>;
RRF := FieldOfFractions(RRR);

rf, rfm := ResidueClassField(URR);
assert WeakValuation(rfm(URR.1) @@ rfm - URR.1) ge 1;

    r := &+[Random(0, 500)*RRR.1^i : i in [0 .. 2*Degree(RRR)]];
    s := &+[Random(0, 300)*RRR.1^i : i in [0 .. 2*Degree(RRR)]];

    assert IsWeaklyEqual(r + s, s + r);
    assert WeakValuation(r + s) ge Minimum(WeakValuation(r), WeakValuation(s));
    assert IsWeaklyEqual(r - s, -(s - r));
    assert IsWeaklyEqual(r*s, s*r);
    assert WeakValuation(r*s) eq WeakValuation(r) + WeakValuation(s);
    // assert r div s eq 1/(s div r);
assert RelativePrecision((r/s)*(s/r) - 1) le 5;
assert WeakValuation((r/s)*(s/r) - 1) ge AbsolutePrecision(r) - 5;
    assert IsWeaklyEqual(r^4, r*r*r*r);

    assert IsWeaklyZero(r + (-r));

    r := &+[Random(0, 500)*RRF.1^i : i in [0 .. 2*Degree(RRF)]];
    s := &+[Random(0, 300)*RRF.1^i : i in [0 .. 2*Degree(RRF)]];

    assert IsWeaklyEqual(r + s, s + r);
    assert WeakValuation(r + s) ge Minimum(WeakValuation(r), WeakValuation(s));
    assert IsWeaklyEqual(r - s, -(s - r));
    assert IsWeaklyEqual(r*s, s*r);
    assert WeakValuation(r*s) eq WeakValuation(r) + WeakValuation(s);
    assert IsWeaklyEqual(r div s, 1/(s div r));
assert RelativePrecision((r/s)*(s/r) - 1) le 5;
assert WeakValuation((r/s)*(s/r) - 1) ge AbsolutePrecision(r) - 5;
    assert IsWeaklyEqual(r^4, r*r*r*r);

    assert IsWeaklyZero(r + (-r));

assert IsWeaklyZero(RRR!0);
assert IsWeaklyZero(URR!0);

assert IsWeaklyZero(RRF!0);
assert IsWeaklyZero(URF!0);

assert IsIntegral(RRR.1);
assert IsIntegral(UniformizingElement(RRR));
assert not IsIntegral(1/UniformizingElement(RRR));

assert IsIntegral(RRF.1);
assert IsIntegral(UniformizingElement(RRF));
assert not IsIntegral(1/UniformizingElement(RRF));

Discriminant(DefiningPolynomial(RRR));

