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)

    assert Type(R) in {RngOrd, RngQuad, RngCyc, RngFunOrd};

    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;

p := 1;
SetClassGroupBounds("GRH");
function random_coprime_ideal(E)
    repeat 
	I := RandomIdeal(E);
    until I + Conductor(E) eq 1*E;
    return I;
end function;
repeat
    p := NextPrime(Random(5, 10)*p);
    Q := QuadraticField(-p);
    time cg := ClassGroup(Q);
    if not IsMaximal(EquationOrder(Q)) and #cg gt 1 then //and #Generators(cg) gt 1 then
	p;
	cg;
	E := EquationOrder(DefiningPolynomial(Q));
	tPP := Cputime();
	time P, mP := PicardGroup(E : UsePowerProduct);
	tPP := Cputime(tPP);
	P;
	"Picard group with power product was";
	cont := false;
	"Test Generators : ";
	t := Cputime();
	for gen in Generators(P) do
	    try
	    assert mP(gen) @@ mP eq gen;
	    catch e
		"error p = ", p, "Generator ", gen, "failed", e;
		cont := true;
	    end try;
	end for;
	"Test Generator time : ", Cputime(t);
	if cont then
	continue;
	end if;
	"Test Random Group Elements : ";
	t := Cputime();
	for i in [1 .. 10] do
	    a := Random(P);
	    try
	    assert mP(a) @@ mP eq a;
	    catch e
		"error p = ", p, "Random ", a, "failed", e;
		continue;
	    end try;
	end for;
	"Test Random time : ", Cputime(t);
	"Test Ideals : ";
	t := Cputime();
	for i in [1 .. 2] do
	    I := random_coprime_ideal(E);
	    assert ImP @@ mP eq <[I], [1]> @@ mP where ImP := mP(<[I], [1]> @@ mP);
	    I := [random_coprime_ideal(E) : i in [1 .. Random(5)]];
	    Ex := [Random(5) : i in [1 .. #I]];
	    assert ImP @@ mP eq <I, Ex> @@ mP where ImP := mP(<I, Ex> @@ mP);
	end for;
	"Test Ideal time : ", Cputime(t);
    end if;
until Cputime() gt (IsOpt() select 100 else 15*60);

