
// This function attempts to replace $L$ be a sublattice
// as in [11, Lemma 11.1]

// Here J is the Jacobian
// W is the image on J of the known rational points on C
// mwBasis is the basis for the free part of J(Q)
// q is a prime of good reduction
// F:=FreeAbelianGroup(r); where $r$ is the mw rank
// L is some subgroup of F
// B is some integer such that L \subseteq B \Z^r

// returns tf, n, L
// where tf is true if all of I--IV succeed and false otherwise
// n is the success level, 1--4 if it fails on I--IV and 5 if it succeeds on all
// L is the old lattice if failure and the new lattice if success.
mwSievePrimeEnhance:=function(F,L,W,J,mwBasis,q,B);
	r:=#mwBasis;
	Jq:=BaseChange(J,GF(q));

	A,psi:=AbelianGroup(Jq); //computing the group structure of J mod q;
	ordA:=#A;

	if GCD(B,ordA) lt (ordA^0.6) then
		//print "Criterion I fails";
		return false, 1, L;
	end if;
	
	mwRed:=[(Jq!D)@@psi : D in mwBasis];

	phi:=hom<F->A | mwRed>;
	phires:=hom<L->A| [(F!(L.i))@phi : i in [1..r]]>;
	
	Lnew:=Kernel(phires);

	Q,theta:=quo<L|Lnew>;

	if #Q eq 1 then
		//print "Criterion II fails";
		return false, 2, L;
	end if;

	reps:=[F!(q@@theta) : q in Q | q ne Q!0];  // non-zero coset reps for L/Lnew
	notests:=(#W)*(#reps);  // Approximate number of tests to do
	if notests gt 2*q then
		//print "Criterion III fails";
		return false, 3, L;
	end if;

	for w in W do
		wim:=(Jq!w);
		for l in reps do
			P:=wim+(l@phi)@psi;
			if Degree(P[1]) le 1 then
				//print "Criterion IV fails";
				return false, 4, L;
			end if;
		end for;
	end for;
	Lnew:=sub<F | [F!(L!Lnew.i) : i in [1..r]]>; //identify Lnew 
						// as subgroup of F
	print "Criteria I--IV succeeded for prime", q;
	print "the new index is", Index(F,Lnew)+0.0; // printing index as 
							// a real number
							// o/w it is too long
	return true, 5, Lnew;
end function;

// repeatedly apply the above using all primes from intialprime up to the n-th prime
// where n = primebound,
// badprimes is the set of primes that are of bad reduction, or primes we don't
// check for they have been already used.
// At the end we compute a new constant newB such that the L is contained in newB Z^r
// so that we can repeat the process but using primes up to the n-th prime that did
// not give information in the previous application.
mwSievePrimesEnhance:=function(F,L,W,J,mwBasis,initialprime,primebound,B,badprimes);
        r:=#mwBasis; //rank of J
        amb:=StandardLattice(r);
        successLevels:=[0,0,0,0,0]; // this records the number of primes
                                    // that fail at criteria 1,..,4
                                    // or succeed in all 
                                    // first entry is number of those that fail at criterion 1
                                    // last is number of those that succeed in all criteria
        Llattice:=amb;
        prime:=initialprime;  // 'prime' is the current prime we are working with
      for q:=1 to primebound do;
            if (prime notin badprimes) then; 
                // print "using the prime", prime, "to enhance the information";
                tf, level, L1:=mwSievePrimeEnhance(F,L,W,J,mwBasis,prime,B);
                successLevels[level]:=successLevels[level]+1;
                if tf then
                        badprimes:=Append(badprimes,prime); // the prime will not give us 
                                                            // new information in the next pass
                        L:=L1;
                        Llattice:=sub<amb | [Eltseq(F!(L.i)) : i in [1..r]]>;
                        mL:=Length(ShortestVectors(Llattice)[1]);
                        print "the shortest vector of the new lattice L has length", mL;
//                   print "success levels so far", successLevels;
                end if;
          end if;
            prime:=NextPrime(prime);
        end for;
      newB:=0;
      for g in Generators(L) do;
                newB:=GCD(GCD(Eltseq(F!g)),newB); 
      end for;
 // We will have now j(C) is contained in W + newB*J
return L,newB,Index(F,L),Length(ShortestVectors(Llattice)[1]),successLevels,badprimes,prime;
end function;
