[Aldor-l] The smallest machine integer is "-"

Christian Aistleitner tmgisi at gmx.at
Mon Mar 5 05:16:04 EST 2007


Hello Ralf,

On Sun, 04 Mar 2007 16:06:58 +0100, Ralf Hemmecke <ralf at hemmecke.de> wrote:

> The smallest machine integer is printed as "-".

I think I reported something like that years ago, sadly enough I cannot
find the bug report.

However, as the aldor.org people are stepping forward with a new release,
let me support them with the bug fix I wrote back then.

For 32bit machines min$MachineInteger is -2147483648 while
max$MachineInteger is 2147483647. That's what can be expected from the way
integers are typically represented within computers, so that's ok.

However, << of MachineInteger comes down to print$IntegerTypeTools. There,
the treatment of negative numbers goes as follows

    if x < 0 then {
      p := p << minus;
      x := -x;
    }

After the if statement, x should hold the absolute value af x's original
value. However, if x is min$MachineInteger before the if statement, x is
still min$MachineInteger after the if statement, because of an overflow.
This overflow is inherent to the format used for number specification.

The implicit assumption that x is positive after the if statement fails.

I propose to perform one division step before negating x. Then -x <
max$MachineInteger and it can be savely inverted. I shifted the
declaration of l and introduced one anticipatory division step. Finally, I
added an assert. This converts print$IntegerTypeTools to the following
function:

    print(x:T, base:T, p:TextWriter):TextWriter == {
      macro REC == Record(digit:Character, next:Pointer);
      import from Boolean, Character, REC;
      zero? x => p << char 48;
      l:REC := nil;
      if x < 0 then {
        p := p << minus;
        -- this brought forward division step
        -- compensates for
        -- -min$MachineInteger > max$MachineInteger
        (x, r) := divide(x, base);
        l := [digit (-r), l pretend Pointer];
        x := -x;
      }
      assert( x > 0 );
      while x > 0 repeat {
        (x, r) := divide(x, base);
        l := [digit r, l pretend Pointer];
      }
      while ~nil? l repeat {
        p := p << l.digit;
        l := l.next pretend REC;
      }
      p;
    }


For those, who need a quick fix can use Aldor's extend functionality. But
you have to be careful not to call <<$MachineInteger from the file you
extended it in. The attached part1.as implements the workaround. Due to
Aldor's extend, you have to use the overridden <<$MachineInteger from
another file, i.e.:part2.as.

Calling via

aldor -Fao -Fo -laldor part1.as && \
ar r libpart1.al part1.ao && \
ar r libpart1.a part1.o && \
aldor -Fx -lpart1 -laldor part2.as && \
./part2

gives

cc1: note: -fwritable-strings is deprecated; see documentation for details
cc1: note: -fwritable-strings is deprecated; see documentation for details
cc1: note: -fwritable-strings is deprecated; see documentation for details
-2147483648
0
1
2147483647

and demonstrates the working workaround.

Kind regards,
Christian
-------------- next part --------------
A non-text attachment was scrubbed...
Name: part1.as
Type: application/octet-stream
Size: 1192 bytes
Desc: not available
Url : http://aldor.org/pipermail/aldor-l_aldor.org/attachments/20070305/2e784848/attachment.obj 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: part2.as
Type: application/octet-stream
Size: 281 bytes
Desc: not available
Url : http://aldor.org/pipermail/aldor-l_aldor.org/attachments/20070305/2e784848/attachment-0001.obj 


More information about the Aldor-l mailing list