reflector_t makeM4Reflector(const reflector_t& thin, const reflector_t& greek, char offset, int ring) { reflector_t reflector = { thin.name + ":" + greek.name + ":" + offset }; offset -= 'A'; offset = static_cast<char> (SubMod(offset, ring - 1)); // make the inverse of the mappings int inverse_thin[26], inverse_greek[26]; for (int i = 0; i < 26; i++) { for (int j = 0; j < 26; j++) { if (thin.map[j] == i) inverse_thin[i] = j; if (greek.map[j] == i) inverse_greek[i] = j; } } // work out effective mapping for (int i = 0; i < 26; i++) { // enter greek rotor int ch = greek.map[AddMod(i, offset)]; // through the thin reflector ch = AddMod(inverse_thin[SubMod(ch, offset)], offset); // and back out the greek rotor reflector.map[i] = static_cast<char> (SubMod(inverse_greek[ch], offset)); } return reflector; }
void mul_aux(vec_zz_p& x, const mat_zz_p& A, const vec_zz_p& b) { long n = A.NumRows(); long l = A.NumCols(); if (l != b.length()) LogicError("matrix mul: dimension mismatch"); x.SetLength(n); zz_p* xp = x.elts(); long p = zz_p::modulus(); mulmod_t pinv = zz_p::ModulusInverse(); long i, k; long acc, tmp; const zz_p* bp = b.elts(); if (n <= 1) { for (i = 0; i < n; i++) { acc = 0; const zz_p* ap = A[i].elts(); for (k = 0; k < l; k++) { tmp = MulMod(rep(ap[k]), rep(bp[k]), p, pinv); acc = AddMod(acc, tmp, p); } xp[i].LoopHole() = acc; } } else { Vec<mulmod_precon_t>::Watcher watch_precon_vec(precon_vec); precon_vec.SetLength(l); mulmod_precon_t *bpinv = precon_vec.elts(); for (k = 0; k < l; k++) bpinv[k] = PrepMulModPrecon(rep(bp[k]), p, pinv); for (i = 0; i < n; i++) { acc = 0; const zz_p* ap = A[i].elts(); for (k = 0; k < l; k++) { tmp = MulModPrecon(rep(ap[k]), rep(bp[k]), p, bpinv[k]); acc = AddMod(acc, tmp, p); } xp[i].LoopHole() = acc; } } }
void InnerProduct(zz_p& x, const vec_zz_p& a, const vec_zz_p& b, long offset) { if (offset < 0) LogicError("InnerProduct: negative offset"); if (NTL_OVERFLOW(offset, 1, 0)) ResourceError("InnerProduct: offset too big"); long n = min(a.length(), b.length()+offset); long i; long accum, t; long p = zz_p::modulus(); mulmod_t pinv = zz_p::ModulusInverse(); const zz_p *ap = a.elts(); const zz_p *bp = b.elts(); accum = 0; for (i = offset; i < n; i++) { t = MulMod(rep(ap[i]), rep(bp[i-offset]), p, pinv); accum = AddMod(accum, t, p); } x.LoopHole() = accum; }
// Compute the mapping between linear array and a hypercube corresponding /// to a single generator tree void ComputeOneGenMapping(Permut& genMap, const OneGeneratorTree& T) { Vec<long> dims(INIT_SIZE, T.getNleaves()); Vec<long> coefs(INIT_SIZE,T.getNleaves()); for (long i=T.getNleaves()-1, leaf=T.lastLeaf(); i>=0; i--, leaf=T.prevLeaf(leaf)) { dims[i] = T[leaf].getData().size; coefs[i] = T[leaf].getData().e; } // A representation of an integer with digits from dims Vec<long> rep(INIT_SIZE, T.getNleaves()); for (long i=0; i<rep.length(); i++) rep[i]=0; // initialize to zero // initialize to all zero long sz = T[0].getData().size; genMap.SetLength(sz); for (long i=0; i<sz; i++) genMap[i]=0; // compute the permutation for (long i=1; i<sz; i++) { addOne(rep, dims); // representation of i in base dims for (long j=0; j<coefs.length(); j++) { long tmp = MulMod(rep[j], coefs[j], sz); genMap[i] = AddMod(genMap[i], tmp, sz); } } }
void InnerProduct(zz_pX& x, const vec_zz_p& v, long low, long high, const vec_zz_pX& H, long n, vec_zz_p& t) { zz_p s; long i, j; zz_p *tp = t.elts(); for (j = 0; j < n; j++) clear(tp[j]); long p = zz_p::modulus(); double pinv = zz_p::ModulusInverse(); high = min(high, v.length()-1); for (i = low; i <= high; i++) { const vec_zz_p& h = H[i-low].rep; long m = h.length(); zz_p w = (v[i]); long W = rep(w); mulmod_precon_t Wpinv = PrepMulModPrecon(W, p, pinv); // ((double) W)*pinv; const zz_p *hp = h.elts(); for (j = 0; j < m; j++) { long S = MulModPrecon(rep(hp[j]), W, p, Wpinv); S = AddMod(S, rep(tp[j]), p); tp[j].LoopHole() = S; } } x.rep = t; x.normalize(); }
long polyEvalMod(const ZZX& poly, long x, long p) { long ret = 0; x %= p; if (x<0) x += p; mulmod_precon_t xpinv = PrepMulModPrecon(x, p); for (long i=deg(poly); i>=0; i--) { long coeff = rem(poly[i], p); ret = AddMod(ret, coeff, p); // Add the coefficient of x^i if (i>0) ret = MulModPrecon(ret, x, p, xpinv); // then mult by x } return ret; }
long simplePolyEval(const ZZX& poly, DynamicPtxtPowers& babyStep, long mod) { assert (deg(poly)<=(long)babyStep.size());// ensure that we have enough powers long ret = rem(ConstTerm(poly), mod); for (long i=0; i<deg(poly); i++) { long coeff = rem(poly[i+1], mod); // f_{i+1} long tmp = babyStep[i]; // X^{i+1} tmp = MulMod(tmp, coeff, mod); // f_{i+1} X^{i+1} ret = AddMod(ret, tmp, mod); } return ret; }
void CModList::copyData( CModList *from ) { // Copy data and counts, etc Reset(); // Remove any current data int i; CMod *p; for ( i = from->getCount()-1; i >= 0 ; i-- ) { p = from->getMod( i ); from->RemoveMod( p ); AddMod( p ); } }
void CPathManager::LoadModsFromDir(const std::string &dir) { try { #if PLATFORM_WINDOWS boost::filesystem::directory_iterator iterator(CSystemUtilsWindows::UTF8_Decode(dir)); #else boost::filesystem::directory_iterator iterator(dir); #endif for(; iterator != boost::filesystem::directory_iterator(); ++iterator) { #if PLATFORM_WINDOWS AddMod(CSystemUtilsWindows::UTF8_Encode(iterator->path().wstring())); #else AddMod(iterator->path().string()); #endif } } catch (std::exception &e) { GetLogger()->Warn("Unable to load mods from directory '%s': %s\n", dir.c_str(), e.what()); } }
void CMissionData::ReadFromMessage(ILTCSBase *pInterface, HMESSAGEREAD hMessage) { if (!hMessage) return; // Clear our data... Clear(); // Read in the new data... m_nMission = (int) pInterface->ReadFromMessageFloat(hMessage); m_nLevel = (int) pInterface->ReadFromMessageFloat(hMessage); int nSize = (int) pInterface->ReadFromMessageDWord(hMessage); int i; CWeaponData Weapon; for (i = 0; i < nSize; i++) { Weapon.ReadFromMessage(pInterface, hMessage); AddWeapon(Weapon.m_nID); } nSize = (int) pInterface->ReadFromMessageDWord(hMessage); CAmmoData Ammo; for (i = 0; i < nSize; i++) { Ammo.ReadFromMessage(pInterface, hMessage); AddAmmo(Ammo.m_nID, Ammo.m_nCount); } nSize = (int) pInterface->ReadFromMessageDWord(hMessage); CModData Mod; for (i = 0; i < nSize; i++) { Mod.ReadFromMessage(pInterface, hMessage); AddMod(Mod.m_nID); } nSize = (int) pInterface->ReadFromMessageDWord(hMessage); CGearData Gear; for (i = 0; i < nSize; i++) { Gear.ReadFromMessage(pInterface, hMessage); AddGear(Gear.m_nID); } }
void add(vec_zz_p& x, const vec_zz_p& a, const vec_zz_p& b) { long n = a.length(); if (b.length() != n) LogicError("vector add: dimension mismatch"); long p = zz_p::modulus(); x.SetLength(n); const zz_p *ap = a.elts(); const zz_p *bp = b.elts(); zz_p *xp = x.elts(); long i; for (i = 0; i < n; i++) xp[i].LoopHole() = AddMod(rep(ap[i]), rep(bp[i]), p); }
// This procedure assumes that k*(2^e +1) > deg(poly) > k*(2^e -1), // and that babyStep contains k+ (deg(poly) mod k) powers static long degPowerOfTwo(const ZZX& poly, long k, DynamicPtxtPowers& babyStep, DynamicPtxtPowers& giantStep, long mod, long& recursiveDepth) { if (deg(poly)<=babyStep.size()) { // Edge condition, use simple eval long ret = simplePolyEval(poly, babyStep, mod); recursiveDepth = babyStep.getDepth(deg(poly)); return ret; } long subDepth1 =0, subDepth2=0; long n = deg(poly)/k; // We assume n=2^e or n=2^e -1 n = 1L << NextPowerOfTwo(n); // round up to n=2^e ZZX r = trunc(poly, (n-1)*k); // degree <= k(2^e-1)-1 ZZX q = RightShift(poly, (n-1)*k); // 0 < degree < 2k SetCoeff(r, (n-1)*k); // monic, degree == k(2^e-1) q -= 1; if (verbose) cerr << ", recursing on "<<r<<" + X^"<<(n-1)*k<<"*"<<q<<endl; long ret = PatersonStockmeyer(r, k, n/2, 0, babyStep, giantStep, mod, subDepth2); if (verbose) cerr << " PatersonStockmeyer("<<r<<") returns "<<ret << ", depth="<<subDepth2<<endl; long tmp = simplePolyEval(q, babyStep, mod); // evaluate q subDepth1 = babyStep.getDepth(deg(q)); if (verbose) cerr << " simplePolyEval("<<q<<") returns "<<tmp << ", depth="<<subDepth1<<endl; // multiply by X^{k(n-1)} with minimum depth for (long i=1; i<n; i*=2) { tmp = MulMod(tmp, giantStep.getPower(i), mod); nMults++; subDepth1 = max(subDepth1, giantStep.getDepth(i)) +1; if (verbose) cerr << " after mult by giantStep.getPower("<<i<< ")=" << giantStep.getPower(i)<<" of depth="<< giantStep.getDepth(i) << ", ret="<<tmp<<" and depth is "<<subDepth1<<endl; } totalDepth = max(subDepth1, subDepth2); return AddMod(ret, tmp, mod); // return q * X^{k(n-1)} + r }
ZZ PaillierParty::decrypt(const std::map<uint32_t,ZZ> &partialCiphers, const std::vector<ZZ> &pubKeys) { ZZ sum(0); for (auto &pubKey : pubKeys) { sum = AddMod(sum,pubKey,m_n); } ZZ phi = MulMod(m_a,sum,m_n); ZZ prod(1); for (auto &partialCipher: partialCiphers) { uint32_t partyId = partialCipher.first; prod = MulMod(prod,PowerMod(partialCipher.second, 2*m_lagrangeBasis[partyId],m_field),m_field); } ZZ LResult = L_function(prod); ZZ combinedShare = InvMod(MulMod(4*m_delta*m_delta,phi,m_n),m_n); return MulMod(LResult, combinedShare, m_n); }
void InnerProduct(zz_p& x, const vec_zz_p& a, const vec_zz_p& b) { long n = min(a.length(), b.length()); long i; long accum, t; long p = zz_p::modulus(); mulmod_t pinv = zz_p::ModulusInverse(); const zz_p *ap = a.elts(); const zz_p *bp = b.elts(); accum = 0; for (i = 0; i < n; i++) { t = MulMod(rep(ap[i]), rep(bp[i]), p, pinv); accum = AddMod(accum, t, p); } x.LoopHole() = accum; }
static void BuildMatrix(vec_ZZVec& M, long n, const ZZ_pX& g, const ZZ_pXModulus& F, long verbose) { long i, j, m; ZZ_pXMultiplier G; ZZ_pX h; ZZ t; sqr(t, ZZ_p::modulus()); mul(t, t, n); long size = t.size(); M.SetLength(n); for (i = 0; i < n; i++) M[i].SetSize(n, size); build(G, g, F); set(h); for (j = 0; j < n; j++) { if (verbose && j % 10 == 0) cerr << "+"; m = deg(h); for (i = 0; i < n; i++) { if (i <= m) M[i][j] = rep(h.rep[i]); else clear(M[i][j]); } if (j < n-1) MulMod(h, h, G, F); } for (i = 0; i < n; i++) AddMod(M[i][i], M[i][i], -1, ZZ_p::modulus()); }
ZZ ASTAdd::eval(Environment &env) { pair<VarInfo,VarInfo> p = getTypes(env); VarInfo leftInfo = p.first; VarInfo rightInfo = p.second; // only need to do modular operations if one of the // variables is a group element; otherwise just do things // over the integers bool isElmt = (leftInfo.type == VarInfo::ELEMENT || rightInfo.type == VarInfo::ELEMENT); // integers/exponents can just be added, but if there is an // exponent we want to retain the group information if (isElmt == 0){ return lhs->eval(env) + rhs->eval(env); } else { const Group* lGroup = env.groups.at(leftInfo.group); const Group* rGroup = env.groups.at(rightInfo.group); const Group* retGroup = (lGroup != 0 ? lGroup : rGroup); assert(retGroup); ZZ mod = retGroup->getModulus(); return AddMod(lhs->eval(env), rhs->eval(env), mod); } }
DataEditorControl::DataEditorControl(Ui::MainWindow *ui) { //设置视图模型 mSoldierTableModule = new SoldierTableModule(this); mSoldierTableView = ui->soldierTableView; mSoldierTableView->setModel(mSoldierTableModule); mHorseTableModule = new HorseTableModule(this); mHorseTableView = ui->horseTableView; mHorseTableView->setModel(mHorseTableModule); mPWeaponTableModule = new PWeaponTableModule(this); mPWeaponTableView = ui->pweaponTableView; mPWeaponTableView->setModel(mPWeaponTableModule); mSWeaponTableModule = new SWeaponTableModule(this); mSWeaponTableView = ui->sweaponTableView; mSWeaponTableView->setModel(mSWeaponTableModule); mArmorTableModule = new ArmorTableModule(this); mArmorTableView = ui->armorTableView; mArmorTableView->setModel(mArmorTableModule); mShieldTableModule = new ShieldTableModule(this); mShieldTableView = ui->shieldTableView; mShieldTableView->setModel(mShieldTableModule); mSkillTableModule = new SkillTableModule(this); mSkillTableView = ui->skillTableView; mSkillTableView->setModel(mSkillTableModule); mEffectTableModule = new EffectTableModule(this); mEffectTableView = ui->effectTableView; mEffectTableView->setModel(mEffectTableModule); mSquadTableModule = new SquadTableModule(this); mSquadTableView = ui->squadTableView; mSquadTableView->setModel(mSquadTableModule); mSquadSkillTableModule = new SquadSkillTableModule(this); mSquadSkillTableView = ui->squadSkillTableView; mSquadSkillTableView->setModel(mSquadSkillTableModule); mStringTableModule = new StringTableModule(this); mStringTableView = ui->stringTableView; mStringTableView->setModel(mStringTableModule); mModBox = ui->modBox; mLangBox = ui->langBox; RefreshModList(); //连接消息 connect(ui->addMod,SIGNAL(clicked()),this,SLOT(AddMod())); connect(ui->addLang,SIGNAL(clicked()),this,SLOT(AddLang())); connect(ui->addSoldier,SIGNAL(clicked()),this,SLOT(AddSoldier())); connect(ui->delSoldier,SIGNAL(clicked()),this,SLOT(DelSoldier())); connect(ui->addHorse,SIGNAL(clicked()),this,SLOT(AddHorse())); connect(ui->delHorse,SIGNAL(clicked()),this,SLOT(DelHorse())); connect(ui->addPWeapon,SIGNAL(clicked()),this,SLOT(AddPWeapon())); connect(ui->delPWeapon,SIGNAL(clicked()),this,SLOT(DelPWeapon())); connect(ui->addSWeapon,SIGNAL(clicked()),this,SLOT(AddSWeapon())); connect(ui->delSWeapon,SIGNAL(clicked()),this,SLOT(DelSWeapon())); connect(ui->addArmor,SIGNAL(clicked()),this,SLOT(AddArmor())); connect(ui->delArmor,SIGNAL(clicked()),this,SLOT(DelArmor())); connect(ui->addShield,SIGNAL(clicked()),this,SLOT(AddShield())); connect(ui->delShield,SIGNAL(clicked()),this,SLOT(DelShield())); connect(ui->addSkill,SIGNAL(clicked()),this,SLOT(AddSkill())); connect(ui->delSkill,SIGNAL(clicked()),this,SLOT(DelSkill())); connect(ui->addEffect,SIGNAL(clicked()),this,SLOT(AddEffect())); connect(ui->delEffect,SIGNAL(clicked()),this,SLOT(DelEffect())); connect(ui->addSquad,SIGNAL(clicked()),this,SLOT(AddSquad())); connect(ui->delSquad,SIGNAL(clicked()),this,SLOT(DelSquad())); connect(ui->addSquadSkill,SIGNAL(clicked()),this,SLOT(AddSquadSkill())); connect(ui->delSquadSkill,SIGNAL(clicked()),this,SLOT(DelSquadSkill())); connect(ui->addString,SIGNAL(clicked()),this,SLOT(AddString())); connect(ui->delString,SIGNAL(clicked()),this,SLOT(DelString())); connect(ui->squadTableView,SIGNAL(clicked(const QModelIndex &)),this,SLOT(SelectSquad(const QModelIndex &))); }
// This procedure assumes that poly is monic, deg(poly)=k*(2t-1)+delta // with t=2^e, and that babyStep contains k+delta powers static long PatersonStockmeyer(const ZZX& poly, long k, long t, long delta, DynamicPtxtPowers& babyStep, DynamicPtxtPowers& giantStep, long mod, long& recursiveDepth) { if (verbose) cerr << "PatersonStockmeyer("<<poly<<"), k="<<k<<", t="<<t<<endl; if (deg(poly)<=babyStep.size()) { // Edge condition, use simple eval long ret = simplePolyEval(poly, babyStep, mod); recursiveDepth = babyStep.getDepth(deg(poly)); return ret; } long subDepth1=0, subDepth2=0; long ret, tmp; ZZX r = trunc(poly, k*t); // degree <= k*2^e-1 ZZX q = RightShift(poly, k*t); // degree == k(2^e-1) +delta if (verbose) cerr << " r ="<<r<< ", q="<<q; const ZZ& coef = coeff(r,deg(q)); SetCoeff(r, deg(q), coef-1); // r' = r - X^{deg(q)} if (verbose) cerr << ", r'="<<r; ZZX c,s; DivRem(c,s,r,q); // r' = c*q + s // deg(s)<deg(q), and if c!= 0 then deg(c)<k-delta if (verbose) cerr << ", c="<<c<< ", s ="<<s<<endl; assert(deg(s)<deg(q)); assert(IsZero(c) || deg(c)<k-delta); SetCoeff(s,deg(q)); // s' = s + X^{deg(q)}, deg(s)==deg(q) // reduce the coefficients modulo mod for (long i=0; i<=deg(c); i++) rem(c[i],c[i], to_ZZ(mod)); c.normalize(); for (long i=0; i<=deg(s); i++) rem(s[i],s[i], to_ZZ(mod)); s.normalize(); if (verbose) cerr << " {t==n+1} recursing on "<<s<<" + (X^"<<t*k<<"+"<<c<<")*"<<q<<endl; // Evaluate recursively poly = (c+X^{kt})*q + s' tmp = simplePolyEval(c, babyStep, mod); tmp = AddMod(tmp, giantStep.getPower(t), mod); subDepth1 = max(babyStep.getDepth(deg(c)), giantStep.getDepth(t)); ret = PatersonStockmeyer(q, k, t/2, delta, babyStep, giantStep, mod, subDepth2); if (verbose) { cerr << " PatersonStockmeyer("<<q<<") returns "<<ret << ", depth="<<subDepth2<<endl; if (ret != polyEvalMod(q,babyStep[0], mod)) { cerr << " **1st recursive call failed, q="<<q<<endl; exit(0); } } ret = MulMod(ret, tmp, mod); nMults++; subDepth1 = max(subDepth1, subDepth2)+1; tmp = PatersonStockmeyer(s, k, t/2, delta, babyStep, giantStep, mod, subDepth2); if (verbose) { cerr << " PatersonStockmeyer("<<s<<") returns "<<tmp << ", depth="<<subDepth2<<endl; if (tmp != polyEvalMod(s,babyStep[0], mod)) { cerr << " **2nd recursive call failed, s="<<s<<endl; exit(0); } } ret = AddMod(ret,tmp,mod); recursiveDepth = max(subDepth1, subDepth2); return ret; }
int main(int argc, char* args[]) { int myMachineType = 0; printf("Enigma I/M3 or M4? Enter 3 or 4:\n"); scanf("%d", &myMachineType); getchar(); //pull one newline off the input buffer if (myMachineType < 3 || myMachineType > 4) { printf("ERROR: machine type invalid; must be 3: I/M3 or 4: M4!\n"); return -1; } char plugPairs[40]; //max 13 pairs of letters + space //prompt user for plug board settings printf("Enter plugboard wiring (if any) as space separated pairs"); printf(" (Ex. AN BY CX ):\n"); fgets(plugPairs, sizeof plugPairs, stdin); plugboard_t myPlugboard(plugPairs); reflector_t myReflector, thinReflector, grWheel; char reflektor, grLetter, grStart; int grRing; if (myMachineType == 3) { printf("Enter Reflector (A, B, or C):\n"); scanf("%c", &reflektor); getchar(); //pull one newline off the input buffer reflektor = static_cast<char> (toupper(reflektor)); if (reflektor != 'A' && reflektor != 'B' && reflektor != 'C') { printf("Error - reflector must be A, B, or C.\n"); return -1; } myReflector = makeM3Reflector(reflektor); }//endif machine I/M3 if (myMachineType == 4) { printf("Enter thin reflector (B or C):\n"); scanf("%c", &reflektor); getchar(); //pull one newline off the input buffer reflektor = static_cast<char> (toupper(reflektor)); if (reflektor != 'B' && reflektor != 'C') { printf("Error - thin reflector must be B or C.\n"); return -1; } switch (reflektor) { case 'B': thinReflector = B_Thin; break; case 'C': thinReflector = C_Thin; break; default: printf("Thin reflector value invalid; defaulting to thin B.\n"); thinReflector = B_Thin; break; } //prompt user for greek rotor beta or gamma printf("Enter Greek Rotor ([B]eta or [G]amma):\n"); scanf("%c", &grLetter); getchar(); //pull one newline off the input buffer grLetter = static_cast<char> (toupper(grLetter)); if (grLetter != 'B' && grLetter != 'G') { printf("Error - Greek Rotor must be B/G for Beta/Gamma.\n"); return -1; } switch (grLetter) { case 'B': grWheel = Beta; break; case 'G': grWheel = Gamma; break; default: printf("Greek rotor value invalid; defaulting to Beta.\n"); grWheel = Beta; break; } printf("Enter starting char of greek wheel (A-Z):\n"); scanf("%c", &grStart); getchar(); //pull one newline off the input buffer grStart = static_cast<char> (toupper(grStart)); if (grStart < 'A' || grStart > 'Z') { printf("Error - Start of Greek wheel must be A-Z.\n"); return -1; } printf("Enter greek wheel ring position (1-26):\n"); scanf("%d", &grRing); getchar(); //pull one newline off the input buffer if (grRing < 1 || grRing > 26) { printf("Error - Greek ring must be 1-26.\n"); return -1; } myReflector = makeM4Reflector(thinReflector, grWheel, grStart, grRing); }//endif machine M4 //prompt user for rotors, positions, rings char leftRoman[5], middleRoman[5], rightRoman[5]; printf("Enter left, middle, right rotor numbers (I-VIII) (Ex. I II IV: \n"); scanf("%4s %4s %4s", leftRoman, middleRoman, rightRoman); getchar(); //pull one newline off the input buffer strToUpper(leftRoman); strToUpper(middleRoman); strToUpper(rightRoman); rotor_t myLeftRotor = assignRotor(leftRoman); rotor_t myMiddleRotor = assignRotor(middleRoman); rotor_t myRightRotor = assignRotor(rightRoman); char lStart, mStart, rStart; printf("Enter starting chars, msg key, (A-Z) left to right (Ex. A A A):\n"); scanf("%c %c %c", &lStart, &mStart, &rStart); getchar(); //pull one newline off the input buffer lStart = static_cast<char> (toupper(lStart)); mStart = static_cast<char> (toupper(mStart)); rStart = static_cast<char> (toupper(rStart)); if (lStart < 'A' || lStart > 'Z') { printf("Error - Start of left rotor must be A-Z.\n"); return -1; } if (mStart < 'A' || mStart > 'Z') { printf("Error - Start of middle must be A-Z.\n"); return -1; } if (rStart < 'A' || rStart > 'Z') { printf("Error - Start of right rotor must be A-Z.\n"); return -1; } int lRing, mRing, rRing; printf("Enter ring positions (1-26) left to right (Ex. 1 1 1):\n"); scanf("%d %d %d", &lRing, &mRing, &rRing); getchar(); //pull one newline off the input buffer //check if (lRing < 1 || lRing > 26) { printf("Error - left ring must be 1-26.\n"); return -1; } if (mRing < 1 || mRing > 26) { printf("Error - middle ring must be 1-26.\n"); return -1; } if (rRing < 1 || rRing > 26) { printf("Error - right ring must be 1-26.\n"); return -1; } Enigma myEnigma(myReflector, myLeftRotor, myMiddleRotor, myRightRotor); myEnigma.init(lStart - 'A', lRing - 1, mStart - 'A', mRing - 1, rStart - 'A', rRing - 1); printf("Beginning display:\n"); if (myMachineType == 4) { //printf("%c ", myEnigma.reflector.name.back());//c++11 only printf("%c ", myEnigma.reflector.name.at(myEnigma.reflector.name.length() - 1)); } printf("%c %c %c\n", AddMod(myEnigma.left.ofs, lRing - 1) + 'A', AddMod(myEnigma.middle.ofs, mRing - 1) + 'A', AddMod(myEnigma.right.ofs, rRing - 1) + 'A'); char myMessage[256]; //read somewhere messages were <= 250 printf("Enter your message (256 char limit):\n"); fgets(myMessage, sizeof myMessage, stdin); //remove the null terminator and make upper case for (unsigned int i = 0; i < sizeof(myMessage); ++i) { if (myMessage[i] == '\n') { myMessage[i] = '\0'; } myMessage[i] = static_cast<char> (toupper(myMessage[i])); } std::string output; for (int i = 0; myMessage[i]; i++) { myEnigma.advance(); int ch = myPlugboard.map[myMessage[i] - 'A']; assert(ch >= 0 && ch < 26); ch = myEnigma.code(ch); assert(ch >= 0 && ch < 26); ch = myPlugboard.map[ch]; output += ch + 'A'; } //end for msg printf("message: \n\t%s\n", myMessage); printf("encoded: \n\t%s\n", output.c_str()); printf("Ending display:\n"); if (myMachineType == 4) { //printf("%c ", myEnigma.reflector.name.back());//c++11 only printf("%c ", myEnigma.reflector.name.at(myEnigma.reflector.name.length() - 1)); } printf("%c %c %c\n", AddMod(myEnigma.left.ofs, lRing - 1) + 'A', AddMod(myEnigma.middle.ofs, mRing - 1) + 'A', AddMod(myEnigma.right.ofs, rRing - 1) + 'A'); return 0; }
// This procedure assumes that poly is monic and that babyStep contains // at least k+delta powers, where delta = deg(poly) mod k static long recursivePolyEval(const ZZX& poly, long k, DynamicPtxtPowers& babyStep, DynamicPtxtPowers& giantStep, long mod, long& recursiveDepth) { if (deg(poly)<=babyStep.size()) { // Edge condition, use simple eval long ret = simplePolyEval(poly, babyStep, mod); recursiveDepth = babyStep.getDepth(deg(poly)); return ret; } if (verbose) cerr << "recursivePolyEval("<<poly<<")\n"; long delta = deg(poly) % k; // deg(poly) mod k long n = divc(deg(poly),k); // ceil( deg(poly)/k ) long t = 1L<<(NextPowerOfTwo(n)); // t >= n, so t*k >= deg(poly) // Special case for deg(poly) = k * 2^e +delta if (n==t) return degPowerOfTwo(poly, k, babyStep, giantStep, mod, recursiveDepth); // When deg(poly) = k*(2^e -1) we use the Paterson-Stockmeyer recursion if (n == t-1 && delta==0) return PatersonStockmeyer(poly, k, t/2, delta, babyStep, giantStep, mod, recursiveDepth); t = t/2; // In any other case we have kt < deg(poly) < k(2t-1). We then set // u = deg(poly) - k*(t-1) and poly = q*X^u + r with deg(r)<u // and recurse on poly = (q-1)*X^u + (X^u+r) long u = deg(poly) - k*(t-1); ZZX r = trunc(poly, u); // degree <= u-1 ZZX q = RightShift(poly, u); // degree == k*(t-1) q -= 1; SetCoeff(r, u); // degree == u long ret, tmp; long subDepth1=0, subDepth2=0; if (verbose) cerr << " {deg(poly)="<<deg(poly)<<"<k*(2t-1)="<<k*(2*t-1) << "} recursing on "<<r<<" + X^"<<u<<"*"<<q<<endl; ret = PatersonStockmeyer(q, k, t/2, 0, babyStep, giantStep, mod, subDepth1); if (verbose) { cerr << " PatersonStockmeyer("<<q<<") returns "<<ret<<", depth="<<subDepth1<<endl; if (ret != polyEvalMod(q,babyStep[0], mod)) { cerr << " @@1st recursive call failed, q="<<q << ", ret="<<ret<<"!=" << polyEvalMod(q,babyStep[0], mod)<<endl; exit(0); } } tmp = giantStep.getPower(u/k); subDepth2 = giantStep.getDepth(u/k); if (delta!=0) { // if u is not divisible by k then compute it if (verbose) cerr <<" multiplying by X^"<<u <<"=giantStep.getPower("<<(u/k)<<")*babyStep.getPower("<<delta<<")=" << giantStep.getPower(u/k)<<"*"<<babyStep.getPower(delta) << "="<<tmp<<endl; tmp = MulMod(tmp, babyStep.getPower(delta), mod); nMults++; subDepth2++; } ret = MulMod(ret, tmp, mod); nMults ++; subDepth1 = max(subDepth1, subDepth2)+1; if (verbose) cerr << " after mult by X^{k*"<<u<<"+"<<delta<<"}, depth="<< subDepth1<<endl; tmp = recursivePolyEval(r, k, babyStep, giantStep, mod, subDepth2); if (verbose) cerr << " recursivePolyEval("<<r<<") returns "<<tmp<<", depth="<<subDepth2<<endl; if (tmp != polyEvalMod(r,babyStep[0], mod)) { cerr << " @@2nd recursive call failed, r="<<r << ", ret="<<tmp<<"!=" << polyEvalMod(r,babyStep[0], mod)<<endl; exit(0); } recursiveDepth = max(subDepth1, subDepth2); return AddMod(ret, tmp, mod); }
void mul(vec_zz_p& x, const vec_zz_p& a, const mat_zz_p& B) { long l = a.length(); long m = B.NumCols(); if (l != B.NumRows()) LogicError("matrix mul: dimension mismatch"); if (m == 0) { x.SetLength(0); } else if (m == 1) { long p = zz_p::modulus(); mulmod_t pinv = zz_p::ModulusInverse(); long acc, tmp; long k; acc = 0; for(k = 1; k <= l; k++) { tmp = MulMod(rep(a(k)), rep(B(k,1)), p, pinv); acc = AddMod(acc, tmp, p); } x.SetLength(1); x(1).LoopHole() = acc; } else { // m > 1. precondition long p = zz_p::modulus(); mulmod_t pinv = zz_p::ModulusInverse(); vec_long::Watcher watch_mul_aux_vec(mul_aux_vec); mul_aux_vec.SetLength(m); long *acc = mul_aux_vec.elts(); long j, k; const zz_p* ap = a.elts(); for (j = 0; j < m; j++) acc[j] = 0; for (k = 0; k < l; k++) { long aa = rep(ap[k]); if (aa != 0) { const zz_p* bp = B[k].elts(); long T1; mulmod_precon_t aapinv = PrepMulModPrecon(aa, p, pinv); for (j = 0; j < m; j++) { T1 = MulModPrecon(rep(bp[j]), aa, p, aapinv); acc[j] = AddMod(acc[j], T1, p); } } } x.SetLength(m); zz_p *xp = x.elts(); for (j = 0; j < m; j++) xp[j].LoopHole() = acc[j]; } }
void FFT(long* A, const long* a, long k, long q, const long* root, FFTMultipliers& tab) // performs a 2^k-point convolution modulo q { if (k <= 1) { if (k == 0) { A[0] = a[0]; return; } if (k == 1) { long a0 = AddMod(a[0], a[1], q); long a1 = SubMod(a[0], a[1], q); A[0] = a0; A[1] = a1; return; } } // assume k > 1 if (k > tab.MaxK) PrecompFFTMultipliers(k, q, root, tab); NTL_THREAD_LOCAL static Vec<long> AA_store; AA_store.SetLength(1L << k); long *AA = AA_store.elts(); BitReverseCopy(AA, a, k); long n = 1L << k; long s, m, m_half, m_fourth, i, j, t, u, t1, u1, tt, tt1; // s = 1 for (i = 0; i < n; i += 2) { t = AA[i + 1]; u = AA[i]; AA[i] = AddMod(u, t, q); AA[i+1] = SubMod(u, t, q); } for (s = 2; s < k; s++) { m = 1L << s; m_half = 1L << (s-1); m_fourth = 1L << (s-2); const long* wtab = tab.wtab_precomp[s].elts(); const mulmod_precon_t *wqinvtab = tab.wqinvtab_precomp[s].elts(); for (i = 0; i < n; i+= m) { long *AA0 = &AA[i]; long *AA1 = &AA[i + m_half]; #if (NTL_PIPELINE) // pipelining: seems to be faster t = AA1[0]; u = AA0[0]; t1 = MulModPrecon(AA1[1], wtab[1], q, wqinvtab[1]); u1 = AA0[1]; for (j = 0; j < m_half-2; j += 2) { long a02 = AA0[j+2]; long a03 = AA0[j+3]; long a12 = AA1[j+2]; long a13 = AA1[j+3]; long w2 = wtab[j+2]; long w3 = wtab[j+3]; mulmod_precon_t wqi2 = wqinvtab[j+2]; mulmod_precon_t wqi3 = wqinvtab[j+3]; tt = MulModPrecon(a12, w2, q, wqi2); long b00 = AddMod(u, t, q); long b10 = SubMod(u, t, q); tt1 = MulModPrecon(a13, w3, q, wqi3); long b01 = AddMod(u1, t1, q); long b11 = SubMod(u1, t1, q); AA0[j] = b00; AA1[j] = b10; AA0[j+1] = b01; AA1[j+1] = b11; t = tt; u = a02; t1 = tt1; u1 = a03; } AA0[j] = AddMod(u, t, q); AA1[j] = SubMod(u, t, q); AA0[j + 1] = AddMod(u1, t1, q); AA1[j + 1] = SubMod(u1, t1, q); } #else for (j = 0; j < m_half; j += 2) { const long a00 = AA0[j]; const long a01 = AA0[j+1]; const long a10 = AA1[j]; const long a11 = AA1[j+1]; const long w0 = wtab[j]; const long w1 = wtab[j+1]; const mulmod_precon_t wqi0 = wqinvtab[j]; const mulmod_precon_t wqi1 = wqinvtab[j+1]; const long tt = MulModPrecon(a10, w0, q, wqi0); const long uu = a00; const long b00 = AddMod(uu, tt, q); const long b10 = SubMod(uu, tt, q); const long tt1 = MulModPrecon(a11, w1, q, wqi1); const long uu1 = a01; const long b01 = AddMod(uu1, tt1, q); const long b11 = SubMod(uu1, tt1, q); AA0[j] = b00; AA0[j+1] = b01; AA1[j] = b10; AA1[j+1] = b11; } } #endif }
void FFT(long* A, const long* a, long k, long q, const long* root) // performs a 2^k-point convolution modulo q { if (k <= 1) { if (k == 0) { A[0] = a[0]; return; } if (k == 1) { long a0 = AddMod(a[0], a[1], q); long a1 = SubMod(a[0], a[1], q); A[0] = a0; A[1] = a1; return; } } // assume k > 1 NTL_THREAD_LOCAL static Vec<long> wtab_store; NTL_THREAD_LOCAL static Vec<mulmod_precon_t> wqinvtab_store; NTL_THREAD_LOCAL static Vec<long> AA_store; wtab_store.SetLength(1L << (k-2)); wqinvtab_store.SetLength(1L << (k-2)); AA_store.SetLength(1L << k); long * NTL_RESTRICT wtab = wtab_store.elts(); mulmod_precon_t * NTL_RESTRICT wqinvtab = wqinvtab_store.elts(); long *AA = AA_store.elts(); double qinv = 1/((double) q); wtab[0] = 1; wqinvtab[0] = PrepMulModPrecon(1, q, qinv); BitReverseCopy(AA, a, k); long n = 1L << k; long s, m, m_half, m_fourth, i, j, t, u, t1, u1, tt, tt1; long w; mulmod_precon_t wqinv; // s = 1 for (i = 0; i < n; i += 2) { t = AA[i + 1]; u = AA[i]; AA[i] = AddMod(u, t, q); AA[i+1] = SubMod(u, t, q); } for (s = 2; s < k; s++) { m = 1L << s; m_half = 1L << (s-1); m_fourth = 1L << (s-2); w = root[s]; wqinv = PrepMulModPrecon(w, q, qinv); // prepare wtab... if (s == 2) { wtab[1] = MulModPrecon(wtab[0], w, q, wqinv); wqinvtab[1] = PrepMulModPrecon(wtab[1], q, qinv); } else { // some software pipelining i = m_half-1; j = m_fourth-1; wtab[i-1] = wtab[j]; wqinvtab[i-1] = wqinvtab[j]; wtab[i] = MulModPrecon(wtab[i-1], w, q, wqinv); i -= 2; j --; for (; i >= 0; i -= 2, j --) { long wp2 = wtab[i+2]; long wm1 = wtab[j]; wqinvtab[i+2] = PrepMulModPrecon(wp2, q, qinv); wtab[i-1] = wm1; wqinvtab[i-1] = wqinvtab[j]; wtab[i] = MulModPrecon(wm1, w, q, wqinv); } wqinvtab[1] = PrepMulModPrecon(wtab[1], q, qinv); } for (i = 0; i < n; i+= m) { long * NTL_RESTRICT AA0 = &AA[i]; long * NTL_RESTRICT AA1 = &AA[i + m_half]; t = AA1[0]; u = AA0[0]; t1 = MulModPrecon(AA1[1], w, q, wqinv); u1 = AA0[1]; for (j = 0; j < m_half-2; j += 2) { long a02 = AA0[j+2]; long a03 = AA0[j+3]; long a12 = AA1[j+2]; long a13 = AA1[j+3]; long w2 = wtab[j+2]; long w3 = wtab[j+3]; mulmod_precon_t wqi2 = wqinvtab[j+2]; mulmod_precon_t wqi3 = wqinvtab[j+3]; tt = MulModPrecon(a12, w2, q, wqi2); long b00 = AddMod(u, t, q); long b10 = SubMod(u, t, q); t = tt; u = a02; tt1 = MulModPrecon(a13, w3, q, wqi3); long b01 = AddMod(u1, t1, q); long b11 = SubMod(u1, t1, q); t1 = tt1; u1 = a03; AA0[j] = b00; AA1[j] = b10; AA0[j+1] = b01; AA1[j+1] = b11; } AA0[j] = AddMod(u, t, q); AA1[j] = SubMod(u, t, q); AA0[j + 1] = AddMod(u1, t1, q); AA1[j + 1] = SubMod(u1, t1, q); } } // s == k...special case m = 1L << s; m_half = 1L << (s-1); m_fourth = 1L << (s-2); w = root[s]; wqinv = PrepMulModPrecon(w, q, qinv); // j = 0, 1 t = AA[m_half]; u = AA[0]; t1 = MulModPrecon(AA[1+ m_half], w, q, wqinv); u1 = AA[1]; A[0] = AddMod(u, t, q); A[m_half] = SubMod(u, t, q); A[1] = AddMod(u1, t1, q); A[1 + m_half] = SubMod(u1, t1, q); for (j = 2; j < m_half; j += 2) { t = MulModPrecon(AA[j + m_half], wtab[j >> 1], q, wqinvtab[j >> 1]); u = AA[j]; t1 = MulModPrecon(AA[j + 1+ m_half], wtab[j >> 1], q, wqinvtab[j >> 1]); t1 = MulModPrecon(t1, w, q, wqinv); u1 = AA[j + 1]; A[j] = AddMod(u, t, q); A[j + m_half] = SubMod(u, t, q); A[j + 1] = AddMod(u1, t1, q); A[j + 1 + m_half] = SubMod(u1, t1, q); } }
void determinant(zz_p& d, const mat_zz_p& M_in) { long k, n; long i, j; long pos; zz_p t1, t2, t3; zz_p *x, *y; mat_zz_p M; M = M_in; n = M.NumRows(); if (M.NumCols() != n) LogicError("determinant: nonsquare matrix"); if (n == 0) { set(d); return; } zz_p det; set(det); long p = zz_p::modulus(); mulmod_t pinv = zz_p::ModulusInverse(); for (k = 0; k < n; k++) { pos = -1; for (i = k; i < n; i++) { if (!IsZero(M[i][k])) { pos = i; break; } } if (pos != -1) { if (k != pos) { swap(M[pos], M[k]); negate(det, det); } mul(det, det, M[k][k]); inv(t3, M[k][k]); for (i = k+1; i < n; i++) { // M[i] = M[i] - M[k]*M[i,k]*t3 mul(t1, M[i][k], t3); negate(t1, t1); x = M[i].elts() + (k+1); y = M[k].elts() + (k+1); long T1 = rep(t1); mulmod_precon_t t1pinv = PrepMulModPrecon(T1, p, pinv); // T1*pinv; long T2; for (j = k+1; j < n; j++, x++, y++) { // *x = *x + (*y)*t1 T2 = MulModPrecon(rep(*y), T1, p, t1pinv); x->LoopHole() = AddMod(rep(*x), T2, p); } } } else { clear(d); return; } } d = det; }
/************************** //Paillier HE system //len: length of params p,q **************************/ void Paillier(int len=512){ ZZ n, n2, p, q, g, lamda; ZZ p1, q1, p1q1; ZZ miu; ZZ m1, m2; ZZ BSm, HEm; //baseline and HE result ZZ c, c1, c2, cm1, cm2, r; //key gen start = std::clock(); GenPrime(p, len); GenPrime(q, len); mul(n, p, q); mul(n2, n, n); sub(p1,p,1); sub(q1,q,1); GCD(lamda,p1,q1); mul(p1q1,p1,q1); div(lamda, p1q1, lamda); RandomBnd(g, n2); PowerMod(miu,g,lamda,n2); sub(miu, miu, 1); div(miu,miu,n); //should add 1? InvMod(miu, miu, n); duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC; cout<<"Pailler Setup:"<< duration <<'\n'; //Enc start = std::clock(); RandomBnd(m1,n); RandomBnd(m2,n); RandomBnd(r,n); //enc m1 PowerMod(c1, g,m1,n2); PowerMod(c2, r,n,n2); MulMod(cm1, c1,c2, n2); RandomBnd(r,n); //enc m2 PowerMod(c1, g,m2,n2); PowerMod(c2, r,n,n2); MulMod(cm2, c1,c2, n2); duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC; cout<<"Pailler Enc:"<< duration/2 <<'\n'; //Evaluation start = std::clock(); c=cm1; for(int i=0; i<TIMES; i++) MulMod(c,c,cm2,n2); duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC; cout<<"Pailler Eval:"<< duration <<'\n'; //c=cm2; //Dec start = std::clock(); PowerMod(c,c,lamda,n2); sub(c,c,1); div(c,c,n); //should add 1? MulMod(HEm, c, miu, n); duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC; cout<<"Pailler Dec:"<< duration <<'\n'; //baseline BSm=m1; for(int i=0; i<TIMES; i++) AddMod(BSm,BSm,m2,n); assert(BSm==HEm); }
static void mul_aux(mat_zz_p& X, const mat_zz_p& A, const mat_zz_p& B) { long n = A.NumRows(); long l = A.NumCols(); long m = B.NumCols(); if (l != B.NumRows()) LogicError("matrix mul: dimension mismatch"); X.SetDims(n, m); if (m > 1) { // new preconditioning code long p = zz_p::modulus(); mulmod_t pinv = zz_p::ModulusInverse(); vec_long::Watcher watch_mul_aux_vec(mul_aux_vec); mul_aux_vec.SetLength(m); long *acc = mul_aux_vec.elts(); long i, j, k; for (i = 0; i < n; i++) { const zz_p* ap = A[i].elts(); for (j = 0; j < m; j++) acc[j] = 0; for (k = 0; k < l; k++) { long aa = rep(ap[k]); if (aa != 0) { const zz_p* bp = B[k].elts(); long T1; mulmod_precon_t aapinv = PrepMulModPrecon(aa, p, pinv); for (j = 0; j < m; j++) { T1 = MulModPrecon(rep(bp[j]), aa, p, aapinv); acc[j] = AddMod(acc[j], T1, p); } } } zz_p *xp = X[i].elts(); for (j = 0; j < m; j++) xp[j].LoopHole() = acc[j]; } } else { // just use the old code, w/o preconditioning long p = zz_p::modulus(); mulmod_t pinv = zz_p::ModulusInverse(); long i, j, k; long acc, tmp; for (i = 1; i <= n; i++) { for (j = 1; j <= m; j++) { acc = 0; for(k = 1; k <= l; k++) { tmp = MulMod(rep(A(i,k)), rep(B(k,j)), p, pinv); acc = AddMod(acc, tmp, p); } X(i,j).LoopHole() = acc; } } } }
void inv(zz_p& d, mat_zz_p& X, const mat_zz_p& A) { long n = A.NumRows(); if (A.NumCols() != n) LogicError("inv: nonsquare matrix"); if (n == 0) { set(d); X.SetDims(0, 0); return; } long i, j, k, pos; zz_p t1, t2, t3; zz_p *x, *y; mat_zz_p M; M.SetDims(n, 2*n); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { M[i][j] = A[i][j]; clear(M[i][n+j]); } set(M[i][n+i]); } zz_p det; set(det); long p = zz_p::modulus(); mulmod_t pinv = zz_p::ModulusInverse(); for (k = 0; k < n; k++) { pos = -1; for (i = k; i < n; i++) { if (!IsZero(M[i][k])) { pos = i; break; } } if (pos != -1) { if (k != pos) { swap(M[pos], M[k]); negate(det, det); } mul(det, det, M[k][k]); inv(t3, M[k][k]); M[k][k] = t3; for (i = k+1; i < n; i++) { // M[i] = M[i] - M[k]*M[i,k]*t3 mul(t1, M[i][k], t3); negate(t1, t1); x = M[i].elts() + (k+1); y = M[k].elts() + (k+1); long T1 = rep(t1); mulmod_precon_t t1pinv = PrepMulModPrecon(T1, p, pinv); // T1*pinv; long T2; for (j = k+1; j < 2*n; j++, x++, y++) { // *x = *x + (*y)*t1 T2 = MulModPrecon(rep(*y), T1, p, t1pinv); x->LoopHole() = AddMod(rep(*x), T2, p); } } } else { clear(d); return; } } X.SetDims(n, n); for (k = 0; k < n; k++) { for (i = n-1; i >= 0; i--) { clear(t1); for (j = i+1; j < n; j++) { mul(t2, X[j][k], M[i][j]); add(t1, t1, t2); } sub(t1, M[i][n+k], t1); mul(X[i][k], t1, M[i][i]); } } d = det; }
void AddMod(ZZ& x, const ZZ& a, long b, const ZZ& n) { static ZZ B; conv(B, b); AddMod(x, a, B, n); }
long gauss(mat_zz_p& M, long w) { long k, l; long i, j; long pos; zz_p t1, t2, t3; zz_p *x, *y; long n = M.NumRows(); long m = M.NumCols(); if (w < 0 || w > m) LogicError("gauss: bad args"); long p = zz_p::modulus(); mulmod_t pinv = zz_p::ModulusInverse(); long T1, T2; l = 0; for (k = 0; k < w && l < n; k++) { pos = -1; for (i = l; i < n; i++) { if (!IsZero(M[i][k])) { pos = i; break; } } if (pos != -1) { swap(M[pos], M[l]); inv(t3, M[l][k]); negate(t3, t3); for (i = l+1; i < n; i++) { // M[i] = M[i] + M[l]*M[i,k]*t3 mul(t1, M[i][k], t3); T1 = rep(t1); mulmod_precon_t T1pinv = PrepMulModPrecon(T1, p, pinv); clear(M[i][k]); x = M[i].elts() + (k+1); y = M[l].elts() + (k+1); for (j = k+1; j < m; j++, x++, y++) { // *x = *x + (*y)*t1 T2 = MulModPrecon(rep(*y), T1, p, T1pinv); T2 = AddMod(T2, rep(*x), p); (*x).LoopHole() = T2; } } l++; } } return l; }