From baf8d6669df641b8eec4bec75ad51eb94103e644 Mon Sep 17 00:00:00 2001 From: Simon Brooke Date: Fri, 15 Feb 2019 18:48:30 +0000 Subject: [PATCH] OK, it is BETTER, but not FIXED. (expt 2 63) goes weirdly wrong - returns T. Internal representation is correct, so fault is in print. --- src/arith/integer.c | 70 ++++++++++++++++++++------------------------- 1 file changed, 31 insertions(+), 39 deletions(-) diff --git a/src/arith/integer.c b/src/arith/integer.c index db6f71c..1b2667c 100644 --- a/src/arith/integer.c +++ b/src/arith/integer.c @@ -240,7 +240,10 @@ struct cons_pointer append_digit( struct cons_pointer partial, struct cons_point /** * Return a pointer to an integer representing the product of the integers * pointed to by `a` and `b`. If either isn't an integer, will return nil. - * \todo it is MUCH more complicated than this! + * + * Yes, this is one of Muhammad ibn Musa al-Khwarizmi's original recipes, so + * you'd think it would be easy; the reason that each step is documented is + * because I did not find it so. * * @param a an integer; * @param b an integer. @@ -339,38 +342,28 @@ 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 ) { + int base ) { struct cons_pointer result = NIL; - struct cons_space_object integer = pointer2cell( int_pointer ); - __int128_t accumulator = llabs( integer.payload.integer.value ); - bool is_negative = integer.payload.integer.value < 0; - int digits = 0; - if ( accumulator == 0 && nilp( integer.payload.integer.more ) ) { - result = c_string_to_lisp_string( L"0" ); - } else { - while ( accumulator > 0 || !nilp( integer.payload.integer.more ) ) { - if ( !nilp( integer.payload.integer.more ) ) { - integer = pointer2cell( integer.payload.integer.more ); - accumulator += integer.payload.integer.value; - debug_print - ( L"integer_to_string: crossing cell boundary, accumulator is: ", - DEBUG_IO ); - debug_print_128bit( accumulator, DEBUG_IO ); - debug_println( DEBUG_IO ); - } + if ( integerp( int_pointer ) ) { + struct cons_pointer next = pointer2cell( int_pointer ).payload.integer.more; + __int128_t accumulator = llabs( pointer2cell( int_pointer ).payload.integer.value ); + bool is_negative = pointer2cell( int_pointer ).payload.integer.value < 0; + int digits = 0; - do { + if ( accumulator == 0 && nilp( next ) ) { + result = c_string_to_lisp_string( L"0" ); + } else { + while ( accumulator > 0 || !nilp( next ) ) { + if ( accumulator < MAX_INTEGER && !nilp( next ) ) { + accumulator += (pointer2cell(next).payload.integer.value << 60); + next = pointer2cell(next).payload.integer.more; + } int offset = ( int ) ( accumulator % base ); debug_printf( DEBUG_IO, - L"integer_to_string: digit is %ld, hexadecimal is %c, accumulator is: ", - 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_print( L"; result is: ", DEBUG_IO ); debug_print_object( result, DEBUG_IO ); @@ -379,20 +372,19 @@ struct cons_pointer integer_to_string( struct cons_pointer int_pointer, result = integer_to_string_add_digit( offset, ++digits, result ); accumulator = accumulator / base; - } while ( accumulator > base ); - } + } - if ( stringp( result ) - && pointer2cell( result ).payload.string.character == L',' ) { - /* if the number of digits in the string is divisible by 3, there will be - * an unwanted comma on the front. */ - struct cons_pointer tmp = result; - result = pointer2cell( result ).payload.string.cdr; - //dec_ref( tmp ); - } + if ( stringp( result ) + && pointer2cell( result ).payload.string.character == L',' ) { + /* if the number of digits in the string is divisible by 3, there will be + * an unwanted comma on the front. */ + result = pointer2cell( result ).payload.string.cdr; + } - if ( is_negative ) { - result = make_string( L'-', result ); + + if ( is_negative ) { + result = make_string( L'-', result ); + } } }