diff --git a/src/lib/ulm/ulmMC68881.Mod b/src/lib/ulm/ulmMC68881.Mod new file mode 100644 index 00000000..503b1306 --- /dev/null +++ b/src/lib/ulm/ulmMC68881.Mod @@ -0,0 +1,183 @@ +(* Oberon Library - SunOS 4.1 - AFB 8/90 *) +(* (c) University of Ulm, Sektion Informatik, D-7900 Ulm *) + +MODULE MC68881; + + (* library interface to MC68881 instructions *) + + IMPORT SYS := SYSTEM; + + CONST + available* = FALSE; (* TRUE if MC68881 present *) + + (* rounding modes *) + toNearest* = 0; + towardZero* = 1; + towardMinusInfinity* = 2; + towardPlusInfinity* = 3; + + (* rounding precision *) + extended* = 0; + single* = 1; + double* = 2; + + (* exceptions *) + branchOnUnordered* = 0; + signalingNotANumber* = 1; + operandError* = 2; + overflow* = 3; + underflow* = 4; + divideByZero* = 5; + inexactOperation* = 6; + inexactDecimalInput* = 7; + + CONST + floatlen* = 4; (* length of a single precision real number *) + + (* monadic operations *) + + PROCEDURE FACOS*(x: LONGREAL) : LONGREAL; + BEGIN + RETURN ABS(x) + END FACOS; + + PROCEDURE FASIN*(x: LONGREAL) : LONGREAL; + BEGIN + RETURN ABS(x) + END FASIN; + + PROCEDURE FATAN*(x: LONGREAL) : LONGREAL; + BEGIN + RETURN ABS(x) + END FATAN; + + PROCEDURE FATANH*(x: LONGREAL) : LONGREAL; + BEGIN + RETURN ABS(x) + END FATANH; + + PROCEDURE FCOS*(x: LONGREAL) : LONGREAL; + BEGIN + RETURN ABS(x) + END FCOS; + + PROCEDURE FCOSH*(x: LONGREAL) : LONGREAL; + BEGIN + RETURN ABS(x) + END FCOSH; + + PROCEDURE FETOX*(x: LONGREAL) : LONGREAL; + BEGIN + RETURN ABS(x) + END FETOX; + + PROCEDURE FETOXM1*(x: LONGREAL) : LONGREAL; + BEGIN + RETURN ABS(x) + END FETOXM1; + + PROCEDURE FGETEXP*(x: LONGREAL) : LONGREAL; + BEGIN + RETURN ABS(x) + END FGETEXP; + + PROCEDURE FGETMAN*(x: LONGREAL) : LONGREAL; + BEGIN + RETURN ABS(x) + END FGETMAN; + + PROCEDURE FLOG10*(x: LONGREAL) : LONGREAL; + BEGIN + RETURN ABS(x) + END FLOG10; + + PROCEDURE FLOG2*(x: LONGREAL) : LONGREAL; + BEGIN + RETURN ABS(x) + END FLOG2; + + PROCEDURE FLOGN*(x: LONGREAL) : LONGREAL; + BEGIN + RETURN ABS(x) + END FLOGN; + + PROCEDURE FLOGNP1*(x: LONGREAL) : LONGREAL; + BEGIN + RETURN ABS(x) + END FLOGNP1; + + PROCEDURE FSIN*(x: LONGREAL) : LONGREAL; + BEGIN + RETURN ABS(x) + END FSIN; + + PROCEDURE FSINH*(x: LONGREAL) : LONGREAL; + BEGIN + RETURN ABS(x) + END FSINH; + + PROCEDURE FSQRT*(x: LONGREAL) : LONGREAL; + BEGIN + RETURN ABS(x) + END FSQRT; + + PROCEDURE FTAN*(x: LONGREAL) : LONGREAL; + BEGIN + RETURN ABS(x) + END FTAN; + + PROCEDURE FTANH*(x: LONGREAL) : LONGREAL; + BEGIN + RETURN ABS(x) + END FTANH; + + PROCEDURE FTENTOX*(x: LONGREAL) : LONGREAL; + BEGIN + RETURN ABS(x) + END FTENTOX; + + PROCEDURE FTWOTOX*(x: LONGREAL) : LONGREAL; + BEGIN + RETURN ABS(x) + END FTWOTOX; + + + PROCEDURE GetExceptionEnable*(VAR exceptions: SET); + BEGIN + exceptions := {}; + END GetExceptionEnable; + + PROCEDURE SetExceptionEnable*(exceptions: SET); + BEGIN + exceptions := {}; + END SetExceptionEnable; + + + PROCEDURE GetRoundingMode*(VAR precision, mode: INTEGER); + BEGIN + precision := 1; + mode := 2; + END GetRoundingMode; + + PROCEDURE SetRoundingMode*(precision, mode: INTEGER); + BEGIN + precision := 1; + mode := 2; + END SetRoundingMode; + + + (* conversions to and from single precision (C's float); + float must consist of at least floatlen bytes + *) + + PROCEDURE RealToFloat*(real: LONGREAL; VAR float: ARRAY OF BYTE); + BEGIN + SYS.WMOVE(SYS.ADR(real), SYS.ADR(float), floatlen DIV 4); + END RealToFloat; + + PROCEDURE FloatToReal*(float: ARRAY OF BYTE; VAR real: LONGREAL); + BEGIN + SYS.WMOVE(SYS.ADR(float), SYS.ADR(real), floatlen DIV 4); + END FloatToReal; + +END MC68881. diff --git a/src/lib/ulm/ulmReals.Mod b/src/lib/ulm/ulmReals.Mod new file mode 100644 index 00000000..96ad8406 --- /dev/null +++ b/src/lib/ulm/ulmReals.Mod @@ -0,0 +1,313 @@ +(* Ulm's Oberon Library + Copyright (C) 1989-1994 by University of Ulm, SAI, D-89069 Ulm, Germany + ---------------------------------------------------------------------------- + Ulm's Oberon Library is free software; you can redistribute it + and/or modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either version + 2 of the License, or (at your option) any later version. + + Ulm's Oberon Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + ---------------------------------------------------------------------------- + E-mail contact: oberon@mathematik.uni-ulm.de + ---------------------------------------------------------------------------- + $Id: Reals.om,v 1.2 2004/03/09 21:38:50 borchert Exp $ + ---------------------------------------------------------------------------- + $Log: Reals.om,v $ + Revision 1.2 2004/03/09 21:38:50 borchert + maxlongexp, minlongexp, and maxlongdignum adapted to SPARC architecture + + Revision 1.1 1994/02/23 07:45:40 borchert + Initial revision + + ---------------------------------------------------------------------------- + AFB 6/89 + ---------------------------------------------------------------------------- +*) + +MODULE Reals; + + IMPORT IEEE, MC68881; + + CONST + (* for REAL *) + maxexp* = 309; + minexp* = -323; + maxdignum* = 16; + (* for LONGREAL *) + (* + maxlongexp = 4932; + minlongexp = -4951; + maxlongdignum = 19; + *) + maxlongexp* = 309; + minlongexp* = -323; + maxlongdignum* = 16; + + powers = 6; + maxbase = 16; + TYPE + PowerRec = + RECORD + p10: LONGREAL; + n: INTEGER; + END; + VAR + powtab: ARRAY powers OF PowerRec; + sigdigits: ARRAY maxbase+1 OF INTEGER; (* valid range: [2..maxbase] *) + + PROCEDURE ExpAndMan*(r: LONGREAL; long: BOOLEAN; base: INTEGER; + VAR exponent: INTEGER; VAR mantissa: LONGREAL); + (* get exponent and mantissa from `r': + + (1.0 >= ABS(mantissa)) & (ABS(mantissa) < base) + + r = mantissa * base^exponent + + long should be false if a REAL-value is passed to `r' + valid values of base: 2, 8, 10, and 16 + *) + VAR + neg: BOOLEAN; + index: INTEGER; + roundoff: LONGREAL; + i: INTEGER; + ndigits: INTEGER; + BEGIN + IF r = 0.0 THEN + exponent := 0; mantissa := 0; RETURN + ELSIF r = IEEE.plusInfinity THEN + IF long THEN + exponent := 9999; + ELSE + exponent := 999; + END; + mantissa := 1; + RETURN + ELSIF r = IEEE.minusInfinity THEN + IF long THEN + exponent := 9999; + ELSE + exponent := 999; + END; + mantissa := -1; + RETURN + ELSIF IEEE.NotANumber(r) THEN + exponent := 0; + mantissa := 0; + RETURN + END; + neg := r < 0.0; + IF neg THEN + r := ABS(r); + END; + exponent := 0; mantissa := r; + IF base = 10 THEN + IF MC68881.available THEN + exponent := SHORT(ENTIER(MC68881.FLOG10(r))); + mantissa := r / MC68881.FTENTOX(exponent); + ELSE + (* use powtab *) + index := 0; + WHILE mantissa < 1.0 DO + WHILE mantissa * powtab[index].p10 < 10 DO + DEC(exponent, powtab[index].n); + mantissa := mantissa * powtab[index].p10; + END; + INC(index); + END; + WHILE mantissa >= 10 DO + WHILE mantissa >= powtab[index].p10 DO + INC(exponent, powtab[index].n); + mantissa := mantissa / powtab[index].p10; + END; + INC(index); + END; + END; + ELSE (* general case *) + WHILE mantissa < 1.0 DO + DEC(exponent); mantissa := mantissa * base; + END; + WHILE mantissa >= base DO + INC(exponent); mantissa := mantissa / base; + END; + END; + IF ~(base IN {2, 4, 16}) THEN + (* roundoff *) + roundoff := base/2; + IF ~long & (base = 10) THEN + ndigits := maxdignum; + ELSE + ndigits := sigdigits[base]; + END; + i := 0; + WHILE i < ndigits DO + roundoff := roundoff/base; INC(i); + END; + mantissa := mantissa + roundoff; + IF mantissa >= base THEN + mantissa := mantissa / base; + INC(exponent); + ELSIF mantissa < 1 THEN + mantissa := mantissa * base; + DEC(exponent); + END; + END; + IF neg THEN + mantissa := -mantissa; + END; + END ExpAndMan; + + PROCEDURE Power*(base: LONGREAL; exp: INTEGER) : LONGREAL; + (* efficient calculation of base^exp *) + VAR + r, res: LONGREAL; + neg: BOOLEAN; (* negative exponent? *) + BEGIN + IF MC68881.available & (base = 10) THEN + RETURN MC68881.FTENTOX(exp) + ELSIF MC68881.available & (base = 2) THEN + RETURN MC68881.FTWOTOX(exp) + ELSE + res := 1.0; + r := base; + neg := exp < 0; + exp := ABS(exp); + LOOP + IF ODD(exp) THEN + res := res * r; + END; + exp := exp DIV 2; + IF exp = 0 THEN + EXIT + END; + r := r * r; + END; + IF neg THEN + RETURN 1 / res + ELSE + RETURN res + END; + END; + END Power; + + PROCEDURE Digits*(mantissa: LONGREAL; base: INTEGER; + VAR buf: ARRAY OF CHAR; + VAR neg: BOOLEAN; + force: BOOLEAN; VAR ndigits: INTEGER); + (* PRE: + mantissa holds the post-condition of ExpAndMan; + valid values for base are 2, 8, 10, and 16 + ndigits > 0: maximal number of digits + POST: + the mantissa is converted into digits 0-9 and A-F (if base = 16); + buf consists of ndigits digits and + is guaranteed to be 0X-terminated; + neg is set to TRUE if mantissa < 0 + force = FALSE: + there are no leading zeroes except on mantissa = 0; + force = TRUE + ndigits is unchanged + *) + VAR + index: INTEGER; (* of buf *) + i: INTEGER; roundoff: LONGREAL; + lastnz: INTEGER; (* last index with buf[index] # "0" *) + ch: CHAR; + digit: LONGINT; + maxdig: CHAR; (* base-1 converted *) + + BEGIN + index := 0; + IF (ndigits <= 0) OR (ndigits+1 >= LEN(buf)) THEN + ndigits := SHORT(LEN(buf) - 1); + END; + IF ~force & (ndigits > sigdigits[base]) THEN + ndigits := sigdigits[base]; + END; + neg := mantissa < 0; + mantissa := ABS(mantissa); + IF mantissa = 0 THEN + buf[index] := "0"; INC(index); + ELSE + (* roundoff *) + roundoff := base/2; + i := 0; + WHILE i < ndigits DO + roundoff := roundoff/base; INC(i); + END; + IF mantissa + roundoff < base THEN + mantissa := mantissa + roundoff; + END; + + (* conversion *) + lastnz := 0; + WHILE (index < ndigits) & (mantissa # 0) DO + digit := ENTIER(mantissa); + (* digit in [0..base-1] *) + IF digit <= 9 THEN + ch := CHR(digit + ORD("0")); + ELSIF digit <= 16 THEN + ch := CHR(digit - 10 + ORD("A")); + ELSE + ch := "?"; + END; + buf[index] := ch; INC(index); + mantissa := (mantissa - digit) * base; + IF ch # "0" THEN + lastnz := index; + END; + END; + index := lastnz; + END; + buf[index] := 0X; ndigits := index; + END Digits; + + PROCEDURE Convert*(digits: ARRAY OF CHAR; base: INTEGER; neg: BOOLEAN; + VAR mantissa: LONGREAL); + (* convert normalized `digits' (decimal point after 1st digit) + into `mantissa' + *) + VAR + index: INTEGER; + factor: LONGREAL; + BEGIN + IF digits = "0" THEN + mantissa := 0; + ELSE + mantissa := ORD(digits[0]) - ORD("0"); + factor := 1 / base; + index := 1; + WHILE (index < LEN(digits)) & (index < sigdigits[base]) & + (digits[index] # 0X) & (factor > 0) DO + mantissa := mantissa + (ORD(digits[index]) - ORD("0")) * factor; + factor := factor / base; + INC(index); + END; + IF neg THEN + mantissa := -mantissa; + END; + END; + END Convert; + +BEGIN + powtab[0].p10 := 1.0D32; powtab[0].n := 32; + powtab[1].p10 := 1.0D16; powtab[1].n := 16; + powtab[2].p10 := 1.0D8; powtab[2].n := 8; + powtab[3].p10 := 1.0D4; powtab[3].n := 4; + powtab[4].p10 := 1.0D2; powtab[4].n := 2; + powtab[5].p10 := 1.0D1; powtab[5].n := 1; + + (* for LONGREAL *) + sigdigits[2] := 64; sigdigits[3] := 40; sigdigits[4] := 32; + sigdigits[5] := 27; sigdigits[6] := 24; sigdigits[7] := 22; + sigdigits[8] := 21; sigdigits[9] := 20; sigdigits[10] := 19; + sigdigits[11] := 18; sigdigits[12] := 17; sigdigits[13] := 17; + sigdigits[14] := 16; sigdigits[15] := 16; sigdigits[16] := 16; +END Reals. diff --git a/src/lib/ulm/ulmStreamDisciplines.Mod b/src/lib/ulm/ulmStreamDisciplines.Mod index 66b8a736..686214c9 100644 --- a/src/lib/ulm/ulmStreamDisciplines.Mod +++ b/src/lib/ulm/ulmStreamDisciplines.Mod @@ -31,11 +31,11 @@ ---------------------------------------------------------------------------- *) -MODULE StreamDisciplines; +MODULE ulmStreamDisciplines; (* definition of general-purpose disciplines for streams *) - IMPORT ASCII, Disciplines := IndirectDisciplines, Events, Sets, Streams; + IMPORT ASCII := ulmASCII, Disciplines := ulmIndirectDisciplines, Events := ulmEvents, Sets := ulmSets, Streams := ulmStreams, SYSTEM; TYPE LineTerminator* = ARRAY 4 OF CHAR; @@ -77,7 +77,7 @@ MODULE StreamDisciplines; VAR disc: StreamDiscipline; BEGIN - IF ~Disciplines.Seek(s, id, disc) THEN + IF ~Disciplines.Seek(s, id, SYSTEM.VAL(Disciplines.Discipline, disc)) THEN InitDiscipline(disc); END; disc.lineterm := lineterm; @@ -89,7 +89,7 @@ MODULE StreamDisciplines; VAR disc: StreamDiscipline; BEGIN - IF Disciplines.Seek(s, id, disc) THEN + IF Disciplines.Seek(s, id, SYSTEM.VAL(Disciplines.Discipline, disc)) THEN lineterm := disc.lineterm; ELSE lineterm := defaultLineTerm; @@ -121,7 +121,7 @@ MODULE StreamDisciplines; Events.Raise(event); RETURN END; - IF ~Disciplines.Seek(s, id, disc) THEN + IF ~Disciplines.Seek(s, id, SYSTEM.VAL(Disciplines.Discipline, disc)) THEN InitDiscipline(disc); END; disc.fieldseps := fieldsepset; @@ -134,7 +134,7 @@ MODULE StreamDisciplines; VAR disc: StreamDiscipline; BEGIN - IF Disciplines.Seek(s, id, disc) THEN + IF Disciplines.Seek(s, id, SYSTEM.VAL(Disciplines.Discipline, disc)) THEN fieldsepset := disc.fieldseps; ELSE fieldsepset := defaultFieldSeps; @@ -145,7 +145,7 @@ MODULE StreamDisciplines; VAR disc: StreamDiscipline; BEGIN - IF ~Disciplines.Seek(s, id, disc) THEN + IF ~Disciplines.Seek(s, id, SYSTEM.VAL(Disciplines.Discipline, disc)) THEN InitDiscipline(disc); END; Sets.InclChar(disc.fieldseps, fieldsep); @@ -161,7 +161,7 @@ MODULE StreamDisciplines; VAR disc: StreamDiscipline; BEGIN - IF Disciplines.Seek(s, id, disc) THEN + IF Disciplines.Seek(s, id, SYSTEM.VAL(Disciplines.Discipline, disc)) THEN fieldsep := disc.fieldsep; ELSE fieldsep := defaultFieldSep; @@ -173,7 +173,7 @@ MODULE StreamDisciplines; VAR disc: StreamDiscipline; BEGIN - IF Disciplines.Seek(s, id, disc) THEN + IF Disciplines.Seek(s, id, SYSTEM.VAL(Disciplines.Discipline, disc)) THEN whitespace := disc.whitespace; ELSE whitespace := defaultWhiteSpace; @@ -184,7 +184,7 @@ MODULE StreamDisciplines; VAR disc: StreamDiscipline; BEGIN - IF ~Disciplines.Seek(s, id, disc) THEN + IF ~Disciplines.Seek(s, id, SYSTEM.VAL(Disciplines.Discipline, disc)) THEN InitDiscipline(disc); END; disc.whitespace := whitespace; @@ -196,7 +196,7 @@ MODULE StreamDisciplines; disc: StreamDiscipline; BEGIN IF indentwidth >= 0 THEN - IF ~Disciplines.Seek(s, id, disc) THEN + IF ~Disciplines.Seek(s, id, SYSTEM.VAL(Disciplines.Discipline, disc)) THEN InitDiscipline(disc); END; disc.indentwidth := indentwidth; @@ -208,7 +208,7 @@ MODULE StreamDisciplines; VAR disc: StreamDiscipline; BEGIN - IF Disciplines.Seek(s, id, disc) THEN + IF Disciplines.Seek(s, id, SYSTEM.VAL(Disciplines.Discipline, disc)) THEN indentwidth := disc.indentwidth; ELSE indentwidth := defaultIndentWidth; @@ -219,7 +219,7 @@ MODULE StreamDisciplines; VAR disc: StreamDiscipline; BEGIN - IF ~Disciplines.Seek(s, id, disc) THEN + IF ~Disciplines.Seek(s, id, SYSTEM.VAL(Disciplines.Discipline, disc)) THEN InitDiscipline(disc); END; IF disc.indentwidth + incr >= 0 THEN @@ -243,4 +243,4 @@ BEGIN Sets.InclChar(defaultWhiteSpace, ASCII.np); Sets.InclChar(defaultWhiteSpace, ASCII.nl); defaultIndentWidth := 0; -END StreamDisciplines. +END ulmStreamDisciplines.