DIRECTORY MathExpr, MathRules, MathDB, MathTypes, MathBox, ImagerFont, ImagerTransformation, Imager, Rope USING [ROPE, Fetch, Length], Vector USING [VEC], Convert USING [RopeFromChar, RopeFromReal], MathConstructors; MathConstructorsImpl: CEDAR PROGRAM IMPORTS MathBox, MathRules, ImagerFont, Imager, ImagerTransformation, MathExpr, MathDB, Convert, Rope EXPORTS MathConstructors ~ BEGIN EXPR: TYPE ~ MathExpr.EXPR; BOX: TYPE ~ MathBox.BOX; ROPE: TYPE ~ Rope.ROPE; VEC: TYPE ~ Vector.VEC; AtomBoxProc: TYPE ~ MathRules.AtomBoxProc; AtomPaintProc: TYPE ~ MathRules.AtomPaintProc; CompoundBoxProc: TYPE ~ MathRules.CompoundBoxProc; CompositionProc: TYPE ~ MathRules.CompositionProc; AtomToRopeProc: TYPE ~ MathRules.AtomToRopeProc; Alignment2D: TYPE ~ MathRules.Alignment2D; Offset: TYPE ~ MathRules.Offset; Size: TYPE ~ MathRules.Size; AtomValue: TYPE ~ MathTypes.AtomValue; AtomRopeValue: TYPE ~ MathTypes.AtomRopeValue; AtomCharValue: TYPE ~ MathTypes.AtomCharValue; AtomBoxValue: TYPE ~ MathTypes.AtomBoxValue; Argument: TYPE ~ MathExpr.Argument; Symbol: TYPE ~ MathExpr.Symbol; AtomClass: TYPE ~ MathExpr.AtomClass; AtomFlavor: TYPE ~ MathExpr.AtomFlavor; 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; MakeAtomClass: PROC[name: ATOM, formatClass: FormatClass, flavor: AtomFlavor, style: Style, boxRule: AtomBoxProc, paintRule: AtomPaintProc, cvtRope: AtomToRopeProc] RETURNS[AtomClass] ~ MathExpr.MakeAtomClass; MakeCompoundClass: PROC[name: ATOM, formatClass: FormatClass, description: ROPE, args: LIST OF Argument, syms: LIST OF Symbol, boxRule: CompoundBoxProc, compBox: CompositionProc, cvtAS: ROPE _ NIL] RETURNS[CompoundClass] ~ MathExpr.MakeCompoundClass; smallGap: REAL = 0.05; medGap: REAL = 0.10; bigGap: REAL = 0.25; thinSpace: ImagerFont.Extents = [leftExtent: 0.0, rightExtent: 0.05, ascent: 0.05, descent: 0.0]; medSpace: ImagerFont.Extents = [leftExtent: 0.0, rightExtent: 0.12, ascent: 0.12, descent: 0.0]; PaintChar: AtomPaintProc ~ { IF (absBox.Type[] # absolute) THEN ERROR wrongBoxType; WITH value SELECT FROM c: AtomCharValue => { font: ImagerFont.Font _ ImagerFont.Find[style.font]; extents: ImagerFont.Extents _ ImagerFont.BoundingBox[font, c.char]; xFactor: REAL _ absBox.Width[] / (extents.leftExtent + extents.rightExtent); yFactor: REAL _ absBox.Height[] / (extents.descent + extents.ascent); Imager.SetXY[context, absBox.Offset[]]; Imager.SetFont[context, ImagerFont.Modify[font, ImagerTransformation.Scale2[[xFactor, yFactor]]]]; Imager.ShowXChar[context, c.char]; }; ENDCASE => ERROR wrongAtomValueType; }; PaintOverlay: AtomPaintProc ~ { IF (absBox.Type[] # absolute) THEN ERROR wrongBoxType; WITH value SELECT FROM r: AtomRopeValue => { font: ImagerFont.Font _ ImagerFont.Find[style.font]; extents: ImagerFont.Extents _ OverlayBox[value, style]; xFactor: REAL _ absBox.Width[] / (extents.rightExtent + extents.leftExtent); yFactor: REAL _ absBox.Height[] / (extents.ascent + extents.descent); font _ ImagerFont.Modify[font, ImagerTransformation.Scale2[[xFactor, yFactor]]]; FOR i:INT IN [0..r.rope.Length[]-1] DO xChar: ImagerFont.XChar _ [set: 0, code: ORD[r.rope.Fetch[i]]]; box: ImagerFont.Extents _ ImagerFont.BoundingBox[font, xChar]; position: VEC _ [MathRules.AlignHorizontal[box, [center], absBox, [center]], MathRules.AlignVertical[box, [center], absBox, [center]]]; Imager.SetXY[context, position]; Imager.SetFont[context, font]; Imager.ShowXChar[context, xChar]; ENDLOOP; }; ENDCASE => ERROR wrongAtomValueType; }; PaintRope: AtomPaintProc ~ { IF (absBox.Type[] # absolute) THEN ERROR wrongBoxType; WITH value SELECT FROM r: AtomRopeValue => { font: ImagerFont.Font _ ImagerFont.Find[style.font]; extents: ImagerFont.Extents _ ImagerFont.RopeBoundingBox[font, r.rope]; xFactor: REAL _ absBox.Width[] / (extents.rightExtent + extents.leftExtent); yFactor: REAL _ absBox.Height[] / (extents.ascent + extents.descent); Imager.SetXY[context, absBox.Offset[]]; Imager.SetFont[context, ImagerFont.Modify[font, ImagerTransformation.Scale2[[xFactor, yFactor]]]]; Imager.ShowRope[context, r.rope]; }; ENDCASE => ERROR wrongAtomValueType; }; PaintLine: AtomPaintProc ~ { r: Imager.Rectangle _ [x: absBox.Offset[].x + absBox.Extents[].leftExtent, y: absBox.Offset[].y + absBox.Extents[].descent, w: absBox.Width[], h: absBox.Height[]]; Imager.MaskRectangle[context, r]; }; PaintSpace: AtomPaintProc ~ { RETURN; }; LineBox: AtomBoxProc ~ { RETURN[[leftExtent: 0.0, rightExtent: 1.0, descent: 0.0, ascent: 0.03]]; }; CvtOtherToRope: AtomToRopeProc ~ { RETURN[""]; }; CharBox: AtomBoxProc ~ { font: ImagerFont.Font _ ImagerFont.Scale[ImagerFont.Find[style.font], style.scale]; WITH value SELECT FROM c: AtomCharValue => RETURN[ImagerFont.BoundingBox[font, c.char]]; ENDCASE => ERROR wrongAtomValueType; }; CvtCharToRope: AtomToRopeProc ~ { WITH value SELECT FROM c: AtomCharValue => RETURN[Convert.RopeFromChar[from: VAL[c.char.code], quote: FALSE]]; ENDCASE => ERROR wrongAtomValueType; }; OverlayBox: AtomBoxProc ~ { font: ImagerFont.Font _ ImagerFont.Scale[ImagerFont.Find[style.font], style.scale]; farLeft, farRight, farUp, farDown: REAL _ 0.0; -- extreme edges of overlayed extents WITH value SELECT FROM r: AtomRopeValue => { FOR i:INT IN [0..r.rope.Length[]-1] DO box: ImagerFont.Extents _ ImagerFont.BoundingBox[font, [set: 0, code: ORD[r.rope.Fetch[i]]]]; farLeft _ MAX[farLeft, box.leftExtent]; farRight _ MAX[farRight, box.rightExtent]; farUp _ MAX[farUp, box.ascent]; farDown _ MAX[farDown, box.descent]; ENDLOOP; RETURN[[leftExtent: farLeft, rightExtent: farRight, descent: farDown, ascent: farUp]]; }; ENDCASE => ERROR wrongAtomValueType; }; RopeBox: AtomBoxProc ~ { font: ImagerFont.Font _ ImagerFont.Scale[ImagerFont.Find[style.font], style.scale]; WITH value SELECT FROM r: AtomRopeValue => RETURN[ImagerFont.RopeBoundingBox[font, r.rope]]; ENDCASE => ERROR wrongAtomValueType; }; CvtRopeToRope: AtomToRopeProc ~ { WITH value SELECT FROM r: AtomRopeValue => RETURN[r.rope]; ENDCASE => ERROR wrongAtomValueType; }; SpaceBox: AtomBoxProc ~ { WITH value SELECT FROM b: AtomBoxValue => RETURN[b.box]; ENDCASE => ERROR wrongAtomValueType; }; CvtSpaceToRope: AtomToRopeProc ~ { RETURN[NIL]; }; FixedSizeBoxRule: CompoundBoxProc ~ { RETURN[boxes]; }; FractionBoxRule: CompoundBoxProc ~ { fbarBox: BOX _ MathBox.GetBox[$fractionBar, boxes]; numBox: BOX _ MathBox.GetBox[$numerator, boxes]; denomBox: BOX _ MathBox.GetBox[$denominator, boxes]; scaleX: REAL _ 1.1 * MAX[numBox.Width[], denomBox.Width[]] / fbarBox.Width[]; fbarBox _ MathBox.Scale[fbarBox, [scaleX, 1.0]]; RETURN[LIST[fbarBox, numBox, denomBox]]; }; ParenBoxRule: CompoundBoxProc ~ { leftParenBox: BOX _ MathBox.GetBox[$leftParen, boxes]; rightParenBox: BOX _ MathBox.GetBox[$rightParen, boxes]; aBox: BOX _ MathBox.GetBox[$a, boxes]; scaleFactor: REAL _ 1.1 * aBox.Height[] / leftParenBox.Height[]; leftParenBox _ MathBox.Scale[leftParenBox, [scaleFactor, scaleFactor]]; rightParenBox _ MathBox.Scale[rightParenBox, [scaleFactor, scaleFactor]]; RETURN[LIST[aBox, leftParenBox, rightParenBox]]; }; RadicalBoxRule: CompoundBoxProc ~ { radRootBox: BOX _ MathBox.GetBox[$radRoot, boxes]; radLineBox: BOX _ MathBox.GetBox[$radLine, boxes]; nBox: BOX _ MathBox.GetBox[$n, boxes]; radicandBox: BOX _ MathBox.GetBox[$radicand, boxes]; rootScale: REAL _ 1.2 * radicandBox.Height[] / radRootBox.Height[]; lineScale: VEC _ [radicandBox.Width[]/radLineBox.Width[], 1.0]; radRootBox _ MathBox.Scale[radRootBox, [rootScale, rootScale]]; radLineBox _ MathBox.Scale[radLineBox, lineScale]; RETURN[LIST[radRootBox, radLineBox, nBox, radicandBox]]; }; PowCompRule: CompositionProc ~ { tempBox: BOX; tempBoxes: LIST OF BOX; vertOffsetExponent, vertOffsetBase: Offset; alignments: LIST OF Alignment2D _ NIL; IF MathBox.GetBox[$base, boxes].Height[] > MathBox.GetBox[$exponent, boxes].Height[] THEN { vertOffsetExponent _ [bottom, 0.2]; vertOffsetBase _ [top]; } ELSE { vertOffsetExponent _ [bottom]; vertOffsetBase _ [top, -0.2]; }; alignments _ LIST[ [$exponent, [$base, [left], [right]], [$base, vertOffsetExponent, vertOffsetBase]]]; [tempBox, tempBoxes] _ MathRules.Compose[boxes, alignments, $base, $base]; RETURN[tempBox, tempBoxes]; }; FractionCompRule: CompositionProc ~ { tempBox: BOX; tempBoxes: LIST OF BOX; alignments: LIST OF Alignment2D _ LIST[[$denominator, [$fractionBar, [center], [center]], [$fractionBar, [top], [bottom, -2*bigGap]]], [$numerator, [$fractionBar, [center], [center]], [$fractionBar, [bottom], [top, 2*bigGap]]]]; [tempBox, tempBoxes] _ MathRules.Compose[boxes, alignments, $fractionBar, $fractionBar]; RETURN[tempBox, tempBoxes]; }; SummationCompRule: CompositionProc ~ { tempBox: BOX; tempBoxes: LIST OF BOX; alignments: LIST OF Alignment2D _ LIST[[$lowerbound, [$sigma, [center], [center]], [$sigma, [top], [bottom, -smallGap]]], [$upperbound, [$sigma, [center], [center]], [$sigma, [bottom], [top, smallGap]]], [$summand, [$sigma, [left], [right, medGap]], [$sigma, [center], [center]]]]; [tempBox, tempBoxes] _ MathRules.Compose[boxes, alignments, $sigma, $summand]; RETURN[tempBox, tempBoxes]; }; RadicalCompRule: CompositionProc ~ { tempBox: BOX; tempBoxes: LIST OF BOX; alignments: LIST OF Alignment2D _ LIST[[$radRoot, [$radicand, [right], [left]], [$radicand, [center], [center]]], [$radLine, [$radRoot, [left], [right]], [$radRoot, [top], [top]]], [$n, [$radRoot, [right], [left, bigGap]], [$radRoot, [bottom], [center, smallGap]]]]; [tempBox, tempBoxes] _ MathRules.Compose[boxes, alignments, $n, $radicand]; RETURN[tempBox, tempBoxes]; }; IntegrationCompRule: CompositionProc ~ { tempBox: BOX; tempBoxes: LIST OF BOX; alignments: LIST OF Alignment2D _ LIST[[$lowerlimit, [$integral, [right], [left, medGap]], [$integral, [top], [bottom, -smallGap]]], [$upperlimit, [$integral, [left], [right, -medGap]], [$integral, [bottom], [top, smallGap]]], [$integrand, [$integral, [left], [right]], [$integral, [center], [center]]], [$dx, [$integrand, [left], [right, smallGap]], [$integrand, [origin], [origin]]], [$wrt, [$dx, [left], [right]], [$dx, [origin], [origin]]]]; [tempBox, tempBoxes] _ MathRules.Compose[boxes, alignments, $lowerlimit, $integrand]; 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, $aliasUnaryOp]; 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, $aliasBinOp]; RETURN[tempBox, tempBoxes]; }; RelationCompRule: CompositionProc ~ { tempBox: BOX; tempBoxes: LIST OF BOX; leftVertOffsetLHS, leftVertOffsetRel, rightVertOffsetRHS, rightVertOffsetRel: Offset; alignments: LIST OF Alignment2D; SELECT MathBox.GetBox[$aliasLHS, boxes].FormatClass[] FROM over => { leftVertOffsetLHS _ [origin]; leftVertOffsetRel _ [center]; }; matrix => { leftVertOffsetLHS _ [center]; leftVertOffsetRel _ [center]; }; ENDCASE => { leftVertOffsetLHS _ [origin]; leftVertOffsetRel _ [origin]; }; SELECT MathBox.GetBox[$aliasRHS, boxes].FormatClass[] FROM over => { rightVertOffsetRHS _ [origin]; rightVertOffsetRel _ [center]; }; matrix => { rightVertOffsetRHS _ [center]; rightVertOffsetRel _ [center]; }; ENDCASE => { rightVertOffsetRHS _ [origin]; rightVertOffsetRel _ [origin]; }; alignments _ LIST[ [$aliasLeftSpace, [$aliasRelation, [right], [left]], [$aliasRelation, [origin], [origin]]], [$aliasLHS, [$aliasLeftSpace, [right], [left]], [$aliasRelation, leftVertOffsetLHS, leftVertOffsetRel]], [$aliasRightSpace, [$aliasRelation, [left], [right]], [$aliasRelation, [origin], [origin]]], [$aliasRHS, [$aliasRightSpace, [left], [right]], [$aliasRelation, rightVertOffsetRHS, rightVertOffsetRel]]]; [tempBox, tempBoxes] _ MathRules.Compose[boxes, alignments, $aliasLHS, $aliasRelation]; RETURN[tempBox, tempBoxes]; }; ComplexCompRule: CompositionProc ~ { tempBox: BOX; tempBoxes: LIST OF BOX; alignments: LIST OF Alignment2D _ LIST[[$a, [$plus, [right], [left, -smallGap]], [$plus, [origin], [origin]]], [$b, [$plus, [left], [right, smallGap]], [$plus, [origin], [origin]]], [$i, [$b, [left], [right, smallGap]], [$b, [origin], [origin]]]]; [tempBox, tempBoxes] _ MathRules.Compose[boxes, alignments, $a, $plus]; RETURN[tempBox, tempBoxes]; }; ProductCompRule: CompositionProc ~ { tempBox: BOX; tempBoxes: LIST OF BOX; alignments: LIST OF Alignment2D _ LIST[[$multiplier, [$multiplicand, [right], [left, -smallGap]], [$multiplicand, [origin], [origin]]]]; [tempBox, tempBoxes] _ MathRules.Compose[boxes, alignments, $multiplier, $multiplier]; RETURN[tempBox, tempBoxes]; }; ParenCompRule: CompositionProc ~ { tempBox: BOX; tempBoxes: LIST OF BOX; alignments: LIST OF Alignment2D _ LIST[ [$leftParen, [$a, [right], [left]], [$a, [center], [center]]], [$rightParen, [$a, [left], [right]], [$a, [center], [center]]]]; [tempBox, tempBoxes] _ MathRules.Compose[boxes, alignments, $leftParen, $a]; RETURN[tempBox, tempBoxes]; }; MakeBinOpClass: PUBLIC PROC[class, op, a, b: ATOM, operation: EXPR, description: ROPE, cvtAS: ROPE] 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, MakeSpace[thinSpace]]; rightSpace: Symbol _ MakeSymbol[$rightThinSpace, LIST[$aliasRightSpace], normal, MakeSpace[thinSpace]]; RETURN[MakeCompoundClass[class, binaryOp, description, LIST[aArg, bArg], LIST[opSym, leftSpace, rightSpace], FixedSizeBoxRule, BinaryOpCompRule, cvtAS]]; }; MakeRelationClass: PUBLIC PROC[class, rel, lhs, rhs: ATOM, relation: EXPR, description: ROPE, cvtAS: ROPE] RETURNS[CompoundClass] ~ { lhsArg: Argument _ MakeArgument[lhs, LIST[$aliasLHS, $aliasHot], normal]; rhsArg: Argument _ MakeArgument[rhs, LIST[$aliasRHS], normal]; relSym: Symbol _ MakeSymbol[rel, LIST[$aliasRelation], normal, relation]; leftSpace: Symbol _ MakeSymbol[$leftSpace, LIST[$aliasLeftSpace], normal, MakeSpace[medSpace]]; rightSpace: Symbol _ MakeSymbol[$rightSpace, LIST[$aliasRightSpace], normal, MakeSpace[medSpace]]; RETURN[MakeCompoundClass[class, relation, description, LIST[lhsArg, rhsArg], LIST[relSym, leftSpace, rightSpace], FixedSizeBoxRule, RelationCompRule, cvtAS]]; }; MakeUnaryOpClass: PUBLIC PROC[class, op, arg: ATOM, operation: EXPR, description: ROPE, cvtAS: ROPE] RETURNS[CompoundClass] ~ { argArg: Argument _ MakeArgument[arg, LIST[$aliasA, $aliasHot], normal]; spaceSym: Symbol _ MakeSymbol[$Space, LIST[$aliasSpace], normal, MakeSpace[medSpace]]; unaryOpSym: Symbol _ MakeSymbol[op, LIST[$aliasUnaryOp], normal, operation]; RETURN[MakeCompoundClass[class, unaryOp, description, LIST[argArg], LIST[unaryOpSym, spaceSym], FixedSizeBoxRule, UnaryOpCompRule, cvtAS]]; }; MakePlainSym: PROC[c: CHAR] RETURNS[EXPR] ~ { RETURN[MathExpr.MakeAtomicExpr[$plainSym, MathExpr.MakeAtomChar[c]]]; }; MakeOverlaySym: PROC[r: ROPE] RETURNS[EXPR] ~ { RETURN[MathExpr.MakeAtomicExpr[$overlaySym, MathExpr.MakeAtomRope[r]]]; }; MakeBigMathSym: PROC[c: CHAR] RETURNS[EXPR] ~ { RETURN[MathExpr.MakeAtomicExpr[$bigMathSym, MathExpr.MakeAtomChar[c]]]; }; MakeSmallMathSym: PROC[c: CHAR] RETURNS[EXPR] ~ { RETURN[MathExpr.MakeAtomicExpr[$smallMathSym, MathExpr.MakeAtomChar[c]]]; }; MakeItalSym: PROC[c: CHAR] RETURNS[EXPR] ~ { RETURN[MathExpr.MakeAtomicExpr[$italicSym, MathExpr.MakeAtomChar[c]]]; }; MakeMathItalSym: PROC[c: CHAR] RETURNS[EXPR] ~ { RETURN[MathExpr.MakeAtomicExpr[$mathItalicSym, MathExpr.MakeAtomChar[c]]]; }; MakeLine: PROC[] RETURNS[EXPR] ~ { RETURN[MathExpr.MakeAtomicExpr[$line, MathExpr.MakeAtomOther[NIL]]]; }; MakeSpace: PROC[b: ImagerFont.Extents] RETURNS[EXPR] ~ { RETURN[MathExpr.MakeAtomicExpr[$space, MathExpr.MakeAtomBox[b]]]; }; MakePlaceHolder: PUBLIC PROC[] RETURNS[EXPR] ~ { RETURN[MathExpr.MakeAtomicExpr[$placeholder, MathExpr.MakeAtomRope["\056\057"]]]; }; MakeInt: PUBLIC PROC[n: ROPE] RETURNS[EXPR] ~ { IF n.Length[] = 0 THEN ERROR badFormat; SELECT n.Fetch[0] FROM IN ['0..'9] => NULL; '- => IF n.Length[] = 1 THEN ERROR badFormat; -- a lone minus sign is invalid ENDCASE => ERROR badFormat; FOR i:INT IN[1..n.Length[]-1] DO SELECT n.Fetch[i] FROM IN ['0..'9] => NULL; ENDCASE => ERROR badFormat; ENDLOOP; RETURN[MathExpr.MakeAtomicExpr[$integer, MathExpr.MakeAtomRope[n]]]; }; MakeReal: PUBLIC PROC[r: REAL] RETURNS[EXPR] ~ { RETURN[MathExpr.MakeAtomicExpr[$real, MathExpr.MakeAtomRope[Convert.RopeFromReal[r]]]]; }; MakeVariable: PUBLIC PROC[var: ROPE] RETURNS[EXPR] ~ { IF var.Length[] = 0 THEN ERROR badFormat; FOR i:INT IN[0..var.Length[]-1] DO SELECT var.Fetch[i] FROM IN ['A..'Z], IN ['a..'z] => NULL; ENDCASE => ERROR badFormat; ENDLOOP; RETURN[MathExpr.MakeAtomicExpr[$variable, MathExpr.MakeAtomRope[var]]]; }; MakeSum: PUBLIC PROC[addend, augend: EXPR] RETURNS[EXPR] ~ { RETURN[MathExpr.MakeCompoundExpr[$sum, LIST[[$addend, addend], [$augend, augend]]]]; }; MakeDifference: PUBLIC PROC[subtrahend, minuend: EXPR] RETURNS[EXPR] ~ { RETURN[MathExpr.MakeCompoundExpr[$difference, LIST[[$subtrahend, subtrahend], [$minuend, minuend]]]]; }; MakeAnd: PUBLIC PROC[a, b: EXPR] RETURNS[EXPR] ~ { RETURN[MathExpr.MakeCompoundExpr[$and, LIST[[$a, a], [$b, b]]]]; }; MakeOr: PUBLIC PROC[a, b: EXPR] RETURNS[EXPR] ~ { RETURN[MathExpr.MakeCompoundExpr[$or, LIST[[$a, a], [$b, b]]]]; }; MakeMatrix: PUBLIC PROC[nRows, nCols: NAT, rows: LIST OF LIST OF EXPR] RETURNS[EXPR] ~ { elements: LIST OF MathExpr.TaggedMathExpr _ NIL; rowCount, colCount: NAT _ 0; FOR l: LIST OF LIST OF EXPR _ rows, l.rest UNTIL l = NIL DO rowCount _ rowCount + 1; colCount _ 0; FOR elts: LIST OF EXPR _ l.first, elts.rest UNTIL elts = NIL DO colCount _ colCount + 1; elements _ CONS[[MathRules.AtomFromRowCol[rowCount, colCount], elts.first], elements]; ENDLOOP; ENDLOOP; RETURN[MathExpr.MakeMatrixExpr[[$matrix, matrix], nRows, nCols, elements, MakeBigMathSym['\042], MakeBigMathSym['\043], MakeSpace[[leftExtent: 0.0, rightExtent: 0.9, descent: 0.0, ascent: 0.6]]]]; }; MakeComplex: PUBLIC PROC[a, b: EXPR] RETURNS[EXPR] ~ { RETURN[MathExpr.MakeCompoundExpr[$complex, LIST[[$a, a], [$b, b]]]]; }; MakeProduct: PUBLIC PROC[multiplier, multiplicand: EXPR] RETURNS[EXPR] ~ { RETURN[MathExpr.MakeCompoundExpr[$product, LIST[[$multiplier, multiplier], [$multiplicand, multiplicand]]]]; }; MakeFraction: PUBLIC PROC[numerator, denominator: EXPR] RETURNS[EXPR] ~ { RETURN[MathExpr.MakeCompoundExpr[$fraction, LIST[[$numerator, numerator], [$denominator, denominator]]]]; }; MakePow: PUBLIC PROC[base, exponent: EXPR] RETURNS[EXPR] ~ { RETURN[MathExpr.MakeCompoundExpr[$pow, LIST[[$base, base], [$exponent, exponent]]]]; }; MakeParen: PUBLIC PROC[a: EXPR] RETURNS[EXPR] ~ { RETURN[MathExpr.MakeCompoundExpr[$paren, LIST[[$a, a]]]]; }; MakeEqFormula: PUBLIC PROC[lhs, rhs: EXPR] RETURNS[EXPR] ~ { RETURN[MathExpr.MakeCompoundExpr[$eqFormula, LIST[[$lhs, lhs], [$rhs, rhs]]]]; }; MakeNotEqFormula: PUBLIC PROC[lhs, rhs: EXPR] RETURNS[EXPR] ~ { RETURN[MathExpr.MakeCompoundExpr[$notEqFormula, LIST[[$lhs, lhs], [$rhs, rhs]]]]; }; MakeLtFormula: PUBLIC PROC[lhs, rhs: EXPR] RETURNS[EXPR] ~ { RETURN[MathExpr.MakeCompoundExpr[$ltFormula, LIST[[$lhs, lhs], [$rhs, rhs]]]]; }; MakeLeFormula: PUBLIC PROC[lhs, rhs: EXPR] RETURNS[EXPR] ~ { RETURN[MathExpr.MakeCompoundExpr[$leFormula, LIST[[$lhs, lhs], [$rhs, rhs]]]]; }; MakeGtFormula: PUBLIC PROC[lhs, rhs: EXPR] RETURNS[EXPR] ~ { RETURN[MathExpr.MakeCompoundExpr[$gtFormula, LIST[[$lhs, lhs], [$rhs, rhs]]]]; }; MakeGeFormula: PUBLIC PROC[lhs, rhs: EXPR] RETURNS[EXPR] ~ { RETURN[MathExpr.MakeCompoundExpr[$geFormula, LIST[[$lhs, lhs], [$rhs, rhs]]]]; }; MakeRadical: PUBLIC PROC[radicand, n: EXPR] RETURNS[EXPR] ~ { RETURN[MathExpr.MakeCompoundExpr[$radical, LIST[[$radicand, radicand], [$n, n]]]]; }; MakeSummation: PUBLIC PROC[lb, ub, summand: EXPR] RETURNS[EXPR] ~ { RETURN[MathExpr.MakeCompoundExpr[$summation, LIST[[$lowerbound, lb], [$summand, summand], [$upperbound, ub]]]]; }; MakeIntegral: PUBLIC PROC[llim, ulim, integrand, wrt: EXPR] RETURNS[EXPR] ~ { RETURN[MathExpr.MakeCompoundExpr[$integration, LIST[[$lowerlimit, llim], [$upperlimit, ulim], [$integrand, integrand], [$wrt, wrt]]]]; }; MakeNot: PUBLIC PROC[a: EXPR] RETURNS[EXPR] ~ { RETURN[MathExpr.MakeCompoundExpr[$not, LIST[[$a, a]]]]; }; MakeNegation: PUBLIC PROC[a: EXPR] RETURNS[EXPR] ~ { RETURN[MathExpr.MakeCompoundExpr[$negation, LIST[[$a, a]]]]; }; wrongAtomValueType: PUBLIC ERROR = CODE; wrongBoxType: PUBLIC ERROR = CODE; badFormat: PUBLIC ERROR = CODE; DefineClasses: PROC [] ~ { cmr10, cmti10, cmmi10, cmex10, cmsy10: Style; integerClass, realClass, variableClass, plainSymClass, overlaySymClass, smallMathSymClass, bigMathSymClass, italSymClass, mathItalSymClass, lineClass, placeholderClass, spaceClass: AtomClass; sumClass, summationClass, fractionClass, integrationClass, differenceClass, powClass, eqFormulaClass, notEqFormulaClass, ltFormulaClass, leFormulaClass, geFormulaClass, gtFormulaClass, radicalClass, complexClass, productClass, orClass, notClass, negationClass, andClass, parenClass: CompoundClass; lbArg, ubArg, summandArg, llimArg, ulimArg, integrandArg, wrtArg, baseArg, exponentArg, numeratorArg, denominatorArg, nArg, radicandArg, multiplierArg, multiplicandArg, realPartArg, imaginaryPartArg, aParenArg: Argument; plusSym, sigmaSym, integralSym, dxSym, lineSym, radRootSym, radLineSym, iSym, leftParenSym, rightParenSym: Symbol; MathDB.ResetAtomClasses[]; MathDB.ResetCompoundClasses[]; cmr10 _ [font: "xerox/pressfonts/cmr60"]; -- standard times roman (1 unit high) cmti10 _ [font: "xerox/pressfonts/cmti60"]; -- italic (1 unit high) cmex10 _ [font: "xerox/pressfonts/cmex60"]; -- math extentsion font (1 unit high) cmmi10 _ [font: "xerox/pressfonts/cmmi60"]; -- math italic font (1 unit high) cmsy10 _ [font: "xerox/pressfonts/cmsy60"]; -- math symbols font (1 unit high) integerClass _ MakeAtomClass[$integer, atom, argument, cmr10, RopeBox, PaintRope, CvtRopeToRope]; realClass _ MakeAtomClass[$real, atom, argument, cmr10, RopeBox, PaintRope, CvtRopeToRope]; variableClass _ MakeAtomClass[$variable, atom, argument, cmti10, RopeBox, PaintRope, CvtRopeToRope]; plainSymClass _ MakeAtomClass[$plainSym, atom, symbol, cmr10, CharBox, PaintChar, CvtCharToRope]; overlaySymClass _ MakeAtomClass[$overlaySym, atom, symbol, cmr10, OverlayBox, PaintOverlay, CvtRopeToRope]; bigMathSymClass _ MakeAtomClass[$bigMathSym, atom, symbol, cmex10, CharBox, PaintChar, CvtCharToRope]; smallMathSymClass _ MakeAtomClass[$smallMathSym, atom, symbol, cmsy10, CharBox, PaintChar, CvtCharToRope]; mathItalSymClass _ MakeAtomClass[$mathItalicSym, atom, symbol, cmmi10, CharBox, PaintChar, CvtCharToRope]; italSymClass _ MakeAtomClass[$italicSym, atom, symbol, cmti10, CharBox, PaintChar, CvtCharToRope]; lineClass _ MakeAtomClass[$line, atom, symbol, cmr10, LineBox, PaintLine, CvtOtherToRope]; placeholderClass _ MakeAtomClass[$placeholder, atom, placeholder, cmmi10, RopeBox, PaintRope, CvtRopeToRope]; spaceClass _ MakeAtomClass[$space, atom, symbol, cmr10, SpaceBox, PaintSpace, CvtSpaceToRope]; MathDB.InstallAtomClass[integerClass]; MathDB.InstallAtomClass[realClass]; MathDB.InstallAtomClass[variableClass]; MathDB.InstallAtomClass[plainSymClass]; MathDB.InstallAtomClass[overlaySymClass]; MathDB.InstallAtomClass[italSymClass]; MathDB.InstallAtomClass[smallMathSymClass]; MathDB.InstallAtomClass[bigMathSymClass]; MathDB.InstallAtomClass[mathItalSymClass]; MathDB.InstallAtomClass[lineClass]; MathDB.InstallAtomClass[placeholderClass]; MathDB.InstallAtomClass[spaceClass]; realPartArg _ MakeArgument[$a, LIST[$aliasA, $aliasHot], normal]; imaginaryPartArg _ MakeArgument[$b, LIST[$aliasB], normal]; iSym _ MakeSymbol[$i, NIL, normal, MakeItalSym['i]]; plusSym _ MakeSymbol[$plus, LIST[$aliasBinOp], normal, MakePlainSym['+]]; multiplierArg _ MakeArgument[$multiplier, LIST[$aliasA, $aliasHot], normal]; multiplicandArg _ MakeArgument[$multiplicand, LIST[$aliasB], normal]; lbArg _ MakeArgument[$lowerbound, NIL, script]; ubArg _ MakeArgument[$upperbound, NIL, script]; summandArg _ MakeArgument[$summand, LIST[$aliasHot], normal]; sigmaSym _ MakeSymbol[$sigma, LIST[$aliasOp], normal, MakeBigMathSym['\130]]; llimArg _ MakeArgument[$lowerlimit, NIL, script]; ulimArg _ MakeArgument[$upperlimit, NIL, script]; integrandArg _ MakeArgument[$integrand, LIST[$aliasHot], normal]; wrtArg _ MakeArgument[$wrt, NIL, script]; integralSym _ MakeSymbol[$integral, LIST[$aliasOp], normal, MakeBigMathSym['\132]]; dxSym _ MakeSymbol[$dx, NIL, script, MakeItalSym['d]]; 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]; lineSym _ MakeSymbol[$fractionBar, LIST[$aliasLine], normal, MakeLine[]]; nArg _ MakeArgument[$n, LIST[$aliasB], script]; radicandArg _ MakeArgument[$radicand, LIST[$aliasA, $aliasHot], normal]; radRootSym _ MakeSymbol[$radRoot, NIL, normal, MakeBigMathSym['\162]]; radLineSym_ MakeSymbol[$radLine, LIST[$aliasLine], normal, MakeLine[]]; aParenArg _ MakeArgument[$a, LIST[$aliasA, $aliasHot], normal]; leftParenSym _ MakeSymbol[$leftParen, NIL, normal, MakeBigMathSym['\040]]; rightParenSym _ MakeSymbol[$rightParen, NIL, normal, MakeBigMathSym['\041]]; sumClass _ MakeBinOpClass[$sum, $plus, $addend, $augend, MakePlainSym['+], "a + b", "$addend + $augend"]; differenceClass _ MakeBinOpClass[$difference, $minus, $subtrahend, $minuend, MakePlainSym['\173], "a - b", "$subtrahend - $minuend"]; andClass _ MakeBinOpClass[$and, $andOp, $a, $b, MakeSmallMathSym['\136], "a AND b", "$a & $b"]; orClass _ MakeBinOpClass[$or, $orOp, $a, $b, MakeSmallMathSym['\137], "a OR b", "$a | $b"]; negationClass _ MakeUnaryOpClass[$negation, $minus, $a, MakePlainSym['-], "-a", "-$a"]; notClass _ MakeUnaryOpClass[$not, $notOp, $a, MakeSmallMathSym['\072], "~a", "~ $a"]; eqFormulaClass _ MakeRelationClass[$eqFormula, $equals, $lhs, $rhs, MakePlainSym['=], "lhs = rhs", "$lhs = $rhs"]; notEqFormulaClass _ MakeRelationClass[$notEqFormula, $equals, $lhs, $rhs, MakeOverlaySym["=/"], "lhs # rhs", "$lhs # $rhs"]; ltFormulaClass _ MakeRelationClass[$ltFormula, $lt, $lhs, $rhs, MakeMathItalSym['<], "lhs < rhs", "$lhs < $rhs"]; gtFormulaClass _ MakeRelationClass[$gtFormula, $gt, $lhs, $rhs, MakeMathItalSym['>], "lhs > rhs", "$lhs > $rhs"]; leFormulaClass _ MakeRelationClass[$leFormula, $le, $lhs, $rhs, MakeSmallMathSym['\024], "lhs <= rhs", "$lhs <= $rhs"]; geFormulaClass _ MakeRelationClass[$geFormula, $ge, $lhs, $rhs, MakeSmallMathSym['\025], "lhs >= rhs", "$lhs >= $rhs"]; complexClass _ MakeCompoundClass[$complex, other, "a + bi", LIST[realPartArg, imaginaryPartArg], LIST[iSym, plusSym], FixedSizeBoxRule, ComplexCompRule, "($a + $bi)"]; productClass _ MakeCompoundClass[$product, binaryOp, "a * b", LIST[multiplierArg, multiplicandArg], NIL, FixedSizeBoxRule, ProductCompRule, "$multiplier $multiplicand"]; summationClass _ MakeCompoundClass[$summation, op, "summation", LIST[lbArg, ubArg, summandArg], LIST[sigmaSym], FixedSizeBoxRule, SummationCompRule, "(summation ($lowerbound) ($upperbound) ($summand))"]; integrationClass _ MakeCompoundClass[$integration, op, "integration", LIST[llimArg, ulimArg, integrandArg, wrtArg], LIST[integralSym, dxSym], FixedSizeBoxRule, IntegrationCompRule, "(integral ($lowerlimit) ($upperlimit) ($integrand) ($wrt))"]; powClass _ MakeCompoundClass[$pow, other, "a^b", LIST[baseArg, exponentArg], NIL, FixedSizeBoxRule, PowCompRule, "$base^$exponent"]; parenClass _ MakeCompoundClass[$paren, paren, "( a )", LIST[aParenArg], LIST[leftParenSym, rightParenSym], ParenBoxRule, ParenCompRule, "( $a )"]; fractionClass _ MakeCompoundClass[$fraction, over, "a / b", LIST[numeratorArg, denominatorArg], LIST[lineSym], FractionBoxRule, FractionCompRule, "$numerator / $denominator"]; radicalClass _ MakeCompoundClass[$radical, radical, "radical", LIST[nArg, radicandArg], LIST[radRootSym, radLineSym], RadicalBoxRule, RadicalCompRule, "(root ($radicand) ($n))"]; MathDB.InstallCompoundClass[sumClass]; MathDB.InstallCompoundClass[differenceClass]; MathDB.InstallCompoundClass[andClass]; MathDB.InstallCompoundClass[orClass]; MathDB.InstallCompoundClass[notClass]; MathDB.InstallCompoundClass[negationClass]; MathDB.InstallCompoundClass[powClass]; MathDB.InstallCompoundClass[parenClass]; MathDB.InstallCompoundClass[complexClass]; MathDB.InstallCompoundClass[productClass]; MathDB.InstallCompoundClass[summationClass]; MathDB.InstallCompoundClass[integrationClass]; MathDB.InstallCompoundClass[fractionClass]; MathDB.InstallCompoundClass[radicalClass]; MathDB.InstallCompoundClass[eqFormulaClass]; MathDB.InstallCompoundClass[notEqFormulaClass]; MathDB.InstallCompoundClass[ltFormulaClass]; MathDB.InstallCompoundClass[leFormulaClass]; MathDB.InstallCompoundClass[gtFormulaClass]; MathDB.InstallCompoundClass[geFormulaClass]; }; DefineClasses[]; END. ΈMathConstructorsImpl.mesa Carl Waldspurger, August 19, 1986 11:16:17 pm PDT Type Abbreviations Procedure Abbreviations Constants Common Rule Procs Common Paint Procs effects: Paints value.char onto context in absBox check types anything but char is a type error effects: Paints value.rope as a sequence of centered superimposed characters. This is useful for things like negated symbols (/ slashed through)... check types scale Font paint chars, one by one, on tope of each other anything but rope is a type error effects: Paints value.rope onto context in absBox check types anything but rope is a type error effects: Paints a line onto context filling absBox caveats: Ignores value & style effects: none Common Box Procs & AtomToRopeProcs effects: Returns a bounding box for a line Note that this is always a dummy value don't really need any data from value; always return [0, 1, 0, 1] effects: Always returns the empty rope "". effects: Returns a bounding box for value.char anything but a char is a type error effects: Returns value as a rope. anything but a char is a type error effects: Returns a bounding box for value.rope as a sequence of overlayed chars anything but a rope is a type error effects: Returns a bounding box for value.rope anything but a rope is a type error effects: Returns value. anything but a rope is a type error effects: Returns a bounding box for value.box anything but a rope is a type error effects: Returns the empty rope NIL. Common Compound Procs Box Rules effects: Returns unaltered boxes (i.e. no resizing takes place) 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 effects: Sizes boxes for expr of form ($paren $a) right and left parentheses must be as tall as expression a effects: Sizes boxes for expr of form ($radRoot $radLine $n $radicand) should ENABLE noSuchBox line must be exactly as long as radicand, root symbol must be 1.2 * as tall as radicand adjust symbol extents Composition Rules effects: Composes layout for expr of form ($exponent $base) effects: Composes layout for expr of form ($fractionBar $numerator $denominator) effects: Composes layout for expr of form ($summation $lowerbound $upperbound $summand) effects: Compose layout for expr of form ($radRoot $radLine $n $radicand) effects: Composes layout for expr of form ($integral $lowerlimit $upperlimit $integrand $dx $wrt) 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 ($aliasRelation $aliasLHS $aliasRHS) with symbols $aliasLeftSpace & $aliasRightSpace. set vertical offset depending on format classes of lhs & rhs arguments effects: Composes layout for expr of form ($complex $a $b) effects: Composes layout for expr of form ($product $multiplier $multiplicand) effects: Composes layout for expr of form ($paren $a) with symbols $leftParen and $rightParen Class Constructors 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". effects: Creates and returns standard relation compound class named "class". The alignment is "lhs relation rhs"; alignment is thru baselines. All of lhs, rhs, rel are of fixed size "normal". 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". High Level Expression Constructors Atoms effects: Returns a symbol expression which is all the chars in r superimposed. effects: Constructs and returns an integer expression for n. SIGNALS badFormat if n is not a legal integer. check that each char in n is a legal digit effects: Constructs and returns a real expression for n. effects: Constructs and returns a variable expression for var. SIGNALS badFormat if n is not a legal variable (e.g. invalid chars). check that each char is an alphabetic char A thru Z, either case Binary Ops Matrix local declarations Other Relations Radical Ops Unary Ops Signals & Errors Define & Install Atom and Compound Classes local declarations (lots of 'em) reset current DB state (i.e. clean slate) plain vanilla TeX fonts define Atom Classes register atom classes define info for "complex a b" (a + bi) define info for "product multiplier multiplicand" define info for "summation lowerbound upperbound summand" define info for "integral lowerlimit upperlimit integrand" define info for "pow base exponent" define info for "fraction numerator denominator" define info for "radical n radicand" define info for "( a )" define compound classes binary operations unary operations relations others register compound classes binary ops unary ops others relations Install Classes Defined in this Module Κ˜Jšœ™Jšœ1™1J˜J˜codešΟk ˜ Kšœ ˜ Kšœ ˜ K˜K˜ K˜Kšœ ˜ K˜Kšœ˜Kšœœœ˜!Kšœœœ˜Kšœœ˜+Kšœ˜K˜—J˜šΟnœœœ˜$šœI˜PJ˜—Jšœ˜J˜Jš˜—˜Jšž™˜Jšœœ œ˜Jšœœ œ˜Jšœœœ˜Jšœœ œ˜Jšœ œ˜*Jšœœ˜.Jšœœ˜2Jšœœ˜2Jšœœ˜0Jšœ œ˜*Jšœœ˜ Jšœœ˜Jšœ œ˜&Jšœœ˜.Jšœœ˜.Jšœœ˜,J˜Jšœ œ˜#Jšœœ˜Jšœ œ˜%Jšœ œ˜'Jšœœ˜-Jšœ œ˜*Jšœœ˜—J˜šž™J˜Jšž œœœ œœœœ#˜lJ˜Jšž œœœ œœœœœ˜sJ˜Jšž œœœ‡œ%˜ΡJ˜Jšžœœœ)œœœœœDœœœ-˜ϊJ˜—J˜Jšž ™ ˜Jšœ œ˜Jšœœ˜Jšœœ˜J˜J˜aJ˜`J˜—J™šž™J˜Jšž™J˜šž œ˜Kšœ2™2K˜Kšœ ™ Kšœœœ˜6K˜šœœ˜˜K˜4K˜CKšœ œ?˜LKšœ œ8˜EK˜K˜'Kšœc˜cK˜"K˜—K˜Kšœ!™!Kšœœ˜$—K˜K˜—K˜šž œ˜KšœN™NKšœP™PK™Kšœ ™ Kšœœœ˜6K˜šœœ˜šœ˜K˜4K˜7Kšœ œ?˜LKšœ œ8˜EKšœ ™ KšœQ˜QK˜Kšœ.™.šœœœ˜&Kšœ)œ˜?K˜>Kšœ œ?˜LK˜:K˜ K˜Kšœ!˜!Kšœ˜—K˜K˜—Kšœ!™!Kšœœ˜$—K˜K˜—K˜šž œ˜Kšœ2™2K˜Kšœ ™ Kšœœœ˜6K˜šœœ˜šœ˜K˜4K˜GKšœ œ?˜LKšœ œ8˜EK˜K˜'K˜bK˜!K˜K˜—Kšœ!™!Kšœœ˜$—K˜K˜K˜—šž œ˜Kšœ3™3Kšœ™K˜Kšœ£˜£Kšœ!˜!K˜—K˜šž œ˜Kšœ™Kšœ˜K˜K˜K˜—Kšž"™"K˜šžœ˜Kšœ+™+Kšœ0™0K˜KšœA™AKšœB˜HK˜—K˜šžœ˜"Kšœ+™+Kšœ˜ K˜K˜—šžœ˜Kšœ.™.K˜K˜Sšœœ˜Kšœœ'˜AKšœ#™#Kšœœ˜$—K˜—K˜šž œ˜!Kšœ"™"K˜šœœ˜Kšœœœœ˜WKšœ#™#Kšœœ˜$—K˜—K˜šž œ˜KšœO™OK˜K˜SKšœ#œ Οc%˜UK˜šœœ˜šœ˜šœœœ˜&KšœFœ˜]Kšœ œ˜'Kšœ œ˜*Kšœœ˜Kšœ œ˜$Kšœ˜—KšœP˜VK˜—Kšœ#™#Kšœœ˜$—K˜K˜—šžœ˜Kšœ/™/K˜K˜Sšœœ˜Kšœœ+˜EKšœ#™#Kšœœ˜$—K˜—K˜šž œ˜!Kšœ™K˜šœœ˜Kšœœ ˜#Kšœ#™#Kšœœ˜$—K˜—K˜šžœ˜Kšœ.™.K˜šœœ˜Kšœœ˜!Kšœ#™#Kšœœ˜$—K˜—K˜šžœ˜"Kšœ%™%Kšœœ˜ K˜K˜—K˜K˜—šž™K˜Kšž ™ K˜šžœ˜%Kšœ@™@Kšœ˜K˜—K˜šžœ˜$KšœM™MK˜Kšœ™Kšœ œ'˜3Kšœœ%˜0Kšœ œ'˜4K˜KšœC™CKšœœ œ5˜MK˜Kšœ™K˜0K˜Kšœœ˜(K˜K˜—šž œ˜!Kšœ2™2K™Kšœœ%˜6Kšœœ&˜8Kšœœ˜&K˜Kšœ:™:Kšœ œ/˜@K˜GK˜IK˜Kšœœ%˜0K˜K˜—K˜šžœ˜#KšœG™GK˜Kšœ™Kšœ œ%˜4Kšœ œ%˜4Kšœœ˜'Kšœ œ$˜4K˜Kšœ)™)Kšœ-™-Kšœ œ4˜CKšœ œ1˜?K˜Kšœ™K˜?K˜2K˜Kšœœ-˜8K˜—K˜K˜Kšž™K˜šž œ˜ Kšœ<™Kšœ!œ$˜IKšœ+œ0˜_Kšœ-œ1˜bK˜Kšœ1œœM˜žK˜—K˜šžœœœœ œœ œœ˜KšœT™TKšœJ™JKšœ2™2K™Kšœ%œ˜GKšœ&œ,˜VKšœ$œ%˜MKšœ0œ œC˜‹K˜K˜—K˜—šž"™"K˜Kšž™K˜š ž œœœœœ˜-Kšœ?˜EK˜—K˜š žœœœœœ˜/KšœO™OKšœA˜GK˜K˜—š žœœœœœ˜/KšœA˜GK˜—K˜š žœœœœœ˜1KšœC˜IK˜—K˜š ž œœœœœ˜,Kšœ@˜FK˜—K˜š žœœœœœ˜0KšœD˜JK˜—K˜šžœœœœ˜"Kšœ7œ˜DK˜——˜šž œœœœ˜8Kšœ;˜AK˜K˜—š žœœœœœ˜0KšœL˜RK˜—K˜š žœœœœœœ˜/Kšœ=™=Kšœ8™8K™Kšœœœ ˜'K˜šœ ˜Kšœ œ˜Kšœœœœ Ÿ˜NKšœœ ˜—K˜Kšœ*™*šœœœ˜ šœ ˜Kšœ œ˜Kšœœ ˜—Kšœ˜—Kšœ>˜DK˜—K˜š žœœœœœœ˜0Kšœ9™9K™KšœQ˜WK˜—K˜š ž œœœœœœ˜6Kšœ?™?KšœN™NK™Kšœœœ ˜)K™Kšœ@™@šœœœ˜"šœ˜Kšœ œ œ˜!Kšœœ ˜—Kšœ˜—K™KšœA˜GK˜K˜—K˜Kšž ™ K˜š žœœœœœœ˜˜oK˜—K˜š ž œœœœœœ˜MKšœ)œS˜†K˜—K˜Kšž ™ K™š žœœœœœœ˜/Kšœ!œ ˜7K˜—K˜š ž œœœœœœ˜4Kšœ&œ ˜œ"œB˜©Kšœ@œœg˜ΛKšœFœ*œ{˜σKšœ1œœ4˜„Kšœ7œ œG˜“Kšœ<œ œK˜―Kšœ?œœV˜²K˜Kšœ™K™Kšœ ™ K˜&K˜-K˜&K˜%K˜Kšœ ™ K˜'K˜,K˜Kšœ™K˜&K˜(K˜*K˜*K˜,K˜.K˜+K˜*K˜Kšœ ™ K˜,K˜/K˜,K˜,K˜,K˜,K˜K˜—K˜Kšœ&™&K˜K˜K˜—šœ˜K˜———…—yV¬&