<> <> DIRECTORY Basics, Real, ShortRational; ShortRationalImpl: CEDAR PROGRAM IMPORTS Basics, Real EXPORTS ShortRational = BEGIN Inverse: PROC [real: REAL] RETURNS [REAL] ~ {RETURN [1.0/real]}; <> FloorN: PROC [real: REAL] RETURNS [NAT] ~ {RETURN [Real.FixI[real]]}; <> <> FromReal: PUBLIC PROC [real: REAL] RETURNS [ans: ShortRational.Rational] ~ { abs: REAL ~ ABS[real]; p: NAT _ 1; q: CARDINAL _ 0; BEGIN ENABLE Real.RealException => GOTO Done; f: NAT _ FloorN[abs]; r: REAL _ abs-f; pp: NAT _ p; qq: CARDINAL _ q; p _ f; q _ 1; WHILE r # 0 DO rinv: REAL _ Inverse[r]; fnew: NAT _ FloorN[rinv]; pnew: LONG CARDINAL _ Basics.LongMult[fnew, p] + pp; qnew: LONG CARDINAL _ Basics.LongMult[fnew, q] + qq; IF pnew > NAT.LAST OR qnew > CARDINAL.LAST THEN EXIT; pp _ p; qq _ q; p _ pnew; q _ qnew; r _ rinv - fnew; ENDLOOP; EXITS Done => NULL; END; ans.numerator _ p; ans.denominator _ q; IF real < 0 THEN ans.numerator _ -ans.numerator; }; END.