Skip to content

Commit 9769030

Browse files
authored
Move some utils from libiop to libff (#100)
* Update profiling functions to be compatible with libiop * Move common utils from libiop to libff * Add tests for log2 * Add field utils from libiop * Fix infinite recursion in double * Add power as well as its tests from libiop * Update changelog
1 parent accdf9e commit 9769030

13 files changed

+382
-27
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ This update introduces new field and curve API's, and enforces they are used con
1313
- #83 Make run-clang-tidy return an error when linting fails
1414
- #85 Add more unit tests for fields (Thanks @alexander-zw)
1515
- #86 Add binary fields from [libiop](https://github.com/scipr-lab/libiop)
16+
- #100 Move utils in from [libiop](https://github.com/scipr-lab/libiop)
1617

1718
### Bug fixes
1819
- #75 Get rid of warning for unused constant PI, in complex field

libff/CMakeLists.txt

+31-13
Original file line numberDiff line numberDiff line change
@@ -191,17 +191,30 @@ if ("${IS_LIBFF_PARENT}")
191191
)
192192

193193
add_executable(
194-
algebra_binary_fields_test
195-
EXCLUDE_FROM_ALL
194+
algebra_binary_fields_test
195+
EXCLUDE_FROM_ALL
196+
197+
algebra/fields/tests/test_binary_fields.cpp
198+
)
199+
target_link_libraries(
200+
algebra_binary_fields_test
201+
202+
ff
203+
gtest_main
204+
)
205+
206+
add_executable(
207+
common_test
208+
EXCLUDE_FROM_ALL
196209

197-
algebra/fields/tests/test_binary_fields.cpp
198-
)
199-
target_link_libraries(
200-
algebra_binary_fields_test
210+
common/tests/test_common.cpp
211+
)
212+
target_link_libraries(
213+
common_test
201214

202-
ff
203-
gtest_main
204-
)
215+
ff
216+
gtest_main
217+
)
205218

206219
include(CTest)
207220
add_test(
@@ -224,17 +237,22 @@ if ("${IS_LIBFF_PARENT}")
224237
NAME algebra_fpn_fields_test
225238
COMMAND algebra_fpn_fields_test
226239
)
227-
add_test(
228-
NAME algebra_binary_fields_test
229-
COMMAND algebra_binary_fields_test
230-
)
240+
add_test(
241+
NAME algebra_binary_fields_test
242+
COMMAND algebra_binary_fields_test
243+
)
244+
add_test(
245+
NAME common_test
246+
COMMAND common_test
247+
)
231248

232249
add_dependencies(check algebra_bilinearity_test)
233250
add_dependencies(check algebra_groups_test)
234251
add_dependencies(check algebra_field_utils_test)
235252
add_dependencies(check algebra_all_fields_test)
236253
add_dependencies(check algebra_fpn_fields_test)
237254
add_dependencies(check algebra_binary_fields_test)
255+
add_dependencies(check common_test)
238256

239257
find_package(OpenSSL REQUIRED)
240258
INCLUDE_DIRECTORIES(${OPENSSL_INCLUDE_DIR})

libff/algebra/field_utils/algorithms.hpp

+10
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,16 @@ FieldT power(const FieldT &base, const bigint<m> &exponent);
2525
template<typename FieldT>
2626
FieldT power(const FieldT &base, const unsigned long exponent);
2727

28+
/**
29+
* The unsigned long long versions exist because libiop tends to use size_t instead
30+
* of unsigned long, and size_t may be the same size as ul or ull.
31+
*/
32+
template<typename FieldT>
33+
FieldT power(const FieldT &base, const unsigned long long exponent);
34+
35+
template<typename FieldT>
36+
FieldT power(const FieldT &base, const std::vector<unsigned long long> exponent);
37+
2838
/**
2939
* Tonelli-Shanks square root with given s, t, and quadratic non-residue.
3040
* Only terminates if there is a square root. Only works if required parameters

libff/algebra/field_utils/algorithms.tcc

+52
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,58 @@ FieldT power(const FieldT &base, const unsigned long exponent)
4747
return power<FieldT>(base, bigint<1>(exponent));
4848
}
4949

50+
template<typename FieldT>
51+
FieldT power(const FieldT &base, const unsigned long long exponent)
52+
{
53+
FieldT result = FieldT::one();
54+
55+
bool found_one = false;
56+
57+
for (long i = 8 * sizeof(exponent) - 1; i >= 0; --i)
58+
{
59+
if (found_one)
60+
{
61+
result = result.squared();
62+
}
63+
64+
if (exponent & (1ull << i))
65+
{
66+
found_one = true;
67+
result *= base;
68+
}
69+
}
70+
71+
return result;
72+
}
73+
74+
template<typename FieldT>
75+
FieldT power(const FieldT &base, const std::vector<unsigned long long> exponent)
76+
{
77+
FieldT result = FieldT::one();
78+
79+
bool found_one = false;
80+
81+
for (unsigned long long j = 0; j < exponent.size(); j++)
82+
{
83+
unsigned long long cur_exp = exponent[j];
84+
for (long i = 8 * sizeof(cur_exp) - 1; i >= 0; --i)
85+
{
86+
if (found_one)
87+
{
88+
result = result.squared();
89+
}
90+
91+
if (cur_exp & (1ull << i))
92+
{
93+
found_one = true;
94+
result *= base;
95+
}
96+
}
97+
}
98+
99+
return result;
100+
}
101+
50102
template<typename FieldT>
51103
FieldT tonelli_shanks_sqrt(const FieldT &value)
52104
{

libff/algebra/field_utils/field_utils.hpp

+82-3
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,91 @@
99
#define FIELD_UTILS_HPP_
1010
#include <cstdint>
1111

12-
#include <libff/algebra/field_utils/bigint.hpp>
13-
#include <libff/common/double.hpp>
14-
#include <libff/common/utils.hpp>
12+
#include "libff/algebra/field_utils/bigint.hpp"
13+
#include "libff/common/double.hpp"
14+
#include "libff/common/utils.hpp"
15+
16+
#include "libff/algebra/fields/binary/gf64.hpp"
17+
#include "libff/algebra/fields/binary/gf128.hpp"
18+
#include "libff/algebra/fields/binary/gf192.hpp"
19+
#include "libff/algebra/fields/binary/gf256.hpp"
20+
#include "libff/algebra/fields/prime_base/fp.hpp"
1521

1622
namespace libff {
1723

24+
template<typename FieldT>
25+
struct is_additive {
26+
static const bool value = false;
27+
};
28+
29+
template<>
30+
struct is_additive<gf64> {
31+
static const bool value = true;
32+
};
33+
34+
template<>
35+
struct is_additive<gf128> {
36+
static const bool value = true;
37+
};
38+
39+
template<>
40+
struct is_additive<gf192> {
41+
static const bool value = true;
42+
};
43+
44+
template<>
45+
struct is_additive<gf256> {
46+
static const bool value = true;
47+
};
48+
49+
template<typename FieldT>
50+
struct is_multiplicative {
51+
static const bool value = false;
52+
};
53+
54+
template<mp_size_t n, const bigint<n>& modulus>
55+
struct is_multiplicative<Fp_model<n, modulus>> {
56+
static const bool value = true;
57+
};
58+
59+
enum field_type {
60+
multiplicative_field_type = 1,
61+
additive_field_type = 2
62+
};
63+
64+
template<typename FieldT>
65+
field_type get_field_type(const typename enable_if<is_multiplicative<FieldT>::value, FieldT>::type elem);
66+
67+
template<typename FieldT>
68+
field_type get_field_type(const typename enable_if<is_additive<FieldT>::value, FieldT>::type elem);
69+
70+
template<typename FieldT>
71+
std::size_t log_of_field_size_helper(
72+
typename enable_if<is_multiplicative<FieldT>::value, FieldT>::type field_elem);
73+
74+
template<typename FieldT>
75+
std::size_t log_of_field_size_helper(
76+
typename enable_if<is_additive<FieldT>::value, FieldT>::type field_elem);
77+
78+
template<typename FieldT>
79+
std::size_t soundness_log_of_field_size_helper(
80+
typename enable_if<is_multiplicative<FieldT>::value, FieldT>::type field_elem);
81+
82+
template<typename FieldT>
83+
std::size_t soundness_log_of_field_size_helper(
84+
typename enable_if<is_additive<FieldT>::value, FieldT>::type field_elem);
85+
86+
template<typename FieldT>
87+
std::size_t get_word_of_field_elem(
88+
typename enable_if<is_additive<FieldT>::value, FieldT>::type field_elem, size_t word);
89+
90+
template<typename FieldT>
91+
std::size_t get_word_of_field_elem(
92+
typename enable_if<is_multiplicative<FieldT>::value, FieldT>::type field_elem, size_t word);
93+
94+
template<typename FieldT>
95+
FieldT coset_shift();
96+
1897
// returns root of unity of order n (for n a power of 2), if one exists
1998
template<typename FieldT>
2099
typename std::enable_if<std::is_same<FieldT, Double>::value, FieldT>::type

libff/algebra/field_utils/field_utils.tcc

+66-3
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,76 @@
1313
#include <complex>
1414
#include <stdexcept>
1515

16-
#include <libff/common/double.hpp>
17-
#include <libff/common/utils.hpp>
18-
1916
namespace libff {
2017

2118
using std::size_t;
2219

20+
template<typename FieldT>
21+
field_type get_field_type(const typename enable_if<is_multiplicative<FieldT>::value, FieldT>::type elem)
22+
{
23+
UNUSED(elem); // only to identify field type
24+
return multiplicative_field_type;
25+
}
26+
27+
template<typename FieldT>
28+
field_type get_field_type(const typename enable_if<is_additive<FieldT>::value, FieldT>::type elem)
29+
{
30+
UNUSED(elem); // only to identify field type
31+
return additive_field_type;
32+
}
33+
34+
template<typename FieldT>
35+
std::size_t log_of_field_size_helper(
36+
typename enable_if<is_multiplicative<FieldT>::value, FieldT>::type field_elem)
37+
{
38+
UNUSED(field_elem);
39+
return FieldT::ceil_size_in_bits();
40+
}
41+
42+
template<typename FieldT>
43+
std::size_t log_of_field_size_helper(
44+
typename enable_if<is_additive<FieldT>::value, FieldT>::type field_elem)
45+
{
46+
UNUSED(field_elem);
47+
return FieldT::extension_degree();
48+
}
49+
50+
template<typename FieldT>
51+
std::size_t soundness_log_of_field_size_helper(
52+
typename enable_if<is_multiplicative<FieldT>::value, FieldT>::type field_elem)
53+
{
54+
UNUSED(field_elem);
55+
/** size in bits is the number of bits needed to represent a field element.
56+
* However there isn't perfect alignment between the number of bits and the number of field elements,
57+
* there could be a factor of two difference.
58+
* For calculating soundness, we use the log of field size as number of bits - 1,
59+
* as (2 << returned) size lower bounds the actual size.
60+
*/
61+
return FieldT::ceil_size_in_bits() - 1;
62+
}
63+
64+
template<typename FieldT>
65+
std::size_t soundness_log_of_field_size_helper(
66+
typename enable_if<is_additive<FieldT>::value, FieldT>::type field_elem)
67+
{
68+
UNUSED(field_elem);
69+
return FieldT::extension_degree();
70+
}
71+
72+
template<typename FieldT>
73+
std::size_t get_word_of_field_elem(
74+
typename enable_if<is_additive<FieldT>::value, FieldT>::type field_elem, size_t word)
75+
{
76+
return field_elem.to_words()[word];
77+
}
78+
79+
template<typename FieldT>
80+
std::size_t get_word_of_field_elem(
81+
typename enable_if<is_multiplicative<FieldT>::value, FieldT>::type field_elem, size_t word)
82+
{
83+
return field_elem.as_bigint().data[word];
84+
}
85+
2386
template<typename FieldT>
2487
FieldT coset_shift()
2588
{

libff/algebra/field_utils/tests/test_field_utils.cpp

+39-1
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,54 @@
11
/**
22
*****************************************************************************
3-
Basic tests for some of the field utils in this directory, mainly bigint.
3+
Basic tests for some of the field utils in this directory, mainly bigint
4+
and power.
45
*****************************************************************************
56
* @author This file is part of libff, developed by SCIPR Lab
67
* and contributors (see AUTHORS).
78
* @copyright MIT license (see LICENSE file)
89
*****************************************************************************/
910
#include "libff/algebra/field_utils/bigint.hpp"
11+
#include "libff/algebra/field_utils/algorithms.hpp"
12+
#include "libff/algebra/fields/binary/gf64.hpp"
1013
#include <gtest/gtest.h>
1114

1215
using namespace libff;
1316

17+
template<typename FieldT>
18+
FieldT power_naive(const FieldT &base, const std::size_t exponent)
19+
{
20+
FieldT result = FieldT::one();
21+
22+
for (std::size_t i = 1; i <= exponent; ++i)
23+
{
24+
result *= base;
25+
}
26+
27+
return result;
28+
}
29+
30+
31+
TEST(ExponentiationTest, SimpleTest) {
32+
typedef gf64 FieldT;
33+
34+
const unsigned long max_power = 3000;
35+
FieldT X = FieldT::random_element();
36+
37+
FieldT X_i = FieldT::one();
38+
for (unsigned long i = 0 ; i < max_power; ++i)
39+
{
40+
const FieldT X_i_naive = power_naive<FieldT>(X, i);
41+
const FieldT X_i_square_and_multiply_ul = power<FieldT>(X, i);
42+
const FieldT X_i_square_and_multiply_ull = power<FieldT>(X, (unsigned long long) i);
43+
44+
EXPECT_EQ(X_i, X_i_naive);
45+
EXPECT_EQ(X_i, X_i_square_and_multiply_ul);
46+
EXPECT_EQ(X_i, X_i_square_and_multiply_ull);
47+
48+
X_i *= X;
49+
}
50+
}
51+
1452
TEST(FieldUtilsTest, BigintTest)
1553
{
1654
bigint<3> zero = bigint<3>("0");

libff/common/double.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ bool Double::operator==(const Double &other) const
117117

118118
bool Double::operator!=(const Double &other) const
119119
{
120-
return Double(val) != other;
120+
return !(*this == other);
121121
}
122122

123123
bool Double::operator<(const Double &other) const

0 commit comments

Comments
 (0)