/*
Test all the basic constructions of the language.
AKS 3/7/95.
*/

Z := IntegerRing();

q := [];
q[1] := [];
q[1][1] := [1];
q[2] := [[3]];
q[3] := [];
assert q eq [[[1]], [[3]], []];

t := <1/2, "a">;
t[1] := 2;
t[2] := "b";
assert t eq <2/1, "b">;

R := GF(5);
V := RSpace(R, 2);
v := V ! 0;
v[1] := 9;
assert v[1] eq R ! 9;

R := GF(5);
V := RMatrixSpace(R, 2, 3);
X := V ! 0;
X[1] := Parent(X[1]) ! [1, 2, 3];
X[2][1] := 2;
assert X eq V ! [1,2,3, 2,0,0];

R := GF(5);
V := MatrixAlgebra(R, 2);
X := V ! 0;
X[1] := Parent(X[1]) ! [1, 2];
X[2][1] := 2;
assert X eq V ! [1,2, 2,0];

f := recformat<a, b>;
r := rec<f | a := 2>;
assert assigned r`a;
assert not assigned r`b;
r`b := "a";
assert r`a eq 2 and r`b eq "a";
assert r``"a" eq 2 and r``"b" eq "a";

R := rec<recformat<a> | a := 1>;
s := "a";
assert R``s eq 1;
R``s := 2;
assert R``s eq 2;
R``s := [3];
assert R``s eq [3];
assert (R``s)[1] eq 3;
R``s[2] := 4;
assert R``"a" eq [3, 4];


p := procedure(~x, ~q)
    x := q;
    q[1] := 2;
end procedure;

q := [];
p(~x, ~q);
assert x eq [];
assert q eq [2];
_ := 1;

if false then
    assert false;
elif false then
    assert false;
else
    assert true;
end if;

while false do
    assert false;
end while;

i := 1;
repeat
    assert i eq 1;
    i +:= 1;
until i eq 2;

for_test := procedure(a, b, s)
    q := [];
    for x := a to b by s do
	Append(~q, x);
    end for;
    assert q eq [a .. b by s];
    qq := [];
    for x in [a .. b by s] do
	Append(~qq, x);
    end for;
    assert qq eq q;
end procedure;

for_test(1, 10, 1);
for_test(1, 10, 3);
for_test(1, 10, -3);
for_test(1, 10, 20);
for_test(10, 1, 1);
for_test(10, 1, -1);
for_test(10, 1, 100);
for_test(10^10, 10^10 + 5, 1);

p := procedure(~a)
    a := 1;
end procedure;
p(~p);

a, b := function() return 1, "a"; end function();
assert a eq 1 and b eq "a";

S := [];
for random x in [1 .. 5] do
    Include(~S, x);
    break;
end for;
assert #S eq 1;

assert exists{x: x in [1 .. 5] | IsPrime(x)};
assert exists(t){x: x in [1 .. 5] | IsPrime(x)};
assert t eq 2;

assert forall{x: x in [2, 3, 5, 7] | IsPrime(x)};
assert not forall(t){x: x in [2, 3, 5, 6, 7] | IsPrime(x)};
assert t eq 6;

for i := 1 to 10 do
    x := random{ x: i in [1 .. 100] | IsPrime(x) where x is i^2 + 1};
    assert IsPrime(x);
end for;

x := rep{ x + 1: i in [50 .. 100] | IsPrime(x) where x is i^2 + 1};
assert x eq 2918;

forward f;
g := func<n | n eq 0 select 1 else n * f(n - 1)>;
f := func<n | g(n)>;
for i in [0, 1, 5, 50] do
    assert g(i) eq Factorial(i);
end for;

f := func<x | func<| x>>;
g := f(7);
assert g() eq 7;

x := 1;
assert x where x is 10 eq 10;
assert x eq 1;

assert (Order(G) + Degree(G) where G is Sym(3)) eq 9;

x := 1;
y := 2;
assert (x + y where x is 5 where y is 6) eq 11;
assert ((x + y where x is 5) where y is 6) eq 11;
assert (x + y where x is (5 where y is 6)) eq 7;
assert (x + y where x is y where y is 6) eq 12;
assert ((x + y where x is y) where y is 6) eq 12;
assert (x + y where x is (y where y is 6)) eq 8;
assert { a: i in [1 .. 10] | IsPrime(a) where a is 3*i + 1 } eq
       { 7, 13, 19, 31 };
assert [<x, y>: i in [1 .. 10] | IsPrime(x) and IsPrime(y) where
	x is y + 2 where y is 2 * i + 1] eq
	[ <5, 3>, <7, 5>, <13, 11>, <19, 17> ];

x := 1;
assert assigned x;
assert not assigned abcdefghijklmnopqrstuvwxyz;
p := procedure(~x, ~y) y := assigned x; end procedure;
x := 1;
p(~x, ~y);
assert y;
delete x;
p(~x, ~y);
assert not y;

f := map<Z -> Z | x :-> x^2>;
assert f(3) eq 9;
assert 3 @ f eq 9;
assert true or 1 div 0;
assert not (false and 1 div 0);
assert true select true else false;
assert false select false else true;

assert 1 + 1 + 3 + 7 + 7^2 eq 61;
assert 1 + 2 + 3^2 eq 12;
f := func<x|x^2>;
assert 1 + 2 + 3@f eq 12;

P<x> := PolynomialRing(Z);
assert 1 + x + 1 + 2^2 eq x + 6;
assert 1 + x + 1 + 2@f eq x + 6;

f := 7 + x^196608;
assert f eq x^196608+7;
assert f eq 7 + x^(2^16*3);

S<z>:=GF(3^10);
P<x>:=PolynomialRing(S);
f := x^5 + z^56175*x^4;
g := z^56175*x^4 + x^5;
assert f eq g;

//quit;
