From 8b1ace860ffbbec0d8d0dd722d59fdc556a356c3 Mon Sep 17 00:00:00 2001 From: HarryR Date: Sun, 21 Jul 2019 18:46:08 +0100 Subject: [PATCH 1/4] Do not use try/catch for control flow in get_evaluation_domain --- .../domains/arithmetic_sequence_domain.hpp | 2 ++ .../domains/arithmetic_sequence_domain.tcc | 12 ++++++++ .../domains/basic_radix2_domain.hpp | 2 ++ .../domains/basic_radix2_domain.tcc | 21 +++++++++++++ .../domains/extended_radix2_domain.hpp | 2 ++ .../domains/extended_radix2_domain.tcc | 26 ++++++++++++++++ .../domains/geometric_sequence_domain.hpp | 2 ++ .../domains/geometric_sequence_domain.tcc | 12 ++++++++ .../domains/step_radix2_domain.hpp | 2 ++ .../domains/step_radix2_domain.tcc | 27 +++++++++++++++++ .../get_evaluation_domain.tcc | 30 +++++++++++++++++++ 11 files changed, 138 insertions(+) diff --git a/libfqfft/evaluation_domain/domains/arithmetic_sequence_domain.hpp b/libfqfft/evaluation_domain/domains/arithmetic_sequence_domain.hpp index e3f42ba..26304c2 100755 --- a/libfqfft/evaluation_domain/domains/arithmetic_sequence_domain.hpp +++ b/libfqfft/evaluation_domain/domains/arithmetic_sequence_domain.hpp @@ -28,6 +28,8 @@ namespace libfqfft { FieldT arithmetic_generator; void do_precomputation(); + static bool valid_for_size(const size_t m); + arithmetic_sequence_domain(const size_t m); void FFT(std::vector &a); diff --git a/libfqfft/evaluation_domain/domains/arithmetic_sequence_domain.tcc b/libfqfft/evaluation_domain/domains/arithmetic_sequence_domain.tcc index 3b59ae2..8ae9431 100755 --- a/libfqfft/evaluation_domain/domains/arithmetic_sequence_domain.tcc +++ b/libfqfft/evaluation_domain/domains/arithmetic_sequence_domain.tcc @@ -23,6 +23,18 @@ namespace libfqfft { +template +bool arithmetic_sequence_domain::valid_for_size(const size_t m) +{ + if (m <=1) + return false; + + if (FieldT::arithmetic_generator() == FieldT::zero()) + return false; + + return true; +} + template arithmetic_sequence_domain::arithmetic_sequence_domain(const size_t m) : evaluation_domain(m) { diff --git a/libfqfft/evaluation_domain/domains/basic_radix2_domain.hpp b/libfqfft/evaluation_domain/domains/basic_radix2_domain.hpp index 7b77b29..2ce3dc1 100755 --- a/libfqfft/evaluation_domain/domains/basic_radix2_domain.hpp +++ b/libfqfft/evaluation_domain/domains/basic_radix2_domain.hpp @@ -26,6 +26,8 @@ class basic_radix2_domain : public evaluation_domain { FieldT omega; + static bool valid_for_size(const size_t m); + basic_radix2_domain(const size_t m); void FFT(std::vector &a); diff --git a/libfqfft/evaluation_domain/domains/basic_radix2_domain.tcc b/libfqfft/evaluation_domain/domains/basic_radix2_domain.tcc index 2486f7a..e0a48ff 100755 --- a/libfqfft/evaluation_domain/domains/basic_radix2_domain.tcc +++ b/libfqfft/evaluation_domain/domains/basic_radix2_domain.tcc @@ -22,6 +22,27 @@ namespace libfqfft { +template +bool basic_radix2_domain::valid_for_size(const size_t m) +{ + if ( m <= 1 ) + return false; + + // Will `get_root_of_unity` throw? + if (!std::is_same::value) + { + const size_t logm = libff::log2(m); + + if (logm > FieldT::s) + return false; + + if (m != 1u << logm) + return false; + } + + return true; +} + template basic_radix2_domain::basic_radix2_domain(const size_t m) : evaluation_domain(m) { diff --git a/libfqfft/evaluation_domain/domains/extended_radix2_domain.hpp b/libfqfft/evaluation_domain/domains/extended_radix2_domain.hpp index 7637925..53e9c11 100755 --- a/libfqfft/evaluation_domain/domains/extended_radix2_domain.hpp +++ b/libfqfft/evaluation_domain/domains/extended_radix2_domain.hpp @@ -27,6 +27,8 @@ class extended_radix2_domain : public evaluation_domain { FieldT omega; FieldT shift; + static bool valid_for_size(const size_t m); + extended_radix2_domain(const size_t m); void FFT(std::vector &a); diff --git a/libfqfft/evaluation_domain/domains/extended_radix2_domain.tcc b/libfqfft/evaluation_domain/domains/extended_radix2_domain.tcc index b6a31fa..25dcc19 100755 --- a/libfqfft/evaluation_domain/domains/extended_radix2_domain.tcc +++ b/libfqfft/evaluation_domain/domains/extended_radix2_domain.tcc @@ -17,6 +17,32 @@ namespace libfqfft { +template +bool extended_radix2_domain::valid_for_size(const size_t m) +{ + if ( m <= 1 ) + return false; + + // Will `get_root_of_unity` throw? + if (!std::is_same::value) + { + const size_t logm = libff::log2(m); + + if (logm != (FieldT::s + 1)) + return false; + + size_t small_m = m / 2; + + if (small_m > FieldT::s) + return false; + + if (m != (1u << small_m)) + return false; + } + + return true; +} + template extended_radix2_domain::extended_radix2_domain(const size_t m) : evaluation_domain(m) { diff --git a/libfqfft/evaluation_domain/domains/geometric_sequence_domain.hpp b/libfqfft/evaluation_domain/domains/geometric_sequence_domain.hpp index 22bd783..70a2da2 100755 --- a/libfqfft/evaluation_domain/domains/geometric_sequence_domain.hpp +++ b/libfqfft/evaluation_domain/domains/geometric_sequence_domain.hpp @@ -27,6 +27,8 @@ namespace libfqfft { std::vector geometric_triangular_sequence; void do_precomputation(); + static bool valid_for_size(const size_t m); + geometric_sequence_domain(const size_t m); void FFT(std::vector &a); diff --git a/libfqfft/evaluation_domain/domains/geometric_sequence_domain.tcc b/libfqfft/evaluation_domain/domains/geometric_sequence_domain.tcc index 1535810..fe5bdaa 100755 --- a/libfqfft/evaluation_domain/domains/geometric_sequence_domain.tcc +++ b/libfqfft/evaluation_domain/domains/geometric_sequence_domain.tcc @@ -23,6 +23,18 @@ namespace libfqfft { +template +bool geometric_sequence_domain::valid_for_size(const size_t m) +{ + if ( m <= 1 ) + return false; + + if (FieldT::geometric_generator() == FieldT::zero()) + return false; + + return true; +} + template geometric_sequence_domain::geometric_sequence_domain(const size_t m) : evaluation_domain(m) { diff --git a/libfqfft/evaluation_domain/domains/step_radix2_domain.hpp b/libfqfft/evaluation_domain/domains/step_radix2_domain.hpp index 33ba7f4..72fc090 100755 --- a/libfqfft/evaluation_domain/domains/step_radix2_domain.hpp +++ b/libfqfft/evaluation_domain/domains/step_radix2_domain.hpp @@ -29,6 +29,8 @@ class step_radix2_domain : public evaluation_domain { FieldT big_omega; FieldT small_omega; + static bool valid_for_size(const size_t m); + step_radix2_domain(const size_t m); void FFT(std::vector &a); diff --git a/libfqfft/evaluation_domain/domains/step_radix2_domain.tcc b/libfqfft/evaluation_domain/domains/step_radix2_domain.tcc index e9a984e..ece95e1 100755 --- a/libfqfft/evaluation_domain/domains/step_radix2_domain.tcc +++ b/libfqfft/evaluation_domain/domains/step_radix2_domain.tcc @@ -17,6 +17,33 @@ namespace libfqfft { +template +bool step_radix2_domain::valid_for_size(const size_t m) +{ + if ( m <= 1 ) + return false; + + const size_t big_m = 1ul<<(libff::log2(m)-1); + const size_t small_m = m - big_m; + + if (small_m != 1ul<::value) + { + const size_t logm = libff::log2(m); + + if (m != (1u << logm)) + return false; + + if (logm > FieldT::s) + return false; + } + + return true; +} + template step_radix2_domain::step_radix2_domain(const size_t m) : evaluation_domain(m) { diff --git a/libfqfft/evaluation_domain/get_evaluation_domain.tcc b/libfqfft/evaluation_domain/get_evaluation_domain.tcc index 299537c..d60be30 100755 --- a/libfqfft/evaluation_domain/get_evaluation_domain.tcc +++ b/libfqfft/evaluation_domain/get_evaluation_domain.tcc @@ -38,6 +38,35 @@ std::shared_ptr > get_evaluation_domain(const size_t m const size_t small = min_size - big; const size_t rounded_small = (1ul<::valid_for_size(min_size) ) { + result.reset(new basic_radix2_domain(min_size)); + } + else if ( extended_radix2_domain::valid_for_size(min_size) ) { + result.reset(new extended_radix2_domain(min_size)); + } + else if ( step_radix2_domain::valid_for_size(min_size) ) { + result.reset(new step_radix2_domain(min_size)); + } + else if ( basic_radix2_domain::valid_for_size(big + rounded_small) ) { + result.reset(new basic_radix2_domain(big + rounded_small)); + } + else if ( extended_radix2_domain::valid_for_size(big + rounded_small) ) { + result.reset(new extended_radix2_domain(big + rounded_small)); + } + else if ( step_radix2_domain::valid_for_size(big + rounded_small) ) { + result.reset(new step_radix2_domain(big + rounded_small)); + } + else if ( geometric_sequence_domain::valid_for_size(min_size) ) { + result.reset(new geometric_sequence_domain(min_size)); + } + else if ( arithmetic_sequence_domain::valid_for_size(min_size) ) { + result.reset(new arithmetic_sequence_domain(min_size)); + } + else { + throw DomainSizeException("get_evaluation_domain: no matching domain"); + } + + /* try { result.reset(new basic_radix2_domain(min_size)); } catch(...) { try { result.reset(new extended_radix2_domain(min_size)); } catch(...) { try { result.reset(new step_radix2_domain(min_size)); } @@ -47,6 +76,7 @@ std::shared_ptr > get_evaluation_domain(const size_t m catch(...) { try { result.reset(new geometric_sequence_domain(min_size)); } catch(...) { try { result.reset(new arithmetic_sequence_domain(min_size)); } catch(...) { throw DomainSizeException("get_evaluation_domain: no matching domain"); }}}}}}}} + */ return result; } From c4f5457bdab81e2971918b51159944a80137c203 Mon Sep 17 00:00:00 2001 From: HarryR Date: Sun, 21 Jul 2019 21:44:13 +0100 Subject: [PATCH 2/4] Fixed tests to get evaluation domain --- .../domains/basic_radix2_domain.tcc | 6 ++--- .../domains/extended_radix2_domain.tcc | 11 +++----- .../domains/step_radix2_domain.tcc | 16 +++++------- .../evaluation_domain/evaluation_domain.hpp | 25 +++++++++++++++++++ 4 files changed, 38 insertions(+), 20 deletions(-) diff --git a/libfqfft/evaluation_domain/domains/basic_radix2_domain.tcc b/libfqfft/evaluation_domain/domains/basic_radix2_domain.tcc index e0a48ff..7365ca6 100755 --- a/libfqfft/evaluation_domain/domains/basic_radix2_domain.tcc +++ b/libfqfft/evaluation_domain/domains/basic_radix2_domain.tcc @@ -35,11 +35,11 @@ bool basic_radix2_domain::valid_for_size(const size_t m) if (logm > FieldT::s) return false; - - if (m != 1u << logm) - return false; } + if( get_root_of_unity_will_throw(m) ) + return false; + return true; } diff --git a/libfqfft/evaluation_domain/domains/extended_radix2_domain.tcc b/libfqfft/evaluation_domain/domains/extended_radix2_domain.tcc index 25dcc19..50dfea0 100755 --- a/libfqfft/evaluation_domain/domains/extended_radix2_domain.tcc +++ b/libfqfft/evaluation_domain/domains/extended_radix2_domain.tcc @@ -30,15 +30,12 @@ bool extended_radix2_domain::valid_for_size(const size_t m) if (logm != (FieldT::s + 1)) return false; + } - size_t small_m = m / 2; - - if (small_m > FieldT::s) - return false; + size_t small_m = m / 2; - if (m != (1u << small_m)) - return false; - } + if( get_root_of_unity_will_throw(small_m) ) + return false; return true; } diff --git a/libfqfft/evaluation_domain/domains/step_radix2_domain.tcc b/libfqfft/evaluation_domain/domains/step_radix2_domain.tcc index ece95e1..733975e 100755 --- a/libfqfft/evaluation_domain/domains/step_radix2_domain.tcc +++ b/libfqfft/evaluation_domain/domains/step_radix2_domain.tcc @@ -29,17 +29,13 @@ bool step_radix2_domain::valid_for_size(const size_t m) if (small_m != 1ul<::value) - { - const size_t logm = libff::log2(m); - - if (m != (1u << logm)) - return false; + // omega + if( get_root_of_unity_will_throw(1ul< FieldT::s) - return false; - } + // small_omega + if( get_root_of_unity_will_throw(1ul< +#include namespace libfqfft { +template +typename std::enable_if::value, bool>::type +get_root_of_unity_will_throw(const size_t n) +{ + return false; +} + + +template +typename std::enable_if::value, bool>::type +get_root_of_unity_will_throw(const size_t n) +{ + const size_t logn = libff::log2(n); + + if (n != (1u << logn)) + return true; + + if (logn > FieldT::s) + return true; + + return false; +} + + /** * An evaluation domain. */ From 954e77db064bf7b9fab12ba11d857bdef5d05d21 Mon Sep 17 00:00:00 2001 From: HarryR Date: Sun, 21 Jul 2019 22:24:03 +0100 Subject: [PATCH 3/4] Don't use empty inline-assembly, removes need to patch libfqfft for emscripten build --- .../evaluation_domain/domains/basic_radix2_domain_aux.tcc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libfqfft/evaluation_domain/domains/basic_radix2_domain_aux.tcc b/libfqfft/evaluation_domain/domains/basic_radix2_domain_aux.tcc index 3c00e5a..6ecbe60 100755 --- a/libfqfft/evaluation_domain/domains/basic_radix2_domain_aux.tcc +++ b/libfqfft/evaluation_domain/domains/basic_radix2_domain_aux.tcc @@ -61,7 +61,7 @@ void _basic_serial_radix2_FFT(std::vector &a, const FieldT &omega) // w_m is 2^s-th root of unity now const FieldT w_m = omega^(n/(2*m)); - asm volatile ("/* pre-inner */"); + //asm volatile ("/* pre-inner */"); for (size_t k = 0; k < n; k += 2*m) { FieldT w = FieldT::one(); @@ -73,7 +73,7 @@ void _basic_serial_radix2_FFT(std::vector &a, const FieldT &omega) w *= w_m; } } - asm volatile ("/* post-inner */"); + //asm volatile ("/* post-inner */"); m *= 2; } } From f5f8c5afbde1bfca34cb142b410f0ec2827050c0 Mon Sep 17 00:00:00 2001 From: HarryR Date: Fri, 2 Aug 2019 23:22:33 +0100 Subject: [PATCH 4/4] Removed unnecessary comments --- libfqfft/evaluation_domain/get_evaluation_domain.tcc | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/libfqfft/evaluation_domain/get_evaluation_domain.tcc b/libfqfft/evaluation_domain/get_evaluation_domain.tcc index d60be30..282b2f3 100755 --- a/libfqfft/evaluation_domain/get_evaluation_domain.tcc +++ b/libfqfft/evaluation_domain/get_evaluation_domain.tcc @@ -66,18 +66,6 @@ std::shared_ptr > get_evaluation_domain(const size_t m throw DomainSizeException("get_evaluation_domain: no matching domain"); } - /* - try { result.reset(new basic_radix2_domain(min_size)); } - catch(...) { try { result.reset(new extended_radix2_domain(min_size)); } - catch(...) { try { result.reset(new step_radix2_domain(min_size)); } - catch(...) { try { result.reset(new basic_radix2_domain(big + rounded_small)); } - catch(...) { try { result.reset(new extended_radix2_domain(big + rounded_small)); } - catch(...) { try { result.reset(new step_radix2_domain(big + rounded_small)); } - catch(...) { try { result.reset(new geometric_sequence_domain(min_size)); } - catch(...) { try { result.reset(new arithmetic_sequence_domain(min_size)); } - catch(...) { throw DomainSizeException("get_evaluation_domain: no matching domain"); }}}}}}}} - */ - return result; }