<> <> <<>> DIRECTORY Rope, Ieee, PrincOpsUtils, Process, RuntimeError, IO, Basics, Atom, Real, BigCardinals, AlgebraClasses, Points, BigCardExtras, MathExpr, MathConstructors, BigRats; BigRatsImpl: CEDAR PROGRAM IMPORTS Rope, Basics, Ieee, IO, PrincOpsUtils, Process, RuntimeError, BigCardinals, AlgebraClasses, BigCardExtras, MathConstructors EXPORTS BigRats = BEGIN OPEN BigRats, BC: BigCardinals, AC: AlgebraClasses, PTS: Points, BCE: BigCardExtras; <> BigRatsError: PUBLIC SIGNAL [reason: ATOM _ $Unspecified] = CODE; bitsPerWord: CARDINAL = Basics.bitsPerWord; CARD: TYPE = LONG CARDINAL; ROPE: TYPE = Rope.ROPE; STREAM: TYPE = IO.STREAM; <> ClassPrintName: AC.PrintNameProc = { RETURN["BigRats"]; }; ClassCharacteristic: AC.StructureRankOp = { RETURN[ 0 ] }; ClassLegalFirstChar: AC.LegalFirstCharOp = { SELECT char FROM IN ['0..'9] => RETURN[TRUE]; '+, '- => RETURN[TRUE]; ENDCASE; RETURN[FALSE]; }; ClassZero: AC.NullaryOp = { RETURN[ RatZero ] }; ClassOne: AC.NullaryOp = { RETURN[ RatOne ] }; RationalClass: AC.StructureClass _ NEW[AC.StructureClassRec _ [ category: field, printName: ClassPrintName, structureEqual: AC.defaultStructureEqualityTest, characteristic: ClassCharacteristic, isElementOf: AC.defaultElementOfProc, legalFirstChar: ClassLegalFirstChar, read: Read, fromRope: FromRope, toRope: ToRope, write: Write, toExpr: ToExpr, add: Add, negate: Negate, subtract: Subtract, zero: ClassZero, multiply: Multiply, commutative: TRUE, invert: Invert, divide: Divide, one: ClassOne, equal: Equal, ordered: TRUE, sign: Sign, abs: Abs, compare: Compare, integralDomain: TRUE, completeField: FALSE, realField: TRUE, realClosedField: FALSE, algebraicallyClosedField: FALSE, propList: NIL ] ]; BigRats: PUBLIC AC.Structure _ NEW[AC.StructureRec _ [ class: RationalClass, instanceData: NIL ] ]; BigCardZero: BigCard = BigCardinals.BigFromSmall[0]; -- do after BigRats set BigCardOne: BigCard = BigCardinals.BigFromSmall[1]; BigCardTwo: BigCard = BigCardinals.BigFromSmall[2]; BigCardTen: BigCard = BigCardinals.BigFromSmall[10]; RatZero: BigRat = NEW[AC.ObjectRec _ [structure: BigRats,data: NEW[BigRatDataRec _ [sign: equal, num: BigCardZero, den: BigCardOne]]]]; -- do after BigRats set so structure field gets nonNIL Value RatOne: BigRat = NEW[AC.ObjectRec _ [structure: BigRats,data: NEW[BigRatDataRec _ [sign: greater, num: BigCardOne, den: BigCardOne]]]]; -- call to FromBC would be circular RatTwo: BigRat = FromBC[BigCardTwo]; RatHalf: BigRat = Breed[BigCardOne, BigCardTwo, FALSE]; <> <> <> <> <> <> <> <> <<}>> <> <> <> <<[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]]; }; <> Read: PUBLIC AC.ReadOp ~ { <> num, den: BC.BigCARD; bigCARDRope: Rope.ROPE; 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[ ]; }; [bigCARDRope, charsSkipped] _ in.GetTokenRope[]; num _ BC.BigFromDecimalRope[bigCARDRope]; []_ in.SkipWhitespace[]; IF in.EndOf[] OR in.PeekChar[ ]#'/ THEN -- No / in BigRat IF BC.BigZero[num] THEN out _ RatZero ELSE out _ FromPairBC[num, BigCardOne, sign=less ] ELSE { [ ] _ in.GetChar[ ]; -- toss /; []_ in.SkipWhitespace[]; [bigCARDRope, charsSkipped] _ in.GetTokenRope[]; 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]]]; }; <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<};>> <<>> 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] ]]; }; ToExpr: 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] ] ] }; 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] = bigEqual 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]]; }; <> <> <> <> <> <> <> <> <> <> <<};>> <> <<}>> <<};>> <<>> Write: PUBLIC AC.WriteOp = { IO.PutRope[ stream, ToRope[in] ] }; <> <> <> <> <> <> <> <> <> <> <<[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;>> <<};>> <<>> Equal: PUBLIC AC.EqualityOp = { firstData: BigRatData _ NARROW[firstArg.data]; secondData: BigRatData _ NARROW[secondArg.data]; IF firstArg = secondArg THEN RETURN [TRUE]; IF firstData.sign = secondData.sign THEN SELECT BigCardinals.BigCompare[firstData.num, secondData.num] FROM bigEqual => SELECT BigCardinals.BigCompare[firstData.den, secondData.den] FROM bigEqual => RETURN [TRUE]; ENDCASE; ENDCASE; RETURN [FALSE]; }; 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];>> <> <> <> <> <> <<};>> <> <> <