
VERB := false;

set_test := procedure(A, size, rand_alg)
    print "set_test:", size, A;

    S := {rand_alg(A): i in {1 .. size}};
    T := {rand_alg(A): i in {1 .. size}};

    if VERB then
	print "#S:", #S;
	print "#T:", #T;
    end if;

    assert not IsNull(S);
    assert not IsEmpty(S);

    assert { Universe(S) | } eq { A | };

    assert {x: x in S} eq S;
    assert &and{x in S: x in S};
    assert {T | x: x in T} eq T;

    C := {};      
    for x in S do
        Include(~C, x);
    end for;
    assert C eq S;        
                       
    assert S in Parent(S); 
    assert Rep(S) in S;
    assert S ! Rep(S) in S;                             
                                                        
    repeat          
        x := rand_alg(A);
    until x notin S;

    C := S;
    //assert Refcount(C) eq 2;
    Include(~C, x);
    //assert Refcount(C) eq 1;
    assert C ne S;

    repeat
        x := rand_alg(A);
    until x notin C;

    Include(~C, x);
    //assert Refcount(C) eq 1;
    assert C ne S;

    loop_size := Max(10, size div 2);

    if VERB then
	print "loop_size:", loop_size;
    end if;

    L := { 1 .. loop_size };

    M := S meet T;
    if VERB then
	print "#M:", #M;
    end if;
    assert M subset S;
    assert M subset T;
    if #M gt 0 then
	for i in L do
	    r := Random(M);
	    assert r in M;
	    assert r in S;
	    assert r in T;
	end for;
    end if;

    J := S join T;
    if VERB then
	print "#J:", #J;
    end if;
    assert S subset J;
    assert T subset J;
    assert {Random(S) : i in L} subset J;
    assert {Random(T) : i in L} subset J;
    assert {Random(S) : i in L} join {Random(T) : i in L} subset J;
    for i in L do
	r := Random(J);
	assert r in S or r in T;
    end for;

    D := S diff T;
    if VERB then
	print "#(S diff T):", #D;
    end if;
    assert D subset S;
    assert D meet T eq {};
    assert D join M eq S;
    assert D join T eq J;

    D := T diff S;
    if VERB then
	print "#(T diff S):", #D;
    end if;
    assert D subset T;
    assert D meet S eq {};
    assert D join M eq T;
    assert D join S eq J;

    SD := S sdiff T;
    if VERB then
	print "#SD:", #SD;
    end if;
    assert SD meet M eq {};
    assert SD join M eq J;
    assert J diff SD eq M;
end procedure;

sym_rand := func<G | Random(G: Short := true)>;

//show mem;
//set mark := true;

set_test(IntegerRing(), 100, func<x | Random(-50, 50)>);

set_test(MatrixAlgebra(GF(2), 4), 10000, Random);   
set_test(MatrixAlgebra(GF(23), 10), 1000, Random);   

set_test(SL(3, GF(4)), 1000, Random);   

set_test(Sym(5), 10, sym_rand);
set_test(Sym(10), 5000, sym_rand);

set_test(IntegerRing(), 10000, func<x | Random(-1000000, 1000000)>);

set_test(RationalField(), 1000, func<x | Random(-100, 100) / Random(1, 100)>);

set_test(
    PowerSet(IntegerRing()), 100, func<x | {Random(1, 10) : i in {1..10}}>
);

set_test(
    PowerSet(PowerSet(RationalField())), 500,
    func<x | {{Random(1, 3) / Random(1, 3) : i in {1..3}}: j in {1..3}}>
);

//show active;
//show mem;

//quit;
