|
|
#include "unity/unity.h" |
|
|
#include "zlib.h" |
|
|
|
|
|
#include <stdint.h> |
|
|
#include <stdlib.h> |
|
|
#include <stdio.h> |
|
|
#include <time.h> |
|
|
|
|
|
|
|
|
extern unsigned long test_multmodp(unsigned long a, unsigned long b); |
|
|
|
|
|
static uint32_t ref_multmodp(uint32_t a, uint32_t b) { |
|
|
|
|
|
const uint32_t POLY = 0xEDB88320u; |
|
|
uint32_t p = 0; |
|
|
while (a) { |
|
|
if (a & 1u) { |
|
|
p ^= b; |
|
|
} |
|
|
a >>= 1; |
|
|
if (b & 1u) { |
|
|
b = (b >> 1) ^ POLY; |
|
|
} else { |
|
|
b >>= 1; |
|
|
} |
|
|
} |
|
|
return p; |
|
|
} |
|
|
|
|
|
void setUp(void) { |
|
|
|
|
|
} |
|
|
|
|
|
void tearDown(void) { |
|
|
|
|
|
} |
|
|
|
|
|
static uint32_t call_ut(uint32_t a, uint32_t b) { |
|
|
|
|
|
unsigned long r = test_multmodp((unsigned long)a, (unsigned long)b); |
|
|
return (uint32_t)r; |
|
|
} |
|
|
|
|
|
void test_multmodp_identity_right(void) { |
|
|
uint32_t a = 0xCAFEBABEu; |
|
|
uint32_t b = 1u; |
|
|
uint32_t got = call_ut(a, b); |
|
|
TEST_ASSERT_EQUAL_HEX32(a, got); |
|
|
} |
|
|
|
|
|
void test_multmodp_identity_left(void) { |
|
|
uint32_t a = 1u; |
|
|
uint32_t b = 0xAABBCCDDu; |
|
|
uint32_t got = call_ut(a, b); |
|
|
TEST_ASSERT_EQUAL_HEX32(b, got); |
|
|
} |
|
|
|
|
|
void test_multmodp_zero_b(void) { |
|
|
uint32_t a = 0x12345678u; |
|
|
uint32_t b = 0u; |
|
|
uint32_t got = call_ut(a, b); |
|
|
TEST_ASSERT_EQUAL_HEX32(0u, got); |
|
|
} |
|
|
|
|
|
void test_multmodp_commutative_fixed(void) { |
|
|
uint32_t a = 0x13579BDFu; |
|
|
uint32_t b = 0x2468ACE1u; |
|
|
uint32_t ab = call_ut(a, b); |
|
|
uint32_t ba = call_ut(b, a); |
|
|
TEST_ASSERT_EQUAL_HEX32(ab, ba); |
|
|
|
|
|
|
|
|
uint32_t ref = ref_multmodp(a, b); |
|
|
TEST_ASSERT_EQUAL_HEX32(ref, ab); |
|
|
} |
|
|
|
|
|
void test_multmodp_distributive_over_xor(void) { |
|
|
uint32_t a = 0xDEADBEEFu; |
|
|
uint32_t b = 0x0F0F0F0Fu; |
|
|
uint32_t c = 0x33333333u; |
|
|
|
|
|
uint32_t left = call_ut(a, b ^ c); |
|
|
uint32_t right = call_ut(a, b) ^ call_ut(a, c); |
|
|
TEST_ASSERT_EQUAL_HEX32(right, left); |
|
|
} |
|
|
|
|
|
void test_multmodp_single_bit_a_positions(void) { |
|
|
uint32_t b = 0x89ABCDEFu; |
|
|
|
|
|
uint8_t positions[] = {0, 1, 7, 15, 31}; |
|
|
for (size_t i = 0; i < sizeof(positions)/sizeof(positions[0]); i++) { |
|
|
uint32_t a = 1u << positions[i]; |
|
|
uint32_t got = call_ut(a, b); |
|
|
uint32_t exp = ref_multmodp(a, b); |
|
|
TEST_ASSERT_EQUAL_HEX32(exp, got); |
|
|
} |
|
|
} |
|
|
|
|
|
void test_multmodp_max_values(void) { |
|
|
uint32_t a = 0xFFFFFFFFu; |
|
|
uint32_t b = 0xFFFFFFFFu; |
|
|
uint32_t got = call_ut(a, b); |
|
|
uint32_t exp = ref_multmodp(a, b); |
|
|
TEST_ASSERT_EQUAL_HEX32(exp, got); |
|
|
} |
|
|
|
|
|
static uint32_t rand32(void) { |
|
|
|
|
|
uint32_t r = 0; |
|
|
r ^= ((uint32_t)rand() & 0x3FFu) << 22; |
|
|
r ^= ((uint32_t)rand() & 0x7FFFu) << 7; |
|
|
r ^= ((uint32_t)rand() & 0x7Fu); |
|
|
return r; |
|
|
} |
|
|
|
|
|
void test_multmodp_matches_reference_random(void) { |
|
|
srand(12345); |
|
|
for (int i = 0; i < 100; i++) { |
|
|
uint32_t a = rand32() | 1u; |
|
|
uint32_t b = rand32(); |
|
|
uint32_t got = call_ut(a, b); |
|
|
uint32_t exp = ref_multmodp(a, b); |
|
|
TEST_ASSERT_EQUAL_HEX32(exp, got); |
|
|
} |
|
|
} |
|
|
|
|
|
int main(void) { |
|
|
UNITY_BEGIN(); |
|
|
RUN_TEST(test_multmodp_identity_right); |
|
|
RUN_TEST(test_multmodp_identity_left); |
|
|
RUN_TEST(test_multmodp_zero_b); |
|
|
RUN_TEST(test_multmodp_commutative_fixed); |
|
|
RUN_TEST(test_multmodp_distributive_over_xor); |
|
|
RUN_TEST(test_multmodp_single_bit_a_positions); |
|
|
RUN_TEST(test_multmodp_max_values); |
|
|
RUN_TEST(test_multmodp_matches_reference_random); |
|
|
return UNITY_END(); |
|
|
} |