[m-dev.] Re: for review: big ints again
Fergus Henderson
fjh at cs.mu.OZ.AU
Fri Apr 10 00:40:42 AEST 1998
On 09-Apr-1998, Bert Thompson <aet at hydra.cs.mu.oz.au> wrote:
> Fergus Henderson <fjh at cs.mu.OZ.AU> writes:
>
> | > :- func int_to_integer(int) = integer.
> | > int_to_integer(D) = i(signum(D), pos_int_to_digits(AD)) :-
> | > int__abs(D, AD).
>
> |This function does the wrong thing for MININT.
> |(See, isn't code review wonderful? ;-)
>
> Well spotted. 8^)
>
> Here's the new diff.
...
> + % Note: Since most machines use 2's complement arithmetic,
> + % INT_MIN is usually -INT_MAX-1, hence -INT_MIN will
> + % cause int overflow. We handle overflow below.
> :- func int_to_integer(int) = integer.
> ! int_to_integer(D) = Int :-
> ! int__abs(D, AD),
> ! ( (AD < 0 ; AD=0, D \= 0) ->
> ! % int overflow occurred.
> ! D2 = D + int_max,
> ! Int = integer(D2) - integer(int_max)
> ! ;
> ! Int = i(signum(D), pos_int_to_digits(AD))
> ! ).
>
> ! :- func int_max = int.
> ! int_max = Maxint :-
> ! int:max_int(Maxint).
It would be better to explicitly test for int_min before calling
int__abs, because future implementations of Mercury might actually
trap int overflow, rather than just silently ignoring it.
Also it's enough to just add/subtract 1 rather than int_max.
(This is slightly simpler, IMHO, and may be very slightly more efficient.)
Thus I suggest the following code:
int_to_integer(D) = Int :-
( int__min_int(D) ->
% if we were to call int__abs, int overflow might occur
Int = integer(D + 1) - one
;
int__abs(D, AD),
Int = i(signum(D), pos_int_to_digits(AD))
).
Otherwise, that looks fine, so please commit this stuff when you're ready.
--
Fergus Henderson <fjh at cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3 | -- the last words of T. S. Garp.
More information about the developers
mailing list