ECP::Point EcPrecomputation<ECP>::CascadeMultiply(const Integer &exponent, const EcPrecomputation<ECP> &pc2, const Integer &exponent2) const { return FromMontgomery(*m_mr, m_ep.CascadeExponentiate(exponent, pc2.m_ep, exponent2)); }
void ECP::SimultaneousMultiply(ECP::Point *results, const ECP::Point &P, const Integer *expBegin, unsigned int expCount) const { if (!GetField().IsMontgomeryRepresentation()) { ECP ecpmr(*this, true); const ModularArithmetic &mr = ecpmr.GetField(); ecpmr.SimultaneousMultiply(results, ToMontgomery(mr, P), expBegin, expCount); for (unsigned int i=0; i<expCount; i++) results[i] = FromMontgomery(mr, results[i]); return; } ProjectiveDoubling rd(GetField(), m_a, m_b, P); std::vector<ProjectivePoint> bases; std::vector<WindowSlider> exponents; exponents.reserve(expCount); std::vector<std::vector<word32> > baseIndices(expCount); std::vector<std::vector<bool> > negateBase(expCount); std::vector<std::vector<word32> > exponentWindows(expCount); unsigned int i; for (i=0; i<expCount; i++) { assert(expBegin->NotNegative()); exponents.push_back(WindowSlider(*expBegin++, InversionIsFast(), 5)); exponents[i].FindNextWindow(); } unsigned int expBitPosition = 0; bool notDone = true; while (notDone) { notDone = false; bool baseAdded = false; for (i=0; i<expCount; i++) { if (!exponents[i].finished && expBitPosition == exponents[i].windowBegin) { if (!baseAdded) { bases.push_back(rd.P); baseAdded =true; } exponentWindows[i].push_back(exponents[i].expWindow); baseIndices[i].push_back((word32)bases.size()-1); negateBase[i].push_back(exponents[i].negateNext); exponents[i].FindNextWindow(); } notDone = notDone || !exponents[i].finished; } if (notDone) { rd.Double(); expBitPosition++; } } // convert from projective to affine coordinates ParallelInvert(GetField(), ZIterator(bases.begin()), ZIterator(bases.end())); for (i=0; i<bases.size(); i++) { if (bases[i].z.NotZero()) { bases[i].y = GetField().Multiply(bases[i].y, bases[i].z); bases[i].z = GetField().Square(bases[i].z); bases[i].x = GetField().Multiply(bases[i].x, bases[i].z); bases[i].y = GetField().Multiply(bases[i].y, bases[i].z); } } std::vector<BaseAndExponent<Point, Integer> > finalCascade; for (i=0; i<expCount; i++) { finalCascade.resize(baseIndices[i].size()); for (unsigned int j=0; j<baseIndices[i].size(); j++) { ProjectivePoint &base = bases[baseIndices[i][j]]; if (base.z.IsZero()) finalCascade[j].base.identity = true; else { finalCascade[j].base.identity = false; finalCascade[j].base.x = base.x; if (negateBase[i][j]) finalCascade[j].base.y = GetField().Inverse(base.y); else finalCascade[j].base.y = base.y; } finalCascade[j].exponent = Integer(Integer::POSITIVE, 0, exponentWindows[i][j]); } results[i] = GeneralCascadeMultiplication(*this, finalCascade.begin(), finalCascade.end()); } }
ECP::Point EcPrecomputation<ECP>::Multiply(const Integer &exponent) const { return FromMontgomery(*m_mr, m_ep.Exponentiate(exponent)); }