xfail scan-tree-dump-not throw in g++.dg/pr99966.C on hppa*64*-*-*
[official-gcc.git] / gcc / m2 / gm2-libs-iso / ConvStringReal.mod
blob67db2b5bf7f4faa649776682e5668c3f26cff899
1 (* ConvStringReal.mod translate floating point numbers to Strings.
3 Copyright (C) 2009-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)
11 any later version.
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 ConvStringReal ;
29 FROM DynamicStrings IMPORT InitString, KillString, ConCat, ConCatChar,
30 Slice, Length, Mult, Mark, InitStringCharStar,
31 InitStringChar, Index, char ;
32 FROM StringConvert IMPORT IntegerToString, ToSigFig ;
33 FROM dtoa IMPORT dtoa, Mode ;
34 FROM libc IMPORT free, printf ;
35 FROM SYSTEM IMPORT ADDRESS ;
37 CONST
38 Debugging = FALSE ;
42 IsDigit - returns TRUE if, ch, lies between '0'..'9'.
45 PROCEDURE IsDigit (ch: CHAR) : BOOLEAN ;
46 BEGIN
47 RETURN (ch>='0') AND (ch<='9')
48 END IsDigit ;
52 RealToFloatString - converts a real with, sigFigs, into a string
53 and returns the result as a string.
56 PROCEDURE RealToFloatString (real: REAL; sigFigs: CARDINAL) : String ;
57 VAR
58 point, l,
59 powerOfTen: INTEGER ;
60 s : String ;
61 r : ADDRESS ;
62 sign : BOOLEAN ;
63 BEGIN
64 r := dtoa(real, maxsignificant, 100, point, sign) ;
65 s := InitStringCharStar(r) ;
66 free(r) ;
67 IF sigFigs>0
68 THEN
69 l := Length(s) ;
70 IF (l>0) AND IsDigit(char(s, 0))
71 THEN
72 IF VAL(INTEGER, sigFigs)<l
73 THEN
74 s := Slice(ToSigFig(s, sigFigs), 0, sigFigs)
75 ELSE
76 (* add '0's to make up significant figures *)
77 s := ConCat(s, Mark(Mult(InitStringChar('0'), l-VAL(INTEGER, sigFigs))))
78 END ;
79 l := Length(s) ;
81 * we reassign point to 1 and adjust the exponent
82 * accordingly, so we can achieve the format X.XXXE+X
84 powerOfTen := point-1 ;
85 point := 1 ;
87 IF (point<l) AND (point<VAL(INTEGER, sigFigs))
88 THEN
89 s := ConCat(ConCatChar(Slice(s, 0, point), '.'),
90 Slice(s, point, 0))
91 END ;
93 IF powerOfTen#0
94 THEN
95 s := ConCat(ConCatChar(s, 'E'),
96 IntegerToString(powerOfTen, 0, ' ', TRUE, 10, FALSE))
97 END
98 END ;
99 IF sign
100 THEN
101 s := ConCat(InitStringChar('-'), Mark(s))
103 END ;
104 RETURN( s )
105 END RealToFloatString ;
109 RealToEngString - converts the value of real to floating-point
110 string form, with sigFigs significant figures.
111 The number is scaled with one to three digits
112 in the whole number part and with an exponent
113 that is a multiple of three.
116 PROCEDURE RealToEngString (real: REAL; sigFigs: CARDINAL) : String ;
118 offset,
119 point,
120 powerOfTen: INTEGER ;
121 s : String ;
122 l : CARDINAL ;
123 r : ADDRESS ;
124 sign : BOOLEAN ;
125 BEGIN
126 r := dtoa(real, maxsignificant, 100, point, sign) ;
127 s := InitStringCharStar(r) ;
128 free(r) ;
129 IF sigFigs>0
130 THEN
131 l := Length(s) ;
132 IF (l>0) AND IsDigit(char(s, 0))
133 THEN
134 IF sigFigs<l
135 THEN
136 s := Slice(ToSigFig(s, sigFigs), 0, sigFigs)
137 ELSE
138 (* add '0's to make up significant figures *)
139 s := ConCat(s, Mark(Mult(InitStringChar('0'), l-sigFigs)))
140 END ;
141 l := Length(s) ;
142 IF (point>0) AND (point<=2)
143 THEN
144 (* current range is fine, no need for a exponent *)
145 powerOfTen := 0 ;
146 IF point>VAL(INTEGER, sigFigs)
147 THEN
148 (* add '0's to make up required mantissa length *)
149 s := ConCat(s, Mark(Mult(InitStringChar('0'), point-VAL(INTEGER, sigFigs)))) ;
150 l := Length(s)
152 ELSE
154 * desire a value of point which lies between 1..3
155 * this allows the mantissa to have the format
156 * X.XXX or XX.XX or XXX.X
158 powerOfTen := point-VAL(INTEGER, l) ;
159 point := point-powerOfTen ;
160 offset := 0 ;
161 IF point>3
162 THEN
163 offset := (point DIV 3) * 3 ;
164 point := point-offset ;
165 powerOfTen := powerOfTen+offset
166 ELSIF point<0
167 THEN
168 offset := (ABS(point) DIV 3) * 3 ;
169 point := point+offset ;
170 powerOfTen := powerOfTen-offset
171 END ;
172 IF powerOfTen<0
173 THEN
174 IF ABS(powerOfTen) MOD 3#0
175 THEN
176 offset := 3-(ABS(powerOfTen) MOD 3)
178 ELSE
179 (* at this stage, point >= sigFigs *)
180 IF powerOfTen MOD 3#0
181 THEN
182 offset := -(3-(powerOfTen MOD 3))
184 END ;
185 IF offset+point>VAL(INTEGER, sigFigs)
186 THEN
187 (* add '0's to make up required mantissa length *)
188 s := ConCat(s, Mark(Mult(InitStringChar('0'), offset+point-VAL(INTEGER, sigFigs)))) ;
189 l := Length(s)
190 END ;
191 (* now adjust point and powerOfTen by offset *)
192 point := point + offset ;
193 powerOfTen := powerOfTen - offset
194 END ;
196 IF point<0
197 THEN
198 s := ConCat(ConCat(InitString('0.'), Mult(InitStringChar('0'), -point)), s)
199 ELSIF (point>0) AND (point<VAL(INTEGER, l)) AND (point<VAL(INTEGER, sigFigs))
200 THEN
201 s := ConCat(ConCatChar(Slice(s, 0, point), '.'),
202 Slice(s, point, 0))
203 END ;
205 IF powerOfTen#0
206 THEN
207 s := ConCat(ConCatChar(s, 'E'),
208 IntegerToString(powerOfTen, 0, ' ', TRUE, 10, FALSE))
210 END ;
211 IF sign
212 THEN
213 s := ConCat(InitStringChar('-'), Mark(s))
215 END ;
216 RETURN( s )
217 END RealToEngString ;
221 RealToFixedString - returns the number of characters in the fixed-point
222 string representation of real rounded to the given
223 place relative to the decimal point.
226 PROCEDURE RealToFixedString (real: REAL; place: INTEGER) : String ;
229 point: INTEGER ;
230 sign : BOOLEAN ;
231 r : ADDRESS ;
232 s : String ;
233 BEGIN
234 r := dtoa(real, maxsignificant, 100, point, sign) ;
235 s := InitStringCharStar(r) ;
236 free(r) ;
237 l := Length(s) ;
238 IF Debugging
239 THEN
240 printf("length of string returned is %d decimal point at position %d\n", l, point)
241 END ;
242 IF (l>0) AND IsDigit(char(s, 0))
243 THEN
244 IF point+place>=0
245 THEN
246 (* add decimal point at correct position *)
247 IF point<0
248 THEN
249 s := ConCat(ConCat(InitString('0.'), Mult(InitStringChar('0'), -point)), s)
250 ELSIF point=0
251 THEN
252 s := ConCat(InitString('0.'), Mark(s))
253 ELSIF point<l
254 THEN
255 s := ConCat(ConCatChar(Slice(s, 0, point), '.'),
256 Slice(s, point, 0))
257 END ;
258 IF place<0
259 THEN
260 s := ToSigFig(s, point+place+1)
261 ELSE
262 s := ToSigFig(s, point+place)
263 END ;
264 l := Length(s) ;
265 IF place>=0
266 THEN
267 IF Index(s, '.', 0)<0
268 THEN
269 s := ConCatChar(s, '.') ;
270 s := ConCat(s, Mark(Mult(InitStringChar('0'), place)))
271 ELSE
272 point := Index(s, '.', 0) ;
273 IF l-point<place
274 THEN
275 s := ConCat(s, Mark(Mult(InitStringChar('0'), l-point-place)))
279 ELSE
280 IF place<0
281 THEN
282 s := InitString('0')
283 ELSIF place=0
284 THEN
285 s := InitString('0.')
286 ELSE
287 s := InitString('0.0')
290 END ;
291 IF sign
292 THEN
293 s := ConCat(InitStringChar('-'), Mark(s))
294 END ;
295 RETURN( s )
296 END RealToFixedString ;
299 END ConvStringReal.