DIRECTORY MathExpr, MathRules, MathDB, MathTypes, MathBox, Imager, Rope, Vector, MathConstructors; MathExprClassesArithmetic: CEDAR PROGRAM IMPORTS MathBox, MathRules, MathExpr, MathDB, MathConstructors ~ BEGIN EXPR: TYPE ~ MathExpr.EXPR; BOX: TYPE ~ MathBox.BOX; ROPE: TYPE ~ Rope.ROPE; VEC: TYPE ~ Vector.VEC; CompoundBoxProc: TYPE ~ MathRules.CompoundBoxProc; CompositionProc: TYPE ~ MathRules.CompositionProc; Alignment2D: TYPE ~ MathRules.Alignment2D; Offset: TYPE ~ MathRules.Offset; Size: TYPE ~ MathRules.Size; Argument: TYPE ~ MathExpr.Argument; Symbol: TYPE ~ MathExpr.Symbol; CompoundClass: TYPE ~ MathExpr.CompoundClass; FormatClass: TYPE ~ MathTypes.FormatClass; Style: TYPE ~ MathTypes.Style; MakeArgument: PROC[name: ATOM, aliases: LIST OF ATOM, size: Size] RETURNS[Argument] ~ MathExpr.MakeArgument; MakeSymbol: PROC[name: ATOM, aliases: LIST OF ATOM, size: Size, value: EXPR] RETURNS[Symbol] ~ MathExpr.MakeSymbol; MakeCompoundClass: PROC[name: ATOM, formatClass: FormatClass, description: ROPE, args: LIST OF Argument, syms: LIST OF Symbol, boxRule: CompoundBoxProc, compBox: CompositionProc, cvtAS, cvtReduce, cvtSMP, cvtOther: ROPE _ NIL] RETURNS[CompoundClass] ~ MathExpr.MakeCompoundClass; smallGap: REAL = 0.05; medGap: REAL = 0.10; bigGap: REAL = 0.25; FixedSizeBoxRule: CompoundBoxProc ~ { RETURN[boxes]; }; AbsBoxRule: CompoundBoxProc ~ { leftBox: BOX _ MathBox.GetBox[$leftAbs, boxes]; rightBox: BOX _ MathBox.GetBox[$rightAbs, boxes]; aBox: BOX _ MathBox.GetBox[$a, boxes]; scaleFactor: REAL _ MAX[0.25, 1.1 * aBox.Height[] / leftBox.Height[] ]; -- don't allow scaling to less than 1/4 size leftBox _ MathBox.Scale[leftBox, [1.2 * scaleFactor, scaleFactor]]; -- make wider than tall rightBox _ MathBox.Scale[rightBox, [1.2 * scaleFactor, scaleFactor]]; RETURN[LIST[aBox, leftBox, rightBox]]; }; FractionBoxRule: CompoundBoxProc ~ { fbarBox: BOX _ MathBox.GetBox[$fractionBar, boxes]; numBox: BOX _ MathBox.GetBox[$numerator, boxes]; denomBox: BOX _ MathBox.GetBox[$denominator, boxes]; topSpaceBox: BOX _ MathBox.GetBox[$topSpace, boxes]; bottomSpaceBox: BOX _ MathBox.GetBox[$bottomSpace, boxes]; scaleX: REAL _ 1.1 * MAX[numBox.Width[], denomBox.Width[] ] / fbarBox.Width[]; fbarBox _ MathBox.Scale[fbarBox, [scaleX, 1.0]]; RETURN[LIST[fbarBox, numBox, denomBox, topSpaceBox, bottomSpaceBox]]; }; PowCompRule: CompositionProc ~ { tempBox: BOX; tempBoxes: LIST OF BOX; vertOffsetExponent, vertOffsetBase, horizOffsetBase: Offset; alignments: LIST OF Alignment2D _ NIL; baseBox: BOX _ MathBox.GetBox[$base, boxes]; exponentBox: BOX _ MathBox.GetBox[$exponent, boxes]; hintBox: BOX _ baseBox.SuperscriptHint[]; -- hint about where to place subscript w/i base IF hintBox # NIL THEN { horizOffsetBase _ [origin, hintBox.Offset[].x + hintBox.Extents[].rightExtent]; IF (hintBox.Height[] * baseBox.Height[]) > exponentBox.Height[] THEN { vertOffsetExponent _ [bottom, 0.2]; vertOffsetBase _ [origin, hintBox.Offset[].y + hintBox.Extents[].ascent]; } ELSE { vertOffsetExponent _ [bottom]; vertOffsetBase _ [origin, 0.8 * (hintBox.Offset[].y + hintBox.Extents[].ascent)]; }; } ELSE { horizOffsetBase _ [right]; IF baseBox.Height[] > exponentBox.Height[] THEN { vertOffsetExponent _ [bottom, 0.2]; vertOffsetBase _ [top]; } ELSE { vertOffsetExponent _ [bottom]; vertOffsetBase _ [top, -0.2]; }; }; alignments _ LIST[ [$exponent, [$base, [left], horizOffsetBase], [$base, vertOffsetExponent, vertOffsetBase]]]; [tempBox, tempBoxes] _ MathRules.Compose[boxes, alignments, [$base, [origin]], [$base, [origin]]]; RETURN[tempBox, tempBoxes]; }; FractionCompRule: CompositionProc ~ { tempBox: BOX; tempBoxes: LIST OF BOX; alignments: LIST OF Alignment2D _ LIST[ [$topSpace, [$fractionBar, [center], [center]], [$fractionBar, [bottom], [top]]], [$bottomSpace, [$fractionBar, [center], [center]], [$fractionBar, [top], [bottom]]], [$numerator, [$fractionBar, [center], [center]], [$topSpace, [bottom], [top]]], [$denominator, [$fractionBar, [center], [center]], [$bottomSpace, [top], [bottom]]]]; [tempBox, tempBoxes] _ MathRules.Compose[boxes, alignments, [$fractionBar, [origin]], [$fractionBar, [origin]]]; RETURN[tempBox, tempBoxes]; }; UnaryOpCompRule: CompositionProc ~ { tempBox: BOX; tempBoxes: LIST OF BOX; alignments: LIST OF Alignment2D _ LIST[ [$aliasSpace, [$aliasUnaryOp, [left], [right]], [$aliasUnaryOp, [origin], [origin]]], [$aliasA, [$aliasSpace, [left], [right]], [$aliasSpace, [origin], [origin]]]]; [tempBox, tempBoxes] _ MathRules.Compose[boxes, alignments, [$aliasUnaryOp, [origin]], [$aliasUnaryOp, [origin]]]; RETURN[tempBox, tempBoxes]; }; BinaryOpCompRule: CompositionProc ~ { tempBox: BOX; tempBoxes: LIST OF BOX; leftVertOffsetA, leftVertOffsetOp, rightVertOffsetB, rightVertOffsetOp: Offset; alignments: LIST OF Alignment2D; SELECT MathBox.GetBox[$aliasA, boxes].FormatClass[] FROM over => { leftVertOffsetA _ [origin]; leftVertOffsetOp _ [center]; }; matrix => { leftVertOffsetA _ [center]; leftVertOffsetOp _ [center]; }; ENDCASE => { leftVertOffsetA _ [origin]; leftVertOffsetOp _ [origin]; }; SELECT MathBox.GetBox[$aliasB, boxes].FormatClass[] FROM over => { rightVertOffsetB _ [origin]; rightVertOffsetOp _ [center]; }; matrix => { rightVertOffsetB _ [center]; rightVertOffsetOp _ [center]; }; ENDCASE => { rightVertOffsetB _ [origin]; rightVertOffsetOp _ [origin]; }; alignments _ LIST[ [$aliasLeftSpace, [$aliasBinOp, [right], [left]], [$aliasBinOp, [origin], [origin]]], [$aliasA, [$aliasLeftSpace, [right], [left]], [$aliasBinOp, leftVertOffsetA, leftVertOffsetOp]], [$aliasRightSpace, [$aliasBinOp, [left], [right]], [$aliasBinOp, [origin], [origin]]], [$aliasB, [$aliasRightSpace, [left], [right]], [$aliasBinOp, rightVertOffsetB, rightVertOffsetOp]]]; [tempBox, tempBoxes] _ MathRules.Compose[boxes, alignments, [$aliasA, [origin]], [$aliasBinOp, [origin]]]; RETURN[tempBox, tempBoxes]; }; FactorialCompRule: CompositionProc ~ { tempBox: BOX; tempBoxes: LIST OF BOX; alignments: LIST OF Alignment2D _ LIST[ [$space, [$a, [left], [right]], [$a, [origin], [origin]]], [$bang, [$space, [left], [right]], [$a, [origin], [origin]]]]; [tempBox, tempBoxes] _ MathRules.Compose[boxes, alignments, [$a, [origin]], [$a, [origin]]]; RETURN[tempBox, tempBoxes]; }; AbsCompRule: CompositionProc ~ { tempBox: BOX; tempBoxes: LIST OF BOX; alignments: LIST OF Alignment2D _ LIST[ [$leftAbs, [$a, [right], [left]], [$a, [center], [center]]], [$rightAbs, [$a, [left], [right]], [$a, [center], [center]]]]; [tempBox, tempBoxes] _ MathRules.Compose[boxes, alignments, [$leftAbs, [origin]], [$self, [center, -0.25]]]; RETURN[tempBox, tempBoxes]; }; MakeUnaryOpClass: PUBLIC PROC[class, op, arg: ATOM, operation: EXPR, description: ROPE, cvtAS, cvtReduce, cvtSMP, cvtOther: ROPE _ NIL] RETURNS[CompoundClass] ~ { argArg: Argument _ MakeArgument[arg, LIST[$aliasA, $aliasHot], normal]; spaceSym: Symbol _ MakeSymbol[$Space, LIST[$aliasSpace], normal, MathConstructors.MakeSpace[$medium]]; unaryOpSym: Symbol _ MakeSymbol[op, LIST[$aliasUnaryOp], normal, operation]; RETURN[MakeCompoundClass[class, unaryOp, description, LIST[argArg], LIST[unaryOpSym, spaceSym], FixedSizeBoxRule, UnaryOpCompRule, cvtAS, cvtReduce, cvtSMP, cvtOther]]; }; MakeBinOpClass: PUBLIC PROC[class, op, a, b: ATOM, operation: EXPR, description: ROPE, cvtAS, cvtReduce, cvtSMP, cvtOther: ROPE _ NIL] RETURNS[CompoundClass] ~ { aArg: Argument _ MakeArgument[a, LIST[$aliasA, $aliasHot], normal]; bArg: Argument _ MakeArgument[b, LIST[$aliasB], normal]; opSym: Symbol _ MakeSymbol[op, LIST[$aliasBinOp], normal, operation]; leftSpace: Symbol _ MakeSymbol[$leftThinSpace, LIST[$aliasLeftSpace], normal, MathConstructors.MakeSpace[$thin]]; rightSpace: Symbol _ MakeSymbol[$rightThinSpace, LIST[$aliasRightSpace], normal, MathConstructors.MakeSpace[$thin]]; RETURN[MakeCompoundClass[class, binaryOp, description, LIST[aArg, bArg], LIST[opSym, leftSpace, rightSpace], FixedSizeBoxRule, BinaryOpCompRule, cvtAS, cvtReduce, cvtSMP, cvtOther]]; }; wrongBoxType: PUBLIC ERROR = CODE; InstallArithmeticClassesA: PROC [] ~ { sumClass, fractionClass, differenceClass, powClass, productClass, negationClass, inverseClass: CompoundClass; baseArg, exponentArg, numeratorArg, denominatorArg: Argument; lineSym, numerSpSym, denomSpSym: Symbol; baseArg _ MakeArgument[$base, LIST[$aliasA, $aliasHot], normal]; exponentArg _ MakeArgument[$exponent, LIST[$aliasB], script]; numeratorArg _ MakeArgument[$numerator, LIST[$aliasA, $aliasHot], normal]; denominatorArg _ MakeArgument[$denominator, LIST[$aliasB], normal]; denomSpSym _ MakeSymbol[$bottomSpace, LIST[$aliasSpace], normal, MathConstructors.MakeSpace[$thin]]; numerSpSym _ MakeSymbol[$topSpace, LIST[$aliasSpace], normal, MathConstructors.MakeSpace[$thin]]; lineSym _ MakeSymbol[$fractionBar, LIST[$aliasLine], normal, MathConstructors.MakeLine[]]; inverseClass _ MakeUnaryOpClass[$invert, $inv, $a, MathConstructors.MakePlainRope["inv"], "inv a", "recip($a)", "$a ** (-1)"]; negationClass _ MakeUnaryOpClass[$negation, $minus, $a, MathConstructors.MakePlainSym['-], "-a", "-$a", "minus($a)", "Minus[$a]"]; sumClass _ MakeBinOpClass[$sum, $plus, $addend, $augend, MathConstructors.MakePlainSym['+], "a + b", "$addend + $augend", "plus($addend, $augend)", "Plus[$addend, $augend]"]; differenceClass _ MakeBinOpClass[$difference, $minus, $subtrahend, $minuend, MathConstructors.MakePlainSym['-], "a - b", "$subtrahend - $minuend", "difference($subtrahend, $minuend)", "Minus[$subtrahend, $minuend]"]; productClass _ MakeBinOpClass[$product, $times, $multiplier, $multiplicand, MathConstructors.MakeSpace[$product], "a * b", "$multiplier * $multiplicand", "times($multiplier, $multiplicand)", "Mult[$multiplier, $multiplicand]"]; powClass _ MakeCompoundClass[$pow, other, "a^b", LIST[baseArg, exponentArg], NIL, FixedSizeBoxRule, PowCompRule, "$base ** $exponent", "expt($base, $exponent)", "Pow[$base, $exponent]"]; fractionClass _ MakeCompoundClass[$fraction, over, "a / b", LIST[numeratorArg, denominatorArg], LIST[lineSym, numerSpSym, denomSpSym], FractionBoxRule, FractionCompRule, "$numerator / $denominator", "quotient($numerator, $denominator)", "Div[$numerator, $denominator]"]; MathDB.InstallCompoundClass[sumClass]; MathDB.AddOperator[sumClass, $Arithmetic]; MathDB.InstallCompoundClass[negationClass]; MathDB.AddOperator[negationClass, $Arithmetic]; MathDB.InstallCompoundClass[differenceClass]; MathDB.AddOperator[differenceClass, $Arithmetic]; MathDB.InstallCompoundClass[productClass]; MathDB.AddOperator[productClass, $Arithmetic]; MathDB.InstallCompoundClass[powClass]; MathDB.AddOperator[powClass, $Arithmetic]; MathDB.InstallCompoundClass[fractionClass]; MathDB.AddOperator[fractionClass, $Arithmetic]; MathDB.InstallCompoundClass[inverseClass]; MathDB.AddOperator[inverseClass, $Arithmetic]; }; InstallArithmeticClassesAA: PROC [] ~ { absClass, factorialClass: CompoundClass; aAbsArg, factorialArg: Argument; leftAbsSym, rightAbsSym, factorialSym, factorialSpSym: Symbol; aAbsArg _ MakeArgument[$a, LIST[$aliasA, $aliasHot], normal]; leftAbsSym _ MakeSymbol[$leftAbs, NIL, normal, MathConstructors.MakePlainSym['\174]]; rightAbsSym _ MakeSymbol[$rightAbs, NIL, normal, MathConstructors.MakePlainSym['\174]]; factorialArg _ MakeArgument[$a, LIST[$aliasA, $aliasHot], normal]; factorialSym _ MakeSymbol[$bang, NIL, normal, MathConstructors.MakePlainSym['!]]; factorialSpSym _ MakeSymbol[$space, LIST[$aliasSpace], normal, MathConstructors.MakeSpace[$thin]]; absClass _ MakeCompoundClass[$abs, paren, "| a |", LIST[aAbsArg], LIST[leftAbsSym, rightAbsSym], AbsBoxRule, AbsCompRule, "| $a |"]; factorialClass _ MakeCompoundClass[$factorial, other, "a!", LIST[factorialArg], LIST[factorialSym, factorialSpSym], FixedSizeBoxRule, FactorialCompRule, "$a!"]; MathDB.InstallCompoundClass[absClass]; MathDB.AddOperator[absClass, $Arithmetic]; MathDB.InstallCompoundClass[factorialClass]; MathDB.AddOperator[factorialClass, $Arithmetic]; }; InstallArithmeticClassesA[]; InstallArithmeticClassesAA[]; END. 2MathExprClassesArithmetic.mesa Carl Waldspurger, August 30, 1986 7:12:37 pm PDT Bier, November 20, 1986 2:02:38 pm PST Arnon, March 24, 1987 4:15:37 pm PST Type Abbreviations from Imported Interfaces Procedure Abbreviations from Imported Interfaces Constants Box Procs for Compound Expr Classes effects: Returns unaltered boxes (i.e. no resizing takes place) effects: Sizes boxes for expr of form ($abs $a) right and left absolute value bars must be as tall as expression "a" effects: Sizes boxes for expr of form ($fractionBar $numerator $denominator) should ENABLE noSuchBox fraction bar must be as wide as the wider of numerator, denominator adjust fbarBox extents Composition Procs for Compound Expr Classes effects: Composes layout for expr of form ($exponent $base) hint, so align exponent with base via hintBox top of hint box inside base box 0.8 way up on hint box no hint, so align exponent directly with base effects: Composes layout for expr of form ($fractionBar $numerator $denominator) effects: Composes layout for expr of form ($aliasUnaryOp $aliasA). effects: Composes layout for expr of form ($aliasBinOp $aliasA $aliasB) with symbols $aliasLeftSpace & $aliasRightSpace. set vertical offset depending on format classes of A & B arguments effects: Composes layout for expr of form ($bang $a $space) effects: Composes layout for expr of form ($abs $a) with symbols $absBar and $absBar Class Constructors effects: Creates and returns standard unary operation compound class named "class". The alignment is "operation arg"; alignment is thru baselines. Both op, arg are of fixed size "normal". effects: Creates and returns standard binary operation compound class named "class". The alignment is "a operation b"; alignment is thru baselines. All of a, b, op are of fixed size "normal". Signals & Errors Define & Install Expression Classes local declarations define info for "pow base exponent" & "subscript base subscript" & "hat base hat" define info for "fraction numerator denominator" define compound classes Register compound classes in user-friendly order MathDB.InstallCompoundClass[gcdClass]; MathDB.AddOperator[gcdClass, $Arithmetic]; local declarations define info for "| a |" define into for factorial Install Classes Defined in this Module ส ˜Jšœ™šœ0™0Icode™&K™$—J˜J˜šฯk ˜ Kšœ ˜ Kšœ ˜ K˜K˜ K˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜K˜—J˜šฯnœœœ˜)šœ˜&Jšœ˜—Jšœ˜J˜Jš˜—J˜headšž+™+Jšœœ œ˜Jšœœ œ˜Jšœœœ˜Jšœœ œ˜Jšœœ˜2Jšœœ˜2Jšœ œ˜*Jšœœ˜ Jšœœ˜J˜Jšœ œ˜#Jšœœ˜Jšœœ˜-Jšœ œ˜*Jšœœ˜—šž0™0Jšž œœœ œœœœ#˜lJ˜Jšž œœœ œœœœœ˜sJ˜Jšžœœœ)œœœœœaœœœ-˜——šž ™ Jšœ œ˜Jšœœ˜Jšœœ˜—šž#™#šžœ˜%Kšœ@™@Kšœ˜K˜K˜—šž œ˜Kšœ0™0K™Kšœ œ#˜/Kšœ œ$˜1Kšœœ˜&K˜KšœD™DKšœ œœ1ฯc,˜tKšœDŸ˜[KšœE˜EKšœœ˜&K˜K˜—šžœ˜$KšœM™MK˜Kšœ™Kšœ œ'˜3Kšœœ%˜0Kšœ œ'˜4K˜4K˜:K˜KšœC™CKšœœ œ6˜NK˜Kšœ™Kšœ0˜0K˜Kšœœ:˜EK˜K˜——šž+™+šž œ˜ Kšœ<™œ˜FK˜#Kšœ™KšœK˜KK˜—šœ˜Kšœ˜Kšœ™KšœS˜SK˜—K˜—šœ˜Kšœ-™-K˜šœ)œ˜1K˜#K˜K˜—šœ˜K˜K˜K˜—K˜K˜—šœ œ˜˜ K˜!K˜.K˜——˜K˜LK˜—Kšœ˜K˜—šžœ˜%KšœQ™QK˜Kšœ œ˜ Kšœ œœœ˜šœ œœœ˜'˜ K˜#K˜!—˜K˜#K˜!—˜ K˜#K˜—˜K˜#K˜"K˜——K˜sK˜Kšœ˜K˜—šžœ˜$KšœC™CK˜Kšœ œ˜ Kšœ œœœ˜šœ œœœ˜'˜ K˜!K˜%—˜ K˜K˜$K˜——K˜sK˜Kšœ˜˜K˜——šžœ˜%KšœM™MK™5K™Kšœ œ˜ Kšœ œœœ˜K˜OKšœ œœ ˜ K˜KšœB™Bšœ.˜8˜ K˜K˜K˜—˜ K˜K˜K˜—šœ˜ K˜K˜K˜K˜——šœ.˜8˜ K˜K˜K˜—˜ K˜K˜K˜—šœ˜ K˜K˜K˜——K˜šœ œ˜˜Kšœ˜K˜#—˜ K˜#K˜2—˜K˜K˜#—˜ K˜$K˜5K˜——K˜jK˜Kšœ˜K˜K˜—šžœ˜&Kšœ<™˜qKšœ1œ?˜tK˜Kšœ1œœi˜ถK˜—K˜—šž™Kšœœœœ˜"—šž$™$šžœœ˜&K˜Kšœ™Kšœm˜mKšœ=˜=Kšœ)˜)K˜K˜KšœQ™QKšœœ˜@Kšœ&œ˜=K˜Kšœ0™0Kšœ(œ˜JKšœ,œ˜CKšœ&œ:˜dKšœ#œ:˜aKšœ#œ3˜ZK˜K˜Kšœ™K™K˜Kšœ~˜~Kšœ‚˜‚Kšœฎ˜ฎKšœุ˜ุKšœภฯfœ˜ใKšœ1œœ8 œ.˜บKšœ<œ œd œ>˜ŽK˜K™1K™K˜&Kšœ*˜*K˜+Kšœ/˜/K˜-Kšœ1˜1K˜*Kšœ.˜.K™&Kšœ*™*K˜&Kšœ*˜*K˜+Kšœ/˜/Kšœ*˜*Kšœ.˜.K˜K˜—šžœœ˜'K˜Kšœ™Kšœ(˜(Kšœ ˜ Kšœ>˜>K˜K˜Kšœ™Kšœ=˜=KšœU˜UKšœW˜WK˜K˜Kšœ™Kšœ œ˜BKšœ!œ-˜QKšœ$œ:˜bK˜K˜Kšœ…˜…Kšœ<œœL˜ K˜K˜Kšœ&˜&Kšœž œ˜*K˜,Kšœž œ˜0K˜——šž&™&K˜K˜—K˜šœ˜K˜—J˜J˜J˜—…—/ CY