| | #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(); |
| | } |