Original HUSH source code based on ZEC 1.0.8 . For historical purposes only!
https://hush.is
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
183 lines
4.7 KiB
183 lines
4.7 KiB
/** @file
|
|
*****************************************************************************
|
|
Implementation of misc. math and serialization utility functions
|
|
*****************************************************************************
|
|
* @author This file is part of libsnark, developed by SCIPR Lab
|
|
* and contributors (see AUTHORS).
|
|
* @copyright MIT license (see LICENSE file)
|
|
*****************************************************************************/
|
|
|
|
#ifndef FIELD_UTILS_TCC_
|
|
#define FIELD_UTILS_TCC_
|
|
|
|
#include "common/utils.hpp"
|
|
|
|
namespace libsnark {
|
|
|
|
template<typename FieldT>
|
|
FieldT coset_shift()
|
|
{
|
|
return FieldT::multiplicative_generator.squared();
|
|
}
|
|
|
|
template<typename FieldT>
|
|
FieldT get_root_of_unity(const size_t n)
|
|
{
|
|
const size_t logn = log2(n);
|
|
assert(n == (1u << logn));
|
|
assert(logn <= FieldT::s);
|
|
|
|
FieldT omega = FieldT::root_of_unity;
|
|
for (size_t i = FieldT::s; i > logn; --i)
|
|
{
|
|
omega *= omega;
|
|
}
|
|
|
|
return omega;
|
|
}
|
|
|
|
template<typename FieldT>
|
|
std::vector<FieldT> pack_int_vector_into_field_element_vector(const std::vector<size_t> &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<FieldT> result(repacked_size);
|
|
|
|
for (size_t i = 0; i < repacked_size; ++i)
|
|
{
|
|
bigint<FieldT::num_limbs> 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<typename FieldT>
|
|
std::vector<FieldT> 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<FieldT> result(repacked_size);
|
|
|
|
for (size_t i = 0; i < repacked_size; ++i)
|
|
{
|
|
bigint<FieldT::num_limbs> 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<typename FieldT>
|
|
std::vector<FieldT> pack_bit_vector_into_field_element_vector(const bit_vector &v)
|
|
{
|
|
return pack_bit_vector_into_field_element_vector<FieldT>(v, FieldT::capacity());
|
|
}
|
|
|
|
template<typename FieldT>
|
|
std::vector<FieldT> convert_bit_vector_to_field_element_vector(const bit_vector &v)
|
|
{
|
|
std::vector<FieldT> result;
|
|
result.reserve(v.size());
|
|
|
|
for (const bool b : v)
|
|
{
|
|
result.emplace_back(b ? FieldT::one() : FieldT::zero());
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
template<typename FieldT>
|
|
bit_vector convert_field_element_vector_to_bit_vector(const std::vector<FieldT> &v)
|
|
{
|
|
bit_vector result;
|
|
|
|
for (const FieldT &el : v)
|
|
{
|
|
const bit_vector el_bits = convert_field_element_to_bit_vector<FieldT>(el);
|
|
result.insert(result.end(), el_bits.begin(), el_bits.end());
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
template<typename FieldT>
|
|
bit_vector convert_field_element_to_bit_vector(const FieldT &el)
|
|
{
|
|
bit_vector result;
|
|
|
|
bigint<FieldT::num_limbs> 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<typename FieldT>
|
|
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<typename FieldT>
|
|
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<typename FieldT>
|
|
void batch_invert(std::vector<FieldT> &vec)
|
|
{
|
|
std::vector<FieldT> 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 = vec.size()-1; i >= 0; --i)
|
|
{
|
|
const FieldT old_el = vec[i];
|
|
vec[i] = acc_inverse * prod[i];
|
|
acc_inverse = acc_inverse * old_el;
|
|
}
|
|
}
|
|
|
|
} // libsnark
|
|
#endif // FIELD_UTILS_TCC_
|
|
|