procedure verifyrat(p,r1,r2) #: verification tests for rational procedures return write("Testing ",p,"( ",rat2str(r1),", ",rat2str(\r2) | &null," ) ==> ","returned " || rat2str(p(r1,r2)) | "failed") end procedure makerat(x) #: make rational (from integer, real, or strings) local n,d static c initial c := &digits++'+-' return case type(x) of { "real" : real2rat(x) "integer" : ratred(rational(x,1,1)) "string" : if x ? ( n := integer(tab(many(c))), ="/", d := integer(tab(many(c))), pos(0)) then ratred(rational(n,d,1)) else makerat(numeric(x)) } end procedure absrat(r1) #: abs(rational) r1 := ratred(r1) r1.sign := 1 return r1 end invocable all # for string invocation procedure xoprat(op,r1,r2) #: support procedure for binary operations that cross denominators local numer, denom, div r1 := ratred(r1) r2 := ratred(r2) return if op(r1.numer * r2.denom,r2.numer * r1.denom) then r2 # return right argument on success end procedure eqrat(r1,r2) #: rational r1 = r2 return xoprat("=",r1,r2) end procedure nerat(r1,r2) #: rational r1 ~= r2 return xoprat("~=",r1,r2) end procedure ltrat(r1,r2) #: rational r1 < r2 return xoprat("<",r1,r2) end procedure lerat(r1,r2) #: rational r1 <= r2 return xoprat("<=",r1,r2) end procedure gerat(r1,r2) #: rational r1 >= r2 return xoprat(">=",r1,r2) end procedure gtrat(r1,r2) #: rational r1 > r2 return xoprat(">",r1,r2) end link rational