|
|
#include "../../unity/unity.h" |
|
|
#include <stdlib.h> |
|
|
#include <string.h> |
|
|
#include <stdint.h> |
|
|
#include <stdbool.h> |
|
|
#include <gmp.h> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static uuint ref_mod2_gmp(mp_limb_t a1, mp_limb_t a0, mp_limb_t d1, mp_limb_t d0) |
|
|
{ |
|
|
|
|
|
mpz_t A, D, R; |
|
|
mpz_init(A); |
|
|
mpz_init(D); |
|
|
mpz_init(R); |
|
|
|
|
|
mp_limb_t a_arr[2]; |
|
|
mp_limb_t d_arr[2]; |
|
|
a_arr[0] = a0; a_arr[1] = a1; |
|
|
d_arr[0] = d0; d_arr[1] = d1; |
|
|
|
|
|
mpz_import(A, 2, -1, sizeof(mp_limb_t), 0, 0, a_arr); |
|
|
mpz_import(D, 2, -1, sizeof(mp_limb_t), 0, 0, d_arr); |
|
|
|
|
|
mpz_mod(R, A, D); |
|
|
|
|
|
mp_limb_t r_arr[2] = {0, 0}; |
|
|
size_t count = 0; |
|
|
mpz_export(r_arr, &count, -1, sizeof(mp_limb_t), 0, 0, R); |
|
|
|
|
|
mp_limb_t r0 = (count >= 1) ? r_arr[0] : (mp_limb_t)0; |
|
|
mp_limb_t r1 = (count >= 2) ? r_arr[1] : (mp_limb_t)0; |
|
|
|
|
|
mpz_clear(A); |
|
|
mpz_clear(D); |
|
|
mpz_clear(R); |
|
|
|
|
|
return make_uuint(r1, r0); |
|
|
} |
|
|
|
|
|
void setUp(void) { |
|
|
|
|
|
} |
|
|
|
|
|
void tearDown(void) { |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
void test_mod2_mod_by_base_returns_low_word(void) |
|
|
{ |
|
|
mp_limb_t a1 = (((mp_limb_t)1) << (W_TYPE_SIZE - 1)) | (mp_limb_t)123u; |
|
|
mp_limb_t a0 = (mp_limb_t)0xDEADBEEFu; |
|
|
mp_limb_t d1 = (mp_limb_t)1; |
|
|
mp_limb_t d0 = (mp_limb_t)0; |
|
|
|
|
|
uuint r = mod2(a1, a0, d1, d0); |
|
|
|
|
|
TEST_ASSERT_TRUE(hi(r) == 0); |
|
|
TEST_ASSERT_TRUE(lo(r) == a0); |
|
|
} |
|
|
|
|
|
|
|
|
void test_mod2_A_less_than_D_returns_A(void) |
|
|
{ |
|
|
mp_limb_t a1 = (mp_limb_t)1; |
|
|
mp_limb_t a0 = (mp_limb_t)12345u; |
|
|
mp_limb_t d1 = (mp_limb_t)2; |
|
|
mp_limb_t d0 = (mp_limb_t)0; |
|
|
|
|
|
uuint r = mod2(a1, a0, d1, d0); |
|
|
|
|
|
TEST_ASSERT_TRUE(hi(r) == a1); |
|
|
TEST_ASSERT_TRUE(lo(r) == a0); |
|
|
} |
|
|
|
|
|
|
|
|
void test_mod2_a1_zero_returns_a(void) |
|
|
{ |
|
|
mp_limb_t a1 = (mp_limb_t)0; |
|
|
mp_limb_t a0 = (mp_limb_t)987u; |
|
|
mp_limb_t d1 = (mp_limb_t)1; |
|
|
mp_limb_t d0 = (mp_limb_t)123u; |
|
|
|
|
|
uuint r = mod2(a1, a0, d1, d0); |
|
|
|
|
|
TEST_ASSERT_TRUE(hi(r) == 0); |
|
|
TEST_ASSERT_TRUE(lo(r) == a0); |
|
|
} |
|
|
|
|
|
|
|
|
void test_mod2_general_against_gmp(void) |
|
|
{ |
|
|
|
|
|
{ |
|
|
mp_limb_t a1 = (((mp_limb_t)1) << (W_TYPE_SIZE - 1)) | (mp_limb_t)0x55u; |
|
|
mp_limb_t a0 = (mp_limb_t)0xA5A5A5A5u; |
|
|
mp_limb_t d1 = a1 >> 5; |
|
|
if (d1 == 0) d1 = 1; |
|
|
mp_limb_t d0 = (mp_limb_t)0x54321u; |
|
|
|
|
|
uuint r = mod2(a1, a0, d1, d0); |
|
|
uuint g = ref_mod2_gmp(a1, a0, d1, d0); |
|
|
TEST_ASSERT_TRUE(hi(r) == hi(g)); |
|
|
TEST_ASSERT_TRUE(lo(r) == lo(g)); |
|
|
} |
|
|
|
|
|
|
|
|
{ |
|
|
mp_limb_t a1 = ((((mp_limb_t)1) << (W_TYPE_SIZE - 2)) | (mp_limb_t)77u); |
|
|
mp_limb_t a0 = (mp_limb_t)0x12345678u; |
|
|
mp_limb_t d1 = a1 >> 3; |
|
|
if (d1 == 0) d1 = 1; |
|
|
mp_limb_t d0 = (mp_limb_t)0x9ABCDEFFu; |
|
|
|
|
|
uuint r = mod2(a1, a0, d1, d0); |
|
|
uuint g = ref_mod2_gmp(a1, a0, d1, d0); |
|
|
TEST_ASSERT_TRUE(hi(r) == hi(g)); |
|
|
TEST_ASSERT_TRUE(lo(r) == lo(g)); |
|
|
} |
|
|
|
|
|
|
|
|
{ |
|
|
mp_limb_t a1 = (((mp_limb_t)1) << (W_TYPE_SIZE - 1)); |
|
|
mp_limb_t a0 = (mp_limb_t)0xCAFEBABEu; |
|
|
mp_limb_t d1 = a1 >> 7; |
|
|
if (d1 == 0) d1 = 1; |
|
|
mp_limb_t d0 = (mp_limb_t)0; |
|
|
|
|
|
uuint r = mod2(a1, a0, d1, d0); |
|
|
uuint g = ref_mod2_gmp(a1, a0, d1, d0); |
|
|
TEST_ASSERT_TRUE(hi(r) == hi(g)); |
|
|
TEST_ASSERT_TRUE(lo(r) == lo(g)); |
|
|
} |
|
|
|
|
|
|
|
|
{ |
|
|
mp_limb_t a1 = (((mp_limb_t)1) << (W_TYPE_SIZE - 1)) | (mp_limb_t)0xF0u; |
|
|
mp_limb_t a0 = (mp_limb_t)0x0BADF00Du; |
|
|
mp_limb_t d1 = (mp_limb_t)1; |
|
|
mp_limb_t d0 = (mp_limb_t)0x11111111u; |
|
|
|
|
|
uuint r = mod2(a1, a0, d1, d0); |
|
|
uuint g = ref_mod2_gmp(a1, a0, d1, d0); |
|
|
TEST_ASSERT_TRUE(hi(r) == hi(g)); |
|
|
TEST_ASSERT_TRUE(lo(r) == lo(g)); |
|
|
} |
|
|
|
|
|
|
|
|
{ |
|
|
mp_limb_t a1 = (mp_limb_t)(~(mp_limb_t)0); |
|
|
mp_limb_t a0 = (mp_limb_t)0xFFFFFFFFu; |
|
|
mp_limb_t d1 = a1 >> 4; |
|
|
if (d1 == 0) d1 = 1; |
|
|
mp_limb_t d0 = (mp_limb_t)0xFEEDFACEu; |
|
|
|
|
|
uuint r = mod2(a1, a0, d1, d0); |
|
|
uuint g = ref_mod2_gmp(a1, a0, d1, d0); |
|
|
TEST_ASSERT_TRUE(hi(r) == hi(g)); |
|
|
TEST_ASSERT_TRUE(lo(r) == lo(g)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void test_mod2_divisible_case_zero_remainder(void) |
|
|
{ |
|
|
mp_limb_t d1 = (mp_limb_t)1; |
|
|
mp_limb_t d0 = (mp_limb_t)0x11111111u; |
|
|
|
|
|
|
|
|
mp_limb_t a0 = d0 << 1; |
|
|
mp_limb_t carry = (d0 >> (W_TYPE_SIZE - 1)); |
|
|
mp_limb_t a1 = (d1 << 1) + carry; |
|
|
|
|
|
uuint r = mod2(a1, a0, d1, d0); |
|
|
|
|
|
TEST_ASSERT_TRUE(hi(r) == 0); |
|
|
TEST_ASSERT_TRUE(lo(r) == 0); |
|
|
} |
|
|
|
|
|
int main(void) |
|
|
{ |
|
|
UNITY_BEGIN(); |
|
|
RUN_TEST(test_mod2_mod_by_base_returns_low_word); |
|
|
RUN_TEST(test_mod2_A_less_than_D_returns_A); |
|
|
RUN_TEST(test_mod2_a1_zero_returns_a); |
|
|
RUN_TEST(test_mod2_general_against_gmp); |
|
|
RUN_TEST(test_mod2_divisible_case_zero_remainder); |
|
|
return UNITY_END(); |
|
|
} |