long makeDivisible(VecInt& vec, long p2e, long p2r, long q, double alpha) { assert(((p2e % p2r == 0) && (q % p2e == 1)) || ((p2r % p2e == 0) && (q % p2r == 1))); long maxU =0; ZZ maxZ; for (long i=0; i<vec.length(); i++) { ZZ z, z2; conv(z, vec[i]); long u=0, v=0; long zMod1=0, zMod2=0; if (p2r < p2e && alpha>0) { zMod1 = rem(z,p2r); if (zMod1 > p2r/2) zMod1 -= p2r; // map to the symmetric interval // make z divisible by p^r by adding a multiple of q z2 = z - to_ZZ(zMod1)*q; zMod2 = rem(z2,p2e); // z mod p^e, still divisible by p^r if (zMod2 > p2e/2) zMod2 -= p2e; // map to the symmetric interval zMod2 /= -p2r; // now z+ p^r*zMod2=0 (mod p^e) and |zMod2|<=p^{r(e-1)}/2 u = ceil(alpha * zMod2); v = zMod2 - u; // = floor((1-alpha) * zMod2) z = z2 + u*p2r + to_ZZ(q)*v*p2r; } else { // r >= e or alpha==0, use only mulitples of q zMod1 = rem(z,p2e); if (zMod1 > p2e/2) zMod1 -= p2e; // map to the symmetric interval z -= to_ZZ(zMod1) * q; } if (abs(u) > maxU) maxU = abs(u); if (abs(z) > maxZ) maxZ = abs(z); if (rem(z,p2e) != 0) { // sanity check cerr << "**error: original z["<<i<<"]=" << vec[i] << std::dec << ", p^r="<<p2r << ", p^e="<<p2e << endl; cerr << "z' = z - "<<zMod1<<"*q = "<< z2<<endl; cerr << "z''=z' +" <<u<<"*p^r +"<<v<<"*p^r*q = "<<z<<endl; exit(1); } conv(vec[i], z); // convert back to native format } return maxU; }