1 (* LowLong.mod implement ISO LowLong specification.
3 Copyright (C) 2010-2024 Free Software Foundation, Inc.
4 Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.
6 This file is part of GNU Modula-2.
8 GNU Modula-2 is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
13 GNU Modula-2 is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 Under Section 7 of GPL version 3, you are granted additional
19 permissions described in the GCC Runtime Library Exception, version
20 3.1, as published by the Free Software Foundation.
22 You should have received a copy of the GNU General Public License and
23 a copy of the GCC Runtime Library Exception along with this program;
24 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
25 <http://www.gnu.org/licenses/>. *)
27 IMPLEMENTATION MODULE LowLong ;
29 FROM SYSTEM IMPORT ADDRESS ;
30 FROM Builtins IMPORT ilogbl, modfl, signbitl, scalbnl, huge_vall, nextafterl ;
31 FROM dtoa IMPORT Mode, strtod, dtoa ;
32 FROM libc IMPORT free ;
33 FROM RealMath IMPORT power ;
34 FROM ConvStringReal IMPORT RealToFloatString ;
35 FROM StringConvert IMPORT ToSigFig ;
37 FROM EXCEPTIONS IMPORT ExceptionSource, AllocateSource, RAISE, CurrentNumber,
38 IsCurrentSource, IsExceptionalExecution ;
40 FROM DynamicStrings IMPORT String, InitString, KillString, Slice, Mark,
41 Mult, InitStringCharStar, Length, ConCat,
42 ConCatChar, InitStringChar, string ;
45 FloatingPointExceptions = (badparam) ;
52 exponent - returns the exponent value of x
55 PROCEDURE exponent (x: LONGREAL) : INTEGER ;
62 fraction - returns the significand (or significant part) of x
65 PROCEDURE fraction (x: LONGREAL) : LONGREAL ;
67 RETURN scalbnl(x, -ilogbl (x))
71 sign - returns the signum of x. sign(x) = 1.0 for all x>0.0
72 sign(x) = -1.0 for all x<0.0.
73 may be either -1.0 or 1.0 if x = 0.0
76 PROCEDURE sign (x: LONGREAL) : LONGREAL ;
88 succ - returns the next value of the type REAL greater than x
91 PROCEDURE succ (x: LONGREAL) : LONGREAL ;
93 RETURN nextafterl(x, huge_vall())
98 ulp - returns the value of a unit in the last place of x.
101 ulp(x) = succ(x)-x or
102 ulp(x) = x-pred(x) or both are true.
104 if the value does not exist then an exception is raised.
107 PROCEDURE ulp (x: LONGREAL) : LONGREAL ;
119 pred - returns the previous value of the type REAL less than x.
122 PROCEDURE pred (x: LONGREAL) : LONGREAL ;
124 RETURN nextafterl(x, -huge_vall())
129 intpart - returns the integer part of x
132 PROCEDURE intpart (x: LONGREAL) : LONGREAL ;
142 fractpart - returns the fractional part of x
145 PROCEDURE fractpart (x: LONGREAL) : LONGREAL ;
154 scale - returns the value of x * radix ** n
156 The following holds true:
158 x = synthesize(exponent(x),fraction(x))
159 x = scale(fraction(x), exponent(x))
162 PROCEDURE scale (x: LONGREAL; n: INTEGER) : LONGREAL ;
169 trunc - returns the value of the first n places of x.
172 PROCEDURE trunc (x: LONGREAL; n: INTEGER) : LONGREAL ;
180 powerOfTen: INTEGER ;
184 (* exception raised *)
185 RAISE(except, ORD(badparam),
186 'LowLong.trunc: cannot truncate to a negative number of digits') ;
189 r := dtoa(x, maxsignificant, 100, point, sign) ;
190 s := InitStringCharStar(r) ;
195 s := Slice(ToSigFig(s, n), 0, n)
197 (* add '0's to make up significant figures *)
198 s := ConCat(s, Mark(Mult(InitStringChar('0'), l-VAL(INTEGER, n))))
200 powerOfTen := point-1 ;
203 IF (point<l) AND (point<VAL(INTEGER, n))
205 s := ConCat(ConCatChar(Slice(s, 0, point), '.'),
208 y := strtod(string(s), error) ;
211 y := power(y, FLOATL(powerOfTen))
220 round - returns the value of x rounded to the first n places.
221 n significant figures.
224 PROCEDURE round (x: LONGREAL; n: INTEGER) : LONGREAL ;
232 (* exception raised *)
233 RAISE(except, ORD(badparam),
234 'LowLong.round: cannot round to a negative number of digits') ;
237 s := RealToFloatString(x, n) ;
238 y := strtod(string(s), error) ;
246 synthesize - returns a value of the type REAL constructed from
247 the given expart and frapart.
249 The following holds true:
251 x = synthesize(exponent(x),fraction(x))
252 x = scale(fraction(x), exponent(x))
255 PROCEDURE synthesize (expart: INTEGER; frapart: LONGREAL) : LONGREAL ;
257 RETURN scalbnl(frapart, expart)
262 setMode - sets status flags appropriate to the underlying implementation
266 PROCEDURE setMode (m: Modes) ;
273 currentMode - returns the current status flags in the form set by setMode
276 PROCEDURE currentMode () : Modes ;
283 IsLowException - returns TRUE if the current coroutine is in the exceptional
284 execution state because of the raising of an exception in a
285 routine from this module; otherwise returns FALSE.
288 PROCEDURE IsLowException () : BOOLEAN ;
290 RETURN( IsExceptionalExecution() AND IsCurrentSource(except) )
295 except: ExceptionSource ;
297 AllocateSource(except)