From 263431c486bcaddf442c912cf56171a778322316 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 28 May 2018 00:27:54 +0100 Subject: [PATCH] Pippenger multiexp Based on sarang's python code --- src/ringct/bulletproofs.cc | 6 +- src/ringct/multiexp.cc | 133 +++++++++++++++++++++++++++ src/ringct/multiexp.h | 2 + tests/performance_tests/main.cpp | 142 +++++++++++++++++++++++++++++ tests/performance_tests/multiexp.h | 5 +- 5 files changed, 284 insertions(+), 4 deletions(-) diff --git a/src/ringct/bulletproofs.cc b/src/ringct/bulletproofs.cc index 884c99537..83005eaa4 100644 --- a/src/ringct/bulletproofs.cc +++ b/src/ringct/bulletproofs.cc @@ -72,10 +72,10 @@ static boost::mutex init_mutex; static inline rct::key multiexp(const std::vector &data, bool HiGi) { static const size_t STEP = getenv("STRAUS_STEP") ? atoi(getenv("STRAUS_STEP")) : 0; - if (HiGi || data.size() < 1000) - return straus(data, HiGi ? HiGi_cache: NULL, STEP); + if (HiGi) + return data.size() <= 256 ? straus(data, HiGi_cache, STEP) : pippenger(data, get_pippenger_c(data.size())); else - return bos_coster_heap_conv_robust(data); + return data.size() <= 64 ? straus(data, NULL, STEP) : pippenger(data, get_pippenger_c(data.size())); } //addKeys3acc_p3 diff --git a/src/ringct/multiexp.cc b/src/ringct/multiexp.cc index 52c6feb71..fd2d1cbd7 100644 --- a/src/ringct/multiexp.cc +++ b/src/ringct/multiexp.cc @@ -55,6 +55,30 @@ extern "C" // 1 0 52.7 67 67.1 // 1 1 52.8 70.4 70.2 +// Pippenger: +// 1 2 3 4 5 6 7 8 9 bestN +// 2 555 598 621 804 1038 1733 2486 5020 8304 1 +// 4 783 747 800 1006 1428 2132 3285 5185 9806 2 +// 8 1174 1071 1095 1286 1640 2398 3869 6378 12080 2 +// 16 2279 1874 1745 1739 2144 2831 4209 6964 12007 4 +// 32 3910 3706 2588 2477 2782 3467 4856 7489 12618 4 +// 64 7184 5429 4710 4368 4010 4672 6027 8559 13684 5 +// 128 14097 10574 8452 7297 6841 6718 8615 10580 15641 6 +// 256 27715 20800 16000 13550 11875 11400 11505 14090 18460 6 +// 512 55100 41250 31740 26570 22030 19830 20760 21380 25215 6 +// 1024 111520 79000 61080 49720 43080 38320 37600 35040 36750 8 +// 2048 219480 162680 122120 102080 83760 70360 66600 63920 66160 8 +// 4096 453320 323080 247240 210200 180040 150240 132440 114920 110560 9 + +// 2 4 8 16 32 64 128 256 512 1024 2048 4096 +// Bos Coster 858 994 1316 1949 3183 5512 9865 17830 33485 63160 124280 246320 +// Straus 226 341 548 980 1870 3538 7039 14490 29020 57200 118640 233640 +// Straus/cached 226 315 485 785 1514 2858 5753 11065 22970 45120 98880 194840 +// Pippenger 555 747 1071 1739 2477 4010 6718 11400 19830 35040 63920 110560 + +// Best/cached Straus Straus Straus Straus Straus Straus Straus Straus Pip Pip Pip Pip +// Best/uncached Straus Straus Straus Straus Straus Straus Pip Pip Pip Pip Pip Pip + namespace rct { @@ -91,6 +115,26 @@ static inline rct::key pow2(size_t n) return res; } +static inline int test(const rct::key &k, size_t n) +{ + if (n >= 256) return 0; + return k[n >> 3] & (1 << (n & 7)); +} + +static inline void add(ge_p3 &p3, const ge_cached &other) +{ + ge_p1p1 p1; + ge_add(&p1, &p3, &other); + ge_p1p1_to_p3(&p3, &p1); +} + +static inline void add(ge_p3 &p3, const ge_p3 &other) +{ + ge_cached cached; + ge_p3_to_cached(&cached, &other); + add(p3, cached); +} + rct::key bos_coster_heap_conv(std::vector data) { MULTIEXP_PERF(PERF_TIMER_START_UNIT(bos_coster, 1000000)); @@ -487,4 +531,93 @@ skipfirst: return res; } +size_t get_pippenger_c(size_t N) +{ +// 2:1, 4:2, 8:2, 16:3, 32:4, 64:4, 128:5, 256:6, 512:7, 1024:7, 2048:8, 4096:9 + if (N <= 2) return 1; + if (N <= 8) return 2; + if (N <= 16) return 3; + if (N <= 64) return 4; + if (N <= 128) return 5; + if (N <= 256) return 6; + if (N <= 1024) return 7; + if (N <= 2048) return 8; + return 9; +} + +rct::key pippenger(const std::vector &data, size_t c) +{ + CHECK_AND_ASSERT_THROW_MES(c <= 9, "c is too large"); + + ge_p3 result = ge_p3_identity; + std::unique_ptr buckets{new ge_p3[1< cached_points{new ge_cached[data.size()]}; + + for (size_t i = 0; i < data.size(); ++i) + { + ge_p3_to_cached(&cached_points[i], &data[i].point); + } + + rct::key maxscalar = rct::zero(); + for (size_t i = 0; i < data.size(); ++i) + if (maxscalar < data[i].scalar) + maxscalar = data[i].scalar; + size_t groups = 0; + while (groups < 256 && pow2(groups) < maxscalar) + ++groups; + groups = (groups + c - 1) / c; + + for (size_t k = groups; k-- > 0; ) + { + if (memcmp(&result, &ge_p3_identity, sizeof(ge_p3))) + { + ge_p2 p2; + ge_p3_to_p2(&p2, &result); + for (size_t i = 0; i < c; ++i) + { + ge_p1p1 p1; + ge_p2_dbl(&p1, &p2); + if (i == c - 1) + ge_p1p1_to_p3(&result, &p1); + else + ge_p1p1_to_p2(&p2, &p1); + } + } + for (size_t i = 0; i < (1u< 0; --i) + { + if (memcmp(&buckets[i], &ge_p3_identity, sizeof(ge_p3))) + add(pail, buckets[i]); + if (memcmp(&pail, &ge_p3_identity, sizeof(ge_p3))) + add(result, pail); + } + } + + rct::key res; + ge_p3_tobytes(res.bytes, &result); + return res; +} + } diff --git a/src/ringct/multiexp.h b/src/ringct/multiexp.h index c08c70858..2ed8db279 100644 --- a/src/ringct/multiexp.h +++ b/src/ringct/multiexp.h @@ -60,6 +60,8 @@ rct::key bos_coster_heap_conv_robust(std::vector data); std::shared_ptr straus_init_cache(const std::vector &data); size_t straus_get_cache_size(const std::shared_ptr &cache); rct::key straus(const std::vector &data, const std::shared_ptr &cache = NULL, size_t STEP = 0); +size_t get_pippenger_c(size_t N); +rct::key pippenger(const std::vector &data, size_t c); } diff --git a/tests/performance_tests/main.cpp b/tests/performance_tests/main.cpp index 912376595..c3e1bb4e0 100644 --- a/tests/performance_tests/main.cpp +++ b/tests/performance_tests/main.cpp @@ -222,26 +222,168 @@ int main(int argc, char** argv) TEST_PERFORMANCE1(filter, verbose, test_crypto_ops, op_addKeys3_2); TEST_PERFORMANCE2(filter, verbose, test_multiexp, multiexp_bos_coster, 2); + TEST_PERFORMANCE2(filter, verbose, test_multiexp, multiexp_bos_coster, 4); TEST_PERFORMANCE2(filter, verbose, test_multiexp, multiexp_bos_coster, 8); TEST_PERFORMANCE2(filter, verbose, test_multiexp, multiexp_bos_coster, 16); + TEST_PERFORMANCE2(filter, verbose, test_multiexp, multiexp_bos_coster, 32); + TEST_PERFORMANCE2(filter, verbose, test_multiexp, multiexp_bos_coster, 64); + TEST_PERFORMANCE2(filter, verbose, test_multiexp, multiexp_bos_coster, 128); TEST_PERFORMANCE2(filter, verbose, test_multiexp, multiexp_bos_coster, 256); + TEST_PERFORMANCE2(filter, verbose, test_multiexp, multiexp_bos_coster, 512); TEST_PERFORMANCE2(filter, verbose, test_multiexp, multiexp_bos_coster, 1024); + TEST_PERFORMANCE2(filter, verbose, test_multiexp, multiexp_bos_coster, 2048); TEST_PERFORMANCE2(filter, verbose, test_multiexp, multiexp_bos_coster, 4096); TEST_PERFORMANCE2(filter, verbose, test_multiexp, multiexp_straus, 2); + TEST_PERFORMANCE2(filter, verbose, test_multiexp, multiexp_straus, 4); TEST_PERFORMANCE2(filter, verbose, test_multiexp, multiexp_straus, 8); TEST_PERFORMANCE2(filter, verbose, test_multiexp, multiexp_straus, 16); + TEST_PERFORMANCE2(filter, verbose, test_multiexp, multiexp_straus, 32); + TEST_PERFORMANCE2(filter, verbose, test_multiexp, multiexp_straus, 64); + TEST_PERFORMANCE2(filter, verbose, test_multiexp, multiexp_straus, 128); TEST_PERFORMANCE2(filter, verbose, test_multiexp, multiexp_straus, 256); + TEST_PERFORMANCE2(filter, verbose, test_multiexp, multiexp_straus, 512); TEST_PERFORMANCE2(filter, verbose, test_multiexp, multiexp_straus, 1024); + TEST_PERFORMANCE2(filter, verbose, test_multiexp, multiexp_straus, 2048); TEST_PERFORMANCE2(filter, verbose, test_multiexp, multiexp_straus, 4096); TEST_PERFORMANCE2(filter, verbose, test_multiexp, multiexp_straus_cached, 2); + TEST_PERFORMANCE2(filter, verbose, test_multiexp, multiexp_straus_cached, 4); TEST_PERFORMANCE2(filter, verbose, test_multiexp, multiexp_straus_cached, 8); TEST_PERFORMANCE2(filter, verbose, test_multiexp, multiexp_straus_cached, 16); + TEST_PERFORMANCE2(filter, verbose, test_multiexp, multiexp_straus_cached, 32); + TEST_PERFORMANCE2(filter, verbose, test_multiexp, multiexp_straus_cached, 64); + TEST_PERFORMANCE2(filter, verbose, test_multiexp, multiexp_straus_cached, 128); TEST_PERFORMANCE2(filter, verbose, test_multiexp, multiexp_straus_cached, 256); + TEST_PERFORMANCE2(filter, verbose, test_multiexp, multiexp_straus_cached, 512); TEST_PERFORMANCE2(filter, verbose, test_multiexp, multiexp_straus_cached, 1024); + TEST_PERFORMANCE2(filter, verbose, test_multiexp, multiexp_straus_cached, 2048); TEST_PERFORMANCE2(filter, verbose, test_multiexp, multiexp_straus_cached, 4096); +#if 1 + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 2, 1); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 4, 2); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 8, 2); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 16, 4); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 32, 4); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 64, 5); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 128, 6); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 256, 6); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 512, 6); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 1024, 8); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 2048, 8); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 4096, 9); +#else + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 2, 1); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 2, 2); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 2, 3); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 2, 4); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 2, 5); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 2, 6); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 2, 7); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 2, 8); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 2, 9); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 4, 1); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 4, 2); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 4, 3); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 4, 4); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 4, 5); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 4, 6); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 4, 7); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 4, 8); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 4, 9); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 8, 1); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 8, 2); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 8, 3); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 8, 4); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 8, 5); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 8, 6); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 8, 7); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 8, 8); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 8, 9); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 16, 1); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 16, 2); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 16, 3); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 16, 4); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 16, 5); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 16, 6); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 16, 7); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 16, 8); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 16, 9); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 32, 1); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 32, 2); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 32, 3); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 32, 4); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 32, 5); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 32, 6); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 32, 7); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 32, 8); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 32, 9); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 64, 1); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 64, 2); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 64, 3); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 64, 4); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 64, 5); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 64, 6); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 64, 7); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 64, 8); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 64, 9); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 128, 1); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 128, 2); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 128, 3); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 128, 4); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 128, 5); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 128, 6); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 128, 7); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 128, 8); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 128, 9); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 256, 1); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 256, 2); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 256, 3); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 256, 4); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 256, 5); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 256, 6); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 256, 7); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 256, 8); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 256, 9); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 512, 1); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 512, 2); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 512, 3); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 512, 4); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 512, 5); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 512, 6); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 512, 7); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 512, 8); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 512, 9); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 1024, 1); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 1024, 2); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 1024, 3); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 1024, 4); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 1024, 5); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 1024, 6); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 1024, 7); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 1024, 8); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 1024, 9); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 2048, 1); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 2048, 2); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 2048, 3); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 2048, 4); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 2048, 5); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 2048, 6); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 2048, 7); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 2048, 8); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 2048, 9); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 4096, 1); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 4096, 2); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 4096, 3); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 4096, 4); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 4096, 5); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 4096, 6); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 4096, 7); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 4096, 8); + TEST_PERFORMANCE3(filter, verbose, test_multiexp, multiexp_pippenger, 4096, 9); +#endif + std::cout << "Tests finished. Elapsed time: " << timer.elapsed_ms() / 1000 << " sec" << std::endl; return 0; diff --git a/tests/performance_tests/multiexp.h b/tests/performance_tests/multiexp.h index ab5af166b..294e74116 100644 --- a/tests/performance_tests/multiexp.h +++ b/tests/performance_tests/multiexp.h @@ -39,9 +39,10 @@ enum test_multiexp_algorithm multiexp_bos_coster, multiexp_straus, multiexp_straus_cached, + multiexp_pippenger, }; -template +template class test_multiexp { public: @@ -74,6 +75,8 @@ public: return res == straus(data); case multiexp_straus_cached: return res == straus(data, cache); + case multiexp_pippenger: + return res == pippenger(data, c); default: return false; }