Improve big integer tests, fix bugs, add quick digit multiplication
This commit is contained in:
@@ -84,6 +84,10 @@ int bh_bigint_mul(bh_bigint_t *to,
|
|||||||
bh_bigint_t *left,
|
bh_bigint_t *left,
|
||||||
bh_bigint_t *right);
|
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,
|
int bh_bigint_pow(bh_bigint_t *to,
|
||||||
bh_bigint_t *from,
|
bh_bigint_t *from,
|
||||||
bh_uint32_t power);
|
bh_uint32_t power);
|
||||||
|
|||||||
@@ -5,3 +5,4 @@
|
|||||||
#include <bh/internal/config.h>
|
#include <bh/internal/config.h>
|
||||||
|
|
||||||
#endif /* BH_INTERNAL_H */
|
#endif /* BH_INTERNAL_H */
|
||||||
|
|
||||||
|
|||||||
119
src/bigint.c
119
src/bigint.c
@@ -496,9 +496,14 @@ int bh_bigint_add(bh_bigint_t *to,
|
|||||||
else
|
else
|
||||||
code = bh_bigint_sub_base(to, most, least);
|
code = bh_bigint_sub_base(to, most, least);
|
||||||
|
|
||||||
/* Set result sign */
|
|
||||||
if (!code)
|
if (!code)
|
||||||
to->type = type;
|
{
|
||||||
|
/* Set result sign or zero */
|
||||||
|
if (to->size)
|
||||||
|
to->type = type;
|
||||||
|
else
|
||||||
|
to->type = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Return result code */
|
/* Return result code */
|
||||||
return code;
|
return code;
|
||||||
@@ -538,9 +543,14 @@ int bh_bigint_sub(bh_bigint_t *to,
|
|||||||
else
|
else
|
||||||
code = bh_bigint_add_base(to, most, least);
|
code = bh_bigint_add_base(to, most, least);
|
||||||
|
|
||||||
/* Set result sign */
|
|
||||||
if (!code)
|
if (!code)
|
||||||
to->type = type;
|
{
|
||||||
|
/* Set result sign or zero */
|
||||||
|
if (to->size)
|
||||||
|
to->type = type;
|
||||||
|
else
|
||||||
|
to->type = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Return result code */
|
/* Return result code */
|
||||||
return code;
|
return code;
|
||||||
@@ -639,6 +649,73 @@ int bh_bigint_mul(bh_bigint_t *to,
|
|||||||
return BH_OK;
|
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,
|
int bh_bigint_pow(bh_bigint_t *to,
|
||||||
bh_bigint_t *from,
|
bh_bigint_t *from,
|
||||||
bh_uint32_t power)
|
bh_uint32_t power)
|
||||||
@@ -732,7 +809,7 @@ int bh_bigint_powm(bh_bigint_t *to,
|
|||||||
code = BH_OK;
|
code = BH_OK;
|
||||||
|
|
||||||
/* Shortcut - one of the arguments has error flag set */
|
/* Shortcut - one of the arguments has error flag set */
|
||||||
if (left->error || right->error)
|
if (left->error || right->error || mod->error)
|
||||||
{
|
{
|
||||||
to->error = 1;
|
to->error = 1;
|
||||||
return BH_ERROR;
|
return BH_ERROR;
|
||||||
@@ -993,7 +1070,8 @@ static int bh_bigint_div_base(bh_bigint_t *quotient,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate remainder */
|
/* 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)
|
if (!nleft->size)
|
||||||
break;
|
break;
|
||||||
@@ -1020,6 +1098,9 @@ finish:
|
|||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This follows C99 model (a/b)*b + a%b
|
||||||
|
*/
|
||||||
int bh_bigint_divmod(bh_bigint_t *quotient,
|
int bh_bigint_divmod(bh_bigint_t *quotient,
|
||||||
bh_bigint_t *remainder,
|
bh_bigint_t *remainder,
|
||||||
bh_bigint_t *left,
|
bh_bigint_t *left,
|
||||||
@@ -1111,6 +1192,9 @@ int bh_bigint_divmod(bh_bigint_t *quotient,
|
|||||||
code = bh_bigint_div_base(quotient, tmp, left, right, &shift);
|
code = bh_bigint_div_base(quotient, tmp, left, right, &shift);
|
||||||
if (!code)
|
if (!code)
|
||||||
{
|
{
|
||||||
|
/* Remainder should use sign of the left operand */
|
||||||
|
tmp->type = left->type;
|
||||||
|
|
||||||
/* If remainder required - normilize it */
|
/* If remainder required - normilize it */
|
||||||
if (tmp == remainder)
|
if (tmp == remainder)
|
||||||
bh_bigint_rsh(remainder, remainder, shift);
|
bh_bigint_rsh(remainder, remainder, shift);
|
||||||
@@ -1358,10 +1442,16 @@ int bh_bigint_or(bh_bigint_t *to,
|
|||||||
to->data[i] = tmp;
|
to->data[i] = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Shrink size */
|
||||||
|
while (size && !to->data[size - 1]) size--;
|
||||||
|
|
||||||
/* Update fields */
|
/* Update fields */
|
||||||
to->type = 1;
|
to->type = 1;
|
||||||
to->size = size;
|
to->size = size;
|
||||||
|
|
||||||
|
if (!size)
|
||||||
|
to->type = 0;
|
||||||
|
|
||||||
return BH_OK;
|
return BH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1401,10 +1491,16 @@ int bh_bigint_and(bh_bigint_t *to,
|
|||||||
to->data[i] = tmp;
|
to->data[i] = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Shrink size */
|
||||||
|
while (size && !to->data[size - 1]) size--;
|
||||||
|
|
||||||
/* Update fields */
|
/* Update fields */
|
||||||
to->type = 1;
|
to->type = 1;
|
||||||
to->size = size;
|
to->size = size;
|
||||||
|
|
||||||
|
if (!size)
|
||||||
|
to->type = 0;
|
||||||
|
|
||||||
return BH_OK;
|
return BH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1444,10 +1540,16 @@ int bh_bigint_xor(bh_bigint_t *to,
|
|||||||
to->data[i] = tmp;
|
to->data[i] = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Shrink size */
|
||||||
|
while (size && !to->data[size - 1]) size--;
|
||||||
|
|
||||||
/* Update fields */
|
/* Update fields */
|
||||||
to->type = 1;
|
to->type = 1;
|
||||||
to->size = size;
|
to->size = size;
|
||||||
|
|
||||||
|
if (!size)
|
||||||
|
to->type = 0;
|
||||||
|
|
||||||
return BH_OK;
|
return BH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1472,10 +1574,7 @@ int bh_bigint_negate(bh_bigint_t *to,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Change the sign */
|
/* Change the sign */
|
||||||
if (to->type < 0)
|
to->type = 0 - to->type;
|
||||||
to->type = 1;
|
|
||||||
else if (to->type > 0)
|
|
||||||
to->type = -1;
|
|
||||||
|
|
||||||
return BH_OK;
|
return BH_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user