template <class Element, class Iterator> Element GeneralCascadeMultiplication(const AbstractGroup<Element> &group, Iterator begin, Iterator end) { if (end-begin == 1) return group.ScalarMultiply(begin->base, begin->exponent); else if (end-begin == 2) return group.CascadeScalarMultiply(begin->base, begin->exponent, (begin+1)->base, (begin+1)->exponent); else { Integer q, t; Iterator last = end; --last; std::make_heap(begin, end); std::pop_heap(begin, end); while (!!begin->exponent) { // last->exponent is largest exponent, begin->exponent is next largest t = last->exponent; Integer::Divide(last->exponent, q, t, begin->exponent); if (q == Integer::One()) group.Accumulate(begin->base, last->base); // avoid overhead of ScalarMultiply() else group.Accumulate(begin->base, group.ScalarMultiply(last->base, q)); std::push_heap(begin, end); std::pop_heap(begin, end); } return group.ScalarMultiply(last->base, last->exponent); } }
template <class Element, class Iterator> Element GeneralCascadeMultiplication(const AbstractGroup<Element> &group, Iterator begin, Iterator end) { if (end-begin == 1) return group.IntMultiply((*begin).second, (*begin).first); else if (end-begin == 2) return group.CascadeIntMultiply((*begin).second, (*begin).first, (*(begin+1)).second, (*(begin+1)).first); else { Integer q, r; Iterator last = end; --last; std::make_heap(begin, end); std::pop_heap(begin, end); while (!!(*begin).first) { // (*last).first is largest exponent, (*begin).first is next largest Integer::Divide(r, q, (*last).first, (*begin).first); if (q == Integer::One()) group.Accumulate((*begin).second, (*last).second); // avoid overhead of GeneralizedMultiplication() else group.Accumulate((*begin).second, group.IntMultiply((*last).second, q)); (*last).first = r; std::push_heap(begin, end); std::pop_heap(begin, end); } return group.IntMultiply((*last).second, (*last).first); } }
void SimultaneousMultiplication(Iterator result, const AbstractGroup<Element> &group, const Element &base, ConstIterator expBegin, ConstIterator expEnd) { unsigned int expCount = std::distance(expBegin, expEnd); std::vector<WindowSlider<Element> > exponents(expCount); unsigned int i; bool notDone = false; for (i=0; i<expCount; i++) notDone = exponents[i].FindFirstWindow(group, *expBegin++) || notDone; unsigned int expBitPosition = 0; Element g = base; while (notDone) { notDone = false; for (i=0; i<expCount; i++) { if (expBitPosition < exponents[i].expLen && expBitPosition == exponents[i].windowBegin) { Element &bucket = exponents[i].buckets[exponents[i].nextBucket]; group.Accumulate(bucket, g); exponents[i].FindNextWindow(); } notDone = notDone || exponents[i].windowBegin < exponents[i].expLen; } if (notDone) { g = group.Double(g); expBitPosition++; } } for (i=0; i<expCount; i++) { Element &r = *result++; std::vector<Element> &buckets = exponents[i].buckets; r = buckets[buckets.size()-1]; if (buckets.size() > 1) { for (int j = buckets.size()-2; j >= 1; j--) { group.Accumulate(buckets[j], buckets[j+1]); group.Accumulate(r, buckets[j]); } group.Accumulate(buckets[0], buckets[1]); r = group.Add(group.Double(r), buckets[0]); } } }