DIRECTORY PascalBasic, PascalNoviceFiles, WeitekIeee; WeitekIeeeImplA: PROGRAM IMPORTS PascalNoviceFiles, WeitekIeee EXPORTS WeitekIeee =PUBLIC BEGIN OPEN PascalBasic, PascalNoviceFiles, WeitekIeee; Halt: PROCEDURE [HaltCode: PascalInteger] = { PascalWriteLongString[file: @Output, item: "fatal error: code="]; PascalWriteInteger[file: @Output, item: HaltCode]; PascalWriteLn[file: @Output]; ERROR Error99 }; Xor: PROCEDURE [A, B: Bit] RETURNS [XorResult: Bit] = --Exclusive OR {IF A = B THEN XorResult _ 0 ELSE XorResult _ 1}; Zero: PROCEDURE [ --Returns Normal Zero, undefined sign Result: LONG POINTER TO Number, Gvars: LONG POINTER TO Gvarstype] = { OPEN Gvars^; I: PascalInteger [1..MantBits]; Result^.Expon _ MinExp; --exponent is format's minimum FOR i: INT IN [INT[1]..INT[MantPrec]] DO I _ i; Result^.Mant[I] _ 0 ENDLOOP}; Pluszero: PROCEDURE [ --Returns Positive Normal Zero Result: LONG POINTER TO Number, Gvars: LONG POINTER TO Gvarstype] = { Zero[@Result^, @Gvars^]; Result^.Sign _ 0}; --0=positive Minuszero: PROCEDURE [ --Returns Negative Normal Zero Result: LONG POINTER TO Number, Gvars: LONG POINTER TO Gvarstype] = { Zero[@Result^, @Gvars^]; Result^.Sign _ 1}; --1=negative Issignificandzero: PROCEDURE [ N: LONG POINTER TO Number, Gvars: LONG POINTER TO Gvarstype] RETURNS [IssignificandzeroResult: PascalBoolean] = { OPEN N^, Gvars^; I: PascalInteger [1..MantBitsP1]; OkSoFar: PascalBoolean; OkSoFar _ TRUE; I _ 1; WHILE (INT[I] <= MantPrec) AND OkSoFar DO OkSoFar _ OkSoFar AND (Mant[I] = 0); I _ I + 1 ENDLOOP; IssignificandzeroResult _ OkSoFar AND (Guard = 0) AND (Round = 0) AND (Sticky = 0)}; Iszero: PROCEDURE [ --See if N zero; may be + or - or unnormal N: LONG POINTER TO Number, Gvars: LONG POINTER TO Gvarstype] RETURNS [IszeroResult: PascalBoolean] = { IszeroResult _ Issignificandzero[@N^, @Gvars^] AND (N^.Expon # Gvars^.MaxExp + 1) }; Isnormalzero: PROCEDURE [ --See if N is normal zero; may be positive or negative N: LONG POINTER TO Number, Gvars: LONG POINTER TO Gvarstype] RETURNS [IsnormalzeroResult: PascalBoolean] = { IsnormalzeroResult _ Issignificandzero[@N^, @Gvars^] AND (N^.Expon = Gvars^.MinExp) }; Isinfinity: PROCEDURE [ --See if op is infinity, ignore sign N: LONG POINTER TO Number, Gvars: LONG POINTER TO Gvarstype] RETURNS [IsinfinityResult: PascalBoolean] = { IsinfinityResult _ (N^.Expon = Gvars^.MaxExp + 1) AND Issignificandzero[@N^, @Gvars^] }; Isnan: PROCEDURE [ --See if op is a NaN N: LONG POINTER TO Number, Gvars: LONG POINTER TO Gvarstype] RETURNS [IsnanResult: PascalBoolean] = { IsnanResult _ (N^.Expon = Gvars^.MaxExp + 1) AND (NOT Issignificandzero[@N^, @Gvars^]) }; Istrappingnan: PROCEDURE [ N: LONG POINTER TO Number, Gvars: LONG POINTER TO Gvarstype] RETURNS [IstrappingnanResult: PascalBoolean] = { IF (Gvars^.Format = Single) OR (Gvars^.Format = Double) THEN IstrappingnanResult _ Isnan[@N^, @Gvars^] AND (N^.Mant[2] = 1) ELSE IstrappingnanResult _Isnan[@N^, @Gvars^] AND (N^.Mant[1] = 1)}; Isfinite: PROCEDURE [ N: LONG POINTER TO Number, Gvars: LONG POINTER TO Gvarstype] RETURNS [IsfiniteResult: PascalBoolean] = {IsfiniteResult _ NOT (Isinfinity[@N^, @Gvars^] OR Isnan[@N^, @Gvars^])}; Issame: PROCEDURE [ N1, N2: LONG POINTER TO Number, Gvars: LONG POINTER TO Gvarstype] RETURNS [IssameResult: PascalBoolean] = {--slow I: PascalInteger; IssameResult _ TRUE; IF (N1^.Sign # N2^.Sign) OR (N1^.Expon # N2^.Expon) THEN IssameResult _ FALSE ELSE FOR i: INT IN [INT[1]..INT[Gvars^.MantPrec]] DO I _ i; IF N1^.Mant[I] # N2^.Mant[I] THEN IssameResult _ FALSE ENDLOOP}; Isunnormalized: PROCEDURE [ N: LONG POINTER TO Number, Gvars: LONG POINTER TO Gvarstype] RETURNS [IsunnormalizedResult: PascalBoolean] = {IsunnormalizedResult _ (N^.Mant[1] = 0) AND NOT Isnormalzero[@N^, @Gvars^]}; Isdenormalized: PROCEDURE [ N: LONG POINTER TO Number, Gvars: LONG POINTER TO Gvarstype] RETURNS [IsdenormalizedResult: PascalBoolean] = {IsdenormalizedResult _ Isunnormalized[@N^, @Gvars^] AND (N^.Expon = Gvars^.MinExp)}; Isnormalized: PROCEDURE [ N: LONG POINTER TO Number, Gvars: LONG POINTER TO Gvarstype] RETURNS [IsnormalizedResult: PascalBoolean] = {IsnormalizedResult _ (N^.Mant[1] = 1)}; Gettrappingnan: PROCEDURE [ Result: LONG POINTER TO Number, Gvars: LONG POINTER TO Gvarstype] = { I: PascalInteger [1..MantBits]; Result^.Sign _ 0; Result^.Expon _ Gvars^.MaxExp + 1; FOR i: INT IN [INT[1]..INT[Gvars^.MantPrec]] DO I _ i; Result^.Mant[I] _ 0 ENDLOOP; IF (Gvars^.Format = Single) OR (Gvars^.Format = Double) THEN Result^.Mant[2] _ 1 --most sig explicit mant bit ELSE Result^.Mant[1] _ 1}; --most sig explicit mant bit Getnontrappingnan: PROCEDURE [ Result: LONG POINTER TO Number, Gvars: LONG POINTER TO Gvarstype] = { I: PascalInteger [1..MantBits]; Result^.Sign _ 0; Result^.Expon _ Gvars^.MaxExp + 1; FOR i: INT IN [INT[1]..INT[Gvars^.MantPrec]] DO I _ i; Result^.Mant[I] _ 0 ENDLOOP; IF (Gvars^.Format = Single) OR (Gvars^.Format = Double) THEN Result^.Mant[3] _ 1 --hidden msb ELSE Result^.Mant[2] _ 1}; --explicit msb Getnan: PROCEDURE [ Result: LONG POINTER TO Number, Modes: LONG POINTER TO Modestype, Gvars: LONG POINTER TO Gvarstype] = { IF Modes^.InvalidTrap = Enabled THEN Gettrappingnan[@Result^, @Gvars^] ELSE Getnontrappingnan[@Result^, @Gvars^]}; Selectnan: PROCEDURE [ Result: LONG POINTER TO Number, Op1, Op2: LONG POINTER TO Number] = {Result^ _ Op1^}; Plusinf: PROCEDURE [ Result: LONG POINTER TO Number, Gvars: LONG POINTER TO Gvarstype] = { I: PascalInteger [1..MantBits]; Result^.Sign _ 0; Result^.Expon _ Gvars^.MaxExp + 1; FOR i: INT IN [INT[1]..INT[Gvars^.MantPrec]] DO I _ i; Result^.Mant[I] _ 0 ENDLOOP}; Flmo: PROCEDURE [ Op: LONG POINTER TO MantArray, Gvars: LONG POINTER TO Gvarstype] RETURNS [FlmoResult: PascalInteger] = { OPEN Gvars^; I: PascalInteger [1..MantBits]; FlmoResult _ -1; IF Sticky = 1 THEN FlmoResult _ MantPrec + 2; IF Round = 1 THEN FlmoResult _ MantPrec + 1; IF Guard = 1 THEN FlmoResult _ MantPrec; FOR i: INT DECREASING IN [INT[1]..INT[MantPrec]] DO I _ i; IF Op^[I] = 1 THEN FlmoResult _ I - 1 ENDLOOP}; Oneoperandcase: PROCEDURE [ Op: LONG POINTER TO Number, Gvars: LONG POINTER TO Gvarstype] RETURNS [OneoperandcaseResult: Oneoperandtype] = { IF Isnormalzero[@Op^, @Gvars^] THEN OneoperandcaseResult _ Pmzero ELSE IF Isinfinity[@Op^, @Gvars^] THEN OneoperandcaseResult _ Pminf ELSE IF Isnan[@Op^, @Gvars^] THEN OneoperandcaseResult _ Nan ELSE OneoperandcaseResult _ W}; Twooperandcase: PROCEDURE [ Op1, Op2: LONG POINTER TO Number, Gvars: LONG POINTER TO Gvarstype] RETURNS [TwooperandcaseResult: Twooperandtype] = { SELECT Oneoperandcase[@Op1^, @Gvars^] FROM Pmzero => SELECT Oneoperandcase[@Op2^, @Gvars^] FROM Pmzero => TwooperandcaseResult _ A; W => TwooperandcaseResult _ B; Pminf => TwooperandcaseResult _ C; Nan => TwooperandcaseResult _ Y; ENDCASE; W => SELECT Oneoperandcase[@Op2^, @Gvars^] FROM Pmzero => TwooperandcaseResult _ D; W => TwooperandcaseResult _ E; Pminf => TwooperandcaseResult _ F; Nan => TwooperandcaseResult _ Y; ENDCASE; Pminf => SELECT Oneoperandcase[@Op2^, @Gvars^] FROM Pmzero => TwooperandcaseResult _ G; W => TwooperandcaseResult _ H; Pminf => TwooperandcaseResult _ I; Nan => TwooperandcaseResult _ Y; ENDCASE; Nan => SELECT Oneoperandcase[@Op2^, @Gvars^] FROM Pmzero => TwooperandcaseResult _ X; W => TwooperandcaseResult _ X; Pminf => TwooperandcaseResult _ X; Nan => TwooperandcaseResult _ M; ENDCASE; ENDCASE}; Shftl: PROCEDURE [ N: LONG POINTER TO Number, D: PascalInteger, Gvars: LONG POINTER TO Gvarstype] = { OPEN N^, Gvars^; I: PascalInteger [1..MantBitsM1]; Cntr: PascalInteger; IF D > MantPrec + 3 THEN D _ MantPrec + 3; --allows shift sticky to carry FOR i: INT IN [INT[1]..INT[D]] DO Cntr _ i; IF Carry = 1 THEN Halt[1]; --Shouldn't happen. Carry _ Mant[1]; FOR i: INT IN [INT[1]..INT[MantPrec - 1]] DO I _ i; Mant[I] _ Mant[I + 1] ENDLOOP; Mant[MantPrec] _ Guard; Guard _ Round; Round _ Sticky; --sticky := sticky ENDLOOP}; Shftr: PROCEDURE [ N: LONG POINTER TO Number, D: PascalInteger, Gvars: LONG POINTER TO Gvarstype] = { OPEN N^, Gvars^; I: PascalInteger [2..MantBits]; Cntr: PascalInteger; IF D > MantPrec + 3 THEN D _ MantPrec + 3; --allows shift carry to sticky FOR i: INT IN [INT[1]..INT[D]] DO Cntr _ i; IF Sticky = 0 THEN Sticky _ Round; Round _ Guard; Guard _ Mant[MantPrec]; FOR i: INT DECREASING IN [INT[2]..INT[MantPrec]] DO I _ i; Mant[I] _ Mant[I - 1] ENDLOOP; Mant[1] _ Carry; Carry _ 0; ENDLOOP}; Examine: PROCEDURE [ N: LONG POINTER TO Number, Modes: LONG POINTER TO Modestype, Indics: LONG POINTER TO Indicstype, Gvars: LONG POINTER TO Gvarstype] RETURNS [ExamineResult: PascalBoolean] = { OPEN Modes^, Indics^, Gvars^; Shiftdist: PascalInteger; IF Istrappingnan[@N^, @Gvars^] THEN {SetInvalid[@Indics^]; ExamineResult _ FALSE} ELSE { ExamineResult _ TRUE; IF (UnderMode = Normalizing) AND Isdenormalized[@N^, @Gvars^] THEN { OPEN N^; Shiftdist _ Flmo[@Mant, @Gvars^]; Shftl[@N^, Shiftdist, @Gvars^]; Expon _ Expon - Shiftdist} } }; Roundnum: PROCEDURE [ N: LONG POINTER TO Number, Modes: LONG POINTER TO Modestype, Indics: LONG POINTER TO Indicstype, Gvars: LONG POINTER TO Gvarstype]={--uses GRS Increment: PROCEDURE [M: LONG POINTER TO MantArray] = { I: PascalInteger [1..MantBits]; Sum: PascalInteger [0..2]; C: Bit; Sum _ 0; C _ 1; FOR i: INT DECREASING IN [INT[1]..INT[Gvars^.MantPrec]] DO I _ i; Sum _ M^[I] + C; M^[I] _ Sum MOD 2; C _ Sum/2; ENDLOOP; IF Gvars^.Carry = 1 THEN Halt[2]; Gvars^.Carry _ C}; --what if this carry's out??? BEGIN OPEN N^, Modes^, Indics^, Gvars^; IF (Guard = 1) OR (Round = 1) OR (Sticky = 1) THEN { SetInexact[@Indics^]; SELECT RoundMode FROM Rp => IF (Sign = 0) THEN { Increment[@Mant]; IF Carry = 1 THEN {Shftr[@N^, 1, @Gvars^]; Expon _ Expon + 1} }; Rm => IF (Sign = 1) THEN { Increment[@Mant]; IF Carry = 1 THEN {Shftr[@N^, 1, @Gvars^]; Expon _ Expon + 1} }; Rz => --nada-- NULL; Rn => IF (Guard = 1) AND (((Round = 1) OR (Sticky = 1)) OR ((Round = 0) AND (Sticky = 0) AND (Mant[MantPrec] = 1))) THEN { Increment[@Mant]; IF Carry = 1 THEN {Shftr[@N^, 1, @Gvars^]; Expon _ Expon + 1} }; ENDCASE} END }; Addsignificands: PROCEDURE [ Result: LONG POINTER TO MantArray, Op1, Op2: LONG POINTER TO MantArray, Gvars: LONG POINTER TO Gvarstype] = { OPEN Gvars^; I, Sum: PascalInteger; FOR i: INT DECREASING IN [INT[1]..INT[MantPrec]] DO I _ i; Sum _ Op1^[I] + Op2^[I] + Carry; Result^[I] _ Sum MOD 2; Carry _ Sum/2; ENDLOOP}; Addoperands: PROCEDURE [ Result: LONG POINTER TO Number, Op1, Op2: LONG POINTER TO Number, Gvars: LONG POINTER TO Gvarstype] = { C: Bit; Compl: PROCEDURE [N: LONG POINTER TO MantArray] = { OPEN Gvars^; I: PascalInteger; FOR i: INT DECREASING IN [INT[1]..INT[MantPrec]] DO I _ i; N^[I] _ 1 - N^[I] ENDLOOP; Guard _ 1 - Guard; Round _ 1 - Round; Sticky _ 1 - Sticky}; Addtogrs: PROCEDURE = { --add carry to g,r,s OPEN Gvars^; Sum: PascalInteger [0..2]; Sum _ Carry + Sticky; Sticky _ Sum MOD 2; Carry _ Sum/2; Sum _ Carry + Round; Round _ Sum MOD 2; Carry _ Sum/2; Sum _ Carry + Guard; Guard _ Sum MOD 2; Carry _ Sum/2}; BEGIN OPEN Gvars^; IF Isnormalzero[@Op1^, @Gvars^] THEN Op1^.Expon _ Op2^.Expon; IF Isnormalzero[@Op2^, @Gvars^] THEN Op2^.Expon _ Op1^.Expon; IF Op1^.Expon # Op2^.Expon THEN Halt[3]; --Ref: Hwang, COMPUTER ARITHMETIC Result^.Expon _ Op1^.Expon; -- Wiley&Sons, 1979, p. 73 Carry _ 0; IF Op1^.Sign # Op2^.Sign THEN Compl[@Op2^.Mant]; Addtogrs[]; Addsignificands[@Result^.Mant, @Op1^.Mant, @Op2^.Mant, @Gvars^]; C _ (Carry + Xor[Op1^.Sign, Op2^.Sign])/2; Carry _ (Carry + Xor[Op1^.Sign, Op2^.Sign]) MOD 2; IF C = 1 THEN { Carry _ 1; Addtogrs[]; Addsignificands[@Result^.Mant, @Op1^.Mant, @Op2^.Mant, @Gvars^]; C _ (Carry + Xor[Op1^.Sign, Op2^.Sign])/2; Carry _ (Carry + Xor[Op1^.Sign, Op2^.Sign]) MOD 2}; IF (C = 0) AND (Op1^.Sign # Op2^.Sign) THEN {Compl[@Result^.Mant]; Carry _ 1 - Carry}; IF C = 1 THEN Result^.Sign _ Op1^.Sign ELSE Result^.Sign _ Op2^.Sign; END}; Multsignificands: PROCEDURE [ Result: LONG POINTER TO Number, Op1, Op2: LONG POINTER TO Number, Gvars: LONG POINTER TO Gvarstype] = { OPEN Result^, Gvars^; I: PascalInteger [1..MantBits]; FOR i: INT IN [INT[1]..INT[MantPrec]] DO I _ i; Mant[I] _ 0 ENDLOOP; --clean it up FOR i: INT DECREASING IN [INT[1]..INT[MantPrec]] DO I _ i; Shftr[@Result^, 1, @Gvars^]; IF Op2^.Mant[I] = 1 THEN Addsignificands[@Mant, @Mant, @Op1^.Mant, @Gvars^]; ENDLOOP}; Dividesignificands: PROCEDURE [ Result: LONG POINTER TO Number, Op1, Op2: LONG POINTER TO Number, Gvars: LONG POINTER TO Gvarstype] = { OPEN Gvars^; I: PascalInteger [1..MantBitsP1]; J: PascalInteger [1..MantBitsP2]; Done: PascalBoolean; Dif: PascalInteger [0..3]; Borrow: Bit; G, R: Bit; Doit: PascalBoolean; FOR i: INT IN [INT[1]..INT[MantPrec]] DO I _ i; Result^.Mant[I] _ 0 ENDLOOP; --clean up FOR i: INT IN [INT[1]..INT[MantPrec + 2]] DO J _ i; --compute result[j]gr and update divid Done _ FALSE; I _ 1; Doit _ TRUE; IF J = (MantPrec + 2) THEN R _ 1 ELSE IF J = (MantPrec + 1) THEN G _ 1 ELSE Result^.Mant[J] _ 1; WHILE (INT[I] <= MantPrec) AND NOT Done DO { --see which is bigger IF (Carry = 1) OR (Op1^.Mant[I] # Op2^.Mant[I]) THEN { Done _ TRUE; IF (Carry = 0) AND (INT[Op1^.Mant[I]] < Op2^.Mant[I]) THEN { IF J = (MantPrec + 2) THEN R _ 0 ELSE IF J = (MantPrec + 1) THEN G _ 0 ELSE Result^.Mant[J] _ 0; Doit _ FALSE} }; I _ I + 1} ENDLOOP; IF Doit THEN { --subtract Borrow _ 1; FOR i: INT DECREASING IN [INT[1]..INT[MantPrec]] DO I _ i; Dif _ Op1^.Mant[I] + (1 - Op2^.Mant[I]) + Borrow; Op1^.Mant[I] _ Dif MOD 2; Borrow _ Dif/2; ENDLOOP; Carry _ (Carry + 1 + Borrow) MOD 2}; Shftl[@Op1^, 1, @Gvars^]; ENDLOOP; Guard _ G; Round _ R; Sticky _ Carry; Carry _ 0; FOR i: INT IN [INT[1]..INT[MantPrec]] DO I _ i; IF Sticky = 0 THEN Sticky _ Op1^.Mant[I] ENDLOOP}; Pack: PROCEDURE [ Result: LONG POINTER TO Pervert, N: LONG POINTER TO Number, Gvars: LONG POINTER TO Gvarstype] = { OPEN Gvars^; Temp1: Pervert; Tempe: Pervert; J: PascalInteger [1..MantBits]; Start: PascalInteger [1..2]; IF (((Format = Single) OR (Format = Double)) AND (Isdenormalized[@N^, @Gvars^])) OR Isnormalzero[@N^, @Gvars^] THEN Tempe.I _ 0 ELSE Tempe.I _ N^.Expon + Bias; BEGIN OPEN Temp1; FOR i: INT IN [INT[1]..INT[Expbits]] DO J _ i; B[Expbits + MantPrec - J] _ Tempe.B[Expbits - J + 1] ENDLOOP END; Temp1.B[MantPrec + Expbits] _ N^.Sign; IF Format = Extended THEN Start _ 1 ELSE Start _ 2; BEGIN OPEN Temp1; FOR i: INT IN [INT[Start]..INT[MantPrec]] DO J _ i; B[1 + MantPrec - J] _ N^.Mant[J] ENDLOOP END; Result^ _ Temp1}; Packs: PROCEDURE [ Result: LONG POINTER TO Shortreal, N: LONG POINTER TO Number, Gvars: LONG POINTER TO Gvarstype] = { PackResult: Pervert; Pack[@PackResult, @N^, @Gvars^]; Result^ _ PackResult.R}; Packd: PROCEDURE [ Result: LONG POINTER TO Longreal, N: LONG POINTER TO Number, Gvars: LONG POINTER TO Gvarstype] = { PackResult: Pervert; Pack[@PackResult, @N^, @Gvars^]; Result^ _ PackResult.L}; Packe: PROCEDURE [ Result: LONG POINTER TO Verylongreal, N: LONG POINTER TO Number, Gvars: LONG POINTER TO Gvarstype] = { PackResult: Pervert; Pack[@PackResult, @N^, @Gvars^]; Result^ _ PackResult.Vl}; Unpack: PROCEDURE [ Result: LONG POINTER TO Number, T1: LONG POINTER TO Pervert, Gvars: LONG POINTER TO Gvarstype] = { Te: Pervert; J: PascalInteger [1..MantBits]; Res: Number; Start: PascalInteger; BEGIN OPEN Gvars^, Res; Te.I _ 0; BEGIN OPEN Te; FOR i: INT IN [INT[1]..INT[Expbits]] DO J _ i; B[Expbits - J + 1] _ T1^.B[Expbits + MantPrec - J] ENDLOOP END; Expon _ Te.I - Bias; IF Format = Extended THEN Start _ 1 ELSE Start _ 2; FOR i: INT IN [INT[Start]..INT[MantPrec]] DO J _ i; Mant[J] _ T1^.B[1 + MantPrec - J] ENDLOOP; IF Format # Extended THEN IF Expon >= MinExp --not denorm THEN Mant[1] _ 1 ELSE {Mant[1] _ 0; Expon _ MinExp}; IF Format # Extended THEN IF Expon = MaxExp + 1 --infinity THEN Mant[1] _ 0; Sign _ T1^.B[Expbits + MantPrec]; Result^ _ Res; END}; Unpacks: PROCEDURE [ Result: LONG POINTER TO Number, N: LONG POINTER TO Shortreal, Gvars: LONG POINTER TO Gvarstype] = { T: Pervert; T.R _ N^; Unpack[@Result^, @T, @Gvars^]}; Unpackd: PROCEDURE [ Result: LONG POINTER TO Number, N: LONG POINTER TO Longreal, Gvars: LONG POINTER TO Gvarstype] = { T: Pervert; T.L _ N^; Unpack[@Result^, @T, @Gvars^]}; Unpacke: PROCEDURE [ Result: LONG POINTER TO Number, N: LONG POINTER TO Verylongreal, Gvars: LONG POINTER TO Gvarstype] = { T: Pervert; T.Vl _ N^; Unpack[@Result^, @T, @Gvars^]}; Add: PROCEDURE [ Result: LONG POINTER TO Number, Op1, Op2: Number, Modes: LONG POINTER TO Modestype, Indics: LONG POINTER TO Indicstype, Gvars: LONG POINTER TO Gvarstype] = { Op1ok, Op2ok, Onenormalized: PascalBoolean; Shiftdist: PascalInteger; Temp: Number; Op1ok _ Examine[@Op1, @Modes^, @Indics^, @Gvars^]; Op2ok _ Examine[@Op2, @Modes^, @Indics^, @Gvars^]; IF Op1ok AND Op2ok THEN { OPEN Modes^, Indics^, Gvars^; SELECT Twooperandcase[@Op1, @Op2, @Gvars^] FROM A => IF ((RoundMode # Rm) AND NOT ((Op1.Sign = 1) AND (Op2.Sign = 1))) OR ((Op1.Sign = 0) AND (Op2.Sign = 0)) THEN Pluszero[@Result^, @Gvars^] ELSE Minuszero[@Result^, @Gvars^]; C, F => Result^ _ Op2; --op2 is inf & op1 is not inf or nan G, H => Result^ _ Op1; --op1 is inf & op2 is not inf or nan B, D, E => { IF (NOT Isnormalzero[@Op1, @Gvars^]) AND (NOT Isnormalzero[@Op2, @Gvars^]) AND (Op1.Expon # Op2.Expon) THEN { IF Op1.Expon < Op2.Expon THEN {Temp _ Op1; Op1 _ Op2; Op2 _ Temp}; Shftr[@Op2, Op1.Expon - Op2.Expon, @Gvars^]; Op2.Expon _ Op1.Expon}; Onenormalized _ Isnormalized[@Op1, @Gvars^] OR Isnormalized[@Op2, @Gvars^]; Addoperands[@Result^, @Op1, @Op2, @Gvars^]; IF Carry = 1 THEN { Shftr[@Result^, 1, @Gvars^]; Result^.Expon _ Result^.Expon + 1}; IF Issignificandzero[@Result^, @Gvars^] --a-- THEN { IF RoundMode = Rm THEN Result^.Sign _ 1 ELSE Result^.Sign _ 0; IF Onenormalized THEN Result^.Expon _ Gvars^.MinExp} --b-- ELSE IF Onenormalized THEN { Shiftdist _ Flmo[@Result^.Mant, @Gvars^]; Shftl[@Result^, Shiftdist, @Gvars^]; Result^.Expon _ Result^.Expon - Shiftdist}; CheckUnderAndRound[@Result^, @Modes^, @Indics^, @Gvars^]; CheckInvAndOv[@Result^, @Modes^, @Indics^, @Gvars^]}; I => IF (InfinityMode = Affine) AND (Op1.Sign = Op2.Sign) --both infinity THEN Result^ _ Op1 ELSE {SetInvalid[@Indics^]; Getnan[@Result^, @Modes^, @Gvars^]}; X => Result^ _ Op1; --op1 is NaN, op2 is non-NaN Y => Result^ _ Op2; --op2 is NaN, op1 is non-NaN M => Selectnan[@Result^, @Op1, @Op2] --Both op's are NaN ENDCASE} ELSE Getnan[@Result^, @Modes^, @Gvars^]}; Subtract: PROCEDURE [ Result: LONG POINTER TO Number, Op1, Op2: Number, Modes: LONG POINTER TO Modestype, Indics: LONG POINTER TO Indicstype, Gvars: LONG POINTER TO Gvarstype] = { IF NOT Isnan[@Op2, @Gvars^] THEN Op2.Sign _ 1 - Op2.Sign; Add[@Result^, Op1, Op2, @Modes^, @Indics^, @Gvars^]}; Multiply: PROCEDURE [ Result: LONG POINTER TO Number, Op1, Op2: Number, Modes: LONG POINTER TO Modestype, Indics: LONG POINTER TO Indicstype, Gvars: LONG POINTER TO Gvarstype] = { Op1ok, Op2ok: PascalBoolean; Op1ok _ Examine[@Op1, @Modes^, @Indics^, @Gvars^]; Op2ok _ Examine[@Op2, @Modes^, @Indics^, @Gvars^]; IF Op1ok AND Op2ok THEN { OPEN Modes^, Indics^, Gvars^; SELECT Twooperandcase[@Op1, @Op2, @Gvars^] FROM A, B, D => { Zero[@Result^, @Gvars^]; Result^.Sign _ Xor[Op1.Sign, Op2.Sign]}; C, G => {SetInvalid[@Indics^]; Getnan[@Result^, @Modes^, @Gvars^]}; E => { --1-- Result^.Sign _ Xor[Op1.Sign, Op2.Sign]; Result^.Expon _ Op1.Expon + Op2.Expon; Multsignificands[@Result^, @Op1, @Op2, @Gvars^]; IF Carry = 1 THEN { Shftr[@Result^, 1, @Gvars^]; Result^.Expon _ Result^.Expon + 1}; --3-- CheckUnderAndRound[@Result^, @Modes^, @Indics^, @Gvars^]; CheckInvAndOv[@Result^, @Modes^, @Indics^, @Gvars^]}; F, H, I => IF (Iszero[@Op1, @Gvars^] AND NOT Isnormalzero[@Op1, @Gvars^]) OR (Iszero[@Op2, @Gvars^] AND NOT Isnormalzero[@Op2, @Gvars^]) THEN {SetInvalid[@Indics^]; Getnan[@Result^, @Modes^, @Gvars^]; } ELSE { Plusinf[@Result^, @Gvars^]; Result^.Sign _ Xor[Op1.Sign, Op2.Sign]}; X => Result^ _ Op1; Y => Result^ _ Op2; M => Selectnan[@Result^, @Op1, @Op2]; ENDCASE} ELSE Getnan[@Result^, @Modes^, @Gvars^]}; Divide: PROCEDURE [ Result: LONG POINTER TO Number, Op1, Op2: Number, Modes: LONG POINTER TO Modestype, Indics: LONG POINTER TO Indicstype, Gvars: LONG POINTER TO Gvarstype] = { Op1ok, Op2ok: PascalBoolean; Op1ok _ Examine[@Op1, @Modes^, @Indics^, @Gvars^]; Op2ok _ Examine[@Op2, @Modes^, @Indics^, @Gvars^]; IF Op1ok AND Op2ok THEN { OPEN Modes^, Indics^, Gvars^; SELECT Twooperandcase[@Op1, @Op2, @Gvars^] FROM A, I => {SetInvalid[@Indics^]; Getnan[@Result^, @Modes^, @Gvars^]}; B => { IF Iszero[@Op2, @Gvars^] AND NOT Isnormalzero[@Op2, @Gvars^] THEN {SetInvalid[@Indics^]; Getnan[@Result^, @Modes^, @Gvars^] } ELSE { Zero[@Result^, @Gvars^]; Result^.Sign _ Xor[Op1.Sign, Op2.Sign] } }; C, F => { Zero[@Result^, @Gvars^]; Result^.Sign _ Xor[Op1.Sign, Op2.Sign]}; D => IF Iszero[@Op1, @Gvars^] AND NOT Isnormalzero[@Op1, @Gvars^] THEN {SetInvalid[@Indics^]; Getnan[@Result^, @Modes^, @Gvars^]; } ELSE { SetDivbyzero[@Indics^]; Plusinf[@Result^, @Gvars^]; Result^.Sign _ Xor[Op1.Sign, Op2.Sign]}; E => IF Isunnormalized[@Op2, @Gvars^] THEN {SetInvalid[@Indics^]; Getnan[@Result^, @Modes^, @Gvars^] } ELSE { --1-- Result^.Sign _ Xor[Op1.Sign, Op2.Sign]; Result^.Expon _ Op1.Expon - Op2.Expon; Dividesignificands[@Result^, @Op1, @Op2, @Gvars^]; IF Result^.Mant[1] = 0 THEN { Shftl[@Result^, 1, @Gvars^]; Result^.Expon _ Result^.Expon - 1}; --3-- CheckUnderAndRound[@Result^, @Modes^, @Indics^, @Gvars^]; CheckInvAndOv[@Result^, @Modes^, @Indics^, @Gvars^]}; G, H => { Plusinf[@Result^, @Gvars^]; Result^.Sign _ Xor[Op1.Sign, Op2.Sign]; }; X => Result^ _ Op1; Y => Result^ _ Op2; M => Selectnan[@Result^, @Op1, @Op2]; ENDCASE} ELSE Getnan[@Result^, @Modes^, @Gvars^]}; Remainder: PROCEDURE [ Result: LONG POINTER TO Number, Op1, Op2: Number, Modes: LONG POINTER TO Modestype, Indics: LONG POINTER TO Indicstype, Gvars: LONG POINTER TO Gvarstype] = { Op1ok, Op2ok: PascalBoolean; Op1ok _ Examine[@Op1, @Modes^, @Indics^, @Gvars^]; Op2ok _ Examine[@Op2, @Modes^, @Indics^, @Gvars^]; IF Op1ok AND Op2ok THEN { OPEN Modes^, Indics^, Gvars^; SELECT Twooperandcase[@Op1, @Op2, @Gvars^] FROM A, D, G, H, I => {SetInvalid[@Indics^]; Getnan[@Result^, @Modes^, @Gvars^]}; B, C => IF Isunnormalized[@Op2, @Gvars^] THEN {SetInvalid[@Indics^]; Getnan[@Result^, @Modes^, @Gvars^]; } ELSE Result^ _ Op1; E => --writeln('Part e not yet implemented')-- Halt[4]; F => Result^ _ Op2; X => Result^ _ Op1; Y => Result^ _ Op2; M => Selectnan[@Result^, @Op1, @Op2]; ENDCASE} ELSE Getnan[@Result^, @Modes^, @Gvars^]}; END. ˜WeitekIeeeImplA.mesa Pascal-to-Mesa translator output, translated at June 19, 1984 4:05:37 pm PDT Last Modified by Curry - June 20, 1984 2:16:27 pm PDT Comments From Weitek File: Fred.pas: Last modification <840120.1607> COPYRIGHT (c) 1984 WEITEK INC Known Bugs: If the remainder is zero, its sign should be that of the divid} Extended has two flavors of the smallest exponent Unnormal zero's don't add properly Extended not well tested This program contains IEEE-compatable arithmetic routines. They are externally callable, using single, double, or Extended precision. Entry point Operation - - - - - - - - - - - - - - - - - - - - ADDS Add, single precision ADDD Add, double precision ADDE Add, Extended precision SUBS Subtract, single precision SUBD Subtract, double precision SUBE Subtract, Extended precision MULS MULTIPLY, single precision MULD MULTIPLY, double precision MULE MULTIPLY, Extended precision DIVS Divide, single precision DIVD Divide, double precision DIVE Divide, Extended precision * REMS Remainder, single precision * REMD Remainder, double precision * REME Remainder, Extended precision * SQRTS Square root, single precision * SQRTD Square root, double precision * SQRTE Square root, Extended precision * CONSD Convert single to double precision * CONSE Convert single to Extended precision * CONSH Convert single to 16 bit integer * CONSI Convert single to 32 bit integer * CONDS Convert double to single precision * CONDE Convert double to Extended precision * CONDH Convert double to 16 bit integer * CONDI Convert double to 32 bit integer * CONES Convert Extended to single precision * CONED Convert Extended to double precision * CONEH Convert Extended to 16 bit integer * CONEI Convert Extended to 32 bit integer * CONIS Convert 32 bit integer to single * CONID Convert 32 bit integer to double * CONIE Convert 32 bit integer to Extended * CONIH Convert 32 bit integer to 16 bit integer * CONHS Convert 16 bit integer to single * CONHD Convert 16 bit integer to double * CONHE Convert 16 bit integer to Extended * CONHI Convert 16 bit integer to 32 bit integer INTS Integerize, single precision INTD Integerize, double precision INTE Integerize, Extended precision * SDECBIN Convert decimal string to single precision binary * DDECBIN Convert decimal string to double precision binary * EDECBIN Convert decimal string to Extended precision binary SCOMPARE Compare, single precision DCOMPARE Compare, double precision ECOMPARE Compare, Extended precision * SBINDEC Convert single precision binary to decimal string * DBINDEC Convert double precision binary to decimal string * EBINDEC Convert Extended precision binary to decimal string * COPYSIGN Op1 gets op2's sign * SCALB Adds N to X's exponent * LOGB Returns unbiased exponent of X * NEXTAFTER Next representable X in direction of Y * FINITE True if finite * ISNAN True if NaN * UNORDERED True if unordered * CLASS 1=tNaN, 2=ntNaN, 3=-inf, 4=-norm, 5=-unnorm 6=-denorm, 7=-0, 8=+0, 9=+denorm, 10=+unnorm, 11=+norm, 12=+inf * Not finished yet Returns True if all significand bits are zero. Number of significand bits checked is the current format's precision not a NaN or infinity Return True if op is a trapping NaN This routine is implementation dep}ent! Criteria used here is that most significant explicit mantissa bit is 1 if trapping hidden leading explicit leading Return true if N is unnormalized, includes denormalized Returns false for normal zero, true for unnormal zero Return True if N is denormalized Zero is not denormalized. Return True if N is normalized. Returns false for zero. Implementation Dependent! Returns a trapping NaN. Definition of trapping used here is that Most significant explicit mantissa bit is 1, all other mant bits set to zero Implementation Dependent! Criteria used here is that most significant explicit mantissa bit is zero; here the following bit is set to one to distinguish from infinity Return Trapping NaN if invalid trap enabled, else Nontrapping Both op's are NaN's, pick one This routine is implementation dep}ent! Return positive infinity Find left-most one, far left is 0, far right is mant_prec-1, none is -1 guard is mant_prec, round is mant_prec+1, sticky is mant_prec+2 Unreadable without Coonan's Implementation Guide Unreadable without Coonan's Implementation Guide type row = array[oneoperandtype] of twooperandtype; tabletype = array[oneoperandtype] of row; const TABLE = tabletype[row[a, b, c, Y], row[d, e, f, Y], row[g, h, i, Y], row[X, X, X, M]]; twooperandcase:=table[oneoperandcase(op1,gvars)][oneoperandcase(op2,gvars)] shift significand left, no exponent change, use G,R,S,carry shift significand right, D places, no exp change, use G,R,S,carry If N is trapping NaN, set Invalid If normalizing mode, normalize denormalized operand. Used by ADD, assumes that operands are aligned, GRS set by alignment Extended by adding extra msb guard:=op1.mant[1]; round:=op1.mant[2]; sticky:=op1.mant[3]; 1 2 3 4 2-- 2-- bugs - incomplete If remainder is zero, its sigh is that of the divid} Ê$󘚜™JšœL™LJšœ5™5—J˜šÏk ˜ J˜ J˜J˜ J˜—šÐblœ˜Jšœœ ˜@Jšœœ,˜6J˜šÏf$™$JšŸ™JšŸ™J™JšŸ ™ JšŸ?™?JšŸ1™1JšŸ"™"JšŸ™J™J™JšŸ0™0JšŸ.™.JšŸ&™&J™J™JšŸ™JšŸ+™+JšŸ#™#JšŸ#™#JšŸ%™%JšŸ(™(JšŸ(™(JšŸ*™*JšŸ(™(JšŸ(™(JšŸ*™*JšŸ&™&JšŸ&™&JšŸ(™(JšŸ+™+JšŸ+™+JšŸ-™-JšŸ-™-JšŸ-™-JšŸ/™/JšŸ2™2JšŸ4™4JšŸ0™0JšŸ0™0JšŸ2™2JšŸ4™4JšŸ0™0JšŸ0™0JšŸ4™4JšŸ4™4JšŸ2™2JšŸ2™2JšŸ0™0JšŸ0™0JšŸ2™2JšŸ8™8JšŸ0™0JšŸ0™0JšŸ2™2JšŸ8™8JšŸ*™*JšŸ*™*JšŸ,™,JšŸA™AJšŸA™AJšŸC™CJšŸ'™'JšŸ'™'JšŸ)™)JšŸA™AJšŸA™AJšŸC™CJ™JšŸ#™#JšŸ&™&JšŸ.™.JšŸ6™6JšŸ™JšŸ™JšŸ!™!JšŸ;™;JšŸ-™-JšŸ™J™JšŸ™J˜—šÏnœ œ˜-J˜AJ˜2J˜Jšœ ˜J˜—š  œ œœœœÏc˜EJš œœœœœœ˜1—J˜š œ œ¡%˜8Jš œœœœœœœ˜FJšœ˜ Jšœ˜Jšœ¡˜7Jšœœœœœ œœœœ˜M—J˜š œ œ¡˜5Jš œœœœœœœ˜FJ˜Jšœ¡ ˜ —J˜š  œ œ¡˜5Jš œœœœœœœ˜FJ˜Jšœ¡ ˜ —J˜Jšœ.™.JšœD™Dš œ œ˜Jšœœœœœœœ ˜=Jšœ-˜4Jšœœ ˜Jšœ ˜!J˜Jšœ œ˜Jšœ˜š œœœœ ˜)Jš œœœœœœ˜7—šœ"œ œ ˜AJšœ˜——J˜š œ œ¡*˜>Jšœœœœœœœœ ˜>Jšœ"˜)Jšœ"œ œœ˜TJšœ™—J˜š  œ œ¡6˜PJšœœœœœœœœ ˜>Jšœ(˜/šœ(œ ˜4Jšœœ˜!——J˜š  œ œ¡$˜Jšœ&˜-šœœ˜1Jšœœ˜&——J˜š œ œ¡˜'Jšœœœœœœœœ ˜>Jšœ!˜(šœœ˜,Jšœœœ˜,——J˜Jšœ#™#Jšœ'™'JšœA™AJšœ™š  œ œ˜Jšœœœœœœœœ ˜>Jšœ)˜0šœœ˜7Jšœ™Jšœœ œœ˜CJšœ™Jšœœ œœ˜D—J˜—š œ œ˜Jšœœœœœœœœ ˜>šœ"˜)Jš œœœ œœ˜I—J˜—š œ œ˜Jš œ œœœœœœ ˜CJšœ"¡˜/Jšœ˜Jšœœ˜šœœ˜3Jšœ˜š œœœœœœ˜4Jšœœ œ œœœœ˜G———J˜Jšœ7™7Jšœ5™5š œ œ˜Jšœœœœœœœœ ˜>šœ(˜/Jš œœœœœ ˜M——J˜Jšœ ™ Jšœ™š œ œ˜Jšœœœœœœœœ ˜>šœ(˜/šœ(œ ˜4Jšœœ˜ ———J˜Jšœ™Jšœ™š  œ œ˜Jšœœœœœœœœ ˜>Jšœ&˜-Jšœœ˜(—J˜Jšœ™JšœG™GJšœL™Lš œ œ˜Jš œœœœœœœ˜FJšœ˜J˜J˜"š œœœœœ˜/Jšœœœ˜#—šœœ˜7Jšœ¡˜6Jšœ¡˜7——J˜Jšœ™JšœG™GJšœG™Gš œ œ˜Jš œœœœœœœ˜FJšœ˜J˜J˜"š œœœœœ˜/Jšœœœ˜#—šœœ˜7Jšœ¡ ˜&Jšœ¡˜)——J˜Jšœ=™=š œ œ˜Jš œœœœœœœ ˜CJšœœœœ˜%šœ˜Jšœ"˜&Jšœ'˜+——J˜Jšœ™Jšœ'™'š  œ œ˜Jš œœœœœœœ ˜DJ˜—J˜Jšœ™š œ œ˜Jš œœœœœœœ˜FJšœ˜J˜J˜"š œœœœœ˜/Jšœœœ˜$——J˜šœH™HJšœA™A—š œ œ˜Jš œœœœœœœ ˜BJšœ ˜'Jšœ˜ Jšœ˜J˜Jšœ œ˜-Jšœ œ˜,Jšœ œ˜(š œœ œœœœ ˜3Jš œœœœœœ˜6——J˜Jšœ0™0š œ œ˜Jšœœœœ˜Jšœœœœ ˜"Jšœ+˜2šœ˜Jšœ˜"šœœ˜!Jšœ˜!šœœ˜Jšœ˜Jšœœ˜————J˜Jšœ0™0J™Jšœ5™5Jšœ*™*J™Jšœ)™)Jšœ™Jšœ™Jšœ™š œ œ˜Jšœ œœœ˜"Jšœœœœ ˜"Jšœ+˜2JšœL™Lšœ ˜*˜ šœ ˜*Jšœ!œ˜#Jšœœ˜ Jšœ!œ˜#Jšœœ˜!Jšœ˜——šœ˜šœ ˜*Jšœ!œ˜#Jšœœ˜ Jšœ!œ˜#Jšœœ˜!Jšœ˜——˜šœ ˜*Jšœ!œ˜#Jšœœ˜ Jšœ!œ˜#Jšœœ˜!Jšœ˜——˜šœ ˜*Jšœ!œ˜#Jšœœ˜ Jšœ!œ˜#Jšœœ˜!Jšœ˜——Jšœ˜ ——J˜Jšœ;™;š œ œ˜Jš œœœœ œ˜,Jšœœœœ˜%Jšœœ ˜Jšœ ˜!J˜Jš œœœœ¡˜Jš œœœœœœ˜!J˜ Jšœ œ ¡˜/J˜š œœœœœ˜,Jšœ œ œœ˜%—J˜J˜Jšœ¡˜"Jšœ˜ ——J˜JšœA™Aš œ œ˜Jš œœœœ œ˜,Jšœœœœ˜%Jšœœ ˜Jšœ˜J˜Jš œœœœ¡˜Jš œœœœœœ˜!J˜ Jšœ œ˜"J˜J˜š œœ œœœœ ˜3Jšœ œ œœ˜%—J˜J˜ Jšœ˜ —J˜—Jšœ!™!Jšœ4™4š œ œ˜Jšœœœœœœœ ˜=Jš œœœœœœœ ˜EJšœ#˜*Jšœ˜J˜šœœ ˜Jšœ(œ˜2šœ˜Jšœœ˜šœœœ œ˜DJšœœ˜J˜!Jšœœ˜J˜———J˜—š œ œ˜Jšœœœœœœœ ˜=Jšœœœœœœœ ¡ ˜Qš   œ œœœœœ˜7Jšœ˜J˜Jšœ˜J˜Jšœ˜š œœ œœœœ˜:Jšœ œœœœœœœ œ˜>—Jšœœ ˜!Jšœœ¡˜0—šœœœ˜'šœ œ œœ˜4J˜šœ ˜šœœ œ˜J˜Jšœ œ œ%˜@—šœœ œ˜J˜Jšœ œ œ%˜@—Jšœ¡œœ˜šœœ œœ˜7šœœœœ˜BJ˜Jšœ œ œ%˜@——Jšœ˜——Jšœ˜—J˜J˜—š œ œ˜Jš œœœœœœœ ˜HJšœœœœ˜%Jšœ˜ Jšœ˜š œœ œœœœ ˜3Jšœ˜Jšœ œ œ ˜ Jšœœœ˜J˜Jšœ˜ —J˜—JšœD™Dš  œ œ˜Jš œœœœœœœ˜BJšœœœœ˜%Jšœ˜š  œ œœœœœ˜3Jšœ˜ Jšœ˜š œœ œœœœ ˜3Jš œœœœœœ˜!—J˜J˜J˜—š œ œ¡˜-Jšœ˜ J˜J˜Jšœ œ˜J˜J˜Jšœ œ˜J˜J˜Jšœ œ˜J˜—šœœ˜Jšœœ˜=Jšœœ˜=Jšœœ ¡!˜KJšœ¡!˜>Jšœ™J˜ Jšœœ˜0J˜ J˜@Jšœ)˜*Jšœ,œ˜2šœœœ˜J˜ J˜ J˜@Jšœ)˜*Jšœ,œ˜3—šœœœ˜+J˜*—Jšœœœœ˜EJšœ˜—J˜—š œ œ˜Jš œœœœœœœ˜BJšœœœœ˜%Jšœ˜Jšœ˜Jšœœœœœ œœ œœ¡ ˜Sš œœ œœœœ ˜3Jšœ˜J˜Jšœ œœ4˜LJšœ˜ —J˜—š œ œ˜Jš œœœœœœœ˜BJšœœœœ˜%Jšœ˜ Jšœ ˜!Jšœ ˜!J˜J˜J˜ Jšœœ˜ J˜Jšœœœœœ œœœœ¡ ˜Xš œœœœœ˜,Jšœ¡&˜.Jšœœ˜ Jšœ˜Jšœœ˜ Jšœœœœ˜ Jšœœœœœœœ˜?š œœœœœ˜*Jšœ¡˜š œ œ œœœ˜6Jšœœ˜ š œ œœ œœœ˜Jšœœœœ˜%J˜Jšœœ ˜ Jšœœ˜J˜—š œ œ˜Jšœœœœ œœœœ˜=Jšœœœœ˜%J˜Jšœœ ˜ Jšœœ˜J˜—š œ œ˜Jšœœœœœœœœ˜AJšœœœœ˜%J˜Jšœœ ˜ J˜J˜—š œ œ˜Jš œœœœœœœ ˜=Jšœœœœ˜%J˜ Jšœ˜J˜ J˜š˜Jšœ ˜Jšœœ˜ šœœ˜š œœœœœ ˜'Jš œœ œ œœ˜A—Jšœ˜—Jšœ œ˜Jšœœ œ ˜3š œœœœ œ ˜,Jš œ œœœœ˜1—šœ˜šœ¡ ˜ Jšœ ˜Jšœ˜#——šœ˜šœ¡ ˜!Jšœ ˜——Jšœ œ˜!J˜Jšœ˜—J˜—š œ œ˜Jšœœœœ œœœœ ˜>Jšœœœœ˜%Jšœ ˜ Jšœœœ˜ Jšœœ ˜J˜—š œ œ˜Jšœœœœ œœœœ ˜=Jšœœœœ˜%Jšœ ˜ Jšœœœ˜ Jšœœ ˜J˜—š œ œ˜Jšœœœœ œœœœ˜AJšœœœœ˜%Jšœ ˜ Jšœœ˜ Jšœœ ˜J˜—š œ œ˜Jšœœœœ˜1Jš œœœœœœœ ˜FJšœœœœ˜%J˜+J˜J˜ J˜2J˜2šœœ˜šœ˜Jšœ˜šœ%˜/š œœœœœ˜Fšœœ˜&Jšœ˜ Jšœ˜"——Jšœœ¡$˜Jšœœ˜4—š¡œ˜ šœœ˜J˜)J˜$J˜+———Jšœ™J˜9J˜5—šœœœ¡˜IJšœ˜Jšœ<˜@—Jšœ¡˜1Jšœ¡˜1Jšœ%¡˜9Jšœ˜——Jšœ%˜)—J˜—š œ œ˜Jšœœœœ˜1Jš œœœœœœœ ˜FJšœœœœ˜%Jšœœœ˜9J˜5J˜—š œ œ˜Jšœœœœ˜1Jš œœœœœœœ ˜FJšœœœœ˜%J˜J˜2J˜2šœœ˜šœ˜Jšœ˜šœ%˜/šœœœ˜ J˜J˜(—šœœ˜J˜;—šœ˜Jš¡œ(˜-J˜&J˜0Jšœ™šœ œ˜J˜J˜#—Jš¡œ:˜?J˜5—šœœœ˜ šœœœ˜>Jšœœœ˜CJ˜<—šœ˜J˜J˜(——Jšœ˜Jšœ˜Jšœ$˜%Jšœ˜——Jšœ%˜)—J˜—š œ œ˜Jšœœœœ˜1Jš œœœœœœœ ˜FJšœœœœ˜%J˜J˜2J˜2šœœ˜šœ˜Jšœ˜šœ%˜/šœœ˜J˜;—šœ˜šœœœ˜