add functions to convert to standard types

This commit is contained in:
John Regan
2023-04-02 16:17:57 -04:00
parent 10c6ae2dd7
commit e965c31ec4
2 changed files with 369 additions and 0 deletions

178
bigint.h
View File

@@ -143,6 +143,57 @@ int bigint_from_string(bigint* b, const char* str, size_t len, unsigned int base
BIGINT_API
int bigint_from_cstring(bigint* b, const char* str, unsigned int base);
BIGINT_API
int bigint_from_u8(bigint* b, uint8_t val);
BIGINT_API
int bigint_from_i8(bigint* b, int8_t val);
BIGINT_API
int bigint_from_u16(bigint* b, uint16_t val);
BIGINT_API
int bigint_from_i16(bigint* b, int16_t val);
BIGINT_API
int bigint_from_u32(bigint* b, uint32_t val);
BIGINT_API
int bigint_from_i32(bigint* b, int32_t val);
BIGINT_API
int bigint_from_u64(bigint* b, uint64_t val);
BIGINT_API
int bigint_from_i64(bigint* b, int64_t val);
/* bigint_to functions return 0 on success, 1 if the
* bigint won't fit into the type */
BIGINT_API
int bigint_to_u8(uint8_t *val, const bigint* b);
BIGINT_API
int bigint_to_i8(int8_t *val, const bigint* b);
BIGINT_API
int bigint_to_u16(uint16_t * val, const bigint* b);
BIGINT_API
int bigint_to_i16(int16_t * val, const bigint* b);
BIGINT_API
int bigint_to_u32(uint32_t * val, const bigint* b);
BIGINT_API
int bigint_to_i32(int32_t * val, const bigint* b);
BIGINT_API
int bigint_to_u64(uint64_t * val, const bigint* b);
BIGINT_API
int bigint_to_i64(int64_t * val, const bigint* b);
BIGINT_API
size_t bigint_to_string(char* str, size_t len, const bigint* b, unsigned int base);
@@ -186,6 +237,7 @@ int bigint_rshift_overwrite(bigint* a, size_t bits);
BIGINT_API
void bigint_div_mod_word(bigint* numerator, bigint_word* remainder, bigint_word denominator);
#ifdef __cplusplus
}
#endif
@@ -1121,12 +1173,14 @@ int bigint_copy(bigint *dest, const bigint *src) {
BIGINT_API
int bigint_from_word(bigint* b, bigint_word val) {
bigint_reset(b);
if(!val) return 0;
return bigint_append(b,val);
}
BIGINT_API
int bigint_from_u8(bigint* b, uint8_t val) {
bigint_reset(b);
if(!val) return 0;
return bigint_append(b, (bigint_word)(val & BIGINT_WORD_MASK) );
}
@@ -1134,6 +1188,7 @@ BIGINT_API
int bigint_from_u16(bigint* b, uint16_t val) {
int r;
bigint_reset(b);
if(!val) return 0;
#if BIGINT_WORD_WIDTH < 2
while(val) {
r = bigint_append(b, (bigint_word)(val & BIGINT_WORD_MASK));
@@ -1150,6 +1205,7 @@ BIGINT_API
int bigint_from_u32(bigint* b, uint32_t val) {
int r;
bigint_reset(b);
if(!val) return 0;
#if BIGINT_WORD_WIDTH < 4
while(val) {
r = bigint_append(b, (bigint_word)(val & BIGINT_WORD_MASK));
@@ -1166,6 +1222,7 @@ BIGINT_API
int bigint_from_u64(bigint* b, uint64_t val) {
int r;
bigint_reset(b);
if(!val) return 0;
#if BIGINT_WORD_WIDTH < 8
while(val) {
r = bigint_append(b, (bigint_word)(val & BIGINT_WORD_MASK));
@@ -1222,6 +1279,127 @@ int bigint_from_i64(bigint* b, int64_t val) {
return 0;
}
static inline
uint64_t bigint_to_u64_internal(const bigint* b) {
uint64_t tmp = 0;
size_t i = b->size;
#if BIGINT_WORD_WIDTH == 8
if(i) tmp = b->words[0];
#else
while(i--) {
tmp <<= BIGINT_WORD_BIT;
tmp += b->words[i] & BIGINT_WORD_MASK;
}
#endif
return tmp;
}
BIGINT_API
int bigint_to_u8(uint8_t *val, const bigint* b) {
uint64_t tmp = 0;
if(bigint_bitlength(b) > 8) return 1;
if(b->size) {
tmp = bigint_to_u64_internal(b);
}
*val = (uint8_t)tmp;
return 0;
}
BIGINT_API
int bigint_to_i8(int8_t *val, const bigint* b) {
uint8_t tmp = 0;
uint8_t max = INT8_MAX;
int r = 0;
if( (r = bigint_to_u8(&tmp,b)) != 0) return r;
max += !!b->sign;
if(tmp > max) return 1;
*val = b->sign ? -tmp : tmp;
return 0;
}
BIGINT_API
int bigint_to_u16(uint16_t *val, const bigint* b) {
uint64_t tmp = 0;
if(bigint_bitlength(b) > 16) return 1;
if(b->size) {
tmp = bigint_to_u64_internal(b);
}
*val = (uint16_t)tmp;
return 0;
}
BIGINT_API
int bigint_to_i16(int16_t *val, const bigint* b) {
uint16_t tmp = 0;
uint16_t max = INT16_MAX;
int r = 0;
if( (r = bigint_to_u16(&tmp,b)) != 0) return r;
max += !!b->sign;
if(tmp > max) return 1;
*val = b->sign ? -tmp : tmp;
return 0;
}
BIGINT_API
int bigint_to_u32(uint32_t *val, const bigint* b) {
uint64_t tmp = 0;
if(bigint_bitlength(b) > 32) return 1;
if(b->size) {
tmp = bigint_to_u64_internal(b);
}
*val = (uint32_t)tmp;
return 0;
}
BIGINT_API
int bigint_to_i32(int32_t *val, const bigint* b) {
uint32_t tmp = 0;
uint32_t max = INT32_MAX;
int r = 0;
if( (r = bigint_to_u32(&tmp,b)) != 0) return r;
max += !!b->sign;
if(tmp > max) return 1;
*val = b->sign ? -tmp : tmp;
return 0;
}
BIGINT_API
int bigint_to_u64(uint64_t *val, const bigint* b) {
uint64_t tmp = 0;
if(bigint_bitlength(b) > 64) return 1;
if(b->size) {
tmp = bigint_to_u64_internal(b);
}
*val = (uint64_t)tmp;
return 0;
}
BIGINT_API
int bigint_to_i64(int64_t *val, const bigint* b) {
uint64_t tmp = 0;
uint64_t max = INT64_MAX;
int r = 0;
if( (r = bigint_to_u64(&tmp,b)) != 0) return r;
max += !!b->sign;
if(tmp > max) return 1;
*val = b->sign ? -tmp : tmp;
return 0;
}
static
int bigint_add_signed(bigint* c, const bigint* a, size_t a_sign, const bigint* b, size_t b_sign) {
int r;

191
utest.c
View File

@@ -2505,6 +2505,17 @@ UTEST(bigint,from_int16) {
ASSERT_WEQ(a.words[0],0x8000);
#endif
ASSERT_EQ(bigint_from_i16(&a,INT16_MAX),0);
ASSERT_EQ(a.sign,(size_t)0);
#if BIGINT_WORD_WIDTH == 1
ASSERT_WEQ(a.size,2);
ASSERT_WEQ(a.words[0],0xFF);
ASSERT_WEQ(a.words[1],0x7F);
#else
ASSERT_WEQ(a.size,1);
ASSERT_WEQ(a.words[0],0x7FFF);
#endif
bigint_free(&a);
}
@@ -2643,4 +2654,184 @@ UTEST(bigint,cmp) {
CLEANUP
}
UTEST(bigint,to_uint8) {
PREAMBLE;
uint8_t val = 255;
ASSERT_EQ(bigint_from_u8(&a,0),0);
ASSERT_EQ(bigint_to_u8(&val,&a),0);
ASSERT_EQ(val,0);
ASSERT_EQ(bigint_from_u8(&a,255),0);
ASSERT_EQ(bigint_to_u8(&val,&a),0);
ASSERT_EQ(val,255);
ASSERT_EQ(bigint_inc(&a,&a),0);
ASSERT_EQ(bigint_to_u8(&val,&a),1);
CLEANUP;
}
UTEST(bigint,to_int8) {
PREAMBLE;
int8_t val = 0x7F;
ASSERT_EQ(bigint_from_u8(&a,0),0);
ASSERT_EQ(bigint_to_i8(&val,&a),0);
ASSERT_EQ(val,0);
ASSERT_EQ(bigint_from_u8(&a,0x7F),0);
ASSERT_EQ(bigint_to_i8(&val,&a),0);
ASSERT_EQ(val,0x7F);
ASSERT_EQ(bigint_inc(&a,&a),0);
ASSERT_EQ(bigint_to_i8(&val,&a),1);
a.sign = 1;
ASSERT_EQ(bigint_to_i8(&val,&a),0);
ASSERT_EQ(val,-0x80);
ASSERT_EQ(bigint_dec(&a,&a),0);
ASSERT_EQ(bigint_to_i8(&val,&a),1);
CLEANUP;
}
UTEST(bigint,to_uint16) {
PREAMBLE;
uint16_t val = UINT16_MAX;
ASSERT_EQ(bigint_from_u16(&a,0),0);
ASSERT_EQ(bigint_to_u16(&val,&a),0);
ASSERT_EQ(val,0);
ASSERT_EQ(bigint_from_u16(&a,UINT16_MAX),0);
ASSERT_EQ(bigint_to_u16(&val,&a),0);
ASSERT_EQ(val,UINT16_MAX);
ASSERT_EQ(bigint_inc(&a,&a),0);
ASSERT_EQ(bigint_to_u16(&val,&a),1);
CLEANUP;
}
UTEST(bigint,to_int16) {
PREAMBLE;
int16_t val = INT16_MAX;
ASSERT_EQ(bigint_from_u16(&a,0),0);
ASSERT_EQ(bigint_to_i16(&val,&a),0);
ASSERT_EQ(val,0);
ASSERT_EQ(bigint_from_u16(&a,INT16_MAX),0);
ASSERT_EQ(bigint_to_i16(&val,&a),0);
ASSERT_EQ(val,INT16_MAX);
ASSERT_EQ(bigint_inc(&a,&a),0);
ASSERT_EQ(bigint_to_i16(&val,&a),1);
a.sign = 1;
ASSERT_EQ(bigint_to_i16(&val,&a),0);
ASSERT_EQ(val,INT16_MIN);
ASSERT_EQ(bigint_dec(&a,&a),0);
ASSERT_EQ(bigint_to_i16(&val,&a),1);
CLEANUP;
}
UTEST(bigint,to_uint32) {
PREAMBLE;
uint32_t val = UINT32_MAX;
ASSERT_EQ(bigint_from_u32(&a,0),0);
ASSERT_EQ(bigint_to_u32(&val,&a),0);
ASSERT_WEQ(val,0);
ASSERT_EQ(bigint_from_u32(&a,UINT32_MAX),0);
ASSERT_EQ(bigint_to_u32(&val,&a),0);
ASSERT_EQ(val,UINT32_MAX);
ASSERT_EQ(bigint_inc(&a,&a),0);
ASSERT_EQ(bigint_to_u32(&val,&a),1);
CLEANUP;
}
UTEST(bigint,to_int32) {
PREAMBLE;
int32_t val = INT32_MAX;
ASSERT_EQ(bigint_from_u32(&a,0),0);
ASSERT_EQ(bigint_to_i32(&val,&a),0);
ASSERT_EQ(val,0);
ASSERT_EQ(bigint_from_u32(&a,INT32_MAX),0);
ASSERT_EQ(bigint_to_i32(&val,&a),0);
ASSERT_EQ(val,INT32_MAX);
ASSERT_EQ(bigint_inc(&a,&a),0);
ASSERT_EQ(bigint_to_i32(&val,&a),1);
a.sign = 1;
ASSERT_EQ(bigint_to_i32(&val,&a),0);
ASSERT_EQ(val,INT32_MIN);
ASSERT_EQ(bigint_dec(&a,&a),0);
ASSERT_EQ(bigint_to_i32(&val,&a),1);
CLEANUP;
}
UTEST(bigint,to_uint64) {
PREAMBLE;
uint64_t val = UINT64_MAX;
ASSERT_EQ(bigint_from_u64(&a,0),0);
ASSERT_EQ(bigint_to_u64(&val,&a),0);
ASSERT_WEQ(val,0);
ASSERT_EQ(bigint_from_u64(&a,UINT64_MAX),0);
ASSERT_EQ(bigint_to_u64(&val,&a),0);
ASSERT_EQ(val,UINT64_MAX);
ASSERT_EQ(bigint_inc(&a,&a),0);
ASSERT_EQ(bigint_to_u64(&val,&a),1);
CLEANUP;
}
UTEST(bigint,to_int64) {
PREAMBLE;
int64_t val = INT64_MAX;
ASSERT_EQ(bigint_from_u64(&a,0),0);
ASSERT_EQ(bigint_to_i64(&val,&a),0);
ASSERT_EQ(val,0);
ASSERT_EQ(bigint_from_u64(&a,INT64_MAX),0);
ASSERT_EQ(bigint_to_i64(&val,&a),0);
ASSERT_EQ(val,INT64_MAX);
ASSERT_EQ(bigint_inc(&a,&a),0);
ASSERT_EQ(bigint_to_i64(&val,&a),1);
a.sign = 1;
ASSERT_EQ(bigint_to_i64(&val,&a),0);
ASSERT_EQ(val,INT64_MIN);
ASSERT_EQ(bigint_dec(&a,&a),0);
ASSERT_EQ(bigint_to_i64(&val,&a),1);
CLEANUP;
}
UTEST_MAIN();