diff options
| -rw-r--r-- | include/bh/bigint.h | 4 | ||||
| -rw-r--r-- | include/bh/internal/bh.h | 3 | ||||
| -rw-r--r-- | src/bigint.c | 149 | ||||
| -rw-r--r-- | tests/src/bigint.c | 883 |
4 files changed, 819 insertions, 220 deletions
diff --git a/include/bh/bigint.h b/include/bh/bigint.h index 116256f..c9cd6e0 100644 --- a/include/bh/bigint.h +++ b/include/bh/bigint.h @@ -84,6 +84,10 @@ int bh_bigint_mul(bh_bigint_t *to, bh_bigint_t *left, bh_bigint_t *right); +int bh_bigint_mul_digit(bh_bigint_t *to, + bh_bigint_t *left, + bh_int16_t right); + int bh_bigint_pow(bh_bigint_t *to, bh_bigint_t *from, bh_uint32_t power); diff --git a/include/bh/internal/bh.h b/include/bh/internal/bh.h index 5738c88..2edb222 100644 --- a/include/bh/internal/bh.h +++ b/include/bh/internal/bh.h @@ -4,4 +4,5 @@ #include <bh/bh.h> #include <bh/internal/config.h> -#endif /* BH_INTERNAL_H */
\ No newline at end of file +#endif /* BH_INTERNAL_H */ + diff --git a/src/bigint.c b/src/bigint.c index 240dbb2..c78503d 100644 --- a/src/bigint.c +++ b/src/bigint.c @@ -67,7 +67,7 @@ static size_t bh_bigint_type_log2(BH_BIGINT_TYPE x) tmp = (x >> (BH_BIGINT_BITS - 7)) & 0xFF; if (tmp) return ((BH_BIGINT_BITS + 1) - 8 * (i + 1)) + lookup[tmp]; - + x <<= 8; } @@ -405,7 +405,7 @@ static int bh_bigint_add_base(bh_bigint_t *to, to->size = most->size + 1; else to->size = most->size; - + return BH_OK; } @@ -415,7 +415,7 @@ static int bh_bigint_sub_base(bh_bigint_t *to, { BH_BIGINT_TYPE carry, tmp; size_t size, i; - + /* Clear up result error flag */ to->error = 0; @@ -496,9 +496,14 @@ int bh_bigint_add(bh_bigint_t *to, else code = bh_bigint_sub_base(to, most, least); - /* Set result sign */ if (!code) - to->type = type; + { + /* Set result sign or zero */ + if (to->size) + to->type = type; + else + to->type = 0; + } /* Return result code */ return code; @@ -538,9 +543,14 @@ int bh_bigint_sub(bh_bigint_t *to, else code = bh_bigint_add_base(to, most, least); - /* Set result sign */ if (!code) - to->type = type; + { + /* Set result sign or zero */ + if (to->size) + to->type = type; + else + to->type = 0; + } /* Return result code */ return code; @@ -639,6 +649,73 @@ int bh_bigint_mul(bh_bigint_t *to, return BH_OK; } +int bh_bigint_mul_digit(bh_bigint_t *to, + bh_bigint_t *left, + bh_int16_t right) +{ + BH_BIGINT_TYPE carry; + BH_BIGINT_TMP tmp; + size_t i, size; + + /* Shortcut - one of the arguments has error flag set */ + if (left->error) + { + to->error = 1; + return BH_ERROR; + } + + /* Clear up result error flag */ + to->error = 0; + + /* Shortcut - multiplication by zero */ + if (left->type == 0 || right == 0) + { + to->type = 0; + to->size = 0; + return BH_OK; + } + + /* Reserve space for result */ + if (to->capacity < (left->size + 1)) + { + if (bh_bigint_reserve(to, left->size + 1)) + { + to->error = 1; + return BH_OOM; + } + } + + /* Determine sign */ + if ((left->type > 0 && right < 0) || (left->type < 0 && right > 0)) + to->type = -1; + else + to->type = 1; + + if (right < 0) + right = -right; + + /* Prepare variables */ + carry = 0; + + /* Multiplication loop */ + for (i = 0; i < left->size; i++) + { + tmp = (BH_BIGINT_TMP)left->data[i] * (BH_BIGINT_TMP)right + carry; + carry = tmp >> BH_BIGINT_BITS; + to->data[i] = tmp & BH_BIGINT_MASK; + } + to->data[i] = carry; + + /* Truncate multiplication result size */ + size = left->size + 1; + while (size && !to->data[size - 1]) size--; + + /* Update size */ + to->size = size; + + return BH_OK; +} + int bh_bigint_pow(bh_bigint_t *to, bh_bigint_t *from, bh_uint32_t power) @@ -732,7 +809,7 @@ int bh_bigint_powm(bh_bigint_t *to, code = BH_OK; /* Shortcut - one of the arguments has error flag set */ - if (left->error || right->error) + if (left->error || right->error || mod->error) { to->error = 1; return BH_ERROR; @@ -740,7 +817,7 @@ int bh_bigint_powm(bh_bigint_t *to, /* Clear up result error flag */ to->error = 0; - + /* Shortcut - power is equal to 0 */ if (bh_bigint_is_zero(right)) return bh_bigint_set_int(to, 1); @@ -752,7 +829,7 @@ int bh_bigint_powm(bh_bigint_t *to, /* Shortcut - power is negative */ if (bh_bigint_is_negative(right)) return bh_bigint_clear(to); - + /* Figure out result sign */ if (left->type < 0 && right->data[0] & 0x1) type = -1; @@ -816,7 +893,7 @@ int bh_bigint_powm(bh_bigint_t *to, bh_bigint_mul(base, base, base); bh_bigint_mod(base, base, mod); bh_bigint_rsh(exponent, exponent, 1); - + /* Stop if error occured */ if (base->error || result->error) { @@ -848,14 +925,14 @@ static BH_BIGINT_TYPE bh_bigint_div_guess(bh_bigint_t *left, bh_bigint_t *right) { BH_BIGINT_TMP tmp; - + /* Left is bigger then right */ if (bh_bigint_equal_mod(left, right) < 0) return 0; /* Make a guess */ tmp = left->data[left->size - 1]; - + if (left->size != right->size) tmp = (tmp << BH_BIGINT_BITS) + left->data[left->size - 2]; @@ -959,7 +1036,7 @@ static int bh_bigint_div_base(bh_bigint_t *quotient, } nleft->size--; } - + while (1) { /* Make a guess at what first digit of quotient should be */ @@ -993,7 +1070,8 @@ static int bh_bigint_div_base(bh_bigint_t *quotient, } /* Calculate remainder */ - bh_bigint_sub(remainder, remainder, tmp); + /* Prevent using addition logic and use subtraction */ + bh_bigint_sub_base(remainder, remainder, tmp); if (!nleft->size) break; @@ -1020,6 +1098,9 @@ finish: return code; } +/** + * This follows C99 model (a/b)*b + a%b + */ int bh_bigint_divmod(bh_bigint_t *quotient, bh_bigint_t *remainder, bh_bigint_t *left, @@ -1111,10 +1192,13 @@ int bh_bigint_divmod(bh_bigint_t *quotient, code = bh_bigint_div_base(quotient, tmp, left, right, &shift); if (!code) { + /* Remainder should use sign of the left operand */ + tmp->type = left->type; + /* If remainder required - normilize it */ if (tmp == remainder) bh_bigint_rsh(remainder, remainder, shift); - + /* Fix the sign */ if (quotient) quotient->type = type; @@ -1145,7 +1229,7 @@ int bh_bigint_lsh(bh_bigint_t *to, bh_uint32_t shift) { size_t i, bits, blocks; - BH_BIGINT_TYPE tmp; + BH_BIGINT_TYPE tmp; /* Shortcut - one of the arguments has error flag set */ if (left->error) @@ -1255,7 +1339,7 @@ int bh_bigint_rsh(bh_bigint_t *to, /* Calculate distance in blocks and bits */ blocks = shift / BH_BIGINT_BITS; bits = shift % BH_BIGINT_BITS; - + /* Shortcut - shift is bigger than value or value is 0 */ if (left->type == 0 || left->size < blocks) { @@ -1302,7 +1386,7 @@ int bh_bigint_rsh(bh_bigint_t *to, return BH_OOM; } } - + /* Main loop for aligned shift */ for (i = 0; i < left->size - blocks; i++) to->data[i] = left->data[i + blocks]; @@ -1312,7 +1396,7 @@ int bh_bigint_rsh(bh_bigint_t *to, i = left->size - blocks; while (i && !to->data[i - 1]) i--; - /* Update fields */ + /* Update fields */ to->size = i; to->type = left->type; @@ -1358,10 +1442,16 @@ int bh_bigint_or(bh_bigint_t *to, to->data[i] = tmp; } + /* Shrink size */ + while (size && !to->data[size - 1]) size--; + /* Update fields */ to->type = 1; to->size = size; + if (!size) + to->type = 0; + return BH_OK; } @@ -1401,10 +1491,16 @@ int bh_bigint_and(bh_bigint_t *to, to->data[i] = tmp; } + /* Shrink size */ + while (size && !to->data[size - 1]) size--; + /* Update fields */ to->type = 1; to->size = size; + if (!size) + to->type = 0; + return BH_OK; } @@ -1444,10 +1540,16 @@ int bh_bigint_xor(bh_bigint_t *to, to->data[i] = tmp; } + /* Shrink size */ + while (size && !to->data[size - 1]) size--; + /* Update fields */ to->type = 1; to->size = size; + if (!size) + to->type = 0; + return BH_OK; } @@ -1472,10 +1574,7 @@ int bh_bigint_negate(bh_bigint_t *to, } /* Change the sign */ - if (to->type < 0) - to->type = 1; - else if (to->type > 0) - to->type = -1; + to->type = 0 - to->type; return BH_OK; } @@ -1555,4 +1654,4 @@ size_t bh_bigint_log2(bh_bigint_t *bigint) result = bh_bigint_type_log2(bigint->data[bigint->size - 1]); return result + (bigint->size - 1) * BH_BIGINT_BITS; -}
\ No newline at end of file +} diff --git a/tests/src/bigint.c b/tests/src/bigint.c index b3ae620..9c6d82a 100644 --- a/tests/src/bigint.c +++ b/tests/src/bigint.c @@ -2,6 +2,38 @@ #include <bh/unit.h> #include <string.h> +static int fields(void) +{ + bh_bigint_t bint; + + bh_bigint_init(&bint); + + /* Ensure that methods reflect big integer fields */ + bint.error = 0; + bint.type = 0; + bh_unit_assert(bint.error == bh_bigint_is_error(&bint)); + bh_unit_assert((bint.type < 0) == bh_bigint_is_negative(&bint)); + bh_unit_assert((bint.type == 0) == bh_bigint_is_zero(&bint)); + + bint.error = 0; + bint.type = 1; + bh_unit_assert(bint.error == bh_bigint_is_error(&bint)); + bh_unit_assert((bint.type < 0) == bh_bigint_is_negative(&bint)); + bh_unit_assert((bint.type == 0) == bh_bigint_is_zero(&bint)); + + bint.type = -1; + bh_unit_assert(bint.error == bh_bigint_is_error(&bint)); + bh_unit_assert((bint.type < 0) == bh_bigint_is_negative(&bint)); + bh_unit_assert((bint.type == 0) == bh_bigint_is_zero(&bint)); + + bint.error = 1; + bh_unit_assert(bint.error == bh_bigint_is_error(&bint)); + + bh_bigint_destroy(&bint); + + return 0; +} + static int round_trip(void) { bh_bigint_t *data[10]; @@ -49,11 +81,12 @@ static int round_trip(void) return 0; } -static int addition(void) +static int add_sub(void) { + const bh_uint64_t ta = 0xA3B1DBC158176B96ull, tb = 0x2748D1622F3E90A2ull; bh_bigint_t *a, *b, *c; - bh_uint64_t ta, tb; + /* Allocate new big integers */ a = bh_bigint_new(); b = bh_bigint_new(); c = bh_bigint_new(); @@ -62,136 +95,175 @@ static int addition(void) bh_unit_assert(b != NULL); bh_unit_assert(c != NULL); - ta = 0xA3B1DBC158176B96ull; - tb = 0x2748D1622F3E90A2ull; - - bh_unit_assert(bh_bigint_set_uint64(a, ta) == BH_OK); - bh_unit_assert(bh_bigint_set_uint64(b, tb) == BH_OK); + /* Test correct result sign */ + bh_unit_assert(bh_bigint_set_int(a, 3) == BH_OK); + bh_unit_assert(bh_bigint_set_int(b, 5) == BH_OK); bh_unit_assert(bh_bigint_add(c, a, b) == BH_OK); - bh_unit_assert(bh_bigint_get_uint64(c) == (ta + tb)); - - bh_bigint_free(a); - bh_bigint_free(b); - bh_bigint_free(c); - - return 0; -} - -static int subtraction(void) -{ - bh_bigint_t *a, *b, *c; - bh_uint64_t ta, tb; - - a = bh_bigint_new(); - b = bh_bigint_new(); - c = bh_bigint_new(); - - bh_unit_assert(a != NULL); - bh_unit_assert(b != NULL); - bh_unit_assert(c != NULL); - - ta = 0xA3B1DBC158176B96ull; - tb = 0x2748D1622F3E90A2ull; - - bh_unit_assert(bh_bigint_set_uint64(a, ta) == BH_OK); - bh_unit_assert(bh_bigint_set_uint64(b, tb) == BH_OK); + bh_unit_assert(bh_bigint_get_int(c) == 8); + bh_unit_assert(bh_bigint_is_negative(c) == 0); + bh_unit_assert(bh_bigint_is_zero(c) == 0); + bh_unit_assert(bh_bigint_is_error(c) == 0); bh_unit_assert(bh_bigint_sub(c, a, b) == BH_OK); - bh_unit_assert(bh_bigint_get_uint64(c) == (ta - tb)); - - bh_bigint_free(a); - bh_bigint_free(b); - bh_bigint_free(c); - - return 0; -} + bh_unit_assert(bh_bigint_get_int(c) == -2); + bh_unit_assert(bh_bigint_is_negative(c) != 0); + bh_unit_assert(bh_bigint_is_zero(c) == 0); + bh_unit_assert(bh_bigint_is_error(c) == 0); -static int addition_sign(void) -{ - bh_bigint_t *a, *b, *c; + bh_unit_assert(bh_bigint_set_int(a, -3) == BH_OK); + bh_unit_assert(bh_bigint_set_int(b, 5) == BH_OK); + bh_unit_assert(bh_bigint_add(c, a, b) == BH_OK); + bh_unit_assert(bh_bigint_get_int(c) == 2); + bh_unit_assert(bh_bigint_is_negative(c) == 0); + bh_unit_assert(bh_bigint_is_zero(c) == 0); + bh_unit_assert(bh_bigint_is_error(c) == 0); + bh_unit_assert(bh_bigint_sub(c, a, b) == BH_OK); + bh_unit_assert(bh_bigint_get_int(c) == -8); + bh_unit_assert(bh_bigint_is_negative(c) != 0); + bh_unit_assert(bh_bigint_is_zero(c) == 0); + bh_unit_assert(bh_bigint_is_error(c) == 0); - a = bh_bigint_new(); - b = bh_bigint_new(); - c = bh_bigint_new(); + bh_unit_assert(bh_bigint_set_int(a, 3) == BH_OK); + bh_unit_assert(bh_bigint_set_int(b, -5) == BH_OK); + bh_unit_assert(bh_bigint_add(c, a, b) == BH_OK); + bh_unit_assert(bh_bigint_get_int(c) == -2); + bh_unit_assert(bh_bigint_is_negative(c) != 0); + bh_unit_assert(bh_bigint_is_zero(c) == 0); + bh_unit_assert(bh_bigint_is_error(c) == 0); + bh_unit_assert(bh_bigint_sub(c, a, b) == BH_OK); + bh_unit_assert(bh_bigint_get_int(c) == 8); + bh_unit_assert(bh_bigint_is_negative(c) == 0); + bh_unit_assert(bh_bigint_is_zero(c) == 0); + bh_unit_assert(bh_bigint_is_error(c) == 0); - bh_unit_assert(a != NULL); - bh_unit_assert(b != NULL); - bh_unit_assert(c != NULL); + bh_unit_assert(bh_bigint_set_int(a, -3) == BH_OK); + bh_unit_assert(bh_bigint_set_int(b, -5) == BH_OK); + bh_unit_assert(bh_bigint_add(c, a, b) == BH_OK); + bh_unit_assert(bh_bigint_get_int(c) == -8); + bh_unit_assert(bh_bigint_is_negative(c) != 0); + bh_unit_assert(bh_bigint_is_zero(c) == 0); + bh_unit_assert(bh_bigint_is_error(c) == 0); + bh_unit_assert(bh_bigint_sub(c, a, b) == BH_OK); + bh_unit_assert(bh_bigint_get_int(c) == 2); + bh_unit_assert(bh_bigint_is_negative(c) == 0); + bh_unit_assert(bh_bigint_is_zero(c) == 0); + bh_unit_assert(bh_bigint_is_error(c) == 0); - bh_unit_assert(bh_bigint_set_int(a, 5) == BH_OK); + /* Edge cases for correct sign */ + bh_unit_assert(bh_bigint_set_int(a, 3) == BH_OK); bh_unit_assert(bh_bigint_set_int(b, 3) == BH_OK); bh_unit_assert(bh_bigint_add(c, a, b) == BH_OK); - bh_unit_assert(bh_bigint_get_int(c) == 8); - bh_unit_assert(bh_bigint_add(c, b, a) == BH_OK); - bh_unit_assert(bh_bigint_get_int(c) == 8); + bh_unit_assert(bh_bigint_get_int(c) == 6); + bh_unit_assert(bh_bigint_is_negative(c) == 0); + bh_unit_assert(bh_bigint_is_zero(c) == 0); + bh_unit_assert(bh_bigint_is_error(c) == 0); + bh_unit_assert(bh_bigint_sub(c, a, b) == BH_OK); + bh_unit_assert(bh_bigint_get_int(c) == 0); + bh_unit_assert(bh_bigint_is_negative(c) == 0); + bh_unit_assert(bh_bigint_is_zero(c) != 0); + bh_unit_assert(bh_bigint_is_error(c) == 0); - bh_unit_assert(bh_bigint_set_int(a, -5) == BH_OK); + bh_unit_assert(bh_bigint_set_int(a, -3) == BH_OK); bh_unit_assert(bh_bigint_set_int(b, 3) == BH_OK); bh_unit_assert(bh_bigint_add(c, a, b) == BH_OK); - bh_unit_assert(bh_bigint_get_int(c) == -2); - bh_unit_assert(bh_bigint_add(c, b, a) == BH_OK); - bh_unit_assert(bh_bigint_get_int(c) == -2); + bh_unit_assert(bh_bigint_get_int(c) == 0); + bh_unit_assert(bh_bigint_is_negative(c) == 0); + bh_unit_assert(bh_bigint_is_zero(c) != 0); + bh_unit_assert(bh_bigint_is_error(c) == 0); + bh_unit_assert(bh_bigint_sub(c, a, b) == BH_OK); + bh_unit_assert(bh_bigint_get_int(c) == -6); + bh_unit_assert(bh_bigint_is_negative(c) != 0); + bh_unit_assert(bh_bigint_is_zero(c) == 0); + bh_unit_assert(bh_bigint_is_error(c) == 0); - bh_unit_assert(bh_bigint_set_int(a, 5) == BH_OK); + bh_unit_assert(bh_bigint_set_int(a, 3) == BH_OK); bh_unit_assert(bh_bigint_set_int(b, -3) == BH_OK); bh_unit_assert(bh_bigint_add(c, a, b) == BH_OK); - bh_unit_assert(bh_bigint_get_int(c) == 2); - bh_unit_assert(bh_bigint_add(c, b, a) == BH_OK); - bh_unit_assert(bh_bigint_get_int(c) == 2); + bh_unit_assert(bh_bigint_get_int(c) == 0); + bh_unit_assert(bh_bigint_is_negative(c) == 0); + bh_unit_assert(bh_bigint_is_zero(c) != 0); + bh_unit_assert(bh_bigint_is_error(c) == 0); + bh_unit_assert(bh_bigint_sub(c, a, b) == BH_OK); + bh_unit_assert(bh_bigint_get_int(c) == 6); + bh_unit_assert(bh_bigint_is_negative(c) == 0); + bh_unit_assert(bh_bigint_is_zero(c) == 0); + bh_unit_assert(bh_bigint_is_error(c) == 0); - bh_unit_assert(bh_bigint_set_int(a, -5) == BH_OK); + bh_unit_assert(bh_bigint_set_int(a, -3) == BH_OK); bh_unit_assert(bh_bigint_set_int(b, -3) == BH_OK); bh_unit_assert(bh_bigint_add(c, a, b) == BH_OK); - bh_unit_assert(bh_bigint_get_int(c) == -8); - bh_unit_assert(bh_bigint_add(c, b, a) == BH_OK); - bh_unit_assert(bh_bigint_get_int(c) == -8); - - bh_bigint_free(a); - bh_bigint_free(b); - bh_bigint_free(c); - - return 0; -} - -static int subtraction_sign(void) -{ - bh_bigint_t *a, *b, *c; - - a = bh_bigint_new(); - b = bh_bigint_new(); - c = bh_bigint_new(); + bh_unit_assert(bh_bigint_get_int(c) == -6); + bh_unit_assert(bh_bigint_is_negative(c) != 0); + bh_unit_assert(bh_bigint_is_zero(c) == 0); + bh_unit_assert(bh_bigint_is_error(c) == 0); + bh_unit_assert(bh_bigint_sub(c, a, b) == BH_OK); + bh_unit_assert(bh_bigint_get_int(c) == 0); + bh_unit_assert(bh_bigint_is_negative(c) == 0); + bh_unit_assert(bh_bigint_is_zero(c) != 0); + bh_unit_assert(bh_bigint_is_error(c) == 0); - bh_unit_assert(a != NULL); - bh_unit_assert(b != NULL); - bh_unit_assert(c != NULL); + /* Set 'multi-digit' integers */ + bh_unit_assert(bh_bigint_set_uint64(a, ta) == BH_OK); + bh_unit_assert(bh_bigint_set_uint64(b, tb) == BH_OK); - bh_unit_assert(bh_bigint_set_int(a, 5) == BH_OK); - bh_unit_assert(bh_bigint_set_int(b, 3) == BH_OK); + /* Test addition and subtraction */ + bh_unit_assert(bh_bigint_add(c, a, b) == BH_OK); + bh_unit_assert(bh_bigint_get_uint64(c) == (ta + tb)); bh_unit_assert(bh_bigint_sub(c, a, b) == BH_OK); - bh_unit_assert(bh_bigint_get_int(c) == 2); - bh_unit_assert(bh_bigint_sub(c, b, a) == BH_OK); - bh_unit_assert(bh_bigint_get_int(c) == -2); + bh_unit_assert(bh_bigint_get_uint64(c) == (ta - tb)); - bh_unit_assert(bh_bigint_set_int(a, -5) == BH_OK); - bh_unit_assert(bh_bigint_set_int(b, 3) == BH_OK); - bh_unit_assert(bh_bigint_sub(c, a, b) == BH_OK); - bh_unit_assert(bh_bigint_get_int(c) == -8); - bh_unit_assert(bh_bigint_sub(c, b, a) == BH_OK); - bh_unit_assert(bh_bigint_get_int(c) == 8); + /* Overwrites */ + bh_unit_assert(bh_bigint_set(c, a) == BH_OK); + bh_unit_assert(bh_bigint_add(c, c, b) == BH_OK); + bh_unit_assert(bh_bigint_get_uint64(c) == (ta + tb)); + bh_unit_assert(bh_bigint_set(c, b) == BH_OK); + bh_unit_assert(bh_bigint_add(c, a, c) == BH_OK); + bh_unit_assert(bh_bigint_get_uint64(c) == (ta + tb)); - bh_unit_assert(bh_bigint_set_int(a, 5) == BH_OK); - bh_unit_assert(bh_bigint_set_int(b, -3) == BH_OK); - bh_unit_assert(bh_bigint_sub(c, a, b) == BH_OK); - bh_unit_assert(bh_bigint_get_int(c) == 8); - bh_unit_assert(bh_bigint_sub(c, b, a) == BH_OK); - bh_unit_assert(bh_bigint_get_int(c) == -8); + bh_unit_assert(bh_bigint_set(c, a) == BH_OK); + bh_unit_assert(bh_bigint_sub(c, c, b) == BH_OK); + bh_unit_assert(bh_bigint_get_uint64(c) == (ta - tb)); + bh_unit_assert(bh_bigint_set(c, b) == BH_OK); + bh_unit_assert(bh_bigint_sub(c, a, c) == BH_OK); + bh_unit_assert(bh_bigint_get_uint64(c) == (ta - tb)); - bh_unit_assert(bh_bigint_set_int(a, -5) == BH_OK); - bh_unit_assert(bh_bigint_set_int(b, -3) == BH_OK); + /* Check for error handling */ + a->error = 0; + b->error = 0; + c->error = 1; + bh_unit_assert(bh_bigint_add(c, a, b) == BH_OK); + bh_unit_assert(bh_bigint_is_error(c) == 0); + c->error = 1; bh_unit_assert(bh_bigint_sub(c, a, b) == BH_OK); - bh_unit_assert(bh_bigint_get_int(c) == -2); - bh_unit_assert(bh_bigint_sub(c, b, a) == BH_OK); - bh_unit_assert(bh_bigint_get_int(c) == 2); - + bh_unit_assert(bh_bigint_is_error(c) == 0); + + a->error = 1; + b->error = 0; + c->error = 0; + bh_unit_assert(bh_bigint_add(c, a, b) != BH_OK); + bh_unit_assert(bh_bigint_is_error(c) != 0); + c->error = 0; + bh_unit_assert(bh_bigint_sub(c, a, b) != BH_OK); + bh_unit_assert(bh_bigint_is_error(c) != 0); + + a->error = 0; + b->error = 1; + c->error = 0; + bh_unit_assert(bh_bigint_add(c, a, b) != BH_OK); + bh_unit_assert(bh_bigint_is_error(c) != 0); + c->error = 0; + bh_unit_assert(bh_bigint_sub(c, a, b) != BH_OK); + bh_unit_assert(bh_bigint_is_error(c) != 0); + + a->error = 1; + b->error = 1; + c->error = 0; + bh_unit_assert(bh_bigint_add(c, a, b) != BH_OK); + bh_unit_assert(bh_bigint_is_error(c) != 0); + c->error = 0; + bh_unit_assert(bh_bigint_sub(c, a, b) != BH_OK); + bh_unit_assert(bh_bigint_is_error(c) != 0); + + /* Free big integers */ bh_bigint_free(a); bh_bigint_free(b); bh_bigint_free(c); @@ -201,9 +273,10 @@ static int subtraction_sign(void) static int multiplication(void) { - int i; bh_bigint_t *a, *b, *c, *d; + int i; + /* Allocate new big integers */ a = bh_bigint_new(); b = bh_bigint_new(); c = bh_bigint_new(); @@ -214,31 +287,171 @@ static int multiplication(void) bh_unit_assert(c != NULL); bh_unit_assert(d != NULL); + /* Set big integers to arbitrary number */ bh_unit_assert(bh_bigint_set_int(a, 1234567) == BH_OK); bh_unit_assert(bh_bigint_set_int(b, 1234567) == BH_OK); - bh_unit_assert(bh_bigint_mul(c, a, b) == BH_OK); - bh_unit_assert(bh_bigint_set(d, a) == BH_OK); - bh_unit_assert(bh_bigint_reserve(d, d->size + a->size + 1) == BH_OK); - + /* Reference multiplication by addition */ + bh_unit_assert(bh_bigint_reserve(c, a->size + b->size + 1) == BH_OK); + bh_unit_assert(bh_bigint_set(c, a) == BH_OK); for (i = 1; i < 1234567; i++) - bh_unit_assert(bh_bigint_add(d, d, a) == BH_OK); + bh_unit_assert(bh_bigint_add(c, c, a) == BH_OK); + /* Multiplication and compare for equality */ + bh_unit_assert(bh_bigint_mul(d, a, b) == BH_OK); bh_unit_assert(bh_bigint_equal(c, d) == 0); - bh_unit_assert(memcmp(c->data, d->data, c->size * sizeof(*c->data)) == 0); - bh_unit_assert(bh_bigint_set_int(c, 6) == BH_OK); + /* Check signs */ + bh_unit_assert(bh_bigint_set_int(a, 2) == BH_OK); bh_unit_assert(bh_bigint_set_int(b, 2) == BH_OK); - bh_unit_assert(bh_bigint_set_int(d, 6) == BH_OK); + bh_unit_assert(bh_bigint_mul(c, a, b) == BH_OK); + bh_unit_assert(bh_bigint_get_int(c) == 4); + bh_unit_assert(bh_bigint_is_negative(c) == 0); + bh_unit_assert(bh_bigint_is_zero(c) == 0); - for (i = 0; i < 250; i++) - { - bh_unit_assert(bh_bigint_mul(c, c, b) == BH_OK); - bh_unit_assert(bh_bigint_add(d, d, d) == BH_OK); - } + bh_unit_assert(bh_bigint_set_int(a, 2) == BH_OK); + bh_unit_assert(bh_bigint_set_int(b, -2) == BH_OK); + bh_unit_assert(bh_bigint_mul(c, a, b) == BH_OK); + bh_unit_assert(bh_bigint_get_int(c) == -4); + bh_unit_assert(bh_bigint_is_negative(c) != 0); + bh_unit_assert(bh_bigint_is_zero(c) == 0); - bh_unit_assert(bh_bigint_equal(c, d) == 0); - bh_unit_assert(memcmp(c->data, d->data, c->size * sizeof(*c->data)) == 0); + bh_unit_assert(bh_bigint_set_int(a, -2) == BH_OK); + bh_unit_assert(bh_bigint_set_int(b, 2) == BH_OK); + bh_unit_assert(bh_bigint_mul(c, a, b) == BH_OK); + bh_unit_assert(bh_bigint_get_int(c) == -4); + bh_unit_assert(bh_bigint_is_negative(c) != 0); + bh_unit_assert(bh_bigint_is_zero(c) == 0); + + bh_unit_assert(bh_bigint_set_int(a, -2) == BH_OK); + bh_unit_assert(bh_bigint_set_int(b, -2) == BH_OK); + bh_unit_assert(bh_bigint_mul(c, a, b) == BH_OK); + bh_unit_assert(bh_bigint_get_int(c) == 4); + bh_unit_assert(bh_bigint_is_negative(c) == 0); + bh_unit_assert(bh_bigint_is_zero(c) == 0); + + /* Check multiplication by zero */ + bh_unit_assert(bh_bigint_set_int(a, 2) == BH_OK); + bh_unit_assert(bh_bigint_set_int(b, 0) == BH_OK); + bh_unit_assert(bh_bigint_mul(c, a, b) == BH_OK); + bh_unit_assert(bh_bigint_get_int(c) == 0); + bh_unit_assert(bh_bigint_is_negative(c) == 0); + bh_unit_assert(bh_bigint_is_zero(c) != 0); + + bh_unit_assert(bh_bigint_set_int(a, 0) == BH_OK); + bh_unit_assert(bh_bigint_set_int(b, 2) == BH_OK); + bh_unit_assert(bh_bigint_mul(c, a, b) == BH_OK); + bh_unit_assert(bh_bigint_get_int(c) == 0); + bh_unit_assert(bh_bigint_is_negative(c) == 0); + bh_unit_assert(bh_bigint_is_zero(c) != 0); + + bh_unit_assert(bh_bigint_set_int(a, 0) == BH_OK); + bh_unit_assert(bh_bigint_set_int(b, 0) == BH_OK); + bh_unit_assert(bh_bigint_mul(c, a, b) == BH_OK); + bh_unit_assert(bh_bigint_get_int(c) == 0); + bh_unit_assert(bh_bigint_is_negative(c) == 0); + bh_unit_assert(bh_bigint_is_zero(c) != 0); + + /* Overwrites */ + bh_unit_assert(bh_bigint_set_int(a, 1234) == BH_OK); + bh_unit_assert(bh_bigint_set_int(b, 4321) == BH_OK); + bh_unit_assert(bh_bigint_mul(a, a, b) == BH_OK); + bh_unit_assert(bh_bigint_get_int(a) == 1234 * 4321); + + bh_unit_assert(bh_bigint_set_int(a, 1234) == BH_OK); + bh_unit_assert(bh_bigint_set_int(b, 4321) == BH_OK); + bh_unit_assert(bh_bigint_mul(b, a, b) == BH_OK); + bh_unit_assert(bh_bigint_get_int(b) == 1234 * 4321); + + bh_unit_assert(bh_bigint_set_int(a, 1234) == BH_OK); + bh_unit_assert(bh_bigint_set_int(b, 4321) == BH_OK); + bh_unit_assert(bh_bigint_mul(a, a, a) == BH_OK); + bh_unit_assert(bh_bigint_get_int(a) == 1234 * 1234); + + /* Check digit multiplication */ + bh_unit_assert(bh_bigint_set_int(a, 1234567) == BH_OK); + bh_unit_assert(bh_bigint_mul_digit(c, a, 12345) == BH_OK); + bh_unit_assert(bh_bigint_get_uint64(c) == 15240729615ull); + + /* Check digit multiplication by zero */ + bh_unit_assert(bh_bigint_set_int(a, 2) == BH_OK); + bh_unit_assert(bh_bigint_mul_digit(c, a, 0) == BH_OK); + bh_unit_assert(bh_bigint_get_int(c) == 0); + bh_unit_assert(bh_bigint_is_negative(c) == 0); + bh_unit_assert(bh_bigint_is_zero(c) != 0); + + bh_unit_assert(bh_bigint_set_int(a, 0) == BH_OK); + bh_unit_assert(bh_bigint_mul_digit(c, a, 2) == BH_OK); + bh_unit_assert(bh_bigint_get_int(c) == 0); + bh_unit_assert(bh_bigint_is_negative(c) == 0); + bh_unit_assert(bh_bigint_is_zero(c) != 0); + + bh_unit_assert(bh_bigint_set_int(a, 0) == BH_OK); + bh_unit_assert(bh_bigint_mul_digit(c, a, 0) == BH_OK); + bh_unit_assert(bh_bigint_get_int(c) == 0); + bh_unit_assert(bh_bigint_is_negative(c) == 0); + bh_unit_assert(bh_bigint_is_zero(c) != 0); + + /* Check digit multiplication signs */ + bh_unit_assert(bh_bigint_set_int(a, 2) == BH_OK); + bh_unit_assert(bh_bigint_mul_digit(c, a, 2) == BH_OK); + bh_unit_assert(bh_bigint_get_int(c) == 4); + bh_unit_assert(bh_bigint_is_negative(c) == 0); + bh_unit_assert(bh_bigint_is_zero(c) == 0); + + bh_unit_assert(bh_bigint_set_int(a, 2) == BH_OK); + bh_unit_assert(bh_bigint_mul_digit(c, a, -2) == BH_OK); + bh_unit_assert(bh_bigint_get_int(c) == -4); + bh_unit_assert(bh_bigint_is_negative(c) != 0); + bh_unit_assert(bh_bigint_is_zero(c) == 0); + + bh_unit_assert(bh_bigint_set_int(a, -2) == BH_OK); + bh_unit_assert(bh_bigint_mul_digit(c, a, 2) == BH_OK); + bh_unit_assert(bh_bigint_get_int(c) == -4); + bh_unit_assert(bh_bigint_is_negative(c) != 0); + bh_unit_assert(bh_bigint_is_zero(c) == 0); + + bh_unit_assert(bh_bigint_set_int(a, -2) == BH_OK); + bh_unit_assert(bh_bigint_mul_digit(c, a, -2) == BH_OK); + bh_unit_assert(bh_bigint_get_int(c) == 4); + bh_unit_assert(bh_bigint_is_negative(c) == 0); + bh_unit_assert(bh_bigint_is_zero(c) == 0); + + /* Check for error handling */ + a->error = 0; + b->error = 0; + c->error = 1; + bh_unit_assert(bh_bigint_mul(c, a, b) == BH_OK); + bh_unit_assert(bh_bigint_is_error(c) == 0); + + a->error = 1; + b->error = 0; + c->error = 0; + bh_unit_assert(bh_bigint_mul(c, a, b) != BH_OK); + bh_unit_assert(bh_bigint_is_error(c) != 0); + + a->error = 0; + b->error = 1; + c->error = 0; + bh_unit_assert(bh_bigint_mul(c, a, b) != BH_OK); + bh_unit_assert(bh_bigint_is_error(c) != 0); + + a->error = 1; + b->error = 1; + c->error = 0; + bh_unit_assert(bh_bigint_mul(c, a, b) != BH_OK); + bh_unit_assert(bh_bigint_is_error(c) != 0); + + /* Check for digit multiplication error handling */ + a->error = 0; + c->error = 1; + bh_unit_assert(bh_bigint_mul_digit(c, a, 10) == BH_OK); + bh_unit_assert(bh_bigint_is_error(c) == 0); + + a->error = 1; + c->error = 0; + bh_unit_assert(bh_bigint_mul_digit(c, a, 10) != BH_OK); + bh_unit_assert(bh_bigint_is_error(c) != 0); bh_bigint_free(a); bh_bigint_free(b); @@ -250,12 +463,10 @@ static int multiplication(void) static int logic(void) { + const bh_uint64_t ta = 0xA3B1DBC158176B96ull, tb = 0x2748D1622F3E90A2ull; bh_bigint_t *a, *b, *c; - bh_uint64_t ta, tb; - - ta = 0xA3B1DBC158176B96ull; - tb = 0x2748D1622F3E90A2ull; + /* Allocate big integers */ a = bh_bigint_new(); b = bh_bigint_new(); c = bh_bigint_new(); @@ -264,87 +475,163 @@ static int logic(void) bh_unit_assert(b != NULL); bh_unit_assert(c != NULL); + /* Copy from reference integers */ bh_unit_assert(bh_bigint_set_uint64(a, ta) == BH_OK); bh_unit_assert(bh_bigint_set_uint64(b, tb) == BH_OK); - + + /* Logic OR */ bh_unit_assert(bh_bigint_or(c, a, b) == BH_OK); bh_unit_assert(bh_bigint_get_uint64(c) == (ta | tb)); + bh_unit_assert(bh_bigint_is_negative(c) == 0); + /* Logic AND */ bh_unit_assert(bh_bigint_and(c, a, b) == BH_OK); bh_unit_assert(bh_bigint_get_uint64(c) == (ta & tb)); + bh_unit_assert(bh_bigint_is_negative(c) == 0); + /* Logic XOR */ bh_unit_assert(bh_bigint_xor(c, a, b) == BH_OK); bh_unit_assert(bh_bigint_get_uint64(c) == (ta ^ tb)); + bh_unit_assert(bh_bigint_is_negative(c) == 0); - bh_bigint_free(a); - bh_bigint_free(b); - bh_bigint_free(c); - - return 0; -} - -static int shifts(void) -{ - bh_bigint_t *a, *b; - bh_uint64_t ta, tb; - - ta = 0x73B1DBC158176B96ull; - tb = 0x73B1DBC158176B90ull; - - a = bh_bigint_new(); - b = bh_bigint_new(); - - bh_unit_assert(a != NULL); - bh_unit_assert(b != NULL); - - bh_unit_assert(bh_bigint_set_uint64(a, 0xFFull) == BH_OK); - bh_unit_assert(bh_bigint_lsh(b, a, 4) == BH_OK); - bh_unit_assert(bh_bigint_get_uint64(b) == (0xFFull << 4)); - - bh_unit_assert(bh_bigint_set_uint64(a, 0xFFull) == BH_OK); - bh_unit_assert(bh_bigint_lsh(b, a, 15) == BH_OK); - bh_unit_assert(bh_bigint_get_uint64(b) == (0xFFull << 15)); - - bh_unit_assert(bh_bigint_set_uint64(a, 0xFFull) == BH_OK); - bh_unit_assert(bh_bigint_lsh(b, a, 31) == BH_OK); - bh_unit_assert(bh_bigint_get_uint64(b) == (0xFFull << 31)); - - bh_unit_assert(bh_bigint_set_uint64(a, 0xFFull) == BH_OK); - bh_unit_assert(bh_bigint_lsh(b, a, 35) == BH_OK); - bh_unit_assert(bh_bigint_get_uint64(b) == (0xFFull << 35)); - - bh_unit_assert(bh_bigint_set_uint64(a, ta) == BH_OK); - bh_unit_assert(bh_bigint_lsh(b, a, 1) == BH_OK); - bh_unit_assert(bh_bigint_get_uint64(b) == (ta << 1)); + /* Operations with zero */ + bh_unit_assert(bh_bigint_clear(b) == BH_OK); + bh_unit_assert(bh_bigint_and(c, a, b) == BH_OK); + bh_unit_assert(bh_bigint_get_uint64(c) == 0); + bh_unit_assert(bh_bigint_is_negative(c) == 0); + bh_unit_assert(bh_bigint_is_zero(c) != 0); - bh_unit_assert(bh_bigint_set_uint64(a, ta) == BH_OK); - bh_unit_assert(bh_bigint_rsh(b, a, 31) == BH_OK); - bh_unit_assert(bh_bigint_get_uint64(b) == (ta >> 31)) + bh_unit_assert(bh_bigint_or(c, a, b) == BH_OK); + bh_unit_assert(bh_bigint_get_uint64(c) == ta); + bh_unit_assert(bh_bigint_is_negative(c) == 0); + bh_unit_assert(bh_bigint_is_zero(c) == 0); - bh_unit_assert(bh_bigint_set_uint64(a, ta) == BH_OK); - bh_unit_assert(bh_bigint_rsh(b, a, 15) == BH_OK); - bh_unit_assert(bh_bigint_get_uint64(b) == (ta >> 15)) + bh_unit_assert(bh_bigint_xor(c, a, b) == BH_OK); + bh_unit_assert(bh_bigint_get_uint64(c) == ta); + bh_unit_assert(bh_bigint_is_negative(c) == 0); + bh_unit_assert(bh_bigint_is_zero(c) == 0); + /* Copy from reference integers */ bh_unit_assert(bh_bigint_set_uint64(a, ta) == BH_OK); - bh_unit_assert(bh_bigint_rsh(b, a, 4) == BH_OK); - bh_unit_assert(bh_bigint_get_uint64(b) == (ta >> 4)); - - bh_unit_assert(bh_bigint_lsh(b, b, 4) == BH_OK); - bh_unit_assert(bh_bigint_get_uint64(b) == tb); + bh_unit_assert(bh_bigint_set_uint64(b, tb) == BH_OK); - bh_unit_assert(bh_bigint_rsh(b, a, 60) == BH_OK); - bh_unit_assert(bh_bigint_get_uint64(b) == 0x7); - + /* Logic shift left */ + bh_unit_assert(bh_bigint_lsh(c, b, 1) == BH_OK); + bh_unit_assert(bh_bigint_get_uint64(c) == (tb << 1)); + bh_unit_assert(bh_bigint_is_negative(c) == 0); + bh_unit_assert(bh_bigint_is_zero(c) == 0); + + /* Logic shift right */ + bh_unit_assert(bh_bigint_rsh(c, b, 1) == BH_OK); + bh_unit_assert(bh_bigint_get_uint64(c) == (tb >> 1)); + bh_unit_assert(bh_bigint_is_negative(c) == 0); + bh_unit_assert(bh_bigint_is_zero(c) == 0); + + /* Zero bit shifts */ + bh_unit_assert(bh_bigint_lsh(c, b, 0) == BH_OK); + bh_unit_assert(bh_bigint_get_uint64(c) == tb); + bh_unit_assert(bh_bigint_is_negative(c) == 0); + bh_unit_assert(bh_bigint_is_zero(c) == 0); + + bh_unit_assert(bh_bigint_rsh(c, b, 0) == BH_OK); + bh_unit_assert(bh_bigint_get_uint64(c) == tb); + bh_unit_assert(bh_bigint_is_negative(c) == 0); + bh_unit_assert(bh_bigint_is_zero(c) == 0); + + /* Full width shift */ + bh_unit_assert(bh_bigint_rsh(c, b, 64) == BH_OK); + bh_unit_assert(bh_bigint_get_uint64(c) == 0); + bh_unit_assert(bh_bigint_is_negative(c) == 0); + bh_unit_assert(bh_bigint_is_zero(c) != 0); + + /* Large shifts */ + bh_unit_assert(bh_bigint_rsh(c, a, 60) == BH_OK); + bh_unit_assert(bh_bigint_get_uint64(c) == 0xA); + bh_unit_assert(bh_bigint_is_negative(c) == 0); + bh_unit_assert(bh_bigint_is_zero(c) == 0); + + bh_unit_assert(bh_bigint_lsh(c, a, 100) == BH_OK); + bh_unit_assert(bh_bigint_rsh(c, c, 100) == BH_OK); + bh_unit_assert(bh_bigint_get_uint64(c) == ta); + bh_unit_assert(bh_bigint_is_negative(c) == 0); + bh_unit_assert(bh_bigint_is_zero(c) == 0); + + /* Check for error handling */ + a->error = 0; + b->error = 0; + c->error = 1; + bh_unit_assert(bh_bigint_or(c, a, b) == BH_OK); + bh_unit_assert(bh_bigint_is_error(c) == 0); + c->error = 1; + bh_unit_assert(bh_bigint_and(c, a, b) == BH_OK); + bh_unit_assert(bh_bigint_is_error(c) == 0); + c->error = 1; + bh_unit_assert(bh_bigint_xor(c, a, b) == BH_OK); + bh_unit_assert(bh_bigint_is_error(c) == 0); + c->error = 1; + bh_unit_assert(bh_bigint_lsh(c, a, 1) == BH_OK); + bh_unit_assert(bh_bigint_is_error(c) == 0); + c->error = 1; + bh_unit_assert(bh_bigint_rsh(c, a, 1) == BH_OK); + bh_unit_assert(bh_bigint_is_error(c) == 0); + + a->error = 1; + b->error = 0; + c->error = 0; + bh_unit_assert(bh_bigint_or(c, a, b) != BH_OK); + bh_unit_assert(bh_bigint_is_error(c) != 0); + c->error = 0; + bh_unit_assert(bh_bigint_and(c, a, b) != BH_OK); + bh_unit_assert(bh_bigint_is_error(c) != 0); + c->error = 0; + bh_unit_assert(bh_bigint_xor(c, a, b) != BH_OK); + bh_unit_assert(bh_bigint_is_error(c) != 0); + c->error = 0; + bh_unit_assert(bh_bigint_lsh(c, a, 1) != BH_OK); + bh_unit_assert(bh_bigint_is_error(c) != 0); + c->error = 0; + bh_unit_assert(bh_bigint_rsh(c, a, 1) != BH_OK); + bh_unit_assert(bh_bigint_is_error(c) != 0); + + a->error = 0; + b->error = 1; + c->error = 0; + bh_unit_assert(bh_bigint_or(c, a, b) != BH_OK); + bh_unit_assert(bh_bigint_is_error(c) != 0); + c->error = 0; + bh_unit_assert(bh_bigint_and(c, a, b) != BH_OK); + bh_unit_assert(bh_bigint_is_error(c) != 0); + c->error = 0; + bh_unit_assert(bh_bigint_xor(c, a, b) != BH_OK); + bh_unit_assert(bh_bigint_is_error(c) != 0); + + a->error = 1; + b->error = 1; + c->error = 0; + bh_unit_assert(bh_bigint_or(c, a, b) != BH_OK); + bh_unit_assert(bh_bigint_is_error(c) != 0); + c->error = 0; + bh_unit_assert(bh_bigint_and(c, a, b) != BH_OK); + bh_unit_assert(bh_bigint_is_error(c) != 0); + c->error = 0; + bh_unit_assert(bh_bigint_xor(c, a, b) != BH_OK); + bh_unit_assert(bh_bigint_is_error(c) != 0); + + /* Free big integers */ bh_bigint_free(a); bh_bigint_free(b); + bh_bigint_free(c); return 0; } static int division(void) { + const bh_uint64_t ta = 0x41F915031348A134ull, tb = 0x434115F6ull, tc = 0x153F14ABull; + const bh_uint64_t td = 0xD0D561E41F7EA081ull, te = 0x0459E1CDull; bh_bigint_t *a, *b, *c, *d; + /* Allocate big integers */ a = bh_bigint_new(); b = bh_bigint_new(); c = bh_bigint_new(); @@ -355,16 +642,117 @@ static int division(void) bh_unit_assert(c != NULL); bh_unit_assert(d != NULL); - bh_unit_assert(bh_bigint_set_uint64(a, 0x41F915031348A134ull) == BH_OK); - bh_unit_assert(bh_bigint_set_uint64(b, 0x434115F6ull) == BH_OK); + /* Set integers to test values */ + bh_unit_assert(bh_bigint_set_uint64(a, ta) == BH_OK); + bh_unit_assert(bh_bigint_set_uint64(b, tb) == BH_OK); bh_unit_assert(bh_bigint_mul(a, a, b) == BH_OK); - bh_unit_assert(bh_bigint_set_uint64(b, 0x153F14ABull) == BH_OK); + bh_unit_assert(bh_bigint_set_uint64(b, tc) == BH_OK); + /* Divide and check result for div&mod operation */ bh_unit_assert(bh_bigint_divmod(c, d, a, b) == BH_OK); + bh_unit_assert(bh_bigint_get_uint64(c) == td); + bh_unit_assert(bh_bigint_get_uint64(d) == te); + + /* Check for division */ + bh_unit_assert(bh_bigint_div(c, a, b) == BH_OK); + bh_unit_assert(bh_bigint_get_uint64(c) == td); - bh_unit_assert(bh_bigint_get_uint64(c) == 0xD0D561E41F7EA081ull); - bh_unit_assert(bh_bigint_get_uint64(d) == 0x0459E1CDull); + /* Check for modulos */ + bh_unit_assert(bh_bigint_mod(d, a, b) == BH_OK); + bh_unit_assert(bh_bigint_get_uint64(d) == te); + /* Check division with zero */ + bh_unit_assert(bh_bigint_set_int(a, 0) == BH_OK); + bh_unit_assert(bh_bigint_set_int(b, 50) == BH_OK); + bh_unit_assert(bh_bigint_divmod(c, d, a, b) == BH_OK); + bh_unit_assert(bh_bigint_get_int(c) == 0); + bh_unit_assert(bh_bigint_get_int(d) == 0); + + bh_unit_assert(bh_bigint_set_int(a, 50) == BH_OK); + bh_unit_assert(bh_bigint_set_int(b, 0) == BH_OK); + bh_unit_assert(bh_bigint_divmod(c, d, a, b) != BH_OK); + bh_unit_assert(bh_bigint_is_error(c) != 0); + bh_unit_assert(bh_bigint_is_error(d) != 0); + + /* Check signs */ + bh_unit_assert(bh_bigint_set_int(a, 1773) == BH_OK); + bh_unit_assert(bh_bigint_set_int(b, 50) == BH_OK); + bh_unit_assert(bh_bigint_divmod(c, d, a, b) == BH_OK); + bh_unit_assert(bh_bigint_get_int(c) == 35); + bh_unit_assert(bh_bigint_get_int(d) == 23); + bh_unit_assert(bh_bigint_is_negative(c) == 0); + bh_unit_assert(bh_bigint_is_negative(d) == 0); + bh_unit_assert(bh_bigint_mul(c, c, b) == BH_OK); + bh_unit_assert(bh_bigint_add(c, c, d) == BH_OK); + bh_unit_assert(bh_bigint_get_int(c) == 1773); + + bh_unit_assert(bh_bigint_set_int(a, 1773) == BH_OK); + bh_unit_assert(bh_bigint_set_int(b, -50) == BH_OK); + bh_unit_assert(bh_bigint_divmod(c, d, a, b) == BH_OK); + bh_unit_assert(bh_bigint_get_int(c) == -35); + bh_unit_assert(bh_bigint_get_int(d) == 23); + bh_unit_assert(bh_bigint_is_negative(c) != 0); + bh_unit_assert(bh_bigint_is_negative(d) == 0); + bh_unit_assert(bh_bigint_mul(c, c, b) == BH_OK); + bh_unit_assert(bh_bigint_add(c, c, d) == BH_OK); + bh_unit_assert(bh_bigint_get_int(c) == 1773); + + bh_unit_assert(bh_bigint_set_int(a, -1773) == BH_OK); + bh_unit_assert(bh_bigint_set_int(b, 50) == BH_OK); + bh_unit_assert(bh_bigint_divmod(c, d, a, b) == BH_OK); + bh_unit_assert(bh_bigint_get_int(c) == -35); + bh_unit_assert(bh_bigint_get_int(d) == -23); + bh_unit_assert(bh_bigint_is_negative(c) != 0); + bh_unit_assert(bh_bigint_is_negative(d) != 0); + bh_unit_assert(bh_bigint_mul(c, c, b) == BH_OK); + bh_unit_assert(bh_bigint_add(c, c, d) == BH_OK); + bh_unit_assert(bh_bigint_get_int(c) == -1773); + + bh_unit_assert(bh_bigint_set_int(a, -1773) == BH_OK); + bh_unit_assert(bh_bigint_set_int(b, -50) == BH_OK); + bh_unit_assert(bh_bigint_divmod(c, d, a, b) == BH_OK); + bh_unit_assert(bh_bigint_get_int(c) == 35); + bh_unit_assert(bh_bigint_get_int(d) == -23); + bh_unit_assert(bh_bigint_is_negative(c) == 0); + bh_unit_assert(bh_bigint_is_negative(d) != 0); + bh_unit_assert(bh_bigint_mul(c, c, b) == BH_OK); + bh_unit_assert(bh_bigint_add(c, c, d) == BH_OK); + bh_unit_assert(bh_bigint_get_int(c) == -1773); + + /* Check for error handling */ + a->error = 0; + b->error = 0; + c->error = 1; + d->error = 1; + bh_unit_assert(bh_bigint_divmod(c, d, a, b) == BH_OK); + bh_unit_assert(bh_bigint_is_error(c) == 0); + bh_unit_assert(bh_bigint_is_error(d) == 0); + + a->error = 1; + b->error = 0; + c->error = 0; + d->error = 0; + bh_unit_assert(bh_bigint_divmod(c, d, a, b) != BH_OK); + bh_unit_assert(bh_bigint_is_error(c) != 0); + bh_unit_assert(bh_bigint_is_error(d) != 0); + + a->error = 0; + b->error = 1; + c->error = 0; + d->error = 0; + bh_unit_assert(bh_bigint_divmod(c, d, a, b) != BH_OK); + bh_unit_assert(bh_bigint_is_error(c) != 0); + bh_unit_assert(bh_bigint_is_error(d) != 0); + + a->error = 1; + b->error = 1; + c->error = 0; + d->error = 0; + bh_unit_assert(bh_bigint_divmod(c, d, a, b) != BH_OK); + bh_unit_assert(bh_bigint_is_error(c) != 0); + bh_unit_assert(bh_bigint_is_error(d) != 0); + + /* Deallocate big integers */ bh_bigint_free(a); bh_bigint_free(b); bh_bigint_free(c); @@ -377,6 +765,7 @@ static int power(void) { bh_bigint_t *a, *b, *c, *d, *e; + /* Allocate big integers */ a = bh_bigint_new(); b = bh_bigint_new(); c = bh_bigint_new(); @@ -389,6 +778,114 @@ static int power(void) bh_unit_assert(d != NULL); bh_unit_assert(e != NULL); + /* Check sign */ + bh_unit_assert(bh_bigint_set_int(a, 137) == BH_OK); + bh_unit_assert(bh_bigint_set_int(b, 3) == BH_OK); + bh_unit_assert(bh_bigint_set_int64(c, 10000000ll) == BH_OK); + + bh_unit_assert(bh_bigint_pow(d, a, 3) == BH_OK); + bh_unit_assert(bh_bigint_powm(e, a, b, c) == BH_OK); + bh_unit_assert(bh_bigint_equal(d, e) == 0); + bh_unit_assert(bh_bigint_get_int64(e) == 2571353ll); + + bh_unit_assert(bh_bigint_set_int(a, -137) == BH_OK); + bh_unit_assert(bh_bigint_pow(d, a, 3) == BH_OK); + bh_unit_assert(bh_bigint_powm(e, a, b, c) == BH_OK); + bh_unit_assert(bh_bigint_equal(d, e) == 0); + bh_unit_assert(bh_bigint_get_int64(e) == -2571353ll); + + /* Power of zero */ + bh_unit_assert(bh_bigint_set_int(a, 137) == BH_OK); + bh_unit_assert(bh_bigint_set_int(b, 0) == BH_OK); + bh_unit_assert(bh_bigint_set_int64(c, 10000000ll) == BH_OK); + bh_unit_assert(bh_bigint_pow(d, a, 0) == BH_OK); + bh_unit_assert(bh_bigint_powm(e, a, b, c) == BH_OK); + bh_unit_assert(bh_bigint_equal(d, e) == 0); + bh_unit_assert(bh_bigint_get_int64(e) == 1); + + /* Zero in some power */ + bh_unit_assert(bh_bigint_set_int(a, 0) == BH_OK); + bh_unit_assert(bh_bigint_set_int(b, 50) == BH_OK); + bh_unit_assert(bh_bigint_set_int64(c, 10000000ll) == BH_OK); + bh_unit_assert(bh_bigint_pow(d, a, 50) == BH_OK); + bh_unit_assert(bh_bigint_powm(e, a, b, c) == BH_OK); + bh_unit_assert(bh_bigint_equal(d, e) == 0); + bh_unit_assert(bh_bigint_get_int64(e) == 0); + + /* Zero in power of zero */ + bh_unit_assert(bh_bigint_set_int(a, 0) == BH_OK); + bh_unit_assert(bh_bigint_set_int(b, 0) == BH_OK); + bh_unit_assert(bh_bigint_set_int64(c, 10000000ll) == BH_OK); + bh_unit_assert(bh_bigint_pow(d, a, 0) == BH_OK); + bh_unit_assert(bh_bigint_powm(e, a, b, c) == BH_OK); + bh_unit_assert(bh_bigint_equal(d, e) == 0); + bh_unit_assert(bh_bigint_get_int64(e) == 1); + + /* Error handling */ + a->error = 0; + b->error = 0; + c->error = 0; + d->error = 1; + e->error = 1; + bh_unit_assert(bh_bigint_pow(d, a, 3) == BH_OK); + bh_unit_assert(bh_bigint_powm(e, a, b, c) == BH_OK); + bh_unit_assert(bh_bigint_is_error(d) == 0); + bh_unit_assert(bh_bigint_is_error(e) == 0); + + a->error = 1; + b->error = 0; + c->error = 0; + d->error = 0; + e->error = 0; + bh_unit_assert(bh_bigint_pow(d, a, 3) != BH_OK); + bh_unit_assert(bh_bigint_powm(e, a, b, c) != BH_OK); + bh_unit_assert(bh_bigint_is_error(d) != 0); + bh_unit_assert(bh_bigint_is_error(e) != 0); + + a->error = 0; + b->error = 1; + c->error = 0; + e->error = 0; + bh_unit_assert(bh_bigint_powm(e, a, b, c) != BH_OK); + bh_unit_assert(bh_bigint_is_error(e) != 0); + + a->error = 1; + b->error = 1; + c->error = 0; + e->error = 0; + bh_unit_assert(bh_bigint_powm(e, a, b, c) != BH_OK); + bh_unit_assert(bh_bigint_is_error(e) != 0); + + a->error = 0; + b->error = 0; + c->error = 1; + e->error = 0; + bh_unit_assert(bh_bigint_powm(e, a, b, c) != BH_OK); + bh_unit_assert(bh_bigint_is_error(e) != 0); + + a->error = 1; + b->error = 0; + c->error = 1; + e->error = 0; + bh_unit_assert(bh_bigint_powm(e, a, b, c) != BH_OK); + bh_unit_assert(bh_bigint_is_error(e) != 0); + + a->error = 0; + b->error = 1; + c->error = 1; + e->error = 0; + bh_unit_assert(bh_bigint_powm(e, a, b, c) != BH_OK); + bh_unit_assert(bh_bigint_is_error(e) != 0); + + a->error = 1; + b->error = 1; + c->error = 1; + e->error = 0; + bh_unit_assert(bh_bigint_powm(e, a, b, c) != BH_OK); + bh_unit_assert(bh_bigint_is_error(e) != 0); + + /* Large powers */ + /* TODO: Replace this with some better test */ bh_unit_assert(bh_bigint_set_int(a, 137) == BH_OK); bh_unit_assert(bh_bigint_set_int(b, 2048) == BH_OK); bh_unit_assert(bh_bigint_set_int(c, 100) == BH_OK); @@ -399,6 +896,7 @@ static int power(void) bh_unit_assert(bh_bigint_equal(d, e) == 0); bh_unit_assert(bh_bigint_get_int(d) == 21); + /* Deallocate big integers */ bh_bigint_free(a); bh_bigint_free(b); bh_bigint_free(c); @@ -414,16 +912,13 @@ int main(int argc, char **argv) (void)argv; /* Add unit tests */ + bh_unit_add("fields", fields); bh_unit_add("round_trip", round_trip); - bh_unit_add("addition", addition); - bh_unit_add("subtraction", subtraction); - bh_unit_add("addition_sign", addition_sign); - bh_unit_add("subtraction_sign", subtraction_sign); + bh_unit_add("add_sub", add_sub); bh_unit_add("multiplication", multiplication); bh_unit_add("logic", logic); - bh_unit_add("shifts", shifts); bh_unit_add("division", division); bh_unit_add("power", power); return bh_unit_run(); -}
\ No newline at end of file +} |
