# [m-dev.] for review: big rats

Fergus Henderson fjh at cs.mu.OZ.AU
Wed Apr 8 18:23:46 AEST 1998

```On 08-Apr-1998, Bert Thompson <aet at hydra.cs.mu.oz.au> wrote:
> :- pred rational:'='(rational, rational).
> :- mode rational:'='(in, in) is semidet.
...
> 	% We needn't call rational_norm since rationals can be
> 	% created only by the rational constructors or by rational
> 	% operations, the results of which must be normalised.
> rational:'='(r(An, Ad), r(Bn, Bd)) :-
> 	An = Bn, Ad = Bd.

That code will not have the effect that you expect.
The way to defining equality for a type is with `where equality is <blah>'
in the type declaration, rather than by defining an =/2 predicate.
It's probably a bug if the compiler does not at least warn you
if you try to do that.

In this case, the builtin unification will do the correct thing, so you
can just delete this predicate.  However, a comment next to the type
definition about the type's invariant and why it is needed (to ensure
that the builtin equality gives correct results) would be a good idea.

> rational:'=<'(R1, R2) :-
> 	Cmp = cmp(R1, R2),
> 	(Cmp = lessthan; Cmp = equal).
>
> rational:'>='(R1, R2) :-
> 	Cmp = cmp(R1, R2),
> 	(Cmp = greaterthan; Cmp = equal).

> rational:'+'(r(An, Ad), r(Bn, Bd)) =
> 	rational_norm(r(An*CA + Bn*CB, M)) :-

> :- func inverse(rational) = rational.
> inverse(r(Num, Den)) = Rat :-
> 	(Num = izero ->

> rational:abs(r(Num,Den)) = r(abs(Num),Den).

> 	% The normal form of a rational number has the following
> 	% properties:
> 	%	- numerator and denominator have no common factors.
> 	%	- denominator is positive.
> 	%	- denominator is not zero.
> 	%	- if numerator is zero, then denominator is one.
> :- func rational_norm(rational) = rational.
> rational_norm(r(Num, Den)) = Rat :-

As I said for rat.m, it would be better to make this rational_norm/2

:- func rational_norm(integer, integer) = rational.
rational_norm(Num, Den) = Rat :-
...

rather than rational_norm/1.

> :- pred is_zero(rational).
> :- mode is_zero(in) is semidet.
> is_zero(r(Num,_)) :-
> 	Num = izero.

> :- pred is_negative(rational).
> :- mode is_negative(in) is semidet.
> is_negative(r(Num,_)) :-

Ditto.

Otherwise that looks fine.
I'd like to see another diff for this one.

--
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.

```