Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lagrange basis aurora speedup2 #30

Draft
wants to merge 13 commits into
base: lagrange_basis_aurora_speedup2
Choose a base branch
from
4 changes: 2 additions & 2 deletions libiop/algebra/exponentiation.tcc
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ std::vector<FieldT> subspace_to_power_of_two(const affine_subspace<FieldT> &S,
el = libiop::power(el, power_of_two);
}

const FieldT offset_power = libiop::power(S.offset(), power_of_two);
return all_subset_sums<FieldT>(basis_powers, offset_power);
const FieldT shift_power = libiop::power(S.shift(), power_of_two);
return all_subset_sums<FieldT>(basis_powers, shift_power);
}

template<typename FieldT>
Expand Down
6 changes: 3 additions & 3 deletions libiop/algebra/fft.tcc
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ std::vector<FieldT> additive_FFT(const std::vector<FieldT> &poly_coeffs,
size_t recursed_betas_ptr = 0;

std::vector<FieldT> betas2(domain.basis());
FieldT shift2 = domain.offset();
FieldT shift2 = domain.shift();
for (size_t j = 0; j < m; ++j)
{
FieldT beta = betas2[m-1-j];
Expand Down Expand Up @@ -135,7 +135,7 @@ std::vector<FieldT> additive_IFFT(const std::vector<FieldT> &evals,
std::vector<FieldT> recursed_twists(m, FieldT(0));

std::vector<FieldT> betas2(domain.basis());
FieldT shift2 = domain.offset();
FieldT shift2 = domain.shift();
for (size_t j = 0; j < m; ++j)
{
const FieldT beta = betas2[m-1-j];
Expand Down Expand Up @@ -439,7 +439,7 @@ std::vector<FieldT> IFFT_of_known_degree_over_field_subset(
field_subset<FieldT> domain)
{
/** We do an IFFT over the minimal subgroup needed for this known degree.
* We take the subgroup with the coset's offset as an element.
* We take the subgroup with the coset's shift as an element.
* The evaluations in this coset are every nth element of the evaluations
* over the entire domain, where n = |domain| / |degree|
*/
Expand Down
1 change: 0 additions & 1 deletion libiop/algebra/field_subset/field_subset.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ class field_subset {

FieldT generator() const;

const FieldT& offset() const;
const FieldT shift() const;
const std::vector<FieldT>& basis() const;

Expand Down
14 changes: 3 additions & 11 deletions libiop/algebra/field_subset/field_subset.tcc
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ field_subset<FieldT> field_subset<FieldT>::get_subset_of_order(const std::size_t
input_subspace_basis.resize(subset_dim);
return field_subset<FieldT>(
affine_subspace<FieldT>(input_subspace_basis,
this->offset()));
this->shift()));
}
case multiplicative_coset_type:
// Assumes this subgroup's generator is the default generator for a subgroup of that order.
Expand Down Expand Up @@ -288,20 +288,12 @@ FieldT field_subset<FieldT>::generator() const
return this->coset_->generator();
}

template<typename FieldT>
const FieldT& field_subset<FieldT>::offset() const
{
assert(this->type_ == affine_subspace_type);

return this->subspace_->offset();
}

template<typename FieldT>
const FieldT field_subset<FieldT>::shift() const
{
assert(this->type_ == multiplicative_coset_type);

return this->coset_->shift();
return this->type_ == multiplicative_coset_type?
this->coset_->shift() : this->subspace_->shift();
}

template<typename FieldT>
Expand Down
2 changes: 1 addition & 1 deletion libiop/algebra/field_subset/subgroup.tcc
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ std::size_t multiplicative_subgroup_base<FieldT>::reindex_by_subgroup(const std:
/** Let x be the number of elements in G \ S, for every element in S. Then x = (|G|/|S| - 1).
* At index i in G \ S, the number of elements in S that appear before the index in G to which
* i corresponds to, is floor(i / x) + 1.
* The +1 is because index 0 of G is S_0, so the position is offset by at least one.
* The +1 is because index 0 of G is S_0, so the position is shift by at least one.
* The floor(i / x) term is because after x elements in G \ S, there is one more element from S
* that will have appeared in G. */
const std::size_t x = order_g_over_s - 1;
Expand Down
12 changes: 6 additions & 6 deletions libiop/algebra/field_subset/subspace.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,15 @@ class linear_subspace {
template<typename FieldT>
class affine_subspace : public linear_subspace<FieldT> {
protected:
FieldT offset_;
FieldT shift_;

public:
affine_subspace() = default;
affine_subspace(const std::vector<FieldT> &basis, const FieldT &offset = FieldT(0));
affine_subspace(const linear_subspace<FieldT> &base_space, const FieldT &offset = FieldT(0));
affine_subspace(linear_subspace<FieldT> &&base_space, const FieldT &offset = FieldT(0));
affine_subspace(const std::vector<FieldT> &basis, const FieldT &shift = FieldT(0));
affine_subspace(const linear_subspace<FieldT> &base_space, const FieldT &shift = FieldT(0));
affine_subspace(linear_subspace<FieldT> &&base_space, const FieldT &shift = FieldT(0));

const FieldT& offset() const;
const FieldT shift() const;

std::vector<FieldT> all_elements() const;
FieldT element_by_index(const std::size_t index) const;
Expand All @@ -68,7 +68,7 @@ class affine_subspace : public linear_subspace<FieldT> {

static affine_subspace<FieldT> shifted_standard_basis(
const std::size_t dimension,
const FieldT& offset);
const FieldT& shift);
static affine_subspace<FieldT> random_affine_subspace(const std::size_t dimension);

bool operator==(const affine_subspace<FieldT> &other) const;
Expand Down
42 changes: 21 additions & 21 deletions libiop/algebra/field_subset/subspace.tcc
Original file line number Diff line number Diff line change
Expand Up @@ -128,72 +128,72 @@ bool linear_subspace<FieldT>::operator!=(const linear_subspace<FieldT> &other) c

template<typename FieldT>
affine_subspace<FieldT>::affine_subspace(const std::vector<FieldT> &basis,
const FieldT &offset) :
linear_subspace<FieldT>(basis), offset_(offset)
const FieldT &shift) :
linear_subspace<FieldT>(basis), shift_(shift)
{
}

template<typename FieldT>
affine_subspace<FieldT>::affine_subspace(
const linear_subspace<FieldT> &base_space,
const FieldT &offset) :
const FieldT &shift) :
linear_subspace<FieldT>(base_space),
offset_(offset)
shift_(shift)
{
}

template<typename FieldT>
affine_subspace<FieldT>::affine_subspace(
linear_subspace<FieldT> &&base_space,
const FieldT &offset) :
const FieldT &shift) :
linear_subspace<FieldT>(std::move(base_space)),
offset_(offset)
shift_(shift)
{
}

template<typename FieldT>
const FieldT& affine_subspace<FieldT>::offset() const
const FieldT affine_subspace<FieldT>::shift() const
{
return this->offset_;
return this->shift_;
}

template<typename FieldT>
std::vector<FieldT> affine_subspace<FieldT>::all_elements() const
{
return all_subset_sums<FieldT>(this->basis_, this->offset_);
return all_subset_sums<FieldT>(this->basis_, this->shift_);
}

template<typename FieldT>
FieldT affine_subspace<FieldT>::element_by_index(const std::size_t index) const
{
return (this->offset_ + (linear_subspace<FieldT>::element_by_index(index)));
return (this->shift_ + (linear_subspace<FieldT>::element_by_index(index)));
}


template<typename FieldT>
bool internal_element_in_subset(const typename libiop::enable_if<is_multiplicative<FieldT>::value, FieldT>::type x,
FieldT offset, size_t dimension)
FieldT shift, size_t dimension)
{
throw std::invalid_argument("subspace.element_in_subset() is only supported for binary fields");
}

template<typename FieldT>
bool internal_element_in_subset(const typename libiop::enable_if<is_additive<FieldT>::value, FieldT>::type x,
FieldT offset, size_t dimension)
FieldT shift, size_t dimension)
{
/** TODO: Implement this case */
if (dimension > 64)
{
throw std::invalid_argument(
"subspace.element_in_subset() is currently unimplimented for basis of dimension greater than 64");
}
/** We first remove the offset, and then test if an element is in the standard basis.
/** We first remove the shift, and then test if an element is in the standard basis.
* It is in the standard basis if for all i >= basis.dimension(), the coefficient of x^i is 0.
* Due to the representation of field elements,
* this corresponds to all but the first basis.dimension() bits being 0.
* (using little endian ordering)
*/
const std::vector<uint64_t> words = (x + offset).as_words();
const std::vector<uint64_t> words = (x + shift).as_words();
/* Check that all but the least significant 64 bits are 0 */
for (size_t i = 1; i < words.size(); i++)
{
Expand All @@ -211,7 +211,7 @@ bool affine_subspace<FieldT>::element_in_subset(const FieldT x) const
{
if (this->is_standard_basis_)
{
return internal_element_in_subset(x, this->offset_, this->dimension());
return internal_element_in_subset(x, this->shift_, this->dimension());
}
throw std::invalid_argument("subspace.element_in_subset() is only supported for standard basis");
}
Expand All @@ -221,7 +221,7 @@ FieldT affine_subspace<FieldT>::element_outside_of_subset() const
{
if (this->is_standard_basis_)
{
return this->offset() + FieldT(1ull << this->dimension());
return this->shift() + FieldT(1ull << this->dimension());
}
throw std::invalid_argument("subspace.element_outside_of_subset() is only supported for standard basis");
}
Expand Down Expand Up @@ -255,26 +255,26 @@ linear_subspace<FieldT> standard_basis(const std::size_t dimension)
template<typename FieldT>
affine_subspace<FieldT> affine_subspace<FieldT>::shifted_standard_basis(
const std::size_t dimension,
const FieldT& offset)
const FieldT& shift)
{
const linear_subspace<FieldT> basis =
linear_subspace<FieldT>::standard_basis(dimension);
return affine_subspace<FieldT>(std::move(basis), offset);
return affine_subspace<FieldT>(std::move(basis), shift);
}

template<typename FieldT>
affine_subspace<FieldT> affine_subspace<FieldT>::random_affine_subspace(const std::size_t dimension)
{
const linear_subspace<FieldT> basis =
linear_subspace<FieldT>::standard_basis(dimension);
const FieldT offset = FieldT::random_element();
return affine_subspace<FieldT>(std::move(basis), offset);
const FieldT shift = FieldT::random_element();
return affine_subspace<FieldT>(std::move(basis), shift);
}

template<typename FieldT>
bool affine_subspace<FieldT>::operator==(const affine_subspace<FieldT> &other) const
{
return linear_subspace<FieldT>::operator==(other) && this->offset_ == other->offset_;
return linear_subspace<FieldT>::operator==(other) && this->shift_ == other->shift_;
}

} // namespace libiop
8 changes: 4 additions & 4 deletions libiop/algebra/lagrange.tcc
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ std::vector<FieldT> lagrange_cache<FieldT>::subspace_coefficients_for(
* This already has c cached, which allows the shifted V to be calculated directly in one pass. */
const FieldT k = this->vp_.evaluation_at_point(interpolation_point) * this->c_;
const std::vector<FieldT> V =
all_subset_sums<FieldT>(this->domain_.basis(), interpolation_point + this->domain_.offset());
all_subset_sums<FieldT>(this->domain_.basis(), interpolation_point + this->domain_.shift());
// Handle check if interpolation point is in domain
if (this->interpolation_domain_intersects_domain_ && k == FieldT::zero()) {
std::vector<FieldT> result(this->domain_.num_elements(), FieldT::zero());
Expand Down Expand Up @@ -230,21 +230,21 @@ std::vector<FieldT> lagrange_coefficients(const affine_subspace<FieldT> &domain,
Our computation below computes:

k = (\prod_{i} \alpha - V[i]) = Zero_V(\alpha)
c = 1/{\prod_{j > 0} (V[j] - domain.offset()) = 1 / (Z_{V - offset} / X)(0)
c = 1/{\prod_{j > 0} (V[j] - domain.shift()) = 1 / (Z_{V - shift} / X)(0)

and inverses of (\alpha - V[0]), ..., (\alpha - V[2^n-1])

Then L[j] = k * c / (\alpha - V[j]).
*/

vanishing_polynomial<FieldT> Z(domain);
/* (Z_{V - offset} / X)(0) is the formal derivative of Z_V,
/* (Z_{V - shift} / X)(0) is the formal derivative of Z_V,
* as the affine shift only affects the constant coefficient. */
const FieldT c = Z.formal_derivative_at_point(FieldT::zero()).inverse();
const FieldT k = Z.evaluation_at_point(interpolation_point);

std::vector<FieldT> V =
all_subset_sums<FieldT>(domain.basis(), interpolation_point + domain.offset());
all_subset_sums<FieldT>(domain.basis(), interpolation_point + domain.shift());

const std::vector<FieldT> V_inv = batch_inverse_and_mul<FieldT>(V, c * k);

Expand Down
2 changes: 1 addition & 1 deletion libiop/algebra/polynomials/lagrange_polynomial.tcc
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ std::vector<FieldT> lagrange_polynomial<FieldT>::evaluations_over_field_subset(
* The additive case admits a faster method to create it, hence the separation */
if (this->S_.type() == affine_subspace_type)
{
denominator = all_subset_sums<FieldT>(evaldomain.basis(), this->x_ + evaldomain.offset());
denominator = all_subset_sums<FieldT>(evaldomain.basis(), this->x_ + evaldomain.shift());
}
else if (this->S_.type() == multiplicative_coset_type)
{
Expand Down
22 changes: 11 additions & 11 deletions libiop/algebra/polynomials/linearized_polynomial.tcc
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,17 @@ std::vector<FieldT> linearized_polynomial<FieldT>::evaluations_over_subspace(con

Therefore, evaluating over subspace below, we subtract constant
term from evaluations over the basis, but include the constant
term in the offset calculation. */
term in the shift calculation. */

std::vector<FieldT> eval_at_basis(S.basis());
std::for_each(eval_at_basis.begin(), eval_at_basis.end(),
[this](FieldT &el) {
el = (this->evaluation_at_point(el) -
this->constant_coefficient());
});
const FieldT offset = this->evaluation_at_point(S.offset());
const FieldT shift = this->evaluation_at_point(S.shift());

return all_subset_sums<FieldT>(eval_at_basis, offset);
return all_subset_sums<FieldT>(eval_at_basis, shift);
}

template<typename FieldT>
Expand Down Expand Up @@ -191,17 +191,17 @@ bool linearized_polynomial<FieldT>::operator!=(const linearized_polynomial<Field
}

template<typename FieldT>
void add_scalar_multiple_at_offset(std::vector<FieldT> &result,
void add_scalar_multiple_at_shift(std::vector<FieldT> &result,
const std::vector<FieldT> &p,
const FieldT &factor,
const size_t offset) {
const size_t shift) {
// This is a helper method for linearized polynomial * polynomial
// It adds factor * p to result, starting at offset
// It adds factor * p to result, starting at shift
if (factor == FieldT::zero()) {
return;
}
for (std::size_t i = 0; i < p.size(); i++) {
result[i + offset] += p[i] * factor;
result[i + shift] += p[i] * factor;
}
}

Expand All @@ -212,16 +212,16 @@ polynomial<FieldT> linearized_polynomial<FieldT>::operator*(const polynomial<Fie
// which is L[0] * p + L[1] * p * x + L[2] * p * x^2 + L[3] * p * x^4 + ...
// The polynomial coefficient representation has the constant term on the left,
// and higher degrees growing towards the right.
// This adds each term progressively, using add_scalar_multiple_at_offset
// This adds each term progressively, using add_scalar_multiple_at_shift

// Set num elements in result correctly
std::vector<FieldT> result(p.degree() + 1 + this->degree(), FieldT::zero());
const std::vector<FieldT> p_coeff = p.coefficients();
// set result to be L[0] * p
add_scalar_multiple_at_offset(result, p_coeff, this->coefficients_[0], 0);
add_scalar_multiple_at_shift(result, p_coeff, this->coefficients_[0], 0);
for (std::size_t i = 1; i < this->coefficients_.size(); i++) {
std::size_t offset = 1 << (i - 1);
add_scalar_multiple_at_offset(result, p_coeff, this->coefficients_[i], offset);
std::size_t shift = 1 << (i - 1);
add_scalar_multiple_at_shift(result, p_coeff, this->coefficients_[i], shift);
}
return polynomial<FieldT>(std::move(result));
}
Expand Down
2 changes: 1 addition & 1 deletion libiop/algebra/polynomials/vanishing_polynomial.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class vanishing_polynomial : public polynomial_base<FieldT> {
// subspace type
linearized_polynomial<FieldT> linearized_polynomial_;
// multiplicative coset type
FieldT vp_offset_; /* offset^|H| for cosets, 1 for subgroups */
FieldT vp_shift_; /* shift^|H| for cosets, 1 for subgroups */

public:
explicit vanishing_polynomial() {};
Expand Down
Loading