<> <> <<>> DIRECTORY Rope, Ieee, PrincOpsUtils, Process, RuntimeError, IO, Basics, Atom, Real, BigCardinals, AlgebraClasses, BigCardExtras, MathExpr, MathConstructors, Bools, Ints, BigRats; BigRatsImpl: CEDAR PROGRAM IMPORTS Rope, Basics, Ieee, IO, PrincOpsUtils, Process, RuntimeError, BigCardinals, AlgebraClasses, BigCardExtras, MathConstructors, Ints EXPORTS BigRats = BEGIN OPEN BigRats, BC: BigCardinals, AC: AlgebraClasses, BCE: BigCardExtras; <> BigRatsError: PUBLIC ERROR [reason: ATOM _ $Unspecified] = CODE; bitsPerWord: CARDINAL = Basics.bitsPerWord; CARD: TYPE = LONG CARDINAL; ROPE: TYPE = Rope.ROPE; STREAM: TYPE = IO.STREAM; Object: TYPE = AC.Object; Method: TYPE = AC.Method; <> PrintName: PUBLIC AC.ToRopeOp = { RETURN["BigRats"]; }; ShortPrintName: PUBLIC AC.ToRopeOp = { RETURN["Q"]; }; Characteristic: PUBLIC AC.StructureRankOp = { RETURN[ 0 ] }; <> <> <> <> <> <> <> <> <<}>> <> <> <> <<[out.num, dummy] _ BC.BigDivMod[ num, gcd];>> <<[out.den, dummy] _ BC.BigDivMod[ den, gcd]>> <<}>> <<};>> <<>> <> <> <> <> <> <> <> <<}>> <> <> <> <> <> <<[out.num, dummy] _ BC.BigDivMod[ bignum, gcd];>> <<[out.den, dummy] _ BC.BigDivMod[ bigden, gcd]>> <<}>> <<};>> FromPairBC: PUBLIC PROC [num, den: BigCard, less: BOOL _ FALSE] RETURNS [BigRat] = { RETURN [Simplify[Breed[num, den, less]]]; }; FromPairLC: PUBLIC PROC [num, den: CARD, less: BOOL _ FALSE] RETURNS [BigRat] = { RETURN [Simplify[Breed[BCE.LCToBC[num], BCE.LCToBC[den], less]]]; }; FromBC: PUBLIC PROC [bc: BigCard, less: BOOL _ FALSE] RETURNS [BigRat] = { RETURN [Breed[bc, BigCardOne, less]]; }; FromLC: PUBLIC PROC [lc: CARD, less: BOOL _ FALSE] RETURNS [BigRat] = { IF Basics.HighHalf[lc] = 0 AND NOT less THEN SELECT Basics.LowHalf[lc] FROM 0 => RETURN [RatZero]; 1 => RETURN [RatOne]; ENDCASE; RETURN [Breed[BCE.LCToBC[lc], BigCardOne, less]]; }; <> Recast: PUBLIC AC.BinaryOp = { <> IF AC.StructureEqual[firstArg.class, BigRats] THEN RETURN[firstArg]; IF Ints.CanRecast[firstArg, Ints.Ints] THEN RETURN[ FromRope[Ints.ToRope[ Ints.Recast[firstArg, Ints.Ints] ] ] ]; RETURN[NIL]; }; CanRecast: PUBLIC AC.BinaryPredicate = { firstArgStructure: Object _ IF firstArg.flavor = StructureElement THEN firstArg.class ELSE IF firstArg.flavor = Structure THEN firstArg ELSE ERROR; SELECT TRUE FROM AC.StructureEqual[firstArgStructure, BigRats] => RETURN[TRUE]; Ints.CanRecast[firstArg, Ints.Ints] => RETURN[TRUE]; ENDCASE; RETURN[FALSE]; }; LegalFirstChar: PUBLIC AC.LegalFirstCharOp = { SELECT char FROM IN ['0..'9] => RETURN[TRUE]; '+, '- => RETURN[TRUE]; ENDCASE; RETURN[Ints.LegalFirstChar[char, structure] ]; }; Read: PUBLIC AC.ReadOp ~ { <> num, den: BC.BigCARD; bigCARDRope: Rope.ROPE; tokenKind: IO.TokenKind; charsSkipped: INT; -- dummy output parm for GetTokenRope sign: Basics.Comparison _ greater; []_ in.SkipWhitespace[]; IF in.PeekChar[ ]='- THEN { sign _ less; [] _ in.GetChar[ ]; } ELSE IF in.PeekChar[ ]='+ THEN { sign _ greater; [] _ in.GetChar[ ]; }; [tokenKind, bigCARDRope, charsSkipped] _ in.GetCedarTokenRope[]; IF tokenKind#tokenDECIMAL THEN ERROR IO.Error[$SyntaxError, in]; num _ BC.BigFromDecimalRope[bigCARDRope]; []_ in.SkipWhitespace[]; IF in.EndOf[] THEN { IF BC.BigZero[num] THEN out _ RatZero ELSE out _ FromPairBC[num, BigCardOne, sign=less]; RETURN[out]; }; IF in.PeekChar[]='. THEN IO.Error[$SyntaxError, in]; -- no decimal points allowed IF in.PeekChar[ ]#'/ THEN -- Next char is neither . nor / IF BC.BigZero[num] THEN out _ RatZero ELSE out _ FromPairBC[num, BigCardOne, sign=less] ELSE { [ ] _ in.GetChar[ ]; -- toss /; []_ in.SkipWhitespace[]; <<[bigCARDRope, charsSkipped] _ in.GetTokenRope[];>> [tokenKind, bigCARDRope, charsSkipped] _ in.GetCedarTokenRope[]; IF tokenKind#tokenDECIMAL THEN ERROR BigRatsError[$BadToken]; den _ BC.BigFromDecimalRope[bigCARDRope]; IF BC.BigZero[num] THEN out _ RatZero ELSE out _ FromPairBC[ num, den, sign=less ]; }; RETURN[out]; }; <> <> <> <> <<};>> <<>> FromRope: PUBLIC AC.FromRopeOp = { rope: ROPE _ in; less: BOOL _ Rope.Match["-*", rope]; pos: INT _ 0; len: INT _ 0; IF less THEN rope _ Rope.Substr[rope, 1]; len _ Rope.Length[rope]; pos _ Rope.SkipTo[rope, 0, "/"]; IF pos # len THEN { <> num: ROPE _ Rope.Substr[rope, 0, pos]; den: ROPE _ Rope.Substr[rope, pos+1]; RETURN [FromPairBC[ BigCardinals.BigFromDecimalRope[num], BigCardinals.BigFromDecimalRope[den], less]]; }; pos _ Rope.SkipTo[rope, 0, "."]; IF pos < len THEN { <> whole: ROPE _ Rope.Substr[rope, 0, pos]; fract: ROPE _ Rope.Substr[rope, pos+1]; fractPlaces: INT _ Rope.Length[fract]; number: BigCard _ BigCardinals.BigFromDecimalRope[Rope.Concat[whole, fract]]; tens: BigCard _ InternalBCPower[BigCardOne, BigCardTen, fractPlaces]; RETURN [FromPairBC[number, tens, less]]; }; <> RETURN [FromBC[BigCardinals.BigFromDecimalRope[rope], less ] ]; }; <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<};>> <<>> ToRope: PUBLIC AC.ToRopeOp = { rat: BigRatData _ NARROW[in.data]; IF rat.sign = equal THEN RETURN ["0"]; IF rat.den.size = 1 AND rat.den.contents[0] = 1 THEN { RETURN [Rope.Cat[ IF rat.sign = less THEN "-" ELSE NIL, BigCardinals.BigToDecimalRope[rat.num] ]]; }; RETURN [Rope.Cat[ IF rat.sign = less THEN "-" ELSE NIL, BigCardinals.BigToDecimalRope[rat.num], "/", BigCardinals.BigToDecimalRope[rat.den] ]]; }; Write: PUBLIC AC.WriteOp = { IO.PutRope[ stream, ToRope[in] ] }; ToRopeApprox: PUBLIC PROC [rat: BigRat, places: NAT _ 3] RETURNS [ROPE] = { ratData: BigRatData _ NARROW[rat.data]; ros: STREAM = IO.ROS[]; left, right: BigCard; rat1000: BigRat _ FromLC[1000]; placesRat: BigRat _ BCToTheX[BigCardTen, places]; placesRatData: BigRatData _ NARROW[placesRat.data]; IF ratData.sign = less THEN IO.PutChar[ros, '-]; [left, rat] _ Truncate[rat]; [right, rat] _ Truncate[Multiply[rat, placesRat]]; IF Compare[rat, RatHalf] # less THEN { right _ BigCardinals.BigAdd[right, BigCardinals.BigFromSmall[1]]; IF BigCardinals.BigCompare[right, placesRatData.num] = equal THEN { left _ BigCardinals.BigAdd[right, BigCardinals.BigFromSmall[1]]; right _ BigCardinals.BigFromSmall[0]; }; }; IO.PutRope[ros, BigCardinals.BigToDecimalRope[left]]; IF right.size # 0 THEN { rope: ROPE _ BigCardinals.BigToDecimalRope[right]; IO.PutChar[ros, '.]; THROUGH [Rope.Length[rope]..places) DO IO.PutChar[ros, '0]; ENDLOOP; IO.PutRope[ros, rope]; }; RETURN [IO.RopeFromROS[ros]]; }; <> <> <> <> <> <> <> <> <> <> <<};>> <> <<}>> <<};>> <<>> ToExpr: PUBLIC PROC [in: BigRat] RETURNS [MathExpr.EXPR] = { -- should be made public inData: BigRatData _ NARROW[in.data]; numRope: Rope.ROPE _ BC.BigToDecimalRope[inData.num]; denRope: Rope.ROPE _ BC.BigToDecimalRope[inData.den]; IF inData.sign = equal THEN RETURN [MathConstructors.MakeInt["0"]]; IF inData.sign = less THEN numRope _ Rope.Concat["-", numRope]; IF BCE.BigOne[inData.den] THEN RETURN [MathConstructors.MakeInt[numRope] ]; RETURN[MathConstructors.MakeFraction[MathConstructors.MakeInt[numRope], MathConstructors.MakeInt[denRope] ] ] }; <> <> <> <> <> <> <> <> <> <> <<[type: ty, fr: z, exp10: exp] _ Real.RealToPair[in, precision];>> <> < RETURN [RatZero];>> < RETURN [x];>> < RETURN [y];>> < {>> <> <> <> <> <> <> <> <<}>> <> <> <<[xn, yd] _ SimplifyPair[xn, yd];>> <<[yn, xd] _ SimplifyPair[yn, xd];>> <<};>> <> <> <> <> <<]];>> <<};>> <<};>> <<>> <> <> <<};>> <<>> <> <> < RETURN [SELECT y.sign FROM>> < greater, equal => equal, greater => less, ENDCASE => ERROR];>> < SELECT y.sign FROM>> < {>> <> <> < RETURN [less];>> < SELECT y.sign FROM>> < {};>> < RETURN [greater];>> < ERROR;>> <> <> < {};>> < RETURN [posLess];>> <>> <> < {};>> < RETURN [posGreater];>> < ERROR;>> <> <> < RETURN [posLess];>> < RETURN [equal];>> < RETURN [posGreater];>> < ERROR;>> <<};>> <<>> Integer: PUBLIC PROC [in: BigRat] RETURNS [BOOLEAN] ~ { <> data: BigRatData _ NARROW[in.data]; RETURN[ BCE.BigOne[data.den] ]; }; <> ToTheX: PUBLIC PROC [rat: BigRat, x: INT] RETURNS [BigRat] = { ratData: BigRatData _ NARROW[rat.data]; less: BOOL _ ratData.sign = less; abs: CARD = ABS[x]; num: BigCard _ InternalBCPower[BigCardOne, ratData.num, abs]; den: BigCard _ InternalBCPower[BigCardOne, ratData.den, abs]; IF less AND Basics.LowHalf[abs] MOD 2 = 0 THEN less _ FALSE; RETURN [IF x < 0 THEN Breed[den, num, less] ELSE Breed[num, den, less]]; }; TwoToTheX: PUBLIC PROC [x: INT, less: BOOL _ FALSE] RETURNS [BigRat] = { abs: CARD _ ABS[x]; IF abs = 0 AND NOT less THEN RETURN [RatOne] ELSE { absDiv: CARDINAL _ abs / bitsPerWord; absMod: CARDINAL _ abs MOD bitsPerWord; size: CARDINAL _ absDiv + 1; accum: BigCard _ [size, NEW[BigCardinals.BigCARDRec[size]]]; FOR i: CARDINAL IN [0..absDiv) DO accum.contents[i] _ 0; ENDLOOP; accum.contents[absDiv] _ Basics.BITSHIFT[1, absMod]; IF x < 0 THEN RETURN [Breed[BigCardOne, accum, less]] ELSE RETURN [Breed[accum, BigCardOne, less]]; }; }; BCToTheX: PUBLIC PROC [bc: BigCard, x: INT, less: BOOL _ FALSE] RETURNS [BigRat] = { abs: CARD _ ABS[x]; prod: BigCard _ bc; accum: BigCard _ InternalBCPower[BigCardOne, bc, ABS[x]]; RETURN [IF x < 0 THEN Breed[BigCardOne, accum, less] ELSE Breed[accum, BigCardOne, less]]; }; <> <> <> <> <> <> <> <> <> <> <> <<[xDen, yDen] _ SimplifyPair[xDen, yDen];>> <> <> <> <> <> <<};>> <> <> <