DoubleCRT& DoubleCRT::Op(const DoubleCRT &other, Fun fun, bool matchIndexSets) { if (dryRun) return *this; if (&context != &other.context) Error("DoubleCRT::Op: incompatible objects"); // Match the index sets, if needed if (matchIndexSets && !(map.getIndexSet() >= other.map.getIndexSet())) addPrimes(other.map.getIndexSet() / map.getIndexSet()); // This is expensive // If you need to mod-up the other, do it on a temporary scratch copy DoubleCRT tmp(context, IndexSet()); const IndexMap<vec_long>* other_map = &other.map; if (!(map.getIndexSet() <= other.map.getIndexSet())){ // Even more expensive tmp = other; tmp.addPrimes(map.getIndexSet() / other.map.getIndexSet()); other_map = &tmp.map; } const IndexSet& s = map.getIndexSet(); long phim = context.zMStar.getPhiM(); // add/sub/mul the data, element by element, modulo the respective primes for (long i = s.first(); i <= s.last(); i = s.next(i)) { long pi = context.ithPrime(i); vec_long& row = map[i]; const vec_long& other_row = (*other_map)[i]; for (long j = 0; j < phim; j++) row[j] = fun.apply(row[j], other_row[j], pi); } return *this; }
// Generic operators, Fnc is either AddMod or SubMod // This should have been a template, but gcc refuses to cooperate SingleCRT& SingleCRT::Op(const SingleCRT &other, void (*Fnc)(ZZ&, const ZZ&, const ZZ&, const ZZ&), bool matchIndexSets) { if (&context != &other.context) Error("SingleCRT::Op: incomopatible objects"); // Match the index sets, if needed if (matchIndexSets && !(map.getIndexSet() >= other.map.getIndexSet())) addPrimes(other.map.getIndexSet() / map.getIndexSet()); // This is expensive // INVARIANT: map.getIndexSet() >= other.map.getIndexSet()) SingleCRT tmp(context); // a rare case where you want an empty SingleCRT object const IndexMap<ZZX>* other_map = &other.map; if (map.getIndexSet() > other.map.getIndexSet()) { // Even more expensive tmp = other; tmp.addPrimes(map.getIndexSet() / other.map.getIndexSet()); other_map = &tmp.map; } const IndexSet& s = map.getIndexSet(); // add/sub polynomial, modulo the respective primes for (long i = s.first(); i <= s.last(); i = s.next(i)) { ZZ pi = to_ZZ(context.ithPrime(i)); vec_ZZ& vp1 = map[i].rep; const vec_ZZ& vp2 = (*other_map)[i].rep; long len1 = vp1.length(); long len2 = vp2.length(); long maxlen = max(len1, len2); vp1.SetLength(maxlen); for (long j=len1; j < maxlen; j++) clear(vp1[j]); for (long j=0; j<len2; j++) Fnc(vp1[j], vp1[j], vp2[j], pi); map[i].normalize(); } return *this; }