Fix big_cmp, big_divmod

master
Harald Wolff 2021-03-22 23:41:08 +01:00
parent b977fb217c
commit 8add210a38
2 changed files with 46 additions and 24 deletions

View File

@ -10,12 +10,10 @@ all: linux Darwin
clean:
rm -f ../ln.biginteger/libbigint.so ../ln.biginteger/libbigint.dylib ../ln.biginteger/libbigint.dll
distribute: ../ln.biginteger/libbigint.so
linux: ../ln.biginteger/libbigint.so
../ln.biginteger/libbigint.so: $(SRC)
gcc -shared -o ../ln.biginteger/libbigint.so $(SRC)
gcc -shared -o ../ln.biginteger/libbigint.so $(SRC) -fPIC
Darwin: ../ln.biginteger/libbigint.dylib
../ln.biginteger/libbigint.dylib: $(SRC)
gcc -shared -o ../ln.biginteger/libbigint.dylib $(SRC)
gcc -shared -o ../ln.biginteger/libbigint.dylib $(SRC) -fPIC

View File

@ -9,7 +9,15 @@ int32_t max(int32_t a,int32_t b)
return a>b ? a : b;
}
#define DUMP(op,l) for (int ___p = 0; ___p < l; ___p++) printf("0x%08x", op[___p]); printf("\n");
int32_t big_is_zero( uint32_t* op, int32_t length)
{
for (int n=0;n<length;n++)
if (op[n])
return 0;
return -1;
}
#define DUMP(op,l) for (int ___p = l-1; ___p >= 0; ___p--) printf("%08x", op[___p]); printf("\n");
int32_t big_get_bitlength(uint32_t *op, int32_t length)
{
@ -62,24 +70,6 @@ int32_t big_sign(uint32_t *op, int32_t length)
// }
// }
int32_t big_cmp(uint32_t* op_a, int32_t length_a, uint32_t* op_b, int32_t length_b)
{
int l = max(length_a, length_b);
for (int n=l-1; n >= 0; n--)
{
int a = n < length_a ? op_a[n] : 0;
int b = n < length_b ? op_b[n] : 0;
int d = a - b;
if (d > 0)
return 1;
else if (d < 0)
return -1;
}
return 0;
}
void big_shl(uint32_t *op, int32_t length, int32_t n)
{
if (n > 0)
@ -151,7 +141,7 @@ void big_add(uint32_t* op_a, int32_t length_a, uint32_t* op_b, int32_t length_b)
}
void big_sub(uint32_t* op_a, int32_t length_a, uint32_t* op_b, int32_t length_b)
{
uint64_t c = 0;
int64_t c = 0;
for (int n=0;n<length_a;n++)
{
c += (int64_t)op_a[n] - ((n < length_b) ? op_b[n] : 0);
@ -163,6 +153,21 @@ void big_sub(uint32_t* op_a, int32_t length_a, uint32_t* op_b, int32_t length_b)
}
}
int32_t big_cmp(uint32_t* op_a, int32_t length_a, uint32_t* op_b, int32_t length_b)
{
int32_t l = max(length_a, length_b);
uint32_t temp[l];
memcpy(temp, op_a, length_a << 2);
big_sub( temp, l, op_b, length_b );
if (temp[l-1] & 0x80000000)
return -1;
if (big_is_zero( temp, l ))
return 0;
return 1;
}
void big_twos(uint32_t *op, int32_t length)
{
for (int n=0;n<length;n++)
@ -221,11 +226,26 @@ void big_divmod(uint32_t* op_a, int32_t length_a, uint32_t* op_b, int32_t length
lg2b = big_get_bitlength(divisor, l);
shift = lg2a - lg2b;
// printf("big_divmod():\n");
// printf(" dividend = ");
// DUMP(dividend, l);
// printf(" divisor = ");
// DUMP(divisor, l);
if (shift > 0)
big_shl(divisor, l, shift);
// printf(" divisor (SHIFTED) = ");
// DUMP(divisor, l);
for (int n = 0; n <= (shift); n++)
{
// printf("+++\n");
// printf(" dividend = ");
// DUMP(dividend, l);
// printf(" divisor = ");
// DUMP(divisor, l);
big_shl(op_a, length_a, 1);
if (big_cmp( divisor, l, dividend, l ) <= 0)
@ -234,6 +254,9 @@ void big_divmod(uint32_t* op_a, int32_t length_a, uint32_t* op_b, int32_t length
big_sub( dividend, l, divisor, l );
}
// printf(" result = ");
// DUMP(op_a, length_a);
big_shr( divisor, l, 1);
}
@ -243,6 +266,7 @@ void big_divmod(uint32_t* op_a, int32_t length_a, uint32_t* op_b, int32_t length
big_twos(dividend, l);
memcpy( op_b, dividend, length_b << 2);
// printf("----------------------------------------\n");
}
int32_t big_parse(uint32_t* op, int32_t length, char *source, int32_t radix)