Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ This update introduces new field and curve API's, and enforces they are used con
- #83 Make run-clang-tidy return an error when linting fails
- #85 Add more unit tests for fields (Thanks @alexander-zw)
- #86 Add binary fields from [libiop](https://github.com/scipr-lab/libiop)
- #100 Move utils in from [libiop](https://github.com/scipr-lab/libiop)

### Bug fixes
- #75 Get rid of warning for unused constant PI, in complex field
Expand Down
44 changes: 31 additions & 13 deletions libff/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -191,17 +191,30 @@ if ("${IS_LIBFF_PARENT}")
)

add_executable(
algebra_binary_fields_test
EXCLUDE_FROM_ALL
algebra_binary_fields_test
EXCLUDE_FROM_ALL

algebra/fields/tests/test_binary_fields.cpp
)
target_link_libraries(
algebra_binary_fields_test

ff
gtest_main
)

add_executable(
common_test
EXCLUDE_FROM_ALL

algebra/fields/tests/test_binary_fields.cpp
)
target_link_libraries(
algebra_binary_fields_test
common/tests/test_common.cpp
)
target_link_libraries(
common_test

ff
gtest_main
)
ff
gtest_main
)

include(CTest)
add_test(
Expand All @@ -224,17 +237,22 @@ if ("${IS_LIBFF_PARENT}")
NAME algebra_fpn_fields_test
COMMAND algebra_fpn_fields_test
)
add_test(
NAME algebra_binary_fields_test
COMMAND algebra_binary_fields_test
)
add_test(
NAME algebra_binary_fields_test
COMMAND algebra_binary_fields_test
)
add_test(
NAME common_test
COMMAND common_test
)

add_dependencies(check algebra_bilinearity_test)
add_dependencies(check algebra_groups_test)
add_dependencies(check algebra_field_utils_test)
add_dependencies(check algebra_all_fields_test)
add_dependencies(check algebra_fpn_fields_test)
add_dependencies(check algebra_binary_fields_test)
add_dependencies(check common_test)

find_package(OpenSSL REQUIRED)
INCLUDE_DIRECTORIES(${OPENSSL_INCLUDE_DIR})
Expand Down
10 changes: 10 additions & 0 deletions libff/algebra/field_utils/algorithms.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,16 @@ FieldT power(const FieldT &base, const bigint<m> &exponent);
template<typename FieldT>
FieldT power(const FieldT &base, const unsigned long exponent);

/**
* The unsigned long long versions exist because libiop tends to use size_t instead
* of unsigned long, and size_t may be the same size as ul or ull.
*/
template<typename FieldT>
FieldT power(const FieldT &base, const unsigned long long exponent);

template<typename FieldT>
FieldT power(const FieldT &base, const std::vector<unsigned long long> exponent);

/**
* Tonelli-Shanks square root with given s, t, and quadratic non-residue.
* Only terminates if there is a square root. Only works if required parameters
Expand Down
52 changes: 52 additions & 0 deletions libff/algebra/field_utils/algorithms.tcc
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,58 @@ FieldT power(const FieldT &base, const unsigned long exponent)
return power<FieldT>(base, bigint<1>(exponent));
}

template<typename FieldT>
FieldT power(const FieldT &base, const unsigned long long exponent)
{
FieldT result = FieldT::one();

bool found_one = false;

for (long i = 8 * sizeof(exponent) - 1; i >= 0; --i)
{
if (found_one)
{
result = result.squared();
}

if (exponent & (1ull << i))
{
found_one = true;
result *= base;
}
}

return result;
}

template<typename FieldT>
FieldT power(const FieldT &base, const std::vector<unsigned long long> exponent)
{
FieldT result = FieldT::one();

bool found_one = false;

for (unsigned long long j = 0; j < exponent.size(); j++)
{
unsigned long long cur_exp = exponent[j];
for (long i = 8 * sizeof(cur_exp) - 1; i >= 0; --i)
{
if (found_one)
{
result = result.squared();
}

if (cur_exp & (1ull << i))
{
found_one = true;
result *= base;
}
}
}

return result;
}

template<typename FieldT>
FieldT tonelli_shanks_sqrt(const FieldT &value)
{
Expand Down
85 changes: 82 additions & 3 deletions libff/algebra/field_utils/field_utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,91 @@
#define FIELD_UTILS_HPP_
#include <cstdint>

#include <libff/algebra/field_utils/bigint.hpp>
#include <libff/common/double.hpp>
#include <libff/common/utils.hpp>
#include "libff/algebra/field_utils/bigint.hpp"
#include "libff/common/double.hpp"
#include "libff/common/utils.hpp"

#include "libff/algebra/fields/binary/gf64.hpp"
#include "libff/algebra/fields/binary/gf128.hpp"
#include "libff/algebra/fields/binary/gf192.hpp"
#include "libff/algebra/fields/binary/gf256.hpp"
#include "libff/algebra/fields/prime_base/fp.hpp"

namespace libff {

template<typename FieldT>
struct is_additive {
static const bool value = false;
};

template<>
struct is_additive<gf64> {
static const bool value = true;
};

template<>
struct is_additive<gf128> {
static const bool value = true;
};

template<>
struct is_additive<gf192> {
static const bool value = true;
};

template<>
struct is_additive<gf256> {
static const bool value = true;
};

template<typename FieldT>
struct is_multiplicative {
static const bool value = false;
};

template<mp_size_t n, const bigint<n>& modulus>
struct is_multiplicative<Fp_model<n, modulus>> {
static const bool value = true;
};

enum field_type {
multiplicative_field_type = 1,
additive_field_type = 2
};

template<typename FieldT>
field_type get_field_type(const typename enable_if<is_multiplicative<FieldT>::value, FieldT>::type elem);

template<typename FieldT>
field_type get_field_type(const typename enable_if<is_additive<FieldT>::value, FieldT>::type elem);

template<typename FieldT>
std::size_t log_of_field_size_helper(
typename enable_if<is_multiplicative<FieldT>::value, FieldT>::type field_elem);

template<typename FieldT>
std::size_t log_of_field_size_helper(
typename enable_if<is_additive<FieldT>::value, FieldT>::type field_elem);

template<typename FieldT>
std::size_t soundness_log_of_field_size_helper(
typename enable_if<is_multiplicative<FieldT>::value, FieldT>::type field_elem);

template<typename FieldT>
std::size_t soundness_log_of_field_size_helper(
typename enable_if<is_additive<FieldT>::value, FieldT>::type field_elem);

template<typename FieldT>
std::size_t get_word_of_field_elem(
typename enable_if<is_additive<FieldT>::value, FieldT>::type field_elem, size_t word);

template<typename FieldT>
std::size_t get_word_of_field_elem(
typename enable_if<is_multiplicative<FieldT>::value, FieldT>::type field_elem, size_t word);

template<typename FieldT>
FieldT coset_shift();

// returns root of unity of order n (for n a power of 2), if one exists
template<typename FieldT>
typename std::enable_if<std::is_same<FieldT, Double>::value, FieldT>::type
Expand Down
69 changes: 66 additions & 3 deletions libff/algebra/field_utils/field_utils.tcc
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,76 @@
#include <complex>
#include <stdexcept>

#include <libff/common/double.hpp>
#include <libff/common/utils.hpp>

namespace libff {

using std::size_t;

template<typename FieldT>
field_type get_field_type(const typename enable_if<is_multiplicative<FieldT>::value, FieldT>::type elem)
{
UNUSED(elem); // only to identify field type
return multiplicative_field_type;
}

template<typename FieldT>
field_type get_field_type(const typename enable_if<is_additive<FieldT>::value, FieldT>::type elem)
{
UNUSED(elem); // only to identify field type
return additive_field_type;
}

template<typename FieldT>
std::size_t log_of_field_size_helper(
typename enable_if<is_multiplicative<FieldT>::value, FieldT>::type field_elem)
{
UNUSED(field_elem);
return FieldT::ceil_size_in_bits();
}

template<typename FieldT>
std::size_t log_of_field_size_helper(
typename enable_if<is_additive<FieldT>::value, FieldT>::type field_elem)
{
UNUSED(field_elem);
return FieldT::extension_degree();
}

template<typename FieldT>
std::size_t soundness_log_of_field_size_helper(
typename enable_if<is_multiplicative<FieldT>::value, FieldT>::type field_elem)
{
UNUSED(field_elem);
/** size in bits is the number of bits needed to represent a field element.
* However there isn't perfect alignment between the number of bits and the number of field elements,
* there could be a factor of two difference.
* For calculating soundness, we use the log of field size as number of bits - 1,
* as (2 << returned) size lower bounds the actual size.
*/
return FieldT::ceil_size_in_bits() - 1;
}

template<typename FieldT>
std::size_t soundness_log_of_field_size_helper(
typename enable_if<is_additive<FieldT>::value, FieldT>::type field_elem)
{
UNUSED(field_elem);
return FieldT::extension_degree();
}

template<typename FieldT>
std::size_t get_word_of_field_elem(
typename enable_if<is_additive<FieldT>::value, FieldT>::type field_elem, size_t word)
{
return field_elem.to_words()[word];
}

template<typename FieldT>
std::size_t get_word_of_field_elem(
typename enable_if<is_multiplicative<FieldT>::value, FieldT>::type field_elem, size_t word)
{
return field_elem.as_bigint().data[word];
}

template<typename FieldT>
FieldT coset_shift()
{
Expand Down
40 changes: 39 additions & 1 deletion libff/algebra/field_utils/tests/test_field_utils.cpp
Original file line number Diff line number Diff line change
@@ -1,16 +1,54 @@
/**
*****************************************************************************
Basic tests for some of the field utils in this directory, mainly bigint.
Basic tests for some of the field utils in this directory, mainly bigint
and power.
*****************************************************************************
* @author This file is part of libff, developed by SCIPR Lab
* and contributors (see AUTHORS).
* @copyright MIT license (see LICENSE file)
*****************************************************************************/
#include "libff/algebra/field_utils/bigint.hpp"
#include "libff/algebra/field_utils/algorithms.hpp"
#include "libff/algebra/fields/binary/gf64.hpp"
#include <gtest/gtest.h>

using namespace libff;

template<typename FieldT>
FieldT power_naive(const FieldT &base, const std::size_t exponent)
{
FieldT result = FieldT::one();

for (std::size_t i = 1; i <= exponent; ++i)
{
result *= base;
}

return result;
}


TEST(ExponentiationTest, SimpleTest) {
typedef gf64 FieldT;

const unsigned long max_power = 3000;
FieldT X = FieldT::random_element();

FieldT X_i = FieldT::one();
for (unsigned long i = 0 ; i < max_power; ++i)
{
const FieldT X_i_naive = power_naive<FieldT>(X, i);
const FieldT X_i_square_and_multiply_ul = power<FieldT>(X, i);
const FieldT X_i_square_and_multiply_ull = power<FieldT>(X, (unsigned long long) i);

EXPECT_EQ(X_i, X_i_naive);
EXPECT_EQ(X_i, X_i_square_and_multiply_ul);
EXPECT_EQ(X_i, X_i_square_and_multiply_ull);

X_i *= X;
}
}

TEST(FieldUtilsTest, BigintTest)
{
bigint<3> zero = bigint<3>("0");
Expand Down
2 changes: 1 addition & 1 deletion libff/common/double.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ bool Double::operator==(const Double &other) const

bool Double::operator!=(const Double &other) const
{
return Double(val) != other;
return !(*this == other);
}

bool Double::operator<(const Double &other) const
Expand Down
Loading