Code:
#include "op.h"
int bnum_duvude( bnum_t num, bnum_t const val, bnum_t quo ) {
int ret;
bnum_t rem;
di width;
bit_t n, v;
ui overflow;
--overflow;
PRINT_IF_TRUE( num.sig_bit, return EINVAL; )
PRINT_IF_TRUE( val.sig_bit, return EINVAL; )
PRINT_IF_TRUE( quo.sig_bit, return EINVAL; )
PRINT_IF_TRUE( (ret = bnum_mem_chk(num)) != 0, return ret; )
PRINT_IF_TRUE( (ret = bnum_mem_chk(val)) != 0, return ret; )
PRINT_IF_TRUE( (ret = bnum_mem_chk(quo)) != 0, return ret; )
rem = num;
width = 0;
overflow = -1;
quo.sig_bit = 0;
ret = bnum_op_min(quo);
quo.sig_bit = num.sig_bit;
if ( bnum_op_nil(val) ) {
num.sig_bit = 0;
ret = bnum_op_min( num );
num.sig_bit = quo.sig_bit;
puts("bnum_divide() val == 0");
return ret;
}
/* num is made the remainder by the use of rem */
rem.start = rem.width;
rem.width.b = rem.start.b = 0;
/* The width helps clamp an inifinite division */
while ( rem.width.b < num.width.b &&
(ret = bnum_op_gte( num, val )) == 1 )
{
rem.start = bit_op_dec(rem.start);
rem.start.b = 0;
rem.width.b++;
PRINT_IF_TRUE( (ret = bnum_op_gte(rem,val)) > 1, return ret; )
if ( ret == 1 )
{
PRINT_IF_TRUE( (ret = bnum_op_sub(rem,val)) != 0, return ret; )
quo.value[rem.start.node] |= rem.start.bit;
}
}
PRINT_IF_TRUE( ret > 1, return ret; )
return bnum_op_shl_z(quo,width);
}
int bnum_divide( bnum_t num, bnum_t const val, bnum_t quo ) {
int ret;
bnum_t cpy;
if ( val.sig_bit ) {
PRINT_IF_TRUE( (ret = bnum_op_nil(val)) > 1 || ret < -1, return ret; )
if ( ret < 0 ) {
PRINT_IF_TRUE( (ret = bnum_mem_dup( &cpy, val )) != 0, return ret; )
PRINT_IF_TRUE( (ret = bnum_op_neg(cpy)) != 0, {} )
if ( ret == 0 ) {
cpy.sig_bit = 0;
PRINT_IF_TRUE( (ret = bnum_divide( num, cpy, quo )) != 0, {} )
}
bnum_mem_dec( &cpy, cpy.width.b );
return ret;
}
cpy = val;
cpy.sig_bit = 0;
return bnum_divide( num, cpy, quo );
}
if ( num.sig_bit ) {
PRINT_IF_TRUE( (ret = bnum_mem_chk(quo)) != 0, return ret; )
PRINT_IF_TRUE( (ret = bnum_op_nil(val)) > 1 || ret < -1, return ret; )
if ( ret < 0 ) {
PRINT_IF_TRUE( (ret = bnum_op_neg(num)) != 0, return ret; )
num.sig_bit = 0;
quo.sig_bit = 0;
PRINT_IF_TRUE( (ret = bnum_duvude( num, val, quo )) != 0, {} )
num.sig_bit = 1;
quo.sig_bit = 1;
(void)bnum_op_neg( num );
(void)bnum_op_neg( quo );
return ret;
}
num.sig_bit = 0;
quo.sig_bit = 0;
PRINT_IF_TRUE( (ret = bnum_duvude( num, val, quo )) != 0, {} )
num.sig_bit = 1;
quo.sig_bit = 1;
return ret;
}
return bnum_duvude( num, val, quo );
}
int bnum_op_div( bnum_t num, bnum_t const val ) {
int ret = bnum_mem_chk(num);
bnum_t cpy = num;
if ( ret != 0 ) return ret;
cpy.value = malloc( num.array.bytes );
if ( cpy.value ) {
ret = bnum_divide( num, val, cpy );
if ( ret != 0 ) {
free( cpy.value );
return ret;
}
ret = bnum_op_cpy( num, cpy );
free( cpy.value );
return ret;
}
return ENOMEM;
}
int bnum_op_mod( bnum_t num, bnum_t const val ) {
int ret = bnum_mem_chk(num);
bnum_t cpy = num;
if ( ret != 0 ) return ret;
cpy.value = malloc( num.array.bytes );
if ( cpy.value ) {
ret = bnum_divide( num, val, cpy );
free( cpy.value );
return ret;
}
return ENOMEM;
}