SetDebugOnError(true);
function RandomPrimeIdeal(R)
    if Type(R) in {RngOrd, RngQuad, RngCyc, RngFunOrd} then
        p := RandomPrimeIdeal(CoefficientRing(R));
        ps := Decomposition(R, p);
        if Type(R) in {RngOrd, RngQuad, RngCyc} then
            return ps[i][1] where i is Random([1 .. #ps]);
        else
            return ps[i] where i is Random([1 .. #ps]);
        end if;
    elif Type(R) eq  RngInt then
        return RandomPrime(10);
    elif Type(R) eq RngUPol then
        if Characteristic(R) eq 0 then
            return R!ChangeUniverse(Eltseq(RandomPrimePolynomial(PolynomialRing(GF(NextPrime(100))), 3)), Integers());
        else
            return RandomPrimePolynomial(R, 3);
        end if;
    elif Type(R) eq RngVal then
        return R!(1/FieldOfFractions(R).1);
    end if;

end function;

function RandomIdeal(R)
//{Returns an ideal which is a random product of some random prime ideals}

    if Type(R) notin {RngOrd, RngQuad, RngCyc, RngFunOrd} then
	error "Ring must be an order of a number field or a function field";
    end if;

    r := Random(1, 3);

    I := 1*R;
    for i in [1 .. r] do
        I := I*RandomPrimeIdeal(R)^Random(1, 3);
    end for;

    return I;

end function;

SetVerbose("ClassGroup", 3);
SetVerbose("ClassGroupSieve", 3);

ClearVerbose();
ShowMemoryUsage := procedure() end procedure;

procedure test_class_group_sieve(D, preimage)
K := QuadraticField(D);
O := MaximalOrder(K);
t := Cputime();
ShowMemoryUsage();
time G, m := ClassGroup(O : Al := "Sieve"); G;
ShowMemoryUsage();
for i in [1 .. Ngens(G)] do
    fi := m(G.i);
    if preimage then
	time assert fi @@ m eq G.i;
	time assert not IsPrincipal(fi);
	if Order(G.i) lt 10000 then
	    time fi := fi^Order(G.i);
	    time assert IsPrincipal(fi);
	    _, g := IsPrincipal(fi);
	    "Got generator";
	    p, e := ProductRepresentation(g);
	    if #p lt 10000 and Maximum(e) lt 1000000 then
		assert g*O eq fi;
	    end if;
	end if;
    end if;
end for;
if Ngens(G) eq 0 then
    I := RandomIdeal(O);
    assert IsPrincipal(I);
    _, g := IsPrincipal(I);
    "Got generator";
    p, e := ProductRepresentation(g);
    if #p lt 10000 and Maximum(e) lt 1000000 then
	assert g*O eq I;
    end if;
end if;
if assigned p then
#p, Maximum(e);
end if;
"TIME ", D, " = ", Cputime(t);
ShowMemoryUsage();
end procedure;

D:=-(10^(20) + 3 );	// 0.49s 5/11	0.9s 8/10
test_class_group_sieve(D, true);
D:=-(10^(25) + 3 );	// 0.63s 5/11 	0.95s 8/10
test_class_group_sieve(D, true);
D:=-(10^(30) + 3 );	// 0.9s 5/11	1.59s 8/10 (wo preimage) PROBS IN PREIMAGE
//test_class_group_sieve(D, false);
D:=-(10^(35) + 3 );	// 3.19s 5/11	4.8s 8/10 (wo preimage) PROBS IN PREIMAGE
test_class_group_sieve(D, false);
D:=-(10^(40) + 3 );	// 11.1s 5/11	10.62s 8/10
test_class_group_sieve(D, false);
/*
D:=-(10^(45) + 3 ); 	// 64.95s 5/11	58s for the class group PROBS IN PREIMAGE
test_class_group_sieve(D, false);
D:=-(10^(50) + 3 );	// 224.34s 5/11	170s for the class group PROBS IN PREIMAGE 
test_class_group_sieve(D, false);
D:=-(10^(55) + 3 );	// 1045.87s 5/11 971s for the class group PROBS IN PREIMAGE
test_class_group_sieve(D, false);
D:=-(10^(60) + 3 );	// 1205.1s 5/11	993s for the class group PROBS IN PREIMAGE
test_class_group_sieve(D, false);
D:=-(10^(65) + 3 );	// 6292s 5/11	5920s for the class group PROBS IN PREIMAGE? seg flt
test_class_group_sieve(D, false);
D:=-(10^(67) + 3 );	// 7641s 5/11 	9440s? PROBS IN PREIMAGE (7477s CG 4/11)
test_class_group_sieve(D, false);
D:=-(10^(70) + 3 );	// log_D == 220 3G!! in mat_echelon in find_full_rank_quad_case FOREVER!!
test_class_group_sieve(D, false);
D:=-(10^(75) + 3 );	// log_D == 240
test_class_group_sieve(D, false);
D:=-(10^(80) + 3 );	// log_D == 260
test_class_group_sieve(D, false);
D:=-(10^(85) + 3 );	// log_D == 280
test_class_group_sieve(D, false);
D:=-(10^(90) + 3 );	// log_D == 280
test_class_group_sieve(D, false);
D:=-(10^(95) + 3 );	// log_D == 300
test_class_group_sieve(D, false);
D:=-(10^(100) + 3 );	// log_D == 320
test_class_group_sieve(D, false);
D:=-(10^(101) + 3 );	// log_D == 320
test_class_group_sieve(D, false);
D:=-(10^(102) + 3 );	// log_D == 320
test_class_group_sieve(D, false);
D:=-(10^(103) + 3 );	// log_D == 340
test_class_group_sieve(D, false);
D:=-(10^(105) + 3 );	// log_D == 340
test_class_group_sieve(D, false);
D:= -1570395159076481613496575854860464895664284407372344097463337019130272115;
test_class_group_sieve(D, false);
D:=4*(10^(20)+3);
test_class_group_sieve(D, false);
*/

