/** @file ***************************************************************************** Implementation of misc. math and serialization utility functions ***************************************************************************** * @author This file is part of libff, developed by SCIPR Lab * and contributors (see AUTHORS). * @copyright MIT license (see LICENSE file) *****************************************************************************/ #ifndef FIELD_UTILS_TCC_ #define FIELD_UTILS_TCC_ #include #include #include <../trusted_libff/libff/common/double.hpp> #include <../trusted_libff/libff/common/utils.hpp> namespace libff { template FieldT coset_shift() { return FieldT::multiplicative_generator.squared(); } template typename std::enable_if::value, FieldT>::type get_root_of_unity(const size_t n) { const double PI = 3.141592653589793238460264338328L; return FieldT(cos(2 * PI / n), sin(2 * PI / n)); } template typename std::enable_if::value, FieldT>::type get_root_of_unity(const size_t n) { const size_t logn = log2(n); if (n != (1u << logn)) throw std::invalid_argument("libff::get_root_of_unity: expected n == (1u << logn)"); if (logn > FieldT::s) throw std::invalid_argument("libff::get_root_of_unity: expected logn <= FieldT::s"); FieldT omega = FieldT::root_of_unity; for (size_t i = FieldT::s; i > logn; --i) { omega *= omega; } return omega; } template std::vector pack_int_vector_into_field_element_vector(const std::vector &v, const size_t w) { const size_t chunk_bits = FieldT::capacity(); const size_t repacked_size = div_ceil(v.size() * w, chunk_bits); std::vector result(repacked_size); for (size_t i = 0; i < repacked_size; ++i) { bigint b; for (size_t j = 0; j < chunk_bits; ++j) { const size_t word_index = (i * chunk_bits + j) / w; const size_t pos_in_word = (i * chunk_bits + j) % w; const size_t word_or_0 = (word_index < v.size() ? v[word_index] : 0); const size_t bit = (word_or_0 >> pos_in_word) & 1; b.data[j / GMP_NUMB_BITS] |= bit << (j % GMP_NUMB_BITS); } result[i] = FieldT(b); } return result; } template std::vector pack_bit_vector_into_field_element_vector(const bit_vector &v, const size_t chunk_bits) { assert(chunk_bits <= FieldT::capacity()); const size_t repacked_size = div_ceil(v.size(), chunk_bits); std::vector result(repacked_size); for (size_t i = 0; i < repacked_size; ++i) { bigint b; for (size_t j = 0; j < chunk_bits; ++j) { b.data[j / GMP_NUMB_BITS] |= ((i * chunk_bits + j) < v.size() && v[i * chunk_bits + j] ? 1ll : 0ll) << (j % GMP_NUMB_BITS); } result[i] = FieldT(b); } return result; } template std::vector pack_bit_vector_into_field_element_vector(const bit_vector &v) { return pack_bit_vector_into_field_element_vector(v, FieldT::capacity()); } template std::vector convert_bit_vector_to_field_element_vector(const bit_vector &v) { std::vector result; result.reserve(v.size()); for (const bool b : v) { result.emplace_back(b ? FieldT::one() : FieldT::zero()); } return result; } template bit_vector convert_field_element_vector_to_bit_vector(const std::vector &v) { bit_vector result; for (const FieldT &el : v) { const bit_vector el_bits = convert_field_element_to_bit_vector(el); result.insert(result.end(), el_bits.begin(), el_bits.end()); } return result; } template bit_vector convert_field_element_to_bit_vector(const FieldT &el) { bit_vector result; bigint b = el.as_bigint(); for (size_t i = 0; i < FieldT::size_in_bits(); ++i) { result.push_back(b.test_bit(i)); } return result; } template bit_vector convert_field_element_to_bit_vector(const FieldT &el, const size_t bitcount) { bit_vector result = convert_field_element_to_bit_vector(el); result.resize(bitcount); return result; } template FieldT convert_bit_vector_to_field_element(const bit_vector &v) { assert(v.size() <= FieldT::size_in_bits()); FieldT res = FieldT::zero(); FieldT c = FieldT::one(); for (bool b : v) { res += b ? c : FieldT::zero(); c += c; } return res; } template void batch_invert(std::vector &vec) { std::vector prod; prod.reserve(vec.size()); FieldT acc = FieldT::one(); for (auto el : vec) { assert(!el.is_zero()); prod.emplace_back(acc); acc = acc * el; } FieldT acc_inverse = acc.inverse(); for (long i = static_cast(vec.size()-1); i >= 0; --i) { const FieldT old_el = vec[i]; vec[i] = acc_inverse * prod[i]; acc_inverse = acc_inverse * old_el; } } } // libff #endif // FIELD_UTILS_TCC_