Collect various utility functions into a separate file
This commit is contained in:
parent
7fd0899972
commit
159fc0024d
|
@ -1,7 +1,7 @@
|
|||
TESTS = bls12_381_test c_kzg_util_test fft_common_test fft_fr_test fft_g1_test \
|
||||
fk20_proofs_test kzg_proofs_test poly_test
|
||||
fk20_proofs_test kzg_proofs_test poly_test utility_test
|
||||
BENCH = fft_fr_bench fft_g1_bench
|
||||
LIB_SRC = bls12_381.c c_kzg_util.c das_extension.c fft_common.c fft_fr.c fft_g1.c fk20_proofs.c kzg_proofs.c poly.c
|
||||
LIB_SRC = bls12_381.c c_kzg_util.c das_extension.c fft_common.c fft_fr.c fft_g1.c fk20_proofs.c kzg_proofs.c poly.c utility.c
|
||||
LIB_OBJ = $(LIB_SRC:.c=.o)
|
||||
|
||||
CFLAGS =
|
||||
|
|
|
@ -23,20 +23,6 @@
|
|||
#include "fft_common.h"
|
||||
#include "c_kzg_util.h"
|
||||
|
||||
/**
|
||||
* Utility function to test whether the argument is a power of two.
|
||||
*
|
||||
* @remark This method returns `true` for `is_power_of_two(0)` which is a bit weird, but not an issue in the contexts in
|
||||
* which we use it.
|
||||
*
|
||||
* @param[in] n The number to test
|
||||
* @retval true if @p n is a power of two or zero
|
||||
* @retval false otherwise
|
||||
*/
|
||||
bool is_power_of_two(uint64_t n) {
|
||||
return (n & (n - 1)) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate powers of a root of unity in the field for use in the FFTs.
|
||||
*
|
||||
|
|
|
@ -80,7 +80,6 @@ typedef struct {
|
|||
fr_t *reverse_roots_of_unity; /**< Descending powers of the root of unity, size `width + 1`. */
|
||||
} FFTSettings;
|
||||
|
||||
bool is_power_of_two(uint64_t n);
|
||||
C_KZG_RET expand_root_of_unity(fr_t *out, const fr_t *root, uint64_t width);
|
||||
C_KZG_RET new_fft_settings(FFTSettings *s, unsigned int max_scale);
|
||||
void free_fft_settings(FFTSettings *s);
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "../inc/acutest.h"
|
||||
#include "test_util.h"
|
||||
#include "fft_common.h"
|
||||
#include "utility.h"
|
||||
|
||||
#define NUM_ROOTS 32
|
||||
|
||||
|
@ -78,21 +79,6 @@ void new_fft_settings_is_plausible(void) {
|
|||
free_fft_settings(&s);
|
||||
}
|
||||
|
||||
void is_power_of_two_works(void) {
|
||||
// All actual powers of two
|
||||
for (int i = 0; i <= 63; i++) {
|
||||
TEST_CHECK(true == is_power_of_two((uint64_t)1 << i));
|
||||
TEST_MSG("Case %d", i);
|
||||
}
|
||||
|
||||
// This is a bit weird
|
||||
TEST_CHECK(true == is_power_of_two(0));
|
||||
|
||||
// Not powers of two
|
||||
TEST_CHECK(false == is_power_of_two(123));
|
||||
TEST_CHECK(false == is_power_of_two(1234567));
|
||||
}
|
||||
|
||||
TEST_LIST = {
|
||||
{"FFT_COMMON_TEST", title},
|
||||
{"roots_of_unity_is_the_expected_size", roots_of_unity_is_the_expected_size},
|
||||
|
@ -100,6 +86,5 @@ TEST_LIST = {
|
|||
{"roots_of_unity_are_plausible", roots_of_unity_are_plausible},
|
||||
{"expand_roots_is_plausible", expand_roots_is_plausible},
|
||||
{"new_fft_settings_is_plausible", new_fft_settings_is_plausible},
|
||||
{"is_power_of_two_works", is_power_of_two_works},
|
||||
{NULL, NULL} /* zero record marks the end of the list */
|
||||
};
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include "fft_fr.h"
|
||||
#include "c_kzg_util.h"
|
||||
#include "utility.h"
|
||||
|
||||
/**
|
||||
* Slow Fourier Transform.
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include "fft_g1.h"
|
||||
#include "c_kzg_util.h"
|
||||
#include "utility.h"
|
||||
|
||||
/**
|
||||
* Slow Fourier Transform.
|
||||
|
|
|
@ -23,90 +23,10 @@
|
|||
* @todo Split this out into smaller files.
|
||||
*/
|
||||
|
||||
#include <string.h> // memcpy()
|
||||
#include "fk20_proofs.h"
|
||||
#include "fft_g1.h"
|
||||
#include "c_kzg_util.h"
|
||||
|
||||
/**
|
||||
* Calculate log base two of a power of two.
|
||||
*
|
||||
* In other words, the bit index of the one bit.
|
||||
*
|
||||
* @remark Works only for n a power of two, and only for n up to 2^31.
|
||||
*
|
||||
* @param[in] n The power of two
|
||||
* @return the log base two of n
|
||||
*/
|
||||
int log2_pow2(uint32_t n) {
|
||||
const uint32_t b[] = {0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000};
|
||||
register uint32_t r;
|
||||
r = (n & b[0]) != 0;
|
||||
r |= ((n & b[1]) != 0) << 1;
|
||||
r |= ((n & b[2]) != 0) << 2;
|
||||
r |= ((n & b[3]) != 0) << 3;
|
||||
r |= ((n & b[4]) != 0) << 4;
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the bit order in a 32 bit integer.
|
||||
*
|
||||
* @remark This simply wraps the macro to enforce the type check.
|
||||
*
|
||||
* @param[in] a The integer to be reversed
|
||||
* @return An integer with the bits of @p a reversed
|
||||
*/
|
||||
uint32_t reverse_bits(uint32_t a) {
|
||||
return rev_4byte(a);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the low-order bits in a 32 bit integer.
|
||||
*
|
||||
* The lowest log_base_two(@p n) bits of @p value are returned reversed. @p n must be a power of two.
|
||||
*
|
||||
* @param[in] n To reverse `b` bits, set `n = 2 ^ b`
|
||||
* @param[in] value The bits to be reversed
|
||||
* @return The reversal of the lowest log_2(@p n) bits of the input @p value
|
||||
*/
|
||||
uint32_t reverse_bits_limited(uint32_t n, uint32_t value) {
|
||||
int unused_bit_len = 32 - log2_pow2(n);
|
||||
return reverse_bits(value) >> unused_bit_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reorder an array in reverse bit order of its indices.
|
||||
*
|
||||
* @remark Operates in-place on the array.
|
||||
* @remark Can handle arrays of any type: provide the element size in @p size.
|
||||
*
|
||||
* @param[in,out] values The array, which is re-ordered in-place
|
||||
* @param[in] size The size in bytes of an element of the array
|
||||
* @param[in] n The length of the array, must be a power of two less that 2^32
|
||||
* @retval C_CZK_OK All is well
|
||||
* @retval C_CZK_BADARGS Invalid parameters were supplied
|
||||
*/
|
||||
C_KZG_RET reverse_bit_order(void *values, size_t size, uint64_t n) {
|
||||
CHECK(n >> 32 == 0);
|
||||
CHECK(is_power_of_two(n));
|
||||
|
||||
// Pointer arithmetic on `void *` is naughty, so cast to something definite
|
||||
byte *v = values;
|
||||
byte tmp[size];
|
||||
int unused_bit_len = 32 - log2_pow2(n);
|
||||
for (uint32_t i = 0; i < n; i++) {
|
||||
uint32_t r = reverse_bits(i) >> unused_bit_len;
|
||||
if (r > i) {
|
||||
// Swap the two elements
|
||||
memcpy(tmp, v + (i * size), size);
|
||||
memcpy(v + (i * size), v + (r * size), size);
|
||||
memcpy(v + (r * size), tmp, size);
|
||||
}
|
||||
}
|
||||
|
||||
return C_KZG_OK;
|
||||
}
|
||||
#include "utility.h"
|
||||
|
||||
/**
|
||||
* The first part of the Toeplitz matrix multiplication algorithm: the Fourier
|
||||
|
|
|
@ -18,26 +18,6 @@
|
|||
|
||||
#include "kzg_proofs.h"
|
||||
|
||||
/**
|
||||
* Reverse the bits in a byte.
|
||||
*
|
||||
* From https://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith64BitsDiv
|
||||
*
|
||||
* @param a A byte
|
||||
* @return A byte that is bit-reversed with respect to @p a
|
||||
*
|
||||
* @todo Benchmark some of the other bit-reversal options in the list. Maybe.
|
||||
*/
|
||||
#define rev_byte(a) ((((a)&0xff) * 0x0202020202ULL & 0x010884422010ULL) % 1023)
|
||||
|
||||
/**
|
||||
* Reverse the bits in a 32 bit word.
|
||||
*
|
||||
* @param a A 32 bit unsigned integer
|
||||
* @return A 32 bit unsigned integer that is bit-reversed with respect to @p a
|
||||
*/
|
||||
#define rev_4byte(a) (rev_byte(a) << 24 | rev_byte((a) >> 8) << 16 | rev_byte((a) >> 16) << 8 | rev_byte((a) >> 24))
|
||||
|
||||
/**
|
||||
* Stores the setup and parameters needed for computing FK20 single proofs.
|
||||
*
|
||||
|
@ -59,10 +39,6 @@ typedef struct {
|
|||
uint64_t length; /**< TODO */
|
||||
} FK20MultiSettings;
|
||||
|
||||
int log2_pow2(uint32_t n);
|
||||
uint32_t reverse_bits(uint32_t a);
|
||||
uint32_t reverse_bits_limited(uint32_t n, uint32_t value);
|
||||
C_KZG_RET reverse_bit_order(void *values, size_t size, uint64_t n);
|
||||
C_KZG_RET toeplitz_part_1(g1_t *out, const g1_t *x, uint64_t n, const FFTSettings *fs);
|
||||
C_KZG_RET toeplitz_part_2(g1_t *out, const poly *toeplitz_coeffs, const g1_t *x_ext_fft, const FFTSettings *fs);
|
||||
C_KZG_RET toeplitz_part_3(g1_t *out, const g1_t *h_ext_fft, uint64_t n2, const FFTSettings *fs);
|
||||
|
|
|
@ -18,79 +18,7 @@
|
|||
#include "test_util.h"
|
||||
#include "fk20_proofs.h"
|
||||
#include "c_kzg_util.h"
|
||||
|
||||
void test_reverse_bits_macros(void) {
|
||||
TEST_CHECK(128 == rev_byte(1));
|
||||
TEST_CHECK(128 == rev_byte(257));
|
||||
TEST_CHECK((uint32_t)1 << 31 == rev_4byte(1));
|
||||
TEST_CHECK(0x1e6a2c48 == rev_4byte(0x12345678));
|
||||
TEST_CHECK(0x00000000 == rev_4byte(0x00000000));
|
||||
TEST_CHECK(0xffffffff == rev_4byte(0xffffffff));
|
||||
}
|
||||
|
||||
void test_reverse_bits_0(void) {
|
||||
uint32_t actual, expected;
|
||||
for (int i = 0; i < 32; i++) {
|
||||
expected = (uint32_t)1 << (31 - i);
|
||||
actual = reverse_bits((uint32_t)1 << i);
|
||||
TEST_CHECK(expected == actual);
|
||||
}
|
||||
}
|
||||
|
||||
void test_reverse_bits_1(void) {
|
||||
TEST_CHECK(0x84c2a6e1 == reverse_bits(0x87654321));
|
||||
}
|
||||
|
||||
void test_log2_pow2(void) {
|
||||
int actual, expected;
|
||||
for (int i = 0; i < 32; i++) {
|
||||
expected = i;
|
||||
actual = log2_pow2((uint32_t)1 << i);
|
||||
TEST_CHECK(expected == actual);
|
||||
}
|
||||
}
|
||||
|
||||
void test_reverse_bit_order_g1(void) {
|
||||
int size = 10, n = 1 << size;
|
||||
g1_t a[n], b[n];
|
||||
fr_t tmp;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
fr_from_uint64(&tmp, i);
|
||||
g1_mul(&a[i], &g1_generator, &tmp);
|
||||
b[i] = a[i];
|
||||
}
|
||||
|
||||
TEST_CHECK(C_KZG_OK == reverse_bit_order(a, sizeof(g1_t), n));
|
||||
for (int i = 0; i < n; i++) {
|
||||
TEST_CHECK(true == g1_equal(&b[reverse_bits(i) >> (32 - size)], &a[i]));
|
||||
}
|
||||
|
||||
// Hand check a few select values
|
||||
TEST_CHECK(true == g1_equal(&b[0], &a[0]));
|
||||
TEST_CHECK(false == g1_equal(&b[1], &a[1]));
|
||||
TEST_CHECK(true == g1_equal(&b[n - 1], &a[n - 1]));
|
||||
}
|
||||
|
||||
void test_reverse_bit_order_fr(void) {
|
||||
int size = 12, n = 1 << size;
|
||||
fr_t a[n], b[n];
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
fr_from_uint64(&a[i], i);
|
||||
b[i] = a[i];
|
||||
}
|
||||
|
||||
TEST_CHECK(C_KZG_OK == reverse_bit_order(a, sizeof(fr_t), n));
|
||||
for (int i = 0; i < n; i++) {
|
||||
TEST_CHECK(true == fr_equal(&b[reverse_bits(i) >> (32 - size)], &a[i]));
|
||||
}
|
||||
|
||||
// Hand check a few select values
|
||||
TEST_CHECK(true == fr_equal(&b[0], &a[0]));
|
||||
TEST_CHECK(false == fr_equal(&b[1], &a[1]));
|
||||
TEST_CHECK(true == fr_equal(&b[n - 1], &a[n - 1]));
|
||||
}
|
||||
#include "utility.h"
|
||||
|
||||
void fk_single(void) {
|
||||
// Our polynomial: degree 15, 16 coefficients
|
||||
|
@ -354,12 +282,6 @@ void fk_multi_0(void) {
|
|||
|
||||
TEST_LIST = {
|
||||
{"FK20_PROOFS_TEST", title},
|
||||
{"test_reverse_bits_macros", test_reverse_bits_macros},
|
||||
{"test_reverse_bits_0", test_reverse_bits_0},
|
||||
{"test_reverse_bits_1", test_reverse_bits_1},
|
||||
{"test_log2_pow2", test_log2_pow2},
|
||||
{"test_reverse_bit_order_g1", test_reverse_bit_order_g1},
|
||||
{"test_reverse_bit_order_fr", test_reverse_bit_order_fr},
|
||||
{"fk_single", fk_single},
|
||||
{"fk_single_strided", fk_single_strided},
|
||||
{"fk_multi_settings", fk_multi_settings},
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <stddef.h> // NULL
|
||||
#include "kzg_proofs.h"
|
||||
#include "c_kzg_util.h"
|
||||
#include "utility.h"
|
||||
|
||||
/**
|
||||
* Make a KZG commitment to a polynomial.
|
||||
|
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* Copyright 2021 Benjamin Edgington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file utility.c
|
||||
*
|
||||
* A collection of useful functions used in various places throughout the library.
|
||||
*/
|
||||
|
||||
#include <string.h> // memcpy()
|
||||
#include "utility.h"
|
||||
|
||||
/**
|
||||
* Utility function to test whether the argument is a power of two.
|
||||
*
|
||||
* @remark This method returns `true` for `is_power_of_two(0)` which is a bit weird, but not an issue in the contexts in
|
||||
* which we use it.
|
||||
*
|
||||
* @param[in] n The number to test
|
||||
* @retval true if @p n is a power of two or zero
|
||||
* @retval false otherwise
|
||||
*/
|
||||
bool is_power_of_two(uint64_t n) {
|
||||
return (n & (n - 1)) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate log base two of a power of two.
|
||||
*
|
||||
* In other words, the bit index of the one bit.
|
||||
*
|
||||
* @remark Works only for n a power of two, and only for n up to 2^31.
|
||||
*
|
||||
* @param[in] n The power of two
|
||||
* @return the log base two of n
|
||||
*/
|
||||
int log2_pow2(uint32_t n) {
|
||||
const uint32_t b[] = {0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000};
|
||||
register uint32_t r;
|
||||
r = (n & b[0]) != 0;
|
||||
r |= ((n & b[1]) != 0) << 1;
|
||||
r |= ((n & b[2]) != 0) << 2;
|
||||
r |= ((n & b[3]) != 0) << 3;
|
||||
r |= ((n & b[4]) != 0) << 4;
|
||||
return r;
|
||||
}
|
||||
|
||||
// Adapted from https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
|
||||
uint64_t next_power_of_two(uint64_t v) {
|
||||
v--;
|
||||
v |= v >> 1;
|
||||
v |= v >> 2;
|
||||
v |= v >> 4;
|
||||
v |= v >> 8;
|
||||
v |= v >> 16;
|
||||
v |= v >> 32;
|
||||
v++;
|
||||
return v += (v == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the bit order in a 32 bit integer.
|
||||
*
|
||||
* @remark This simply wraps the macro to enforce the type check.
|
||||
*
|
||||
* @param[in] a The integer to be reversed
|
||||
* @return An integer with the bits of @p a reversed
|
||||
*/
|
||||
uint32_t reverse_bits(uint32_t a) {
|
||||
return rev_4byte(a);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the low-order bits in a 32 bit integer.
|
||||
*
|
||||
* The lowest log_base_two(@p n) bits of @p value are returned reversed. @p n must be a power of two.
|
||||
*
|
||||
* @param[in] n To reverse `b` bits, set `n = 2 ^ b`
|
||||
* @param[in] value The bits to be reversed
|
||||
* @return The reversal of the lowest log_2(@p n) bits of the input @p value
|
||||
*/
|
||||
uint32_t reverse_bits_limited(uint32_t n, uint32_t value) {
|
||||
int unused_bit_len = 32 - log2_pow2(n);
|
||||
return reverse_bits(value) >> unused_bit_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reorder an array in reverse bit order of its indices.
|
||||
*
|
||||
* @remark Operates in-place on the array.
|
||||
* @remark Can handle arrays of any type: provide the element size in @p size.
|
||||
*
|
||||
* @param[in,out] values The array, which is re-ordered in-place
|
||||
* @param[in] size The size in bytes of an element of the array
|
||||
* @param[in] n The length of the array, must be a power of two less that 2^32
|
||||
* @retval C_CZK_OK All is well
|
||||
* @retval C_CZK_BADARGS Invalid parameters were supplied
|
||||
*/
|
||||
C_KZG_RET reverse_bit_order(void *values, size_t size, uint64_t n) {
|
||||
CHECK(n >> 32 == 0);
|
||||
CHECK(is_power_of_two(n));
|
||||
|
||||
// Pointer arithmetic on `void *` is naughty, so cast to something definite
|
||||
byte *v = values;
|
||||
byte tmp[size];
|
||||
int unused_bit_len = 32 - log2_pow2(n);
|
||||
for (uint32_t i = 0; i < n; i++) {
|
||||
uint32_t r = reverse_bits(i) >> unused_bit_len;
|
||||
if (r > i) {
|
||||
// Swap the two elements
|
||||
memcpy(tmp, v + (i * size), size);
|
||||
memcpy(v + (i * size), v + (r * size), size);
|
||||
memcpy(v + (r * size), tmp, size);
|
||||
}
|
||||
}
|
||||
|
||||
return C_KZG_OK;
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright 2021 Benjamin Edgington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file utility.h
|
||||
*
|
||||
* A collection of useful functions used in various places throughout the library.
|
||||
*/
|
||||
|
||||
#include "c_kzg.h"
|
||||
|
||||
/**
|
||||
* Reverse the bits in a byte.
|
||||
*
|
||||
* From https://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith64BitsDiv
|
||||
*
|
||||
* @param a A byte
|
||||
* @return A byte that is bit-reversed with respect to @p a
|
||||
*
|
||||
* @todo Benchmark some of the other bit-reversal options in the list. Maybe.
|
||||
*/
|
||||
#define rev_byte(a) ((((a)&0xff) * 0x0202020202ULL & 0x010884422010ULL) % 1023)
|
||||
|
||||
/**
|
||||
* Reverse the bits in a 32 bit word.
|
||||
*
|
||||
* @param a A 32 bit unsigned integer
|
||||
* @return A 32 bit unsigned integer that is bit-reversed with respect to @p a
|
||||
*/
|
||||
#define rev_4byte(a) (rev_byte(a) << 24 | rev_byte((a) >> 8) << 16 | rev_byte((a) >> 16) << 8 | rev_byte((a) >> 24))
|
||||
|
||||
bool is_power_of_two(uint64_t n);
|
||||
int log2_pow2(uint32_t n);
|
||||
uint64_t next_power_of_two(uint64_t v);
|
||||
uint32_t reverse_bits(uint32_t a);
|
||||
uint32_t reverse_bits_limited(uint32_t n, uint32_t value);
|
||||
C_KZG_RET reverse_bit_order(void *values, size_t size, uint64_t n);
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* Copyright 2021 Benjamin Edgington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "../inc/acutest.h"
|
||||
#include "test_util.h"
|
||||
#include "utility.h"
|
||||
|
||||
void is_power_of_two_works(void) {
|
||||
// All actual powers of two
|
||||
for (int i = 0; i <= 63; i++) {
|
||||
TEST_CHECK(true == is_power_of_two((uint64_t)1 << i));
|
||||
TEST_MSG("Case %d", i);
|
||||
}
|
||||
|
||||
// This is a bit weird
|
||||
TEST_CHECK(true == is_power_of_two(0));
|
||||
|
||||
// Not powers of two
|
||||
TEST_CHECK(false == is_power_of_two(123));
|
||||
TEST_CHECK(false == is_power_of_two(1234567));
|
||||
}
|
||||
|
||||
void test_reverse_bits_macros(void) {
|
||||
TEST_CHECK(128 == rev_byte(1));
|
||||
TEST_CHECK(128 == rev_byte(257));
|
||||
TEST_CHECK((uint32_t)1 << 31 == rev_4byte(1));
|
||||
TEST_CHECK(0x1e6a2c48 == rev_4byte(0x12345678));
|
||||
TEST_CHECK(0x00000000 == rev_4byte(0x00000000));
|
||||
TEST_CHECK(0xffffffff == rev_4byte(0xffffffff));
|
||||
}
|
||||
|
||||
void test_reverse_bits_0(void) {
|
||||
uint32_t actual, expected;
|
||||
for (int i = 0; i < 32; i++) {
|
||||
expected = (uint32_t)1 << (31 - i);
|
||||
actual = reverse_bits((uint32_t)1 << i);
|
||||
TEST_CHECK(expected == actual);
|
||||
}
|
||||
}
|
||||
|
||||
void test_reverse_bits_1(void) {
|
||||
TEST_CHECK(0x84c2a6e1 == reverse_bits(0x87654321));
|
||||
}
|
||||
|
||||
void test_log2_pow2(void) {
|
||||
int actual, expected;
|
||||
for (int i = 0; i < 32; i++) {
|
||||
expected = i;
|
||||
actual = log2_pow2((uint32_t)1 << i);
|
||||
TEST_CHECK(expected == actual);
|
||||
}
|
||||
}
|
||||
|
||||
void test_reverse_bit_order_g1(void) {
|
||||
int size = 10, n = 1 << size;
|
||||
g1_t a[n], b[n];
|
||||
fr_t tmp;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
fr_from_uint64(&tmp, i);
|
||||
g1_mul(&a[i], &g1_generator, &tmp);
|
||||
b[i] = a[i];
|
||||
}
|
||||
|
||||
TEST_CHECK(C_KZG_OK == reverse_bit_order(a, sizeof(g1_t), n));
|
||||
for (int i = 0; i < n; i++) {
|
||||
TEST_CHECK(true == g1_equal(&b[reverse_bits(i) >> (32 - size)], &a[i]));
|
||||
}
|
||||
|
||||
// Hand check a few select values
|
||||
TEST_CHECK(true == g1_equal(&b[0], &a[0]));
|
||||
TEST_CHECK(false == g1_equal(&b[1], &a[1]));
|
||||
TEST_CHECK(true == g1_equal(&b[n - 1], &a[n - 1]));
|
||||
}
|
||||
|
||||
void test_reverse_bit_order_fr(void) {
|
||||
int size = 12, n = 1 << size;
|
||||
fr_t a[n], b[n];
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
fr_from_uint64(&a[i], i);
|
||||
b[i] = a[i];
|
||||
}
|
||||
|
||||
TEST_CHECK(C_KZG_OK == reverse_bit_order(a, sizeof(fr_t), n));
|
||||
for (int i = 0; i < n; i++) {
|
||||
TEST_CHECK(true == fr_equal(&b[reverse_bits(i) >> (32 - size)], &a[i]));
|
||||
}
|
||||
|
||||
// Hand check a few select values
|
||||
TEST_CHECK(true == fr_equal(&b[0], &a[0]));
|
||||
TEST_CHECK(false == fr_equal(&b[1], &a[1]));
|
||||
TEST_CHECK(true == fr_equal(&b[n - 1], &a[n - 1]));
|
||||
}
|
||||
|
||||
TEST_LIST = {
|
||||
{"UTILITY_TEST", title},
|
||||
{"is_power_of_two_works", is_power_of_two_works},
|
||||
{"test_reverse_bits_macros", test_reverse_bits_macros},
|
||||
{"test_reverse_bits_0", test_reverse_bits_0},
|
||||
{"test_reverse_bits_1", test_reverse_bits_1},
|
||||
{"test_log2_pow2", test_log2_pow2},
|
||||
{"test_reverse_bit_order_g1", test_reverse_bit_order_g1},
|
||||
{"test_reverse_bit_order_fr", test_reverse_bit_order_fr},
|
||||
{NULL, NULL} /* zero record marks the end of the list */
|
||||
};
|
Loading…
Reference in New Issue