add functions to convert to standard types
This commit is contained in:
178
bigint.h
178
bigint.h
@@ -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
191
utest.c
@@ -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();
|
||||
|
Reference in New Issue
Block a user