From 0f8bc990f24b9f7a8f6881d5f0b863c08a9afe1e Mon Sep 17 00:00:00 2001 From: Simon Brooke Date: Sat, 19 Jan 2019 16:24:59 +0000 Subject: [PATCH] Much investigation of bignum problems bignum multiply is still not working, but as bignum read and bignum divide depend on it, it's the problem to hit first. --- lisp/expt.lisp | 2 +- lisp/scratchpad.lisp | 48 +++++ lisp/scratchpad2.lisp | 84 +++++++++ src/arith/integer.c | 133 ++++++++------ src/arith/peano.c | 2 +- src/debug.c | 31 ++-- src/ops/read.c | 172 +++++++++--------- unit-tests/bignum-add.sh | 69 +++++-- ...does-it-break.sh => where-does-it-break.sh | 4 +- 9 files changed, 372 insertions(+), 173 deletions(-) create mode 100644 lisp/scratchpad.lisp create mode 100644 lisp/scratchpad2.lisp rename unit-tests/where-does-it-break.sh => where-does-it-break.sh (94%) diff --git a/lisp/expt.lisp b/lisp/expt.lisp index af1fff1..433b0ea 100644 --- a/lisp/expt.lisp +++ b/lisp/expt.lisp @@ -5,4 +5,4 @@ ((= x 1) n) (t (* n (expt n (- x 1))))))) -(expt 2 65) +(expt 2 60) diff --git a/lisp/scratchpad.lisp b/lisp/scratchpad.lisp new file mode 100644 index 0000000..494fe59 --- /dev/null +++ b/lisp/scratchpad.lisp @@ -0,0 +1,48 @@ +(set! i + (+ + 10000000000000000000 + 10000000000000000000 + 10000000000000000000 + 10000000000000000000 + 10000000000000000000 + 10000000000000000000 + 10000000000000000000 + 10000000000000000000 + 10000000000000000000 + 10000000000000000000)) + +(set! j (+ i i i i i i i i i i)) + +(set! k (+ j j j j j j j j j j)) + +(set! l (+ k k k k k k k k k k)) + +(set! m (+ l l l l l l l l l l)) + +(set! n (+ m m m m m m m m m m)) + +(set! o (+ n n n n n n n n n n)) + +(set! p (+ o o o o o o o o o o)) + +(set! q (+ p p p p p p p p p p)) + +(set! r (+ q q q q q q q q q q)) + +(set! s (+ r r r r r r r r r r)) + +(set! t (+ s s s s s s s s s s)) + +(set! u (+ t t t t t t t t t t)) + +(set! v (+ u u u u u u u u u u)) + +(set! x (+ v v v v v v v v v v)) + +(set! y (+ x x x x x x x x x x)) + +"we're OK to here: 10^36, which is below the 2^120 barrier so represented as two cells" +(inspect (set! z (+ y y y y y y y y y y))) + +"This blows up: 10^37, which is a three cell bignum." +(inspect (+ z z z z z z z z z z)) diff --git a/lisp/scratchpad2.lisp b/lisp/scratchpad2.lisp new file mode 100644 index 0000000..e608106 --- /dev/null +++ b/lisp/scratchpad2.lisp @@ -0,0 +1,84 @@ +"This demonstrates that although the print representation of three cell bignums blows up, the internal representation is sane" + +"We start by adding 8 copies of 2^60 - i.e. the first two-cell integer" + +(set! a + (+ + 1152921504606846976 + 1152921504606846976 + 1152921504606846976 + 1152921504606846976 + 1152921504606846976 + 1152921504606846976 + 1152921504606846976 + 1152921504606846976)) + +"Then repeatedly add eight copies of the previous generation" + +(set! b (+ a a a a a a a a)) + +(set! c (+ b b b b b b b b)) + +(set! d (+ c c c c c c c c)) + +(set! e (+ d d d d d d d d)) + +(set! f (+ e e e e e e e e)) + +(set! g (+ f f f f f f f f)) + +(set! h (+ g g g g g g g g)) + +(set! i (+ h h h h h h h h)) + +(set! j (+ i i i i i i i i)) + +(set! k (+ j j j j j j j j)) + +(set! l (+ k k k k k k k k)) + +(set! m (+ l l l l l l l l)) + +(set! n (+ m m m m m m m m)) + +(set! o (+ n n n n n n n n)) + +"p" +(set! p (+ o o o o o o o o)) + +"q" +(set! q (+ p p p p p p p p)) + +"r" +(set! r (+ q q q q q q q q)) + +"s" +(inspect + (set! s (+ r r r r r r r r))) + +"t - first three cell integer. Printing blows up here" +(inspect + (set! t (+ s s s s s s s s))) + +"u" +(inspect + (set! u (+ t t t t t t t t))) + +"v" +(inspect + (set! v (+ u u u u u u u u))) + +"w" +(inspect + (set! w (+ v v v v v v v v))) + +(inspect + (set! x (+ w w w w w w w w))) + +(inspect + (set! y (+ x x x x x x x x))) + +(inspect + (set! z (+ y y y y y y y y))) + +(inspect (+ z z z z z z z z)) diff --git a/src/arith/integer.c b/src/arith/integer.c index 1fb22f1..b5ed859 100644 --- a/src/arith/integer.c +++ b/src/arith/integer.c @@ -36,7 +36,7 @@ /** * hexadecimal digits for printing numbers. */ -const char * hex_digits = "0123456789ABCDEF"; +const char *hex_digits = "0123456789ABCDEF"; /* * Doctrine from here on in is that ALL integers are bignums, it's just @@ -95,6 +95,21 @@ struct cons_pointer make_integer( int64_t value, struct cons_pointer more ) { } +__int128_t cell_value( struct cons_pointer c, char op, bool is_first_cell ) { + long int val = nilp( c ) ? 0 : pointer2cell( c ).payload.integer.value; + long int carry = is_first_cell ? 0 : ( MAX_INTEGER + 1 ); + + __int128_t result = ( __int128_t ) integerp( c ) ? + ( val == 0 ) ? carry : val : op == '*' ? 1 : 0; + debug_printf( DEBUG_ARITH, + L"cell_value: raw value is %ld, op = '%c', is_first_cell = %s; returning ", + val, op, is_first_cell ? "true" : "false" ); + debug_print_128bit( result, DEBUG_ARITH ); + debug_println( DEBUG_ARITH ); + + return result; +} + /** * internal workings of both `add_integers` and `multiply_integers` (and * possibly, later, other operations. Apply the operator `op` to the @@ -106,26 +121,22 @@ struct cons_pointer make_integer( int64_t value, struct cons_pointer more ) { * up significantly WRONG, but the value in the more significant cell * ends up correct. */ struct cons_pointer operate_on_integers( struct cons_pointer a, - struct cons_pointer b, - char op) { + struct cons_pointer b, char op ) { struct cons_pointer result = NIL; struct cons_pointer cursor = NIL; __int128_t carry = 0; + bool is_first_cell = true; if ( integerp( a ) && integerp( b ) ) { debug_print( L"operate_on_integers: \n", DEBUG_ARITH ); debug_dump_object( a, DEBUG_ARITH ); - debug_printf( DEBUG_ARITH, L" %c \n", op); + debug_printf( DEBUG_ARITH, L" %c \n", op ); debug_dump_object( b, DEBUG_ARITH ); debug_println( DEBUG_ARITH ); while ( !nilp( a ) || !nilp( b ) || carry != 0 ) { - __int128_t av = - ( __int128_t ) integerp( a ) ? pointer2cell( a ). - payload.integer.value : op == '*' ? 1 : 0; - __int128_t bv = - ( __int128_t ) integerp( b ) ? pointer2cell( b ). - payload.integer.value : op == '*' ? 1 : 0; + __int128_t av = cell_value( a, op, is_first_cell ); + __int128_t bv = cell_value( b, op, is_first_cell ); /* slightly dodgy. `MAX_INTEGER` is substantially smaller than `LONG_MAX`, and * `LONG_MAX * LONG_MAX` =~ the maximum value for `__int128_t`. So if the carry @@ -135,57 +146,59 @@ struct cons_pointer operate_on_integers( struct cons_pointer a, */ __int128_t rv = NAN; - switch (op) { - case '*': - rv = av * bv * ((carry == 0) ? 1 : carry); - break; - case '+': - rv = av + bv + carry; - break; - } + switch ( op ) { + case '*': + rv = av * bv * ( ( carry == 0 ) ? 1 : carry ); + break; + case '+': + rv = av + bv + carry; + break; + } - debug_printf( DEBUG_ARITH, L"operate_on_integers: op = '%c'; av = ", op); - debug_print_128bit( av, DEBUG_ARITH); - debug_print( L"; bv = ", DEBUG_ARITH); - debug_print_128bit( bv, DEBUG_ARITH); - debug_print( L"; carry = ", DEBUG_ARITH); - debug_print_128bit( carry, DEBUG_ARITH); - debug_print( L"; rv = ", DEBUG_ARITH); - debug_print_128bit( rv, DEBUG_ARITH); - debug_print( L"\n", DEBUG_ARITH); + debug_printf( DEBUG_ARITH, + L"operate_on_integers: op = '%c'; av = ", op ); + debug_print_128bit( av, DEBUG_ARITH ); + debug_print( L"; bv = ", DEBUG_ARITH ); + debug_print_128bit( bv, DEBUG_ARITH ); + debug_print( L"; carry = ", DEBUG_ARITH ); + debug_print_128bit( carry, DEBUG_ARITH ); + debug_print( L"; rv = ", DEBUG_ARITH ); + debug_print_128bit( rv, DEBUG_ARITH ); + debug_print( L"\n", DEBUG_ARITH ); if ( MAX_INTEGER >= rv ) { - carry = 0; + carry = 0; } else { - // TODO: we're correctly detecting overflow, but not yet correctly - // handling it. - carry = rv >> 60; - debug_printf( DEBUG_ARITH, - L"operate_on_integers: 64 bit overflow; setting carry to %ld\n", - ( int64_t ) carry ); - rv &= MAX_INTEGER; + // TODO: we're correctly detecting overflow, but not yet correctly + // handling it. + carry = rv >> 60; + debug_printf( DEBUG_ARITH, + L"operate_on_integers: 64 bit overflow; setting carry to %ld\n", + ( int64_t ) carry ); + rv &= MAX_INTEGER; } struct cons_pointer tail = make_integer( ( int64_t ) rv, NIL ); if ( nilp( cursor ) ) { - cursor = tail; + cursor = tail; } else { - inc_ref( tail ); - /* yes, this is a destructive change - but the integer has not yet been released - * into the wild */ - struct cons_space_object *c = &pointer2cell( cursor ); - c->payload.integer.more = tail; - cursor = tail; + inc_ref( tail ); + /* yes, this is a destructive change - but the integer has not yet been released + * into the wild */ + struct cons_space_object *c = &pointer2cell( cursor ); + c->payload.integer.more = tail; + cursor = tail; } if ( nilp( result ) ) { - result = cursor; + result = cursor; } a = pointer2cell( a ).payload.integer.more; b = pointer2cell( b ).payload.integer.more; + is_first_cell = false; } } @@ -203,7 +216,7 @@ struct cons_pointer operate_on_integers( struct cons_pointer a, struct cons_pointer add_integers( struct cons_pointer a, struct cons_pointer b ) { - return operate_on_integers(a, b, '+'); + return operate_on_integers( a, b, '+' ); } /** @@ -212,7 +225,7 @@ struct cons_pointer add_integers( struct cons_pointer a, */ struct cons_pointer multiply_integers( struct cons_pointer a, struct cons_pointer b ) { - return operate_on_integers( a, b, '*'); + return operate_on_integers( a, b, '*' ); } /** @@ -221,7 +234,7 @@ struct cons_pointer multiply_integers( struct cons_pointer a, struct cons_pointer integer_to_string_add_digit( int digit, int digits, struct cons_pointer tail ) { digits++; - wint_t character = btowc(hex_digits[digit]); + wint_t character = btowc( hex_digits[digit] ); return ( digits % 3 == 0 ) ? make_string( L',', make_string( character, tail ) ) : @@ -239,6 +252,11 @@ struct cons_pointer integer_to_string_add_digit( int digit, int digits, * when we get to the last digit from one integer cell, we have potentially * to be looking to the next. H'mmmm. */ +/* + * TODO: this blows up when printing three-cell integers, but works fine + * for two-cell. What's happening is that when we cross the barrier we + * SHOULD print 2^120, but what we actually print is 2^117. H'mmm. + */ struct cons_pointer integer_to_string( struct cons_pointer int_pointer, int base ) { struct cons_pointer result = NIL; @@ -253,24 +271,27 @@ struct cons_pointer integer_to_string( struct cons_pointer int_pointer, while ( accumulator > 0 || !nilp( integer.payload.integer.more ) ) { if ( !nilp( integer.payload.integer.more ) ) { integer = pointer2cell( integer.payload.integer.more ); - accumulator += + accumulator += integer.payload.integer.value == 0 ? + MAX_INTEGER : ( llabs( integer.payload.integer.value ) * ( MAX_INTEGER + 1 ) ); + debug_print + ( L"integer_to_string: crossing cell boundary, accumulator is: ", + DEBUG_IO ); + debug_print_128bit( accumulator, DEBUG_IO ); + debug_println( DEBUG_IO ); } - debug_printf( DEBUG_IO, - L"integer_to_string: accumulator is %ld\n:", - accumulator ); do { - int offset = (int)(accumulator % base); + int offset = ( int ) ( accumulator % base ); debug_printf( DEBUG_IO, - L"integer_to_string: digit is %ld, hexadecimal is %c\n:", - offset, - hex_digits[offset] ); + L"integer_to_string: digit is %ld, hexadecimal is %c, accumulator is: ", + offset, hex_digits[offset] ); + debug_print_128bit( accumulator, DEBUG_IO ); + debug_println( DEBUG_IO ); result = - integer_to_string_add_digit( offset, digits++, - result ); + integer_to_string_add_digit( offset, digits++, result ); accumulator = accumulator / base; } while ( accumulator > base ); } diff --git a/src/arith/peano.c b/src/arith/peano.c index 1dded80..0dc2ed0 100644 --- a/src/arith/peano.c +++ b/src/arith/peano.c @@ -42,7 +42,7 @@ bool zerop( struct cons_pointer arg ) { switch ( cell.tag.value ) { case INTEGERTV: result = cell.payload.integer.value == 0 && - nilp(cell.payload.integer.more); + nilp( cell.payload.integer.more ); break; case RATIOTV: result = zerop( cell.payload.ratio.dividend ); diff --git a/src/debug.c b/src/debug.c index 392aa71..d694827 100644 --- a/src/debug.c +++ b/src/debug.c @@ -46,23 +46,24 @@ void debug_print( wchar_t *message, int level ) { * stolen from https://stackoverflow.com/questions/11656241/how-to-print-uint128-t-number-using-gcc */ void debug_print_128bit( __int128_t n, int level ) { - #ifdef DEBUG - if ( level & verbosity ) { - if (n == 0) { - fwprintf(stderr, L"0"); - } else { - char str[40] = {0}; // log10(1 << 128) + '\0' - char *s = str + sizeof(str) - 1; // start at the end - while (n != 0) { - if (s == str) return; // never happens +#ifdef DEBUG + if ( level & verbosity ) { + if ( n == 0 ) { + fwprintf( stderr, L"0" ); + } else { + char str[40] = { 0 }; // log10(1 << 128) + '\0' + char *s = str + sizeof( str ) - 1; // start at the end + while ( n != 0 ) { + if ( s == str ) + return; // never happens - *--s = "0123456789"[n % 10]; // save last digit - n /= 10; // drop it - } - fwprintf(stderr, L"%s", s); + *--s = "0123456789"[n % 10]; // save last digit + n /= 10; // drop it + } + fwprintf( stderr, L"%s", s ); + } } - } - #endif +#endif } /** diff --git a/src/ops/read.c b/src/ops/read.c index 4f866d6..6e2a07f 100644 --- a/src/ops/read.c +++ b/src/ops/read.c @@ -157,104 +157,108 @@ struct cons_pointer read_continuation( struct stack_frame *frame, * garbage is collected. */ struct cons_pointer read_number( struct stack_frame *frame, - struct cons_pointer frame_pointer, - FILE * input, - wint_t initial, bool seen_period ) { - debug_print( L"entering read_number\n", DEBUG_IO ); + struct cons_pointer frame_pointer, + FILE * input, + wint_t initial, bool seen_period ) { + debug_print( L"entering read_number\n", DEBUG_IO ); - struct cons_pointer result = make_integer( 0, NIL ); - /* TODO: we really need to be getting `base` from a privileged Lisp name - + struct cons_pointer result = make_integer( 0, NIL ); + /* TODO: we really need to be getting `base` from a privileged Lisp name - * and it should be the same privileged name we use when writing numbers */ - struct cons_pointer base = make_integer( 10, NIL ); - struct cons_pointer dividend = NIL; - int places_of_decimals = 0; - wint_t c; - bool neg = initial == btowc( '-' ); + struct cons_pointer base = make_integer( 10, NIL ); + struct cons_pointer dividend = NIL; + int places_of_decimals = 0; + wint_t c; + bool neg = initial == btowc( '-' ); - if ( neg ) { - initial = fgetwc( input ); - } - - debug_printf( DEBUG_IO, L"read_number starting '%c' (%d)\n", initial, - initial ); - - for ( c = initial; iswdigit( c ) - || c == L'.' || c == L'/' || c == L','; c = fgetwc( input ) ) { - switch (c) { - case L'.': - if ( seen_period || !nilp( dividend ) ) { - return throw_exception( c_string_to_lisp_string - ( L"Malformed number: too many periods" ), - frame_pointer ); - } else { - debug_print(L"read_number: decimal point seen\n", DEBUG_IO); - seen_period = true; - } - break; - case L'/': - if ( seen_period || !nilp( dividend ) ) { - return throw_exception( c_string_to_lisp_string - ( L"Malformed number: dividend of rational must be integer" ), - frame_pointer ); - } else { - debug_print(L"read_number: ratio slash seen\n", DEBUG_IO); - dividend = result; - - result = make_integer( 0, NIL ); - } - break; - case L',' : - // silently ignore it. - break; - default: - result = add_integers( multiply_integers( result, base ), - make_integer( ( int ) c - ( int ) '0', - NIL ) ); - - debug_printf( DEBUG_IO, - L"read_number: added character %c, result now ", c ); - debug_print_object( result, DEBUG_IO); - debug_print( L"\n", DEBUG_IO); - - if ( seen_period ) { - places_of_decimals++; - } + if ( neg ) { + initial = fgetwc( input ); } - } - /* + debug_printf( DEBUG_IO, L"read_number starting '%c' (%d)\n", initial, + initial ); + + for ( c = initial; iswdigit( c ) + || c == L'.' || c == L'/' || c == L','; c = fgetwc( input ) ) { + switch ( c ) { + case L'.': + if ( seen_period || !nilp( dividend ) ) { + return throw_exception( c_string_to_lisp_string + ( L"Malformed number: too many periods" ), + frame_pointer ); + } else { + debug_print( L"read_number: decimal point seen\n", + DEBUG_IO ); + seen_period = true; + } + break; + case L'/': + if ( seen_period || !nilp( dividend ) ) { + return throw_exception( c_string_to_lisp_string + ( L"Malformed number: dividend of rational must be integer" ), + frame_pointer ); + } else { + debug_print( L"read_number: ratio slash seen\n", + DEBUG_IO ); + dividend = result; + + result = make_integer( 0, NIL ); + } + break; + case L',': + // silently ignore it. + break; + default: + result = add_integers( multiply_integers( result, base ), + make_integer( ( int ) c - ( int ) '0', + NIL ) ); + + debug_printf( DEBUG_IO, + L"read_number: added character %c, result now ", + c ); + debug_print_object( result, DEBUG_IO ); + debug_print( L"\n", DEBUG_IO ); + + if ( seen_period ) { + places_of_decimals++; + } + } + } + + /* * push back the character read which was not a digit */ - ungetwc( c, input ); + ungetwc( c, input ); - if ( seen_period ) { - debug_print(L"read_number: converting result to real\n", DEBUG_IO); - struct cons_pointer div = make_ratio( frame_pointer, result, - make_integer( powl - ( to_long_double - ( base ), - places_of_decimals ), - NIL ) ); - inc_ref( div ); + if ( seen_period ) { + debug_print( L"read_number: converting result to real\n", DEBUG_IO ); + struct cons_pointer div = make_ratio( frame_pointer, result, + make_integer( powl + ( to_long_double + ( base ), + places_of_decimals ), + NIL ) ); + inc_ref( div ); - result = make_real( to_long_double( div ) ); + result = make_real( to_long_double( div ) ); - dec_ref( div ); - } else if ( integerp( dividend ) ) { - debug_print(L"read_number: converting result to ratio\n", DEBUG_IO); - result = make_ratio( frame_pointer, dividend, result ); - } + dec_ref( div ); + } else if ( integerp( dividend ) ) { + debug_print( L"read_number: converting result to ratio\n", DEBUG_IO ); + result = make_ratio( frame_pointer, dividend, result ); + } - if ( neg ) { - debug_print(L"read_number: converting result to negative\n", DEBUG_IO); + if ( neg ) { + debug_print( L"read_number: converting result to negative\n", + DEBUG_IO ); - result = negative( frame_pointer, result ); - } + result = negative( frame_pointer, result ); + } - debug_print( L"read_number returning\n", DEBUG_IO ); - debug_dump_object( result, DEBUG_IO ); + debug_print( L"read_number returning\n", DEBUG_IO ); + debug_dump_object( result, DEBUG_IO ); - return result; + return result; } /** diff --git a/unit-tests/bignum-add.sh b/unit-tests/bignum-add.sh index 280eca9..7bbb41e 100755 --- a/unit-tests/bignum-add.sh +++ b/unit-tests/bignum-add.sh @@ -5,12 +5,12 @@ # (right on the boundary) a=1152921504606846975 b=1 -expected='1152921504606846976' -output=`echo "(+ $a $b)" | target/psse -v 2 2>psse.log` +c=`echo "$a + $b" | bc` +expected='t' +output=`echo "(= (+ $a $b) $c)" | target/psse -v 2 2>psse.log` actual=`echo $output |\ - tail -1 |\ - sed 's/\,//g'` + tail -1` echo -n "adding $a to $b: " if [ "${expected}" = "${actual}" ] @@ -36,8 +36,9 @@ fi # (just over the boundary) a='1152921504606846976' b=1 -expected='1152921504606846977' -output=`echo "(+ $a $b)" | target/psse -v 2 2>psse.log` +c=`echo "$a + $b" | bc` +expected='t' +output=`echo "(= (+ $a $b) $c)" | target/psse -v 2 2>psse.log` actual=`echo $output |\ tail -1 |\ @@ -62,13 +63,15 @@ else exit 1 fi + ##################################################################### # add a bignum and a smallnum to produce a bignum # (just over the boundary) a='1152921504606846977' b=1 -expected='1152921504606846978' -output=`echo "(+ $a $b)" | target/psse -v 2 2>psse.log` +c=`echo "$a + $b" | bc` +expected='t' +output=`echo "(= (+ $a $b) $c)" | target/psse -v 2 2>psse.log` actual=`echo $output |\ tail -1 |\ @@ -98,8 +101,9 @@ fi # (just over the boundary) a=1 b=1152921504606846977 -expected='1152921504606846978' -output=`echo "(+ $a $b)" | target/psse -v 2 2>psse.log` +c=`echo "$a + $b" | bc` +expected='t' +output=`echo "(= (+ $a $b) $c)" | target/psse -v 2 2>psse.log` actual=`echo $output |\ tail -1 |\ @@ -124,12 +128,14 @@ else exit 1 fi + ##################################################################### # add two bignums to produce a bignum a=10000000000000000000 b=10000000000000000000 -expected='20000000000000000000' -output=`echo "(+ $a $b)" | target/psse -v 2 2>psse.log` +c=`echo "$a + $b" | bc` +expected='t' +output=`echo "(= (+ $a $b) $c)" | target/psse -v 2 2>psse.log` actual=`echo $output |\ tail -1 |\ @@ -154,13 +160,15 @@ else exit 1 fi + ##################################################################### # add a smallnum and a two-cell bignum to produce a three-cell bignum # (just over the boundary) a=1 b=1329227995784915872903807060280344576 -expected='1329227995784915872903807060280344577' -output=`echo "(+ $a $b)" | target/psse -v 2 2>psse.log` +c=`echo "$a + $b" | bc` +expected='t' +output=`echo "(= (+ $a $b) $c)" | target/psse -v 2 2>psse.log` actual=`echo $output |\ tail -1 |\ @@ -185,3 +193,36 @@ else exit 1 fi + +##################################################################### +# This currently fails: +# (= (+ 1 3064991081731777716716694054300618367237478244367204352) +# 3064991081731777716716694054300618367237478244367204353) +a=1 +b=3064991081731777716716694054300618367237478244367204352 +c=`echo "$a + $b" | bc` +expected='t' +output=`echo "(= (+ $a $b) $c)" | target/psse -v 2 2>psse.log` + +actual=`echo $output |\ + tail -1 |\ + sed 's/\,//g'` + +echo -n "adding $a to $b: " +if [ "${expected}" = "${actual}" ] +then + echo "OK" +else + echo "Fail: expected '${expected}', got '${actual}'" + exit 1 +fi + +echo -n "checking a bignum was created: " +grep 'BIGNUM!' psse.log > /dev/null +if [ $? -eq "0" ] +then + echo "OK" +else + echo "Fail" + exit 1 +fi diff --git a/unit-tests/where-does-it-break.sh b/where-does-it-break.sh similarity index 94% rename from unit-tests/where-does-it-break.sh rename to where-does-it-break.sh index 5c51aca..4d70041 100755 --- a/unit-tests/where-does-it-break.sh +++ b/where-does-it-break.sh @@ -3,9 +3,9 @@ # Not really a unit test, but a check to see where bignum addition breaks broken=0 -i=1152921506900200000 +i=11529215046068469750 # we've already proven we can successfullu get up to here -increment=10000 +increment=1 while [ $broken -eq "0" ] do