-
Bignum math: comparison
I have a bug in my comparison code but I'm struggling to spot it, I'm hoping that someone here can:
Code:
int mcc__int_op_cmp( mcc_int_t const * const num, mcc_int_t const * const val ) {
mcc_bit_t n = {0}, v = {0};
mcc_int_seg_t nb = 0, vb = 0;
if ( num && num->zero.seg ) {
n = dec_for_bit(num->stop, num->zero);
nb = n.b - num->zero.b;
}
if ( val && val->zero.seg ) {
v = dec_for_bit(val->stop, val->zero);
vb = v.b - val->zero.b;
}
if ( !(n.bit) ) return v.bit ? -!!(*(v.seg) & v.bit) : 0;
if ( !(v.bit) ) return n.bit ? !!(*(n.seg) & n.bit) : 0;
if ( nb != vb ) return (nb > vb) ? 1 : -1;
while ( nb ) {
if ( nb ) {
n = dec_for_bit( n, num->zero );
nb = n.b - num->zero.b;
}
if ( vb ) {
v = dec_for_bit( v, val->zero );
vb = v.b - val->zero.b;
}
if ( nb != vb ) return ( nb > vb ) ? 1 : -1;
}
if ( !num || !val ) return nb ? 1 : -1;
return (!(*(n.seg) & n.bit) == !(*(v.seg) & v.bit));
}
#define mcc__int_is_nil( num ) ((mcc__int_op_cmp( num, NULL ) != 0))
#define mcc__int_is_eql( num, val ) (mcc__int_op_cmp( num, val ) == 0)
#define mcc__int_is_neq( num, val ) (mcc__int_op_cmp( num, val ) != 0)
#define mcc__int_is_gth( num, val ) (mcc__int_op_cmp( num, val ) > 0)
#define mcc__int_is_gte( num, val ) (mcc__int_op_cmp( num, val ) >= 0)
#define mcc__int_is_lth( num, val ) (mcc__int_op_cmp( num, val ) < 0)
#define mcc__int_is_lte( num, val ) (mcc__int_op_cmp( num, val ) <= 0)
This is my output using all the bignum functions I have:
Code:
gcc -Wall -o "bimath" "bimath.c" && "./bimath"
_num = 00000001, num = 00000000, b4 = 00000001, val = 00000000, _rem = 00000001, rem = 00000001 op = '!'
_num = 00000000, num = 00000000, b4 = 00000101, val = 00000001, _rem = 00000101, rem = 00000101 op = '=='
_num = 00000001, num = 00000001, b4 = 00000203, val = 00000002, _rem = 00000203, rem = 00000203 op = '!='
_num = 00000001, num = 00000001, b4 = 00000303, val = 00000003, _rem = 00000303, rem = 00000303 op = '>'
_num = 00000001, num = 00000001, b4 = 00000405, val = 00000004, _rem = 00000405, rem = 00000405 op = '>='
_num = 00000000, num = 00000000, b4 = 00000505, val = 00000005, _rem = 00000505, rem = 00000505 op = '<'
_num = 00000000, num = 00000000, b4 = 00000607, val = 00000006, _rem = 00000607, rem = 00000607 op = '<='
_num = 00038380, num = 00038380, b4 = 00000707, val = 00000007, _rem = 00000707, rem = 00000707 op = '<<'
_num = 00000008, num = 00000008, b4 = 00000809, val = 00000008, _rem = 00000809, rem = 00000809 op = '>>'
_num = 00000909, num = 00000909, b4 = 00000909, val = 00000009, _rem = 00000909, rem = 00000909 op = '|'
_num = 0000000A, num = 0000000A, b4 = 00000A0B, val = 0000000A, _rem = 00000A0B, rem = 00000A0B op = '&'
_num = 00000B00, num = 00000B00, b4 = 00000B0B, val = 0000000B, _rem = 00000B0B, rem = 00000B0B op = '^'
_num = 00000C19, num = 00000C19, b4 = 00000C0D, val = 0000000C, _rem = 00000C0D, rem = 00000C0D op = '+'
_num = 0000A9A9, num = 0000A9A9, b4 = 00000D0D, val = 0000000D, _rem = 00000D0D, rem = 00000D0D op = '*'
_num = 00000E01, num = 00000E01, b4 = 00000E0F, val = 0000000E, _rem = 00000E0F, rem = 00000E0F op = '-'
_num = 00000101, num = 00000101, b4 = 00000F0F, val = 0000000F, _rem = 00000000, rem = 00000000 op = '/'
_num = 00001011, num = 00001011, b4 = 00001011, val = 00000010, _rem = 00001011, rem = 00001011 op = '%'
Compilation finished successfully.
-
Whoops, noticed I used the wrong comparison on the is_nil() one, however that wasn't the bug I was getting at, had to re-order the comparisons so that the bug showed since I added in that is_nil() after I found the bug and hadn't tested the fix yet, here's the output with the bug showing:
Code:
gcc -Wall -o "bimath" "bimath.c" && "./bimath"
_num = 00000001, num = 00000000, b4 = 00000001, val = 00000000, _rem = 00000001, rem = 00000001 op = '=='
_num = 00000001, num = 00000001, b4 = 00000101, val = 00000001, _rem = 00000101, rem = 00000101 op = '!='
_num = 00000000, num = 00000000, b4 = 00000203, val = 00000002, _rem = 00000203, rem = 00000203 op = '!'
_num = 00000001, num = 00000001, b4 = 00000303, val = 00000003, _rem = 00000303, rem = 00000303 op = '>'
_num = 00000001, num = 00000001, b4 = 00000405, val = 00000004, _rem = 00000405, rem = 00000405 op = '>='
_num = 00000000, num = 00000000, b4 = 00000505, val = 00000005, _rem = 00000505, rem = 00000505 op = '<'
_num = 00000000, num = 00000000, b4 = 00000607, val = 00000006, _rem = 00000607, rem = 00000607 op = '<='
_num = 00038380, num = 00038380, b4 = 00000707, val = 00000007, _rem = 00000707, rem = 00000707 op = '<<'
_num = 00000008, num = 00000008, b4 = 00000809, val = 00000008, _rem = 00000809, rem = 00000809 op = '>>'
_num = 00000909, num = 00000909, b4 = 00000909, val = 00000009, _rem = 00000909, rem = 00000909 op = '|'
_num = 0000000A, num = 0000000A, b4 = 00000A0B, val = 0000000A, _rem = 00000A0B, rem = 00000A0B op = '&'
_num = 00000B00, num = 00000B00, b4 = 00000B0B, val = 0000000B, _rem = 00000B0B, rem = 00000B0B op = '^'
_num = 00000C19, num = 00000C19, b4 = 00000C0D, val = 0000000C, _rem = 00000C0D, rem = 00000C0D op = '+'
_num = 0000A9A9, num = 0000A9A9, b4 = 00000D0D, val = 0000000D, _rem = 00000D0D, rem = 00000D0D op = '*'
_num = 00000E01, num = 00000E01, b4 = 00000E0F, val = 0000000E, _rem = 00000E0F, rem = 00000E0F op = '-'
_num = 00000101, num = 00000101, b4 = 00000F0F, val = 0000000F, _rem = 00000000, rem = 00000000 op = '/'
_num = 00001011, num = 00001011, b4 = 00001011, val = 00000010, _rem = 00001011, rem = 00001011 op = '%'
Compilation finished successfully.
-
I finally fixed it, I changed the end of the function to this:
Code:
nb = (*(n.seg) & n.bit) ? 1 : 0;
vb = (*(v.seg) & v.bit) ? 1 : 0;
if ( nb != vb ) return (nb > vb) ? 1 : -1;
return 0;