|
|
#include "../../unity/unity.h" |
|
|
#include <stdlib.h> |
|
|
#include <string.h> |
|
|
#include <stdio.h> |
|
|
|
|
|
|
|
|
void setUp(void) { |
|
|
|
|
|
} |
|
|
void tearDown(void) { |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static int find_prime_index(mp_limb_t prime) |
|
|
{ |
|
|
for (int i = 0; i < PRIMES_PTAB_ENTRIES; i++) |
|
|
{ |
|
|
if ((mp_limb_t)primes_ptab[i] == prime) |
|
|
return i; |
|
|
} |
|
|
return -1; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void base_and_offset_for_index(int idx, int *base, int *ioff) |
|
|
{ |
|
|
int off = idx % 8; |
|
|
*ioff = off; |
|
|
*base = idx - off; |
|
|
} |
|
|
|
|
|
static void init_factors(struct factors *f) |
|
|
{ |
|
|
memset(f, 0, sizeof(*f)); |
|
|
} |
|
|
|
|
|
void test_divblock_divides_once_by_3(void) |
|
|
{ |
|
|
int idx = find_prime_index(3); |
|
|
TEST_ASSERT_NOT_EQUAL(-1, idx); |
|
|
int base = 0, off = 0; |
|
|
base_and_offset_for_index(idx, &base, &off); |
|
|
TEST_ASSERT_EQUAL_INT(idx, base + off); |
|
|
|
|
|
struct factors f; init_factors(&f); |
|
|
mp_limb_t t0 = (mp_limb_t)3; |
|
|
mp_limb_t r = divblock(&f, t0, &primes_dtab[base], (idx_t)base, off); |
|
|
|
|
|
TEST_ASSERT(r == (mp_limb_t)1); |
|
|
TEST_ASSERT(f.nfactors == 1); |
|
|
TEST_ASSERT(f.p[0] == (mp_limb_t)3); |
|
|
TEST_ASSERT(f.e[0] == 1); |
|
|
} |
|
|
|
|
|
void test_divblock_divides_twice_by_3(void) |
|
|
{ |
|
|
int idx = find_prime_index(3); |
|
|
TEST_ASSERT_NOT_EQUAL(-1, idx); |
|
|
int base = 0, off = 0; |
|
|
base_and_offset_for_index(idx, &base, &off); |
|
|
|
|
|
struct factors f; init_factors(&f); |
|
|
mp_limb_t t0 = (mp_limb_t)9; |
|
|
mp_limb_t r = divblock(&f, t0, &primes_dtab[base], (idx_t)base, off); |
|
|
|
|
|
TEST_ASSERT(r == (mp_limb_t)1); |
|
|
TEST_ASSERT(f.nfactors == 1); |
|
|
TEST_ASSERT(f.p[0] == (mp_limb_t)3); |
|
|
TEST_ASSERT(f.e[0] == 2); |
|
|
} |
|
|
|
|
|
void test_divblock_non_divisible_returns_input(void) |
|
|
{ |
|
|
int idx = find_prime_index(3); |
|
|
TEST_ASSERT_NOT_EQUAL(-1, idx); |
|
|
int base = 0, off = 0; |
|
|
base_and_offset_for_index(idx, &base, &off); |
|
|
|
|
|
struct factors f; init_factors(&f); |
|
|
mp_limb_t t0 = (mp_limb_t)10; |
|
|
mp_limb_t r = divblock(&f, t0, &primes_dtab[base], (idx_t)base, off); |
|
|
|
|
|
TEST_ASSERT(r == t0); |
|
|
TEST_ASSERT(f.nfactors == 0); |
|
|
} |
|
|
|
|
|
void test_divblock_returns_remaining_quotient_after_divisions(void) |
|
|
{ |
|
|
int idx = find_prime_index(3); |
|
|
TEST_ASSERT_NOT_EQUAL(-1, idx); |
|
|
int base = 0, off = 0; |
|
|
base_and_offset_for_index(idx, &base, &off); |
|
|
|
|
|
struct factors f; init_factors(&f); |
|
|
|
|
|
mp_limb_t t0 = (mp_limb_t)27 * (mp_limb_t)10; |
|
|
mp_limb_t r = divblock(&f, t0, &primes_dtab[base], (idx_t)base, off); |
|
|
|
|
|
TEST_ASSERT(r == (mp_limb_t)10); |
|
|
TEST_ASSERT(f.nfactors == 1); |
|
|
TEST_ASSERT(f.p[0] == (mp_limb_t)3); |
|
|
TEST_ASSERT(f.e[0] == 3); |
|
|
} |
|
|
|
|
|
void test_divblock_works_with_nonzero_offset_prime_23(void) |
|
|
{ |
|
|
int idx = find_prime_index(23); |
|
|
TEST_ASSERT_NOT_EQUAL(-1, idx); |
|
|
int base = 0, off = 0; |
|
|
base_and_offset_for_index(idx, &base, &off); |
|
|
TEST_ASSERT(off >= 0 && off <= 7); |
|
|
TEST_ASSERT_EQUAL_INT(idx, base + off); |
|
|
|
|
|
struct factors f; init_factors(&f); |
|
|
mp_limb_t t0 = (mp_limb_t)23 * (mp_limb_t)7; |
|
|
mp_limb_t r = divblock(&f, t0, &primes_dtab[base], (idx_t)base, off); |
|
|
|
|
|
TEST_ASSERT(r == (mp_limb_t)7); |
|
|
TEST_ASSERT(f.nfactors == 1); |
|
|
TEST_ASSERT(f.p[0] == (mp_limb_t)23); |
|
|
TEST_ASSERT(f.e[0] == 1); |
|
|
} |
|
|
|
|
|
void test_divblock_increments_existing_factor_multiplicity(void) |
|
|
{ |
|
|
int idx = find_prime_index(5); |
|
|
TEST_ASSERT_NOT_EQUAL(-1, idx); |
|
|
int base = 0, off = 0; |
|
|
base_and_offset_for_index(idx, &base, &off); |
|
|
|
|
|
struct factors f; init_factors(&f); |
|
|
|
|
|
f.nfactors = 1; |
|
|
f.p[0] = (mp_limb_t)5; |
|
|
f.e[0] = 2; |
|
|
|
|
|
mp_limb_t t0 = (mp_limb_t)5; |
|
|
mp_limb_t r = divblock(&f, t0, &primes_dtab[base], (idx_t)base, off); |
|
|
|
|
|
TEST_ASSERT(r == (mp_limb_t)1); |
|
|
TEST_ASSERT(f.nfactors == 1); |
|
|
TEST_ASSERT(f.p[0] == (mp_limb_t)5); |
|
|
TEST_ASSERT(f.e[0] == 3); |
|
|
} |
|
|
|
|
|
void test_divblock_t0_equal_1_no_change(void) |
|
|
{ |
|
|
int idx = find_prime_index(7); |
|
|
TEST_ASSERT_NOT_EQUAL(-1, idx); |
|
|
int base = 0, off = 0; |
|
|
base_and_offset_for_index(idx, &base, &off); |
|
|
|
|
|
struct factors f; init_factors(&f); |
|
|
mp_limb_t t0 = (mp_limb_t)1; |
|
|
mp_limb_t r = divblock(&f, t0, &primes_dtab[base], (idx_t)base, off); |
|
|
|
|
|
TEST_ASSERT(r == (mp_limb_t)1); |
|
|
TEST_ASSERT(f.nfactors == 0); |
|
|
} |
|
|
|
|
|
int main(void) |
|
|
{ |
|
|
UNITY_BEGIN(); |
|
|
RUN_TEST(test_divblock_divides_once_by_3); |
|
|
RUN_TEST(test_divblock_divides_twice_by_3); |
|
|
RUN_TEST(test_divblock_non_divisible_returns_input); |
|
|
RUN_TEST(test_divblock_returns_remaining_quotient_after_divisions); |
|
|
RUN_TEST(test_divblock_works_with_nonzero_offset_prime_23); |
|
|
RUN_TEST(test_divblock_increments_existing_factor_multiplicity); |
|
|
RUN_TEST(test_divblock_t0_equal_1_no_change); |
|
|
return UNITY_END(); |
|
|
} |