Thread: Comparison issues

  1. #1
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    549

    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

  2. #2
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    549
    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.
    Last edited by awsdert; 07-09-2019 at 10:44 AM.

  3. #3
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    549
    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
    Last edited by awsdert; 07-09-2019 at 12:08 PM. Reason: Copied case statment for greater than

  4. #4
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    549
    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
    Last edited by awsdert; 07-10-2019 at 02:35 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Pointer Comparison
    By atran in forum C Programming
    Replies: 10
    Last Post: 06-28-2015, 10:42 AM
  2. String Comparison Issues
    By xwielder in forum C# Programming
    Replies: 6
    Last Post: 05-16-2012, 04:39 PM
  3. what the comparison does?
    By dpp in forum C Programming
    Replies: 2
    Last Post: 12-12-2009, 04:20 PM
  4. std::string comparison versus int comparison
    By leeor_net in forum C++ Programming
    Replies: 3
    Last Post: 04-12-2009, 07:28 AM
  5. By comparison
    By kahli_mist in forum C++ Programming
    Replies: 5
    Last Post: 11-30-2005, 02:19 PM

Tags for this Thread