-
Comparison issues
Noticed a random comparison error from my function so I redid the function from scratch, seems the error shows up every time now:
Code:
make run (in directory: /media/lee/ZXUIJI_1TB/github/code)
gcc -o code.elf print.o predef.o chk.o add.o code.o open.o mem_inc.o shut.o init_and_term.o get.o bnum/bit.o bnum/cmp.o bnum/math.o bnum/div.o
./code.elf
Testing Integer Comparisons...
comparison( 846930886, '=', 1804289383 ) call 0
cycle_started 451; cycle_changed 452, cycle_stopped 453
num == val 0, 0
comparison( 1714636915, '!', 1681692777 ) call 1
cycle_started 455; cycle_changed 455, cycle_stopped 456
num != val 1, 1
comparison( 424238335, '>', 1957747793 ) call 2
cycle_started 457; cycle_changed 458, cycle_stopped 458
num >= val 0, 0
comparison( 1649760492, 'g', 719885386 ) call 3
cycle_started 460; cycle_changed 460, cycle_stopped 461
num > val 1, 0
code.c:234: comparison() r != t
Numerical argument out of domain
makefile:16: recipe for target 'run' failed
make: *** [run] Error 1
Compilation failed.
Function:
Code:
int bnum_compare( bnum_t const num, bnum_t const val ) {
int ret, nsb, vsb;
bit_t n, v;
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( num.sig_bit != val.sig_bit, return EINVAL; )
n = num.width;
v = val.width;
if ( num.sig_bit ) {
n = bit_op_dec(n);
v = bit_op_dec(v);
nsb = (num.value[n.node] & n.bit) ? 1 : 0;
vsb = (num.value[v.node] & v.bit) ? 1 : 0;
}
ret = nsb - vsb;
if ( ret != 0 )
return ret;
while ( n.b > v.b ) {
n = bit_op_dec(n);
ret = (num.value[n.node] & n.bit) ? 1 : 0;
if ( ret != nsb )
return 1;
}
while ( v.b > n.b ) {
v = bit_op_dec(v);
ret = (val.value[v.node] & v.bit) ? 1 : 0;
if ( ret != vsb )
return -1;
}
while ( n.b > 0 ) {
n = bit_op_dec(n);
v = bit_op_dec(v);
ret = (num.value[n.node] & n.bit) ? 1 : 0;
ret -= (val.value[n.node] & v.bit) ? 1 : 0;
if ( ret != 0 ) return ret;
}
return 0;
}
int bnum_op_##NAME( bnum_t const num, bnum_t const val ) \
{ \
int ret = bnum_compare( num, val ); \
if ( ret > 1 ) return ret; \
return ( ret OPERATOR 0 ); \
}
bnum_op_compare(eql,==)
bnum_op_compare(neq,!=)
bnum_op_compare(gth,>)
bnum_op_compare(gte,>=)
bnum_op_compare(lth,<)
bnum_op_compare(lte,<=)
#undef bnum_op_compare
Gonna be busy helping my neighbour soon so won't get much time to mull this myself, hoping someone else can spot what I can't
-
Seems it was & wasn't the function, here's the updated version:
Code:
int bnum_compare( bnum_t const num, bnum_t const val ) {
int ret, nsb = 0, vsb = 0;
bit_t n, v;
PRINT_IF_TRUE( (ret = bnum_mem_chk(num)) != 0, return ret; )
PRINT_IF_TRUE( (ret = bnum_mem_chk(val)) != 0, return ret; )
n = num.width;
v = val.width;
if ( num.sig_bit ) {
n = bit_op_dec(n);
nsb = (num.value[n.node] & n.bit) ? 1 : 0;
}
if ( val.sig_bit ) {
v = bit_op_dec(v);
vsb = (num.value[v.node] & v.bit) ? 1 : 0;
}
ret = nsb - vsb;
if ( ret != 0 )
return -ret;
while ( n.b > v.b ) {
n = bit_op_dec(n);
ret = (num.value[n.node] & n.bit) ? 1 : 0;
if ( ret != vsb )
return (vsb == 0) ? 1 : -1;
}
while ( v.b > n.b ) {
v = bit_op_dec(v);
vsb = (val.value[v.node] & v.bit) ? 1 : 0;
if ( ret != nsb )
return (nsb == 0) ? -1 : 1;
}
while ( n.b > 0 ) {
n = bit_op_dec(n);
v = bit_op_dec(v);
ret = (num.value[n.node] & n.bit) ? 1 : 0;
ret -= (val.value[v.node] & v.bit) ? 1 : 0;
/* This line appears to be the problem */
if ( ret != 0 ) return (nsb == 0) ? ret : -ret;
}
return 0;
}
#define bnum_op_compare( NAME, OPERATOR ) \
int bnum_op_##NAME( bnum_t const num, bnum_t const val ) \
{ \
int ret = bnum_compare( num, val ); \
if ( ret < -1 || ret > 1 ) return ret; \
return ( ret OPERATOR 0 ); \
}
bnum_op_compare(eql,==)
bnum_op_compare(neq,!=)
bnum_op_compare(gth,<)
bnum_op_compare(gte,>=)
bnum_op_compare(lth,>)
bnum_op_compare(lte,<=)
#undef bnum_op_compare
As you'll notice at the bottom I had tried changing the comparsion of the bnum_op_gth() function to the opposite one would expect there and got the expected result, only for it to then fail at bnum_op_lth() despite using the same tactic (which techinically means the function is operating both correct and incorrectly, correct because one would expect that from the opposing operator but incorrect BECAUSE it's using the wrong operator)
Any ideas on what to do would be appreciated (btw I have tried returning ret as it is, still same problem, just different variation)
Edit: Was gonna edit my original output with this but can't do that, I modified comparison() to give a bit more info and put the correct operators in the bnum_op_*() set:
Code:
make run (in directory: /media/lee/ZXUIJI_1TB/github/code/bnum)
gcc -o ../bnum/cmp.o -c ../bnum/cmp.c
gcc -o ../code.elf ../print.o ../predef.o ../chk.o ../add.o ../code.o ../open.o ../mem_inc.o ../shut.o ../init_and_term.o ../get.o ../bnum/bit.o ../bnum/cmp.o ../bnum/math.o ../bnum/div.o
./../code.elf
Testing Integer Comparisons...
comparison( 846930886, '=', 1804289383 ) call 0
cycle_started 498; cycle_changed 499, cycle_stopped 500
num == val 0, 0
comparison( 1714636915, '!', 1681692777 ) call 1
cycle_started 502; cycle_changed 503, cycle_stopped 503
num != val 1, 1
comparison( 424238335, '>', 1957747793 ) call 2
cycle_started 505; cycle_changed 505, cycle_stopped 506
num >= val 0, 0
comparison( 1649760492, 'g', 719885386 ) call 3
cycle_started 507; cycle_changed 508, cycle_stopped 508
num > val 1, 0
../code.c:245: comparison() r != t
r = 0b00000000000000000000000000000001, num = 0b01100010010101010101100011101100
t = 0b00000000000000000000000000000000, val = 0b00101010111010001001010001001010
Numerical argument out of domain
../makefile:16: recipe for target 'run' failed
make: *** [run] Error 1
Compilation failed.
-
Ok I found the REAL root of the issue, somehow the values it's supposed to be comparing get overwritten in between passing the comparison, I've just tried dedicated variables and it's still happening:
Code:
int comparison( int num, int op, int val ) {
static int i = 0;
int r = num, t = num, ret = 0, _num = num, _val = val;
bnum_t
n = int2bnum(&_num, sizeof(int), 1),
v = int2bnum(&_val, sizeof(int), 1);
clock_t cycle_started = 0, cycle_changed = 0, cycle_stopped = 0;
PRINT_IF_TRUE( (ret = bnum_mem_chk(n)) != 0, return ret; )
PRINT_IF_TRUE( (ret = bnum_mem_chk(n)) != 0, return ret; )
PRINT_IF_TRUE( n.value != (bitn_t*)&_num, return EFAULT; )
PRINT_IF_TRUE( v.value != (bitn_t*)&_val, return EFAULT; )
(void)printf("comparison( %d, '%c', %d ) call %d\n", num, op, val, i++ );
/* For accurate benchmark results that do NOT
* include the case checking time the individual
* cases must have the time recorded instead of putting
* arround the switch statement */
switch ( op ) {
case '=':
cycle_started = clock(); r = (num == val);
cycle_changed = clock(); t = bnum_op_eql( n, v );
cycle_stopped = clock();
break;
...
case 'g':
cycle_started = clock(); r = (num > val);
cycle_changed = clock(); t = bnum_op_gth( n, v );
cycle_stopped = clock();
break;
...
Code:
...
comparison( 424238335, '>', 1957747793 ) call 2
../bnum/cmp.c:97: bnum_compare() ret > 0
num.value[3] 0b00000000000000000000000000000000
val.value[3] 0b00000000000000000000000111000001
cycle_started 448; cycle_changed 449, cycle_stopped 451
num >= val 0, 1
code.c:243: comparison() r != t
r = 0b00000000000000000000000000000000, num = 0b00011001010010010101110011111111
t = 0b00000000000000000000000000000001, val = 0b01110100101100001101110001010001
Numerical argument out of domain
../makefile:16: recipe for target 'run' failed
make: *** [run] Error 1
Compilation failed.
Edit 1: Accidental newline character removed from output
Edit 2: Copied case statment for greater than
-
I decided I wasn't getting enough info from that output so I made a function to print all the details of a bnum passed to it and shoved a couple of calls to it in bnum_mem_dup() after trying to find where it was losing information needed, this is the result:
Code:
make run (in directory: /media/lee/ZXUIJI_1TB/github/code/bnum)
gcc -o ../code.elf ../print.o ../predef.o ../chk.o ../add.o ../code.o ../open.o ../mem_inc.o ../shut.o ../init_and_term.o ../get.o ../bnum/bit.o ../bnum/cmp.o ../bnum/math.o ../bnum/div.o
./../code.elf
Testing Integer Comparisons...
comparison( 846930886, '=', 1804289383 ) call 1
print_bnum_info() num.value = (nil)
print_bnum_info() num.sig_bit = 1
print_bnum_info() num.start.b = 0
print_bnum_info() num.start.node = 0
print_bnum_info() num.start.bit = 0000000000000001
print_bnum_info() num.width.b = 32
print_bnum_info() num.width.node = 4
print_bnum_info() num.width.bit = 0000000000000001
print_bnum_info() num.array.block = (nil)
print_bnum_info() num.array.bytes = 0
print_bnum_info() num.array.Nsize = 8
print_bnum_info() num.array.total = 0
print_bnum_info() num.array.count = 0
print_bnum_info() num.array.o.block.block = (nil)
print_bnum_info() num.array.o.block.bytes = 0
print_bnum_info() num.array.o.count.Nsize = 8
print_bnum_info() num.array.o.count.total = 0
print_bnum_info() num.array.o.count.count = 0
print_bnum_info() val.value = 0x7ffef0e8a684
print_bnum_info() val.sig_bit = 1
print_bnum_info() val.start.b = 0
print_bnum_info() val.start.node = 0
print_bnum_info() val.start.bit = 0000000000000001
print_bnum_info() val.width.b = 32
print_bnum_info() val.width.node = 4
print_bnum_info() val.width.bit = 0000000000000001
print_bnum_info() val.array.block = 0x7ffef0e8a684
print_bnum_info() val.array.bytes = 4
print_bnum_info() val.array.Nsize = 8
print_bnum_info() val.array.total = 1
print_bnum_info() val.array.count = 1
print_bnum_info() val.array.o.block.block = 0x7ffef0e8a684
print_bnum_info() val.array.o.block.bytes = 4
print_bnum_info() val.array.o.count.Nsize = 8
print_bnum_info() val.array.o.count.total = 1
print_bnum_info() val.array.o.count.count = 1
/media/lee/ZXUIJI_1TB/github/code/bnum/../mem_inc.c:26: array_mem_inc() !items
/media/lee/ZXUIJI_1TB/github/code/bnum/../bnum/bit.c:59: bnum_mem_dup() (ret = bnum_mem_inc( num, val.array.total )) != 0
/media/lee/ZXUIJI_1TB/github/code/bnum/../bnum/cmp.c:33: bnum_compare_by_sub() (ret = bnum_mem_dup(&cpy,num)) != 0
/media/lee/ZXUIJI_1TB/github/code/bnum/../bnum/cmp.c:119: bnum_op_eql() ret < -1 || ret > 1
/media/lee/ZXUIJI_1TB/github/code/bnum/../code.c:224: comparison() (t < 0 || t > 1)
Invalid argument
../makefile:18: recipe for target 'run' failed
make: *** [run] Error 1
Compilation failed.
A copy/paste of the calls in bnum_mem_dup():
Code:
print_bnum_info(*num,"num");
print_bnum_info(val,"val");
PRINT_IF_TRUE( (ret = bnum_mem_inc( num, val.array.total )) != 0, {
if ( num->value )
free( num->value );
return ret;
})
copy/paste of the start in bnum_mem_inc()
Code:
int array_mem_inc( array_t *array, uw items ) {
int ret;
PRINT_IF_TRUE( !array, return EFAULT; )
PRINT_IF_TRUE( !items, return EINVAL; )
...
int bnum_mem_inc( bnum_t *bnum, size_t bits ) {
return array_mem_inc((array_t*)bnum, bits / B_WIDTH);
}
Any ideas how "items" ends up as 0 despite being passed a 1?
Edit: Realised I copy/pasted the wrong function start, left it there since it was kinda relevant, as a result of that however I now noticed I forgot how bnum_mem_inc() was supposed to be used, correcting that now