[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