//Attach("Decompose5");

SetEchoInput(true);

check_decompose:=procedure(f)
    K_ini:=Parent(f); k:=BaseRing(K_ini);
    for dec in Decomposition(f) do
        g:=K_ini.1;
        for i:=1 to #dec do
            g:=Evaluate(dec[i],g);
        end for;
        assert(g eq f);
    end for;
end procedure;


random_limit := 1000;
random_limit := 20;

if IsOpt() then
    random_limit := 3;
else
    random_limit := 2;
end if;

//////////////// Rationals /////////////////

k:=Rationals();

P<x>:=PolynomialRing(k);
f:=x^6 + 4*x^4 + 2*x^3 + 4*x^2 + 4*x + 2;
check_decompose(f);

F<t>:=FunctionField(k);

f:=(t^3+8)^3/(t^3-1)^3*t^3;
check_decompose(f);

f:=(t^8-t^4+1)^3/(t^4-1)^2/t^8;
check_decompose(f);

f:=t^18+t^10+t^2;
check_decompose(f);

f:=(t^10 + 2*t^8 + 2*t^4 + t^2)/(t^12 + 2*t^6 + 1);
check_decompose(f);

f:=t;
check_decompose(f);

f:=(t^24-2*t^12+1)/(t^16+2*t^12+t^8);
check_decompose(f);


f:=(t^5+t+1)/(t^3+2*t+1);
check_decompose(f);

for i in [1 .. random_limit] do
    f := Polynomial([Random(k, 1000) : j in [1 .. Random(5, 50)]])/Polynomial([Random(k, 1000) : j in [1 .. Random(5, 50)]]);
    check_decompose(f);
end for;

/////////////// Finite fields /////////////////
k:=GF(3);

P<x>:=PolynomialRing(k);
f:=x^6+x^4+2*x^3+x^2+x+2;
check_decompose(f);

F<t>:=FunctionField(k);

f:=(t^8-t^4+1)^3/(t^4-1)^2/t^8;
check_decompose(f);

f:=t^18+t^10+t^2;
check_decompose(f);

f:=t;
check_decompose(f);

f:=t^2;
check_decompose(f);


f:=(t^10 + 2*t^8 + 2*t^4 + t^2)/(t^12 + 2*t^6 + 1);
check_decompose(f);


f:=(t^24-2*t^12+1)/(t^16+2*t^12+t^8);
check_decompose(f);


k:=GF(3);
P<x>:=PolynomialRing(k);
f:=x^2+1;
F<t>:=FunctionField(ext<k|f>);

f:=t;
check_decompose(f);

f:=t^9-t;
check_decompose(f);


f:=(t^5+t+1)/(t^3+2*t+1);
check_decompose(f);

for i in [1 .. random_limit] do
    k := GF(RandomPrime(200), Random(1, 5));
    f := Polynomial([Random(k) : j in [1 .. Random(5, 50)]])/Polynomial([Random(k) : j in [1 .. Random(5, 50)]]);
    check_decompose(f);
end for;


///////////// Cyclotomic fields ///////////////
k:=CyclotomicField(3);

P<x>:=PolynomialRing(k);
f:=x^6 + 4*x^4 + 2*x^3 + 4*x^2 + 4*x + 2;
check_decompose(f);

F<t>:=FunctionField(k);

f:=t;
check_decompose(f);

f:=t^2;
check_decompose(f);

f:=(t^3+8)^3/(t^3-1)^3*t^3;
check_decompose(f);

f:=(t^8-t^4+1)^3/(t^4-1)^2/t^8;
check_decompose(f);

f:=t^18+t^10+t^2;
check_decompose(f);

f:=(t^4-t^3-8*t-1)/(2*t^4+t^3-16*t+1);
check_decompose(f);


f:=(2*t^10 + 2*t^8 + 2*t^4 + t^2)/(3*t^12 + 2*t^6 + 1);
check_decompose(f);


f:=(t^5+t+1)/(t^3+2*t+1);
check_decompose(f);

SetProfile(true);
for i in [1 .. random_limit div 20] do
    k := CyclotomicField(Random(1, 15) : Sparse := Random([true, false]));
    f := Polynomial([Random(k, 2) : j in [1 .. Random(5, 20)]])/Polynomial([Random(k, 2) : j in [1 .. Random(5, 20)]]);
    k, f;
    check_decompose(f);
end for;
SetProfile(false);
ProfilePrintByTotalTime(:Max := 20);

/////////////// Number Fields /////////////////
k:=Rationals();
P<x>:=PolynomialRing(k);
f:=x^5-2*x+2;
K<a>:=NumberField(f);


P<x>:=PolynomialRing(K);
f:=2*a^2*x^6 + (16*a^2 + 24*a - 16)*x^4 + 4*a*x^3 + (32*a^4 - 16*a^3 + 32*a^2 + 96*a - 56)*x^2 + (8*a^4 + 16*a + 8)*x + 3;
check_decompose(f);

F<t>:=FunctionField(K);

f:=t;
check_decompose(f);

f:=t^2;
check_decompose(f);

f:=(t^3+8)^3/(t^3-1)^3*t^3;
check_decompose(f);

f:=(t^8-t^4+1)^3/(t^4-1)^2/t^8;
check_decompose(f);

f:=t^18+t^10+t^2;
check_decompose(f);

f:=(a*t^6 + (-4*a^2 + 1)*t^4 + 6*a*t^3 + (4*a^3 + 4*a^2)*t^2 - 4*a^2*t + a)/(t^4 + 4*a*t^3 + 4*a^2*t^2);
check_decompose(f);


f:=(t^10 + 2*t^8 + 2*t^4 + t^2)/(t^12 + 2*t^6 + 1);
check_decompose(f);


f:=(t^5+t+1)/(t^3+2*t+1);
check_decompose(f);

for i in [1 .. random_limit div 20] do
    k := GF(RandomPrime(500));
    k := NumberField(Polynomial(Integers(), RandomPrimePolynomial(PolynomialRing(k), Random(2, 10))));
    f := Polynomial([Random(k, 5) : j in [1 .. Random(5, 10)]])/Polynomial([Random(k, 5) : j in [1 .. Random(5, 10)]]);
    check_decompose(f);
end for;

