DIRECTORY AbSets, BiRels, Histograms, HistogramsViewing, HistogramsViewingExtras, IntStuff, LichenDataOps, LichenDataStructure, LichenIntBasics, Process, Real, RealFns, Rope, SetBasics; LichenChecking: CEDAR PROGRAM IMPORTS AbSets, BiRels, Histograms, HistogramsViewing, HistogramsViewingExtras, IntStuff, LichenDataStructure, LichenIntBasics, Process, Real, RealFns, Rope, SetBasics EXPORTS LichenDataOps = BEGIN OPEN IS:IntStuff, LichenIntBasics, LichenDataOps, LichenDataStructure, Sets:AbSets; Histogram: TYPE ~ Histograms.Histogram; Viewer: TYPE ~ HistogramsViewing.Viewer; CheckDesign: PUBLIC PROC [d: Design] = { CheckSubscript: PROC [pair: BiRels.Pair] RETURNS [BOOL] ~ { pw: PW ~ pair[left].VA; class: PWClass ~ ClassOfPart[pw]; cct: CellType ~ NARROW[d.cct[class].ApplyA[pw].MA]; kids: Seq--of PW-- ~ BiRels.VB[pair[right]]; CheckKid: PROC [pair: BiRels.Pair] RETURNS [BOOL] ~ { index: INT ~ pair[left].VI; kid: PW ~ pair[right].VA; IF class # ClassOfPart[kid] THEN Error["Broken"]; IF d.cct[class].ApplyA[kid].MA # cct THEN Error["Broken"]; IF NOT d.parent.HasAA[kid, pw] THEN Error["Broken"]; RETURN [FALSE]}; IF kids.Scan[CheckKid].found THEN ERROR; RETURN [FALSE]}; CheckParent: PROC [pair: BiRels.Pair] RETURNS [BOOL] ~ { kid: Sets.Value ~ pair[left]; parent: Sets.Value ~ pair[right]; kids: Seq--of PW-- ~ BiRels.VB[d.sub.Apply[parent].Val]; IF NOT kids.HasMapping[kid, rightToLeft] THEN Error["Broken"]; RETURN [FALSE]}; CheckCIType: PROC [pair: BiRels.Pair] RETURNS [BOOL] ~ { ci: CellInstance ~ NARROW[pair[left].VA]; ct: CellType ~ NARROW[pair[right].VA]; IF NOT (d.cellTypes.HasMemA[ct] AND d.partses[i].HasMemA[ci]) THEN ERROR Error["Broken"]; RETURN [FALSE]}; CheckCTName: PROC [pair: BiRels.Pair] RETURNS [BOOL] ~ { ct: CellType ~ NARROW[pair[left].VA]; name: ROPE ~ NARROW[pair[right].VA]; IF NOT d.cellTypes.HasMemA[ct] THEN ERROR Error["Broken"]; RETURN [FALSE]}; CheckArrayElt: PROC [pair: BiRels.Pair] RETURNS [BOOL] ~ { act: CellType ~ NARROW[pair[left].VA]; ect: CellType ~ NARROW[pair[left].VA]; IF NOT (d.cellTypes.HasMemA[act] AND d.cellTypes.HasMemA[ect]) THEN ERROR Error["Broken"]; IF act.asArray=NIL OR d.labelCellTypes.HasMemA[ect] THEN ERROR Error["Broken"]; RETURN [FALSE]}; CheckCIXfm: PROC [pair: BiRels.Pair] RETURNS [BOOL] ~ { ci: CellInstance ~ NARROW[pair[left].VA]; xfm: Transform ~ VXfm[pair[right]]; IF NOT d.partses[i].HasMemA[ci] THEN ERROR Error["Broken"]; RETURN [FALSE]}; PerCellType: PROC [ctv: Sets.Value] RETURNS [BOOL] = { ct: CellType ~ NARROW[ctv.VA]; IF ct.d # d THEN Error["Broken"]; CheckCellType[ct]; RETURN [FALSE]}; IF d.physd # (d.ciXfm#nilBiRel) OR d.physd # (d.scale#0.0) THEN ERROR Error["Broken"]; IF NOT d.labelCellTypes.Subset[d.cellTypes] THEN ERROR Error["Broken"]; IF NOT d.crossedCellTypes.Subset[d.cellTypes] THEN ERROR Error["Broken"]; IF d.sub.Scan[CheckSubscript].found THEN ERROR; Process.CheckForAbort[]; IF d.parent.Scan[CheckParent].found THEN ERROR; Process.CheckForAbort[]; FOR pc: PartClass IN PartClass DO CheckCCT: PROC [pair: BiRels.Pair] RETURNS [BOOL] ~ { part: Part ~ NARROW[pair[left].VA]; cct: CellType ~ NARROW[pair[right].VA]; IF ClassOfPart[part]#pc OR NOT d.cellTypes.HasMemA[cct] THEN ERROR Error["Broken"]; IF pc=i THEN { IF NOT d.ciType.HasMapping[pair[left]] THEN ERROR Error["Broken"]; IF d.physd AND NOT d.ciXfm.HasMapping[pair[left]] THEN ERROR Error["Broken"]}; RETURN [FALSE]}; IF d.cct[pc].Scan[CheckCCT].found THEN ERROR; Process.CheckForAbort[]; ENDLOOP; IF d.ciType.Scan[CheckCIType].found THEN ERROR; Process.CheckForAbort[]; IF d.ctName.Scan[CheckCTName].found THEN ERROR; Process.CheckForAbort[]; IF d.arrayElt.Scan[CheckArrayElt].found THEN ERROR; Process.CheckForAbort[]; IF d.physd AND d.ciXfm.Scan[CheckCIXfm].found THEN ERROR; Process.CheckForAbort[]; IF d.cellTypes.Scan[PerCellType].found THEN ERROR; Process.CheckForAbort[]; RETURN}; CheckCellType: PROC [ct: CellType] = { d: Design ~ ct.d; unorg: BOOL ~ ct.asu # NIL; isarray: BOOL ~ ct.asArray # NIL; IF NOT d.cellTypes.HasMemA[ct] THEN Error["Broken"]; IF (ct.asArray#NIL) # d.arrayElt.HasMapA[ct] THEN Error["Broken"]; IF d.physd # (ct.bbox # fullRange2) THEN Error["Broken"]; FOR pc: PartClass IN PartClass DO CheckFullName: PROC [pair: BiRels.Pair] RETURNS [BOOL] ~ { part: Part ~ pair[left].VA; IF NOT d.cct[pc].HasAA[part, ct] THEN ERROR; RETURN [FALSE]}; IF (ct.fullName[pc]#nilBiRel) # (pc=p OR unorg) THEN Error["Broken"]; IF ct.fullName[pc]#nilBiRel AND ct.fullName[pc].Scan[CheckFullName].found THEN ERROR; Process.CheckForAbort[]; ENDLOOP; IF unorg THEN { CheckConns: PROC [c: Cell, conns: Fn--port _ Wire--, ports: Set--of Port--] ~ { CheckCConn: PROC [pair: BiRels.Pair] RETURNS [BOOL] ~ { p: Port ~ NARROW[pair[left].VA]; w: Wire ~ NARROW[pair[right].VA]; IF NOT w.conns.HasAA[p, c] THEN ERROR; RETURN [FALSE]}; IF ports.ScanIntersection[LIST[d.isAtomic, conns.SetOn[left].Negate]].found THEN Error["Broken"]; IF conns.Scan[CheckCConn].found THEN ERROR; RETURN}; CheckSubcell: PROC [ra: REF ANY] ~ { ci: CellInstance ~ NARROW[ra]; ict: CellType ~ d.CiT[ci]; IF d.physd THEN { xfm: Transform ~ VXfm[d.ciXfm.ApplyA[ci].Val]; ibb: Range2 ~ TransOffRange2[xfm, ci.offset, ict.bbox]; IF NOT Range2Included[ibb, ct.bbox] THEN Error["Broken"]} ELSE IF ci.offset # dullInt2 THEN Error["Broken"]; CheckConns[ci, ci.conns, ict.CTParts[p]]; RETURN}; CheckWire: PROC [wv: Sets.Value] RETURNS [BOOL] ~ { w: Wire ~ NARROW[wv.VA]; CheckWConn: PROC [pair: BiRels.Pair] RETURNS [BOOL] ~ { p: Port ~ NARROW[pair[left].VA]; WITH pair[right].VA SELECT FROM ci: CellInstance => IF NOT ci.conns.HasAA[p, w] THEN Error["Broken"]; t: CellType => {IF t#ct THEN Error["Broken"]; IF NOT ct.asu.exports.HasAA[p, w] THEN Error["Broken"]}; ENDCASE => ERROR; RETURN [FALSE]}; IF w.conns.Scan[CheckWConn].found THEN ERROR; RETURN [FALSE]}; ct.Subcells.EnumA[CheckSubcell]; Process.CheckForAbort[]; IF ct.CTParts[w].Scan[CheckWire].found THEN ERROR; Process.CheckForAbort[]; CheckConns[ct, ct.asu.exports, ct.CTParts[p]]; Process.CheckForAbort[]; }; IF isarray THEN { a: Array ~ ct.asArray; sr: StatRep ~ a.statrep; dr: DumRep ~ a.dumrep; ect: CellType ~ ct.EltType; arrayPorts: Set ~ ct.CTParts[p]; eltPorts: Set ~ ect.CTParts[p]; phaseRange: Range2 ~ SizeRange[a.basePeriod]; aiRange: Range2 ~ SizeRange[a.size2]; CheckStatEdge: PROC [sev: Sets.Value] RETURNS [BOOL] ~ { se: StatEdge ~ NARROW[sev.VA]; svA: StatVertex ~ se.SeRSv[sr, FALSE]; svB: StatVertex ~ se.SeRSv[sr, TRUE]; IF NOT (sr.portEdge[FALSE].HasAA[svA.port, se] AND sr.portEdge[TRUE].HasAA[svB.port, se]) THEN Error["Broken"]; IF NOT InRange[svA.phase, phaseRange] THEN Error["Broken"]; IF svB.phase # AddMod[svA.phase, se.d, a.basePeriod] THEN Error["Broken"]; RETURN [FALSE]}; CheckExport: PROC [pair: BiRels.Pair] RETURNS [BOOL] ~ { ap: Port ~ NARROW[pair[left].VA]; pai: PortAtIndex ~ VPai[pair[right]]; IF NOT (arrayPorts.HasMemA[ap] AND eltPorts.HasMemA[pai.port]) THEN Error["Broken"]; IF NOT InRange[pai.ai, aiRange] THEN Error["Broken"]; RETURN [FALSE]}; CheckDumbWire: PROC [dwv: Sets.Value] RETURNS [BOOL] ~ { dw: DumbWire ~ NARROW[dwv.VA]; CheckEps: PROC [pair: BiRels.Pair] RETURNS [BOOL] ~ { ep: Port ~ NARROW[pair[left].VA]; cai: CompositeArrayIndex ~ pair[right].VI; dws: Fn ~ BiRels.VB[dr.epToWire.ApplyA[ep].Val]; IF cai >= a.size THEN ERROR; IF NOT dws.HasIA[cai, dw] THEN Error["Broken"]; RETURN [FALSE]}; IF dw.eps.Scan[CheckEps].found THEN ERROR; RETURN [FALSE]}; CheckDWS: PROC [pair: BiRels.Pair] RETURNS [BOOL] ~ { ep: Port ~ NARROW[pair[left].VA]; dws: Fn ~ BiRels.VB[pair[right]]; CheckIndex: PROC [pair: BiRels.Pair] RETURNS [BOOL] ~ { cai: CompositeArrayIndex ~ pair[left].VI; dw: DumbWire ~ NARROW[pair[right].VA]; IF NOT dw.eps.HasPair[[AV[ep], IV[cai]]] THEN Error["Broken"]; RETURN [FALSE]}; IF dws.SetOn[right].Difference[dr.wires].NonEmpty THEN Error["Broken"]; IF dws.Scan[CheckIndex].found THEN ERROR; RETURN [FALSE]}; IF a.size # Area[a.size2] THEN Error["Broken"]; FOR dim: Dim2 IN Dim2 DO IF a.basePeriod[dim] > a.size2[dim] THEN Error["Broken"]; ENDLOOP; IF d.physd # (a.fXfm#nilBiRel) OR (a.fXfm#nilBiRel) # (a.offsets#NIL) THEN Error["Broken"]; IF a.buildPhase=statrepFixed AND a.dumrep=NIL THEN Error["Broken"]; IF sr.edges.Scan[CheckStatEdge].found THEN ERROR; Process.CheckForAbort[]; FOR b: BOOL IN BOOL DO IF sr.portEdge[b].SetOn[left].Difference[eltPorts].NonEmpty THEN Error["Broken"]; IF NOT sr.portEdge[b].SetOn[right].Equal[sr.edges] THEN Error["Broken"]; IF NOT sr.svEdge[b].SetOn[right].Equal[sr.edges] THEN Error["Broken"]; ENDLOOP; IF sr.apToPAI.Scan[CheckExport].found THEN ERROR; Process.CheckForAbort[]; IF a.buildPhase = statrepFixed THEN { IF dr.epToWire.SetOn[left].Difference[eltPorts].NonEmpty THEN Error["Broken"]; IF dr.apToWire.SetOn[left].Difference[arrayPorts].NonEmpty THEN Error["Broken"]; IF dr.apToWire.SetOn[right].Difference[dr.wires].NonEmpty THEN Error["Broken"]; IF dr.wires.Scan[CheckDumbWire].found THEN ERROR; IF dr.epToWire.Scan[CheckDWS].found THEN ERROR; }; }; RETURN}; base2: REAL _ RealFns.Power[base: 2.0, exponent: 0.25]; offset2: REAL _ RealFns.Power[base: base2, exponent: Real.Round[RealFns.Log[base: base2, arg: 0.1]]]; Status: TYPE ~ RECORD [i, n: INT _ 0, path, type: ROPE _ NIL]; status: REF Status _ NEW [Status _ []]; Hists: TYPE ~ RECORD [sizeCorr, combSize, wireSize, instSize: HV]; HV: TYPE ~ RECORD [h: Histogram, v: Viewer]; CountDesign: PROC [d: Design, histPrefix: ROPE, root: CellType _ NIL] RETURNS [cmpCellTypes, atmCellTypes, cellInstances, totWires, pubAtmWires, pvtAtmWires, pubCmpWires, pvtCmpWires, exblCmpWires, stuckWires, arrayFudge, atmPorts, cmpPorts, tNames, iNames, wNames, pNames: INT _ 0, hists: Hists] ~ { counted: Set ~ Sets.CreateHashSet[d.eSpace]; unorgUse: BiRel--parent CT X child CT-- ~ d.cct[i].Invert.Compose[d.ciType, ALL[TRUE]]; CountCellType: PROC [ctv: Sets.Value] RETURNS [BOOL] ~ { IF NOT counted.AddElt[ctv] THEN RETURN [FALSE]; IF unorgUse.ScanMapping[ctv, CountCellType].found THEN ERROR; IF d.arrayElt.ScanMapping[ctv, CountCellType].found THEN ERROR; {ct: CellType ~ NARROW[ctv.VA]; ports: Set ~ ct.CTParts[p]; cmp: BOOL ~ ct.asu#NIL OR ct.asArray#NIL; oldInsts: INT ~ cellInstances; oldWires: INT ~ totWires; IF cmp THEN cmpCellTypes _ cmpCellTypes + 1 ELSE atmCellTypes _ atmCellTypes + 1; pNames _ pNames + ct.fullName[p].Size.EN; IF ct.asu#NIL THEN { wires: Set ~ ct.CTParts[w]; atmWires: Set ~ wires.Intersection[d.isAtomic]; cmpWires: Set ~ wires.Intersection[d.isComposite]; nonPubs: Set ~ ct.asu.notPublics; pvts: Set ~ wires.Difference[d.ancest.Image[ct.asu.publics]].CreateHashCopy; exCands: Set ~ nonPubs.Difference[pvts].CreateHashCopy; pvtAtms: Set ~ nonPubs.Intersection[d.isAtomic]; pvtCmps: Set ~ pvts.Difference[atmWires]; troubled: Set ~ ct.asu.troubled.CreateHashCopy; cellInstances _ cellInstances + ct.CTParts[i].Size.EN; pubAtmWires _ pubAtmWires + atmWires.Intersection[ct.asu.publics].Size.EN; pvtAtmWires _ pvtAtmWires + atmWires.Intersection[pvts].Size.EN; pubCmpWires _ pubCmpWires + cmpWires.Intersection[ct.asu.publics].Size.EN; pvtCmpWires _ pvtCmpWires + pvtCmps.Size.EN; exblCmpWires _ exblCmpWires + exCands.Difference[troubled].Size.EN; stuckWires _ stuckWires + exCands.Intersection[troubled].Size.EN; totWires _ totWires + wires.Size.EN; IF totWires # pubAtmWires + pvtAtmWires + pubCmpWires + pvtCmpWires + exblCmpWires + stuckWires THEN ERROR; iNames _ iNames + ct.fullName[i].Size.EN; wNames _ wNames + ct.fullName[w].Size.EN; } ELSE IF ct.asArray#NIL THEN { a: Array ~ ct.asArray; ect: CellType ~ ct.EltType[]; epa: Set ~ ect.CTParts[p].Intersection[d.isAtomic]; dr: DumRep ~ a.dumrep; cmpWires: Set ~ dr.dwParent.Image[dr.wires].CreateHashCopy; someAtmWires: Set ~ dr.wires.Difference[cmpWires].CreateHashCopy; pubWires: Set ~ dr.apToWire.SetOn[right]; somePvtAtmWires: Set ~ someAtmWires.Difference[pubWires]; pvtParents: Set ~ dr.dwParent.Image[somePvtAtmWires].CreateHashCopy; pubParents: Set ~ dr.dwParent.Image[pubWires].CreateHashCopy; ecTot: INT ~ epa.Size.EN * a.size; ecSum: INT _ 0; SumEC: PROC [dwv: Sets.Value] RETURNS [BOOL] ~ { dw: DumbWire ~ NARROW[dwv.VA]; IF dw.children=nilBiRel THEN ecSum _ ecSum + dw.eps.Size.EN; RETURN [FALSE]}; IF dr.dwParent.ImageSize[cmpWires, leftToRight, IS.one]#IS.zero THEN ERROR; IF pubParents.Difference[pubWires].NonEmpty THEN ERROR nyet--need to decide whether exportable or stuck--; IF dr.wires.Scan[SumEC].found THEN ERROR; IF ecSum > ecTot THEN ERROR; {fudge: INT ~ ecTot - ecSum; cellInstances _ cellInstances + a.size; pubAtmWires _ pubAtmWires + someAtmWires.Intersection[pubWires].Size.EN; pvtAtmWires _ pvtAtmWires + somePvtAtmWires.Size.EN + fudge; pubCmpWires _ pubCmpWires + pubParents.Size.EN; pvtCmpWires _ pvtCmpWires + pvtParents.Size.EN; totWires _ totWires + dr.wires.Size.EN + fudge; arrayFudge _ arrayFudge + fudge; IF totWires # pubAtmWires + pvtAtmWires + pubCmpWires + pvtCmpWires + exblCmpWires + stuckWires THEN ERROR; }} ELSE { d _ d}; atmPorts _ atmPorts + ports.Intersection[d.isAtomic].Size[].EN; cmpPorts _ cmpPorts + ports.Intersection[d.isComposite].Size.EN; status.i _ status.i + 1; IF cmp THEN { di: INT ~ MAX[cellInstances - oldInsts, 1]; dw: INT ~ MAX[totWires - oldWires, 1]; hists.sizeCorr.h.ChangeTransformed[di, dw]; hists.combSize.h.ChangeTransformed[di+dw]; hists.wireSize.h.ChangeTransformed[dw]; hists.instSize.h.ChangeTransformed[di]; d _ d}; RETURN [FALSE]}}; tNames _ d.ctName.Size.EN; status^ _ [n: d.cellTypes.Size.EN]; hists.sizeCorr.h _ Histograms.Create2D[iFactor: base2, jFactor: base2, iOffset: offset2, jOffset: offset2, logI: TRUE, logJ: TRUE]; hists.combSize.h _ Histograms.Create1D[factor: 5]; hists.wireSize.h _ Histograms.Create1D[factor: 5]; hists.instSize.h _ Histograms.Create1D[factor: 5]; hists.sizeCorr.v _ HistogramsViewing.Show[h: hists.sizeCorr.h, viewerInit: [name: Rope.Cat[histPrefix, "sizeCorr"]], base: 2.0, updatePeriod: 15]; hists.combSize.v _ HistogramsViewing.Show[h: hists.combSize.h, viewerInit: [name: Rope.Cat[histPrefix, "combSize"]], base: 2.0, updatePeriod: 15]; hists.wireSize.v _ HistogramsViewing.Show[h: hists.wireSize.h, viewerInit: [name: Rope.Cat[histPrefix, "wireSize"]], base: 2.0, updatePeriod: 15]; hists.instSize.v _ HistogramsViewing.Show[h: hists.instSize.h, viewerInit: [name: Rope.Cat[histPrefix, "instSize"]], base: 2.0, updatePeriod: 15]; IF CountCellType[AV[IF root=NIL THEN d.root ELSE root]] THEN ERROR; WriteHV[hists.sizeCorr]; WriteHV[hists.combSize]; WriteHV[hists.wireSize]; WriteHV[hists.instSize]; RETURN}; WriteHV: PROC [hv: HV] ~ { IF NOT hv.v.destroyed THEN HistogramsViewingExtras.ViewerWriteToFile[hv.v, hv.v.name.Cat[".hist"]]; RETURN}; anonymous: Sets.Value ~ SnV[OSn[R["?"]]]; FlatCount: PROC [d: Design, start: CellType _ NIL] RETURNS [cmpCellTypes, atmCellTypes, cellInstances, atmWires, cmpWires: INT _ 0] ~ { cmpCTS: Set ~ d.cct[w].SetOn[right] .Union[d.cct[i].SetOn[right]] .Union[d.arrayElt.SetOn[left]] .CreateHashCopy; atmCTS: Set ~ d.cellTypes.Difference[cmpCTS].CreateHashCopy[]; cmpInsts: Set ~ d.ciType.Image[cmpCTS, rightToLeft]; Work: PROC [ct: CellType, n: NATURAL, root: BOOL, path: ROPE] ~ { status.path _ path; status.type _ ct.ACtName[]; IF ct.asu#NIL THEN { subcells: Set ~ ct.CTParts[i]; cmpSubs: Set ~ subcells.Intersection[cmpInsts]; defWires: Set ~ ct.CTParts[w]; intros: Set ~ IF NOT root THEN defWires.Difference[d.ancest.Image[ct.asu.publics]].CreateHashCopy ELSE defWires; p1: ROPE ~ path.Concat["/"]; PerSub: PROC [civ: Sets.Value] RETURNS [BOOL] ~ { ci: CellInstance ~ NARROW[civ.VA]; ict: CellType ~ d.CiT[ci]; step: ROPE ~ UnparseSteppyName[VSn[ct.fullName[i].Lookup[goal: civ, side: left].DVal[anonymous]]]; Work[ict, n, FALSE, p1.Concat[step]]; RETURN [FALSE]}; cellInstances _ cellInstances + n*(subcells.Size.EN - cmpSubs.Size.EN); atmWires _ atmWires + n*intros.Intersection[d.isAtomic].Size.EN; cmpWires _ cmpWires + n*intros.Intersection[d.isComposite].Size.EN; IF cmpSubs.Scan[PerSub].found THEN ERROR; ct _ ct} ELSE IF ct.asArray#NIL THEN { a: Array ~ ct.asArray; ect: CellType ~ ct.EltType; subn: NATURAL ~ INT[n]*a.size; IF cmpCTS.HasMemA[ect] THEN Work[ect, subn, FALSE, path.Concat["/0"]] ELSE cellInstances _ cellInstances + subn; ct _ ct} ELSE ERROR; }; IF start=NIL THEN start _ d.root; IF NOT d.cellTypes.HasMemA[start] THEN ERROR; cmpCellTypes _ cmpCTS.Size.EN; atmCellTypes _ atmCTS.Size.EN; Work[start, 1, TRUE, ""]; RETURN}; END. \LichenChecking.Mesa Last tweaked by Mike Spreitzer on April 17, 1989 11:25:21 am PDT Κξ– "cedar" style˜code™K™@—K˜KšΟk œ°˜ΉK˜šΡbnxœœ˜Kšœ ˜§Kšœ˜Kšœ˜—K˜Kšœœœ@Οnœ˜YK˜Kšœ œ˜'Kšœœ˜(K˜šŸ œœœ˜(šŸœœœœ˜;Kšœœœ˜K˜!Kšœœœ˜3Kšœ Οc œ œ˜,šŸœœœœ˜5Kšœœœ˜Kšœœœ˜Kšœœ˜1Kšœœœ˜:Kšœœœ˜4Kšœœ˜—Kšœœœ˜(Kšœœ˜—šŸ œœœœ˜8Kšœ˜Kšœ!˜!Kšœ   œ œ˜8Kšœœ#œ˜>Kšœœ˜—šŸ œœœœ˜8Kšœœ œ˜)Kšœœ œ˜&Kš œœœœœ˜YKšœœ˜—šŸ œœœœ˜8Kšœœ œ˜%Kšœœœ œ˜$Kšœœœœ˜:Kšœœ˜—šŸ œœœœ˜:Kšœœ œ˜&Kšœœ œ˜&Kš œœœœœ˜ZKš œ œœœœ˜OKšœœ˜—šŸ œœœœ˜7Kšœœ œ˜)K˜#Kšœœœœ˜;Kšœœ˜—šŸ œœœœ˜6Kšœœœ˜Kšœ œ˜!Kšœ˜Kšœœ˜—Kšœœœœ˜VKšœœ&œœ˜GKšœœ(œœ˜IKšœ"œœ˜/Kšœ˜Kšœ"œœ˜/Kšœ˜šœœ ˜!šŸœœœœ˜5Kšœ œ œ˜#Kšœœ œ˜'Kš œœœœœ˜Sšœœ˜Kšœœ!œœ˜BKš œ œœ œœ˜N—Kšœœ˜—Kšœ œœ˜-Kšœ˜Kšœ˜—Kšœ"œœ˜/Kšœ˜Kšœ"œœ˜/Kšœ˜Kšœ&œœ˜3Kšœ˜Kšœ œ œœ˜9Kšœ˜Kšœ%œœ˜2Kšœ˜Kšœ˜—K˜šŸ œœ˜&K˜Kšœœ œ˜Kšœ œœ˜!Kšœœœ˜4Kšœ œœ˜BKšœ"œ˜9šœœ ˜!šŸ œœœœ˜:Kšœœ˜Kšœœœœ˜,Kšœœ˜—Kšœ$œœ˜EKšœœ+œœ˜UKšœ˜Kšœ˜—šœœ˜š Ÿ œœ Πcm œ   œ˜OšŸ œœœœ˜7Kšœ œ œ˜ Kšœ œ œ˜!Kšœœœœ˜&Kšœœ˜—Kšœœ.œ˜aKšœœœ˜+Kšœ˜—šŸ œœœœ˜$Kšœœ˜Kšœ˜šœ œ˜Kšœ.˜.Kšœ7˜7Kšœœœ˜9—Kšœœœ˜2Kšœ)˜)Kšœ˜—šŸ œœœœ˜3Kšœ œœ˜šŸ œœœœ˜7Kšœ œ œ˜ šœ œœ˜Kšœœœœ˜EKš œœœœœœ˜fKšœœ˜—Kšœœ˜—Kšœ œœ˜-Kšœœ˜—Kšœ ˜ Kšœ˜Kšœ%œœ˜2Kšœ˜Kšœ.˜.Kšœ˜K˜—šœ œ˜K˜K˜K˜K˜K˜ K˜K˜-K˜%šŸ œœœœ˜8Kšœœœ˜Kšœœ˜&Kšœœ˜%Kš œœœœ œœ˜oKšœœ œ˜;Kšœ"Οgœœ˜JKšœœ˜—šŸ œœœœ˜8Kšœ œ œ˜!Kšœ%˜%Kšœœœœ˜TKšœœœ˜5Kšœœ˜—šŸ œœœœ˜8Kšœœœ˜šŸœœœœ˜5Kšœ œ œ˜!Kšœ'œ˜*Kšœœ˜0Kšœœœ˜Kšœœœ˜/Kšœœ˜—Kšœœœ˜*Kšœœ˜—šŸœœœœ˜5Kšœ œ œ˜!Kšœœ˜!šŸ œœœœ˜7Kšœ&œ˜)Kšœœ œ˜&Kš œœœœœ˜>Kšœœ˜—Kšœ0œ˜GKšœœœ˜)Kšœœ˜—Kšœœ˜/šœ œ˜Kšœ"œ˜9Kšœ˜—Kš œ’œœ’œœœ˜[Kšœœ œœ˜CKšœ$œœ˜1Kšœ˜š œœœœ˜Kšœ:œ˜QKšœœ-œ˜HKšœœ+œ˜FKšœ˜—Kšœ$œœ˜1Kšœ˜šœœ˜%Kšœ7œ˜NKšœ9œ˜PKšœ8œ˜OKšœ$œœ˜1Kšœ"œœ˜/K˜—K˜—Kšœ˜—K˜K•StartOfExpansion [base: REAL, exponent: REAL]šœœ,˜7Kšœ œX˜eK˜Kš œœœœœœ˜>Kšœœ œ˜'K˜Kšœœœ*œ˜BKšœœœ˜,K˜š Ÿ œœœœœΕœ˜¬K˜,Kš œ  ‘  œ%œœ˜WšŸ œœœœ˜8Kš œœœœœ˜/Kšœ0œœ˜=Kšœ2œœ˜?Kšœœœ˜K˜Kš œœ œœ œ˜)Kšœ œ˜Kšœ œ ˜Kšœœ!œ!˜QKšœ&œ˜)šœœœ˜K˜Kšœ/˜/Kšœ2˜2Kšœ!˜!K˜LKšœ7˜7Kšœ0˜0Kšœ)˜)Kšœ/˜/Kšœ3œ˜6KšœGœ˜JKšœ=œ˜@KšœGœ˜JKšœ)œ˜,Kšœ@œ˜CKšœ>œ˜AKšœ!œ˜$Kšœ^œœ˜kKšœ&œ˜)Kšœ&œ˜)K˜—šœœ œœ˜K˜Kšœ˜K˜3K˜Kšœ;˜;KšœA˜AKšœ)˜)Kšœ9˜9KšœD˜DKšœ=˜=Kšœœ œ ˜"Kšœœ˜šŸœœœœ˜0Kšœœœ˜Kšœœœ˜˜>Kšœ4˜4š Ÿœœœœœ˜AK˜Kšœ˜šœœœ˜K˜Kšœ/˜/Kšœ˜Kš œœœœDœ ˜pKšœœ˜šŸœœœœ˜1Kšœœœ˜"Kšœ˜KšœœX˜bKšœ œ˜%Kšœœ˜—Kšœ1œœ˜GKšœ=œ˜@Kšœ@œ˜CKšœœœ˜)K˜—šœœ œœ˜K˜Kšœ˜Kšœœœ ˜Kšœœœœ&˜pK˜—Kšœœ˜ K˜—Kšœœœ˜!Kšœœœœ˜-Kšœœ˜Kšœœ˜Kšœœ˜Kšœ˜—K˜Kšœ˜—…—?ψSB