Squashed 'src/snark/' content from commit 9ada3f8
git-subtree-dir: src/snark git-subtree-split: 9ada3f84ab484c57b2247c2f41091fd6a0916573
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
/** @file
|
||||
*****************************************************************************
|
||||
|
||||
Declaration of interfaces for the "basic radix-2" evaluation domain.
|
||||
|
||||
Roughly, the domain has size m = 2^k and consists of the m-th roots of unity.
|
||||
|
||||
*****************************************************************************
|
||||
* @author This file is part of libsnark, developed by SCIPR Lab
|
||||
* and contributors (see AUTHORS).
|
||||
* @copyright MIT license (see LICENSE file)
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef BASIC_RADIX2_DOMAIN_HPP_
|
||||
#define BASIC_RADIX2_DOMAIN_HPP_
|
||||
|
||||
#include "algebra/evaluation_domain/evaluation_domain.hpp"
|
||||
|
||||
namespace libsnark {
|
||||
|
||||
template<typename FieldT>
|
||||
class basic_radix2_domain : public evaluation_domain<FieldT> {
|
||||
public:
|
||||
|
||||
FieldT omega;
|
||||
|
||||
basic_radix2_domain(const size_t m);
|
||||
|
||||
void FFT(std::vector<FieldT> &a);
|
||||
void iFFT(std::vector<FieldT> &a);
|
||||
void cosetFFT(std::vector<FieldT> &a, const FieldT &g);
|
||||
void icosetFFT(std::vector<FieldT> &a, const FieldT &g);
|
||||
std::vector<FieldT> lagrange_coeffs(const FieldT &t);
|
||||
FieldT get_element(const size_t idx);
|
||||
FieldT compute_Z(const FieldT &t);
|
||||
void add_poly_Z(const FieldT &coeff, std::vector<FieldT> &H);
|
||||
void divide_by_Z_on_coset(std::vector<FieldT> &P);
|
||||
|
||||
};
|
||||
|
||||
} // libsnark
|
||||
|
||||
#include "algebra/evaluation_domain/domains/basic_radix2_domain.tcc"
|
||||
|
||||
#endif // BASIC_RADIX2_DOMAIN_HPP_
|
||||
112
src/algebra/evaluation_domain/domains/basic_radix2_domain.tcc
Normal file
112
src/algebra/evaluation_domain/domains/basic_radix2_domain.tcc
Normal file
@@ -0,0 +1,112 @@
|
||||
/** @file
|
||||
*****************************************************************************
|
||||
|
||||
Implementation of interfaces for the "basic radix-2" evaluation domain.
|
||||
|
||||
See basic_radix2_domain.hpp .
|
||||
|
||||
*****************************************************************************
|
||||
* @author This file is part of libsnark, developed by SCIPR Lab
|
||||
* and contributors (see AUTHORS).
|
||||
* @copyright MIT license (see LICENSE file)
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef BASIC_RADIX2_DOMAIN_TCC_
|
||||
#define BASIC_RADIX2_DOMAIN_TCC_
|
||||
|
||||
#include "algebra/evaluation_domain/domains/basic_radix2_domain_aux.hpp"
|
||||
|
||||
namespace libsnark {
|
||||
|
||||
template<typename FieldT>
|
||||
basic_radix2_domain<FieldT>::basic_radix2_domain(const size_t m) : evaluation_domain<FieldT>(m)
|
||||
{
|
||||
assert(m > 1);
|
||||
const size_t logm = log2(m);
|
||||
assert(logm <= (FieldT::s));
|
||||
|
||||
omega = get_root_of_unity<FieldT>(m);
|
||||
}
|
||||
|
||||
template<typename FieldT>
|
||||
void basic_radix2_domain<FieldT>::FFT(std::vector<FieldT> &a)
|
||||
{
|
||||
enter_block("Execute FFT");
|
||||
assert(a.size() == this->m);
|
||||
_basic_radix2_FFT(a, omega);
|
||||
leave_block("Execute FFT");
|
||||
}
|
||||
|
||||
template<typename FieldT>
|
||||
void basic_radix2_domain<FieldT>::iFFT(std::vector<FieldT> &a)
|
||||
{
|
||||
enter_block("Execute inverse FFT");
|
||||
assert(a.size() == this->m);
|
||||
_basic_radix2_FFT(a, omega.inverse());
|
||||
|
||||
const FieldT sconst = FieldT(a.size()).inverse();
|
||||
for (size_t i = 0; i < a.size(); ++i)
|
||||
{
|
||||
a[i] *= sconst;
|
||||
}
|
||||
leave_block("Execute inverse FFT");
|
||||
}
|
||||
|
||||
template<typename FieldT>
|
||||
void basic_radix2_domain<FieldT>::cosetFFT(std::vector<FieldT> &a, const FieldT &g)
|
||||
{
|
||||
enter_block("Execute coset FFT");
|
||||
_multiply_by_coset(a, g);
|
||||
FFT(a);
|
||||
leave_block("Execute coset FFT");
|
||||
}
|
||||
|
||||
template<typename FieldT>
|
||||
void basic_radix2_domain<FieldT>::icosetFFT(std::vector<FieldT> &a, const FieldT &g)
|
||||
{
|
||||
enter_block("Execute inverse coset IFFT");
|
||||
iFFT(a);
|
||||
_multiply_by_coset(a, g.inverse());
|
||||
leave_block("Execute inverse coset IFFT");
|
||||
}
|
||||
|
||||
template<typename FieldT>
|
||||
std::vector<FieldT> basic_radix2_domain<FieldT>::lagrange_coeffs(const FieldT &t)
|
||||
{
|
||||
return _basic_radix2_lagrange_coeffs(this->m, t);
|
||||
}
|
||||
|
||||
template<typename FieldT>
|
||||
FieldT basic_radix2_domain<FieldT>::get_element(const size_t idx)
|
||||
{
|
||||
return omega^idx;
|
||||
}
|
||||
|
||||
template<typename FieldT>
|
||||
FieldT basic_radix2_domain<FieldT>::compute_Z(const FieldT &t)
|
||||
{
|
||||
return (t^this->m) - FieldT::one();
|
||||
}
|
||||
|
||||
template<typename FieldT>
|
||||
void basic_radix2_domain<FieldT>::add_poly_Z(const FieldT &coeff, std::vector<FieldT> &H)
|
||||
{
|
||||
assert(H.size() == this->m+1);
|
||||
H[this->m] += coeff;
|
||||
H[0] -= coeff;
|
||||
}
|
||||
|
||||
template<typename FieldT>
|
||||
void basic_radix2_domain<FieldT>::divide_by_Z_on_coset(std::vector<FieldT> &P)
|
||||
{
|
||||
const FieldT coset = FieldT::multiplicative_generator;
|
||||
const FieldT Z_inverse_at_coset = this->compute_Z(coset).inverse();
|
||||
for (size_t i = 0; i < this->m; ++i)
|
||||
{
|
||||
P[i] *= Z_inverse_at_coset;
|
||||
}
|
||||
}
|
||||
|
||||
} // libsnark
|
||||
|
||||
#endif // BASIC_RADIX2_DOMAIN_TCC_
|
||||
@@ -0,0 +1,48 @@
|
||||
/** @file
|
||||
*****************************************************************************
|
||||
|
||||
Declaration of interfaces for auxiliary functions for the "basic radix-2" evaluation domain.
|
||||
|
||||
These functions compute the radix-2 FFT (in single- or multi-thread mode) and,
|
||||
also compute Lagrange coefficients.
|
||||
|
||||
*****************************************************************************
|
||||
* @author This file is part of libsnark, developed by SCIPR Lab
|
||||
* and contributors (see AUTHORS).
|
||||
* @copyright MIT license (see LICENSE file)
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef BASIC_RADIX2_DOMAIN_AUX_HPP_
|
||||
#define BASIC_RADIX2_DOMAIN_AUX_HPP_
|
||||
|
||||
namespace libsnark {
|
||||
|
||||
/**
|
||||
* Compute the radix-2 FFT of the vector a over the set S={omega^{0},...,omega^{m-1}}.
|
||||
*/
|
||||
template<typename FieldT>
|
||||
void _basic_radix2_FFT(std::vector<FieldT> &a, const FieldT &omega);
|
||||
|
||||
/**
|
||||
* A multi-thread version of _basic_radix2_FFT.
|
||||
*/
|
||||
template<typename FieldT>
|
||||
void _parallel_basic_radix2_FFT(std::vector<FieldT> &a, const FieldT &omega);
|
||||
|
||||
/**
|
||||
* Translate the vector a to a coset defined by g.
|
||||
*/
|
||||
template<typename FieldT>
|
||||
void _multiply_by_coset(std::vector<FieldT> &a, const FieldT &g);
|
||||
|
||||
/**
|
||||
* Compute the m Lagrange coefficients, relative to the set S={omega^{0},...,omega^{m-1}}, at the field element t.
|
||||
*/
|
||||
template<typename FieldT>
|
||||
std::vector<FieldT> _basic_radix2_lagrange_coeffs(const size_t m, const FieldT &t);
|
||||
|
||||
} // libsnark
|
||||
|
||||
#include "algebra/evaluation_domain/domains/basic_radix2_domain_aux.tcc"
|
||||
|
||||
#endif // BASIC_RADIX2_DOMAIN_AUX_HPP_
|
||||
@@ -0,0 +1,242 @@
|
||||
/** @file
|
||||
*****************************************************************************
|
||||
|
||||
Implementation of interfaces for auxiliary functions for the "basic radix-2" evaluation domain.
|
||||
|
||||
See basic_radix2_domain_aux.hpp .
|
||||
|
||||
*****************************************************************************
|
||||
* @author This file is part of libsnark, developed by SCIPR Lab
|
||||
* and contributors (see AUTHORS).
|
||||
* @copyright MIT license (see LICENSE file)
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef BASIC_RADIX2_DOMAIN_AUX_TCC_
|
||||
#define BASIC_RADIX2_DOMAIN_AUX_TCC_
|
||||
|
||||
#include <cassert>
|
||||
#ifdef MULTICORE
|
||||
#include <omp.h>
|
||||
#endif
|
||||
#include "algebra/fields/field_utils.hpp"
|
||||
#include "common/profiling.hpp"
|
||||
#include "common/utils.hpp"
|
||||
|
||||
namespace libsnark {
|
||||
|
||||
#ifdef MULTICORE
|
||||
#define _basic_radix2_FFT _basic_parallel_radix2_FFT
|
||||
#else
|
||||
#define _basic_radix2_FFT _basic_serial_radix2_FFT
|
||||
#endif
|
||||
|
||||
/*
|
||||
Below we make use of pseudocode from [CLRS 2n Ed, pp. 864].
|
||||
Also, note that it's the caller's responsibility to multiply by 1/N.
|
||||
*/
|
||||
template<typename FieldT>
|
||||
void _basic_serial_radix2_FFT(std::vector<FieldT> &a, const FieldT &omega)
|
||||
{
|
||||
const size_t n = a.size(), logn = log2(n);
|
||||
assert(n == (1u << logn));
|
||||
|
||||
/* swapping in place (from Storer's book) */
|
||||
for (size_t k = 0; k < n; ++k)
|
||||
{
|
||||
const size_t rk = bitreverse(k, logn);
|
||||
if (k < rk)
|
||||
std::swap(a[k], a[rk]);
|
||||
}
|
||||
|
||||
size_t m = 1; // invariant: m = 2^{s-1}
|
||||
for (size_t s = 1; s <= logn; ++s)
|
||||
{
|
||||
// w_m is 2^s-th root of unity now
|
||||
const FieldT w_m = omega^(n/(2*m));
|
||||
|
||||
asm volatile ("/* pre-inner */");
|
||||
for (size_t k = 0; k < n; k += 2*m)
|
||||
{
|
||||
FieldT w = FieldT::one();
|
||||
for (size_t j = 0; j < m; ++j)
|
||||
{
|
||||
const FieldT t = w * a[k+j+m];
|
||||
a[k+j+m] = a[k+j] - t;
|
||||
a[k+j] += t;
|
||||
w *= w_m;
|
||||
}
|
||||
}
|
||||
asm volatile ("/* post-inner */");
|
||||
m *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename FieldT>
|
||||
void _basic_parallel_radix2_FFT_inner(std::vector<FieldT> &a, const FieldT &omega, const size_t log_cpus)
|
||||
{
|
||||
const size_t num_cpus = 1ul<<log_cpus;
|
||||
|
||||
const size_t m = a.size();
|
||||
const size_t log_m = log2(m);
|
||||
assert(m == 1ul<<log_m);
|
||||
|
||||
if (log_m < log_cpus)
|
||||
{
|
||||
_basic_serial_radix2_FFT(a, omega);
|
||||
return;
|
||||
}
|
||||
|
||||
enter_block("Shuffle inputs");
|
||||
std::vector<std::vector<FieldT> > tmp(num_cpus);
|
||||
for (size_t j = 0; j < num_cpus; ++j)
|
||||
{
|
||||
tmp[j].resize(1ul<<(log_m-log_cpus), FieldT::zero());
|
||||
}
|
||||
|
||||
#ifdef MULTICORE
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
for (size_t j = 0; j < num_cpus; ++j)
|
||||
{
|
||||
const FieldT omega_j = omega^j;
|
||||
const FieldT omega_step = omega^(j<<(log_m - log_cpus));
|
||||
|
||||
FieldT elt = FieldT::one();
|
||||
for (size_t i = 0; i < 1ul<<(log_m - log_cpus); ++i)
|
||||
{
|
||||
for (size_t s = 0; s < num_cpus; ++s)
|
||||
{
|
||||
// invariant: elt is omega^(j*idx)
|
||||
const size_t idx = (i + (s<<(log_m - log_cpus))) % (1u << log_m);
|
||||
tmp[j][i] += a[idx] * elt;
|
||||
elt *= omega_step;
|
||||
}
|
||||
elt *= omega_j;
|
||||
}
|
||||
}
|
||||
leave_block("Shuffle inputs");
|
||||
|
||||
enter_block("Execute sub-FFTs");
|
||||
const FieldT omega_num_cpus = omega^num_cpus;
|
||||
|
||||
#ifdef MULTICORE
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
for (size_t j = 0; j < num_cpus; ++j)
|
||||
{
|
||||
_basic_serial_radix2_FFT(tmp[j], omega_num_cpus);
|
||||
}
|
||||
leave_block("Execute sub-FFTs");
|
||||
|
||||
enter_block("Re-shuffle outputs");
|
||||
|
||||
#ifdef MULTICORE
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
for (size_t i = 0; i < num_cpus; ++i)
|
||||
{
|
||||
for (size_t j = 0; j < 1ul<<(log_m - log_cpus); ++j)
|
||||
{
|
||||
// now: i = idx >> (log_m - log_cpus) and j = idx % (1u << (log_m - log_cpus)), for idx = ((i<<(log_m-log_cpus))+j) % (1u << log_m)
|
||||
a[(j<<log_cpus) + i] = tmp[i][j];
|
||||
}
|
||||
}
|
||||
leave_block("Re-shuffle outputs");
|
||||
}
|
||||
|
||||
template<typename FieldT>
|
||||
void _basic_parallel_radix2_FFT(std::vector<FieldT> &a, const FieldT &omega)
|
||||
{
|
||||
#ifdef MULTICORE
|
||||
const size_t num_cpus = omp_get_max_threads();
|
||||
#else
|
||||
const size_t num_cpus = 1;
|
||||
#endif
|
||||
const size_t log_cpus = ((num_cpus & (num_cpus - 1)) == 0 ? log2(num_cpus) : log2(num_cpus) - 1);
|
||||
|
||||
#ifdef DEBUG
|
||||
print_indent(); printf("* Invoking parallel FFT on 2^%zu CPUs (omp_get_max_threads = %zu)\n", log_cpus, num_cpus);
|
||||
#endif
|
||||
|
||||
if (log_cpus == 0)
|
||||
{
|
||||
_basic_serial_radix2_FFT(a, omega);
|
||||
}
|
||||
else
|
||||
{
|
||||
_basic_parallel_radix2_FFT_inner(a, omega, log_cpus);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename FieldT>
|
||||
void _multiply_by_coset(std::vector<FieldT> &a, const FieldT &g)
|
||||
{
|
||||
//enter_block("Multiply by coset");
|
||||
FieldT u = g;
|
||||
for (size_t i = 1; i < a.size(); ++i)
|
||||
{
|
||||
a[i] *= u;
|
||||
u *= g;
|
||||
}
|
||||
//leave_block("Multiply by coset");
|
||||
}
|
||||
|
||||
template<typename FieldT>
|
||||
std::vector<FieldT> _basic_radix2_lagrange_coeffs(const size_t m, const FieldT &t)
|
||||
{
|
||||
if (m == 1)
|
||||
{
|
||||
return std::vector<FieldT>(1, FieldT::one());
|
||||
}
|
||||
|
||||
assert(m == (1u << log2(m)));
|
||||
|
||||
const FieldT omega = get_root_of_unity<FieldT>(m);
|
||||
|
||||
std::vector<FieldT> u(m, FieldT::zero());
|
||||
|
||||
/*
|
||||
If t equals one of the roots of unity in S={omega^{0},...,omega^{m-1}}
|
||||
then output 1 at the right place, and 0 elsewhere
|
||||
*/
|
||||
|
||||
if ((t^m) == (FieldT::one()))
|
||||
{
|
||||
FieldT omega_i = FieldT::one();
|
||||
for (size_t i = 0; i < m; ++i)
|
||||
{
|
||||
if (omega_i == t) // i.e., t equals omega^i
|
||||
{
|
||||
u[i] = FieldT::one();
|
||||
return u;
|
||||
}
|
||||
|
||||
omega_i *= omega;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Otherwise, if t does not equal any of the roots of unity in S,
|
||||
then compute each L_{i,S}(t) as Z_{S}(t) * v_i / (t-\omega^i)
|
||||
where:
|
||||
- Z_{S}(t) = \prod_{j} (t-\omega^j) = (t^m-1), and
|
||||
- v_{i} = 1 / \prod_{j \neq i} (\omega^i-\omega^j).
|
||||
Below we use the fact that v_{0} = 1/m and v_{i+1} = \omega * v_{i}.
|
||||
*/
|
||||
|
||||
const FieldT Z = (t^m)-FieldT::one();
|
||||
FieldT l = Z * FieldT(m).inverse();
|
||||
FieldT r = FieldT::one();
|
||||
for (size_t i = 0; i < m; ++i)
|
||||
{
|
||||
u[i] = l * (t - r).inverse();
|
||||
l *= omega;
|
||||
r *= omega;
|
||||
}
|
||||
|
||||
return u;
|
||||
}
|
||||
|
||||
} // libsnark
|
||||
|
||||
#endif // BASIC_RADIX2_DOMAIN_AUX_TCC_
|
||||
125
src/algebra/evaluation_domain/evaluation_domain.hpp
Normal file
125
src/algebra/evaluation_domain/evaluation_domain.hpp
Normal file
@@ -0,0 +1,125 @@
|
||||
/** @file
|
||||
*****************************************************************************
|
||||
|
||||
Declaration of interfaces for evaluation domains.
|
||||
|
||||
Roughly, given a desired size m for the domain, the constructor selects
|
||||
a choice of domain S with size ~m that has been selected so to optimize
|
||||
- computations of Lagrange polynomials, and
|
||||
- FFT/iFFT computations.
|
||||
An evaluation domain also provides other other functions, e.g., accessing
|
||||
individual elements in S or evaluating its vanishing polynomial.
|
||||
|
||||
The descriptions below make use of the definition of a *Lagrange polynomial*,
|
||||
which we recall. Given a field F, a subset S=(a_i)_i of F, and an index idx
|
||||
in {0,...,|S-1|}, the idx-th Lagrange polynomial (wrt to subset S) is defined to be
|
||||
\f[ L_{idx,S}(z) := prod_{k \neq idx} (z - a_k) / prod_{k \neq idx} (a_{idx} - a_k) \f]
|
||||
Note that, by construction:
|
||||
\f[ \forall j \neq idx: L_{idx,S}(a_{idx}) = 1 \text{ and } L_{idx,S}(a_j) = 0 \f]
|
||||
|
||||
*****************************************************************************
|
||||
* @author This file is part of libsnark, developed by SCIPR Lab
|
||||
* and contributors (see AUTHORS).
|
||||
* @copyright MIT license (see LICENSE file)
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef EVALUATION_DOMAIN_HPP_
|
||||
#define EVALUATION_DOMAIN_HPP_
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace libsnark {
|
||||
|
||||
/**
|
||||
* An evaluation domain.
|
||||
*/
|
||||
template<typename FieldT>
|
||||
class evaluation_domain {
|
||||
public:
|
||||
|
||||
const size_t m;
|
||||
|
||||
/**
|
||||
* Construct an evaluation domain S of size m, if possible.
|
||||
*
|
||||
* (See the function get_evaluation_domain below.)
|
||||
*/
|
||||
evaluation_domain(const size_t m) : m(m) {};
|
||||
|
||||
/**
|
||||
* Get the idx-th element in S.
|
||||
*/
|
||||
virtual FieldT get_element(const size_t idx) = 0;
|
||||
|
||||
/**
|
||||
* Compute the FFT, over the domain S, of the vector a.
|
||||
*/
|
||||
virtual void FFT(std::vector<FieldT> &a) = 0;
|
||||
|
||||
/**
|
||||
* Compute the inverse FFT, over the domain S, of the vector a.
|
||||
*/
|
||||
virtual void iFFT(std::vector<FieldT> &a) = 0;
|
||||
|
||||
/**
|
||||
* Compute the FFT, over the domain g*S, of the vector a.
|
||||
*/
|
||||
virtual void cosetFFT(std::vector<FieldT> &a, const FieldT &g) = 0;
|
||||
|
||||
/**
|
||||
* Compute the inverse FFT, over the domain g*S, of the vector a.
|
||||
*/
|
||||
virtual void icosetFFT(std::vector<FieldT> &a, const FieldT &g) = 0;
|
||||
|
||||
/**
|
||||
* Evaluate all Lagrange polynomials.
|
||||
*
|
||||
* The inputs are:
|
||||
* - an integer m
|
||||
* - an element t
|
||||
* The output is a vector (b_{0},...,b_{m-1})
|
||||
* where b_{i} is the evaluation of L_{i,S}(z) at z = t.
|
||||
*/
|
||||
virtual std::vector<FieldT> lagrange_coeffs(const FieldT &t) = 0;
|
||||
|
||||
/**
|
||||
* Evaluate the vanishing polynomial of S at the field element t.
|
||||
*/
|
||||
virtual FieldT compute_Z(const FieldT &t) = 0;
|
||||
|
||||
/**
|
||||
* Add the coefficients of the vanishing polynomial of S to the coefficients of the polynomial H.
|
||||
*/
|
||||
virtual void add_poly_Z(const FieldT &coeff, std::vector<FieldT> &H) = 0;
|
||||
|
||||
/**
|
||||
* Multiply by the evaluation, on a coset of S, of the inverse of the vanishing polynomial of S.
|
||||
*/
|
||||
virtual void divide_by_Z_on_coset(std::vector<FieldT> &P) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return an evaluation domain object in which the domain S has size |S| >= min_size.
|
||||
* The function chooses from different supported domains, depending on min_size.
|
||||
*/
|
||||
template<typename FieldT>
|
||||
std::shared_ptr<evaluation_domain<FieldT> > get_evaluation_domain(const size_t min_size);
|
||||
|
||||
/**
|
||||
* Naive evaluation of a *single* Lagrange polynomial, used for testing purposes.
|
||||
*
|
||||
* The inputs are:
|
||||
* - an integer m
|
||||
* - a domain S = (a_{0},...,a_{m-1}) of size m
|
||||
* - a field element element t
|
||||
* - an index idx in {0,...,m-1}
|
||||
* The output is the polynomial L_{idx,S}(z) evaluated at z = t.
|
||||
*/
|
||||
template<typename FieldT>
|
||||
FieldT lagrange_eval(const size_t m, const std::vector<FieldT> &domain, const FieldT &t, const size_t idx);
|
||||
|
||||
} // libsnark
|
||||
|
||||
#include "algebra/evaluation_domain/evaluation_domain.tcc"
|
||||
|
||||
#endif // EVALUATION_DOMAIN_HPP_
|
||||
117
src/algebra/evaluation_domain/evaluation_domain.tcc
Normal file
117
src/algebra/evaluation_domain/evaluation_domain.tcc
Normal file
@@ -0,0 +1,117 @@
|
||||
/** @file
|
||||
*****************************************************************************
|
||||
|
||||
Imeplementation of interfaces for evaluation domains.
|
||||
|
||||
See evaluation_domain.hpp .
|
||||
|
||||
We currently implement, and select among, three types of domains:
|
||||
- "basic radix-2": the domain has size m = 2^k and consists of the m-th roots of unity
|
||||
- "extended radix-2": the domain has size m = 2^{k+1} and consists of "the m-th roots of unity" union "a coset"
|
||||
- "step radix-2": the domain has size m = 2^k + 2^r and consists of "the 2^k-th roots of unity" union "a coset of 2^r-th roots of unity"
|
||||
|
||||
*****************************************************************************
|
||||
* @author This file is part of libsnark, developed by SCIPR Lab
|
||||
* and contributors (see AUTHORS).
|
||||
* @copyright MIT license (see LICENSE file)
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef EVALUATION_DOMAIN_TCC_
|
||||
#define EVALUATION_DOMAIN_TCC_
|
||||
|
||||
#include <cassert>
|
||||
#include "algebra/fields/field_utils.hpp"
|
||||
#include "algebra/evaluation_domain/domains/basic_radix2_domain.hpp"
|
||||
|
||||
namespace libsnark {
|
||||
|
||||
template<typename FieldT>
|
||||
std::shared_ptr<evaluation_domain<FieldT> > get_evaluation_domain(const size_t min_size)
|
||||
{
|
||||
assert(min_size > 1);
|
||||
const size_t log_min_size = log2(min_size);
|
||||
assert(log_min_size <= (FieldT::s+1));
|
||||
|
||||
std::shared_ptr<evaluation_domain<FieldT> > result;
|
||||
if (min_size == (1u << log_min_size))
|
||||
{
|
||||
if (log_min_size == FieldT::s+1)
|
||||
{
|
||||
if (!inhibit_profiling_info)
|
||||
{
|
||||
print_indent(); printf("* Selected domain: extended_radix2\n");
|
||||
}
|
||||
assert(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!inhibit_profiling_info)
|
||||
{
|
||||
print_indent(); printf("* Selected domain: basic_radix2\n");
|
||||
}
|
||||
result.reset(new basic_radix2_domain<FieldT>(min_size));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const size_t big = 1ul<<(log2(min_size)-1);
|
||||
const size_t small = min_size - big;
|
||||
const size_t rounded_small = (1ul<<log2(small));
|
||||
if (big == rounded_small)
|
||||
{
|
||||
if (log2(big + rounded_small) < FieldT::s+1)
|
||||
{
|
||||
if (!inhibit_profiling_info)
|
||||
{
|
||||
print_indent(); printf("* Selected domain: basic_radix2\n");
|
||||
}
|
||||
result.reset(new basic_radix2_domain<FieldT>(big + rounded_small));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!inhibit_profiling_info)
|
||||
{
|
||||
print_indent(); printf("* Selected domain: extended_radix2\n");
|
||||
}
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!inhibit_profiling_info)
|
||||
{
|
||||
print_indent(); printf("* Selected domain: step_radix2\n");
|
||||
}
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename FieldT>
|
||||
FieldT lagrange_eval(const size_t m, const std::vector<FieldT> &domain, const FieldT &t, const size_t idx)
|
||||
{
|
||||
assert(m == domain.size());
|
||||
assert(idx < m);
|
||||
|
||||
FieldT num = FieldT::one();
|
||||
FieldT denom = FieldT::one();
|
||||
|
||||
for (size_t k = 0; k < m; ++k)
|
||||
{
|
||||
if (k == idx)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
num *= t - domain[k];
|
||||
denom *= domain[idx] - domain[k];
|
||||
}
|
||||
|
||||
return num * denom.inverse();
|
||||
}
|
||||
|
||||
} // libsnark
|
||||
|
||||
#endif // EVALUATION_DOMAIN_TCC_
|
||||
Reference in New Issue
Block a user