300
by john haque
Add infrastructure for MPFR/GMP support. |
1 |
/*
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
2 |
* mpfr.c - routines for arbitrary-precision number support in gawk.
|
300
by john haque
Add infrastructure for MPFR/GMP support. |
3 |
*/
|
4 |
||
408.26.83
by Arnold D. Robbins
Remove trailing whitespace everywhere. Fix Unicode into ASCII. |
5 |
/*
|
731.11.254
by Arnold D. Robbins
Changes to ROUNDMODE now invalidate cached string values. |
6 |
* Copyright (C) 2012, 2013, 2015, 2017, 2018,
|
7 |
* the Free Software Foundation, Inc.
|
|
408.26.83
by Arnold D. Robbins
Remove trailing whitespace everywhere. Fix Unicode into ASCII. |
8 |
*
|
300
by john haque
Add infrastructure for MPFR/GMP support. |
9 |
* This file is part of GAWK, the GNU implementation of the
|
10 |
* AWK Programming Language.
|
|
408.26.83
by Arnold D. Robbins
Remove trailing whitespace everywhere. Fix Unicode into ASCII. |
11 |
*
|
300
by john haque
Add infrastructure for MPFR/GMP support. |
12 |
* GAWK is free software; you can redistribute it and/or modify
|
13 |
* it under the terms of the GNU General Public License as published by
|
|
14 |
* the Free Software Foundation; either version 3 of the License, or
|
|
15 |
* (at your option) any later version.
|
|
408.26.83
by Arnold D. Robbins
Remove trailing whitespace everywhere. Fix Unicode into ASCII. |
16 |
*
|
300
by john haque
Add infrastructure for MPFR/GMP support. |
17 |
* GAWK is distributed in the hope that it will be useful,
|
18 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
19 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
20 |
* GNU General Public License for more details.
|
|
408.26.83
by Arnold D. Robbins
Remove trailing whitespace everywhere. Fix Unicode into ASCII. |
21 |
*
|
300
by john haque
Add infrastructure for MPFR/GMP support. |
22 |
* You should have received a copy of the GNU General Public License
|
23 |
* along with this program; if not, write to the Free Software
|
|
24 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
25 |
*/
|
|
26 |
||
27 |
#include "awk.h" |
|
28 |
||
302.1.1
by john haque
Finish MPFR changes and clean up code. |
29 |
#ifdef HAVE_MPFR
|
30 |
||
731.11.254
by Arnold D. Robbins
Changes to ROUNDMODE now invalidate cached string values. |
31 |
int MPFR_round_mode = 'N'; // default value |
32 |
||
305
by john haque
Bug fixes and tests for MPFR. |
33 |
#if !defined(MPFR_VERSION_MAJOR) || MPFR_VERSION_MAJOR < 3
|
302.1.1
by john haque
Finish MPFR changes and clean up code. |
34 |
typedef mp_exp_t mpfr_exp_t; |
300
by john haque
Add infrastructure for MPFR/GMP support. |
35 |
#endif
|
36 |
||
301
by john haque
New interpreter routine for MPFR. |
37 |
extern NODE **fmt_list; /* declared in eval.c */ |
38 |
||
306
by john haque
Add arbitrary-precision arithmetic on integers. |
39 |
mpz_t mpzval; /* GMP integer type, used as temporary in few places */ |
40 |
mpz_t MNR; |
|
41 |
mpz_t MFNR; |
|
319.1.9
by Arnold D. Robbins
Move to use of bool type, true, false, everywhere. |
42 |
bool do_ieee_fmt; /* IEEE-754 floating-point emulation */ |
316
by john haque
Change MPFR variable RND_MODE to ROUND_MODE. |
43 |
mpfr_rnd_t ROUND_MODE; |
300
by john haque
Add infrastructure for MPFR/GMP support. |
44 |
|
408.28.1
by Andrew J. Schorr
Fix MPFR bug where precision was reduced to that of the function argument. |
45 |
static mpfr_prec_t default_prec; |
46 |
||
302.1.1
by john haque
Finish MPFR changes and clean up code. |
47 |
static mpfr_rnd_t get_rnd_mode(const char rmode); |
48 |
static NODE *mpg_force_number(NODE *n); |
|
49 |
static NODE *mpg_make_number(double); |
|
50 |
static NODE *mpg_format_val(const char *format, int index, NODE *s); |
|
51 |
static int mpg_interpret(INSTRUCTION **cp); |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
52 |
|
305
by john haque
Bug fixes and tests for MPFR. |
53 |
static mpfr_exp_t min_exp = MPFR_EMIN_DEFAULT; |
54 |
static mpfr_exp_t max_exp = MPFR_EMAX_DEFAULT; |
|
300
by john haque
Add infrastructure for MPFR/GMP support. |
55 |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
56 |
/* temporary MPFR floats used to hold converted GMP integer operands */
|
57 |
static mpfr_t _mpf_t1; |
|
58 |
static mpfr_t _mpf_t2; |
|
59 |
||
60 |
/*
|
|
61 |
* PRECISION_MIN is the precision used to initialize _mpf_t1 and _mpf_t2.
|
|
62 |
* 64 bits should be enough for exact conversion of most integers to floats.
|
|
63 |
*/
|
|
64 |
||
65 |
#define PRECISION_MIN 64
|
|
66 |
||
67 |
/* mf = { _mpf_t1, _mpf_t2 } */
|
|
68 |
static inline mpfr_ptr mpg_tofloat(mpfr_ptr mf, mpz_ptr mz); |
|
69 |
/* T = {t1, t2} */
|
|
70 |
#define MP_FLOAT(T) is_mpg_integer(T) ? mpg_tofloat(_mpf_##T, (T)->mpg_i) : (T)->mpg_numbr
|
|
71 |
||
300
by john haque
Add infrastructure for MPFR/GMP support. |
72 |
|
73 |
/* init_mpfr --- set up MPFR related variables */
|
|
74 |
||
75 |
void
|
|
312
by john haque
Remove an unneeded define, more fixes for gcc -Wall. |
76 |
init_mpfr(mpfr_prec_t prec, const char *rmode) |
300
by john haque
Add infrastructure for MPFR/GMP support. |
77 |
{
|
408.28.1
by Andrew J. Schorr
Fix MPFR bug where precision was reduced to that of the function argument. |
78 |
mpfr_set_default_prec(default_prec = prec); |
316
by john haque
Change MPFR variable RND_MODE to ROUND_MODE. |
79 |
ROUND_MODE = get_rnd_mode(rmode[0]); |
80 |
mpfr_set_default_rounding_mode(ROUND_MODE); |
|
302.1.1
by john haque
Finish MPFR changes and clean up code. |
81 |
make_number = mpg_make_number; |
82 |
str2number = mpg_force_number; |
|
83 |
format_val = mpg_format_val; |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
84 |
cmp_numbers = mpg_cmp; |
85 |
||
86 |
mpz_init(MNR); |
|
87 |
mpz_init(MFNR); |
|
319.1.9
by Arnold D. Robbins
Move to use of bool type, true, false, everywhere. |
88 |
do_ieee_fmt = false; |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
89 |
|
90 |
mpfr_init2(_mpf_t1, PRECISION_MIN); |
|
91 |
mpfr_init2(_mpf_t2, PRECISION_MIN); |
|
300
by john haque
Add infrastructure for MPFR/GMP support. |
92 |
mpz_init(mpzval); |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
93 |
|
302.1.1
by john haque
Finish MPFR changes and clean up code. |
94 |
register_exec_hook(mpg_interpret, 0); |
300
by john haque
Add infrastructure for MPFR/GMP support. |
95 |
}
|
96 |
||
408.5.226
by Arnold D. Robbins
Clean up some memory in MPFR. |
97 |
/* cleanup_mpfr --- clean stuff up, mainly for valgrind */
|
98 |
||
99 |
void
|
|
100 |
cleanup_mpfr(void) |
|
101 |
{
|
|
102 |
mpfr_clear(_mpf_t1); |
|
103 |
mpfr_clear(_mpf_t2); |
|
104 |
}
|
|
105 |
||
306
by john haque
Add arbitrary-precision arithmetic on integers. |
106 |
/* mpg_node --- allocate a node to store MPFR float or GMP integer */
|
300
by john haque
Add infrastructure for MPFR/GMP support. |
107 |
|
108 |
NODE * |
|
731.11.49
by Arnold D. Robbins
Make MPFR division by zero fatal in intdiv.c. Some other cleanups. |
109 |
mpg_node(unsigned int flags) |
300
by john haque
Add infrastructure for MPFR/GMP support. |
110 |
{
|
731.11.49
by Arnold D. Robbins
Make MPFR division by zero fatal in intdiv.c. Some other cleanups. |
111 |
NODE *r = make_number_node(flags); |
302
by john haque
Finish builtins for MPFR. |
112 |
|
731.11.49
by Arnold D. Robbins
Make MPFR division by zero fatal in intdiv.c. Some other cleanups. |
113 |
if (flags == MPFN) |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
114 |
/* Initialize, set precision to the default precision, and value to NaN */
|
115 |
mpfr_init(r->mpg_numbr); |
|
731.11.1
by Andrew J. Schorr
Enhance API to support extended-precision arithmetic and implement intdiv as a demonstration. |
116 |
else
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
117 |
/* Initialize and set value to 0 */
|
118 |
mpz_init(r->mpg_i); |
|
300
by john haque
Add infrastructure for MPFR/GMP support. |
119 |
return r; |
120 |
}
|
|
121 |
||
306
by john haque
Add arbitrary-precision arithmetic on integers. |
122 |
/*
|
123 |
* mpg_make_number --- make a arbitrary-precision number node
|
|
124 |
* and initialize with a C double
|
|
125 |
*/
|
|
300
by john haque
Add infrastructure for MPFR/GMP support. |
126 |
|
301
by john haque
New interpreter routine for MPFR. |
127 |
static NODE * |
302.1.1
by john haque
Finish MPFR changes and clean up code. |
128 |
mpg_make_number(double x) |
300
by john haque
Add infrastructure for MPFR/GMP support. |
129 |
{
|
130 |
NODE *r; |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
131 |
double ival; |
302.1.1
by john haque
Finish MPFR changes and clean up code. |
132 |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
133 |
if ((ival = double_to_int(x)) != x) { |
134 |
int tval; |
|
135 |
r = mpg_float(); |
|
316
by john haque
Change MPFR variable RND_MODE to ROUND_MODE. |
136 |
tval = mpfr_set_d(r->mpg_numbr, x, ROUND_MODE); |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
137 |
IEEE_FMT(r->mpg_numbr, tval); |
138 |
} else { |
|
139 |
r = mpg_integer(); |
|
140 |
mpz_set_d(r->mpg_i, ival); |
|
141 |
}
|
|
300
by john haque
Add infrastructure for MPFR/GMP support. |
142 |
return r; |
143 |
}
|
|
144 |
||
408.26.83
by Arnold D. Robbins
Remove trailing whitespace everywhere. Fix Unicode into ASCII. |
145 |
/* mpg_strtoui --- assign arbitrary-precision integral value from a string */
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
146 |
|
147 |
int
|
|
148 |
mpg_strtoui(mpz_ptr zi, char *str, size_t len, char **end, int base) |
|
149 |
{
|
|
150 |
char *s = str; |
|
151 |
char *start; |
|
152 |
int ret = -1; |
|
153 |
||
154 |
/*
|
|
155 |
* mpz_set_str does not like leading 0x or 0X for hex (or 0 for octal)
|
|
156 |
* with a non-zero base argument.
|
|
157 |
*/
|
|
158 |
if (base == 16 && len >= 2 && *s == '0' && (s[1] == 'x' || s[1] == 'X')) { |
|
159 |
s += 2; len -= 2; |
|
160 |
} else if (base == 8 && len >= 1 && *s == '0') { |
|
161 |
s++; len--; |
|
162 |
}
|
|
163 |
start = s; |
|
164 |
||
165 |
while (len > 0) { |
|
166 |
switch (*s) { |
|
167 |
case '0': |
|
168 |
case '1': |
|
169 |
case '2': |
|
170 |
case '3': |
|
171 |
case '4': |
|
172 |
case '5': |
|
173 |
case '6': |
|
174 |
case '7': |
|
175 |
break; |
|
176 |
case '8': |
|
177 |
case '9': |
|
178 |
if (base == 8) |
|
179 |
goto done; |
|
180 |
break; |
|
181 |
case 'a': |
|
182 |
case 'b': |
|
183 |
case 'c': |
|
184 |
case 'd': |
|
185 |
case 'e': |
|
186 |
case 'f': |
|
187 |
case 'A': |
|
188 |
case 'B': |
|
189 |
case 'C': |
|
190 |
case 'D': |
|
191 |
case 'E': |
|
192 |
case 'F': |
|
193 |
if (base == 16) |
|
194 |
break; |
|
195 |
default: |
|
196 |
goto done; |
|
197 |
}
|
|
198 |
s++; len--; |
|
199 |
}
|
|
200 |
done: |
|
201 |
if (s > start) { |
|
202 |
char save = *s; |
|
203 |
*s = '\0'; |
|
204 |
ret = mpz_set_str(zi, start, base); |
|
205 |
*s = save; |
|
206 |
}
|
|
207 |
if (end != NULL) |
|
208 |
*end = s; |
|
209 |
return ret; |
|
210 |
}
|
|
211 |
||
212 |
||
213 |
/* mpg_maybe_float --- test if a string may contain arbitrary-precision float */
|
|
214 |
||
215 |
static int |
|
216 |
mpg_maybe_float(const char *str, int use_locale) |
|
217 |
{
|
|
218 |
int dec_point = '.'; |
|
219 |
const char *s = str; |
|
220 |
||
221 |
#if defined(HAVE_LOCALE_H)
|
|
222 |
/*
|
|
223 |
* loc.decimal_point may not have been initialized yet,
|
|
224 |
* so double check it before using it.
|
|
225 |
*/
|
|
226 |
if (use_locale && loc.decimal_point != NULL && loc.decimal_point[0] != '\0') |
|
227 |
dec_point = loc.decimal_point[0]; /* XXX --- assumes one char */ |
|
228 |
#endif
|
|
229 |
||
230 |
if (strlen(s) >= 3 |
|
231 |
&& ( ( (s[0] == 'i' || s[0] == 'I') |
|
232 |
&& (s[1] == 'n' || s[1] == 'N') |
|
233 |
&& (s[2] == 'f' || s[2] == 'F')) |
|
234 |
|| ( (s[0] == 'n' || s[0] == 'N') |
|
235 |
&& (s[1] == 'a' || s[1] == 'A') |
|
236 |
&& (s[2] == 'n' || s[2] == 'N')))) |
|
319.1.9
by Arnold D. Robbins
Move to use of bool type, true, false, everywhere. |
237 |
return true; |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
238 |
|
239 |
for (; *s != '\0'; s++) { |
|
240 |
if (*s == dec_point || *s == 'e' || *s == 'E') |
|
319.1.9
by Arnold D. Robbins
Move to use of bool type, true, false, everywhere. |
241 |
return true; |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
242 |
}
|
243 |
||
319.1.9
by Arnold D. Robbins
Move to use of bool type, true, false, everywhere. |
244 |
return false; |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
245 |
}
|
246 |
||
247 |
||
248 |
/* mpg_zero --- initialize with arbitrary-precision integer(GMP) and set value to zero */
|
|
249 |
||
250 |
static inline void |
|
251 |
mpg_zero(NODE *n) |
|
252 |
{
|
|
253 |
if (is_mpg_float(n)) { |
|
254 |
mpfr_clear(n->mpg_numbr); |
|
255 |
n->flags &= ~MPFN; |
|
256 |
}
|
|
257 |
if (! is_mpg_integer(n)) { |
|
408.26.83
by Arnold D. Robbins
Remove trailing whitespace everywhere. Fix Unicode into ASCII. |
258 |
mpz_init(n->mpg_i); /* this also sets its value to 0 */ |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
259 |
n->flags |= MPZN; |
260 |
} else |
|
261 |
mpz_set_si(n->mpg_i, 0); |
|
262 |
}
|
|
263 |
||
264 |
||
265 |
/* force_mpnum --- force a value to be a GMP integer or MPFR float */
|
|
266 |
||
267 |
static int |
|
268 |
force_mpnum(NODE *n, int do_nondec, int use_locale) |
|
269 |
{
|
|
270 |
char *cp, *cpend, *ptr, *cp1; |
|
408.30.14
by Andrew J. Schorr
Optimization: support unterminated field strings inside gawk, but make terminated copies for the API. |
271 |
char save; |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
272 |
int tval, base = 10; |
273 |
||
274 |
if (n->stlen == 0) { |
|
275 |
mpg_zero(n); |
|
319.1.9
by Arnold D. Robbins
Move to use of bool type, true, false, everywhere. |
276 |
return false; |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
277 |
}
|
300
by john haque
Add infrastructure for MPFR/GMP support. |
278 |
|
279 |
cp = n->stptr; |
|
280 |
cpend = n->stptr + n->stlen; |
|
281 |
while (cp < cpend && isspace((unsigned char) *cp)) |
|
282 |
cp++; |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
283 |
if (cp == cpend) { /* only spaces */ |
284 |
mpg_zero(n); |
|
319.1.9
by Arnold D. Robbins
Move to use of bool type, true, false, everywhere. |
285 |
return false; |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
286 |
}
|
287 |
||
408.30.14
by Andrew J. Schorr
Optimization: support unterminated field strings inside gawk, but make terminated copies for the API. |
288 |
save = *cpend; |
289 |
*cpend = '\0'; |
|
290 |
||
306
by john haque
Add arbitrary-precision arithmetic on integers. |
291 |
if (*cp == '+' || *cp == '-') |
292 |
cp1 = cp + 1; |
|
293 |
else
|
|
294 |
cp1 = cp; |
|
295 |
||
296 |
if (do_nondec) |
|
731.8.3
by Andrew J. Schorr
Fix possible string overrun in strtonum function. |
297 |
base = get_numbase(cp1, cpend - cp1, use_locale); |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
298 |
|
299 |
if (! mpg_maybe_float(cp1, use_locale)) { |
|
300 |
mpg_zero(n); |
|
301 |
errno = 0; |
|
302 |
mpg_strtoui(n->mpg_i, cp1, cpend - cp1, & ptr, base); |
|
303 |
if (*cp == '-') |
|
304 |
mpz_neg(n->mpg_i, n->mpg_i); |
|
305 |
goto done; |
|
306 |
}
|
|
307 |
||
308 |
if (is_mpg_integer(n)) { |
|
309 |
mpz_clear(n->mpg_i); |
|
310 |
n->flags &= ~MPZN; |
|
311 |
}
|
|
312 |
||
313 |
if (! is_mpg_float(n)) { |
|
314 |
mpfr_init(n->mpg_numbr); |
|
315 |
n->flags |= MPFN; |
|
316 |
}
|
|
300
by john haque
Add infrastructure for MPFR/GMP support. |
317 |
|
318 |
errno = 0; |
|
316
by john haque
Change MPFR variable RND_MODE to ROUND_MODE. |
319 |
tval = mpfr_strtofr(n->mpg_numbr, cp, & ptr, base, ROUND_MODE); |
305
by john haque
Bug fixes and tests for MPFR. |
320 |
IEEE_FMT(n->mpg_numbr, tval); |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
321 |
done: |
300
by john haque
Add infrastructure for MPFR/GMP support. |
322 |
/* trailing space is OK for NUMBER */
|
408.26.17
by Andrew J. Schorr
When checking for trailing spaces in numeric strings, avoid running off the end. |
323 |
while (ptr < cpend && isspace((unsigned char) *ptr)) |
300
by john haque
Add infrastructure for MPFR/GMP support. |
324 |
ptr++; |
408.30.14
by Andrew J. Schorr
Optimization: support unterminated field strings inside gawk, but make terminated copies for the API. |
325 |
*cpend = save; |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
326 |
if (errno == 0 && ptr == cpend) |
319.1.9
by Arnold D. Robbins
Move to use of bool type, true, false, everywhere. |
327 |
return true; |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
328 |
errno = 0; |
408.26.83
by Arnold D. Robbins
Remove trailing whitespace everywhere. Fix Unicode into ASCII. |
329 |
return false; |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
330 |
}
|
331 |
||
332 |
/* mpg_force_number --- force a value to be a multiple-precision number */
|
|
333 |
||
334 |
static NODE * |
|
335 |
mpg_force_number(NODE *n) |
|
336 |
{
|
|
408.26.1
by Andrew J. Schorr
Fix usage of scalar type flag bits and fix some bugs in numeric conversions and lint checks. |
337 |
if ((n->flags & NUMCUR) != 0) |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
338 |
return n; |
408.26.1
by Andrew J. Schorr
Fix usage of scalar type flag bits and fix some bugs in numeric conversions and lint checks. |
339 |
n->flags |= NUMCUR; |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
340 |
|
319.1.9
by Arnold D. Robbins
Move to use of bool type, true, false, everywhere. |
341 |
if (force_mpnum(n, (do_non_decimal_data && ! do_traditional), true)) { |
408.30.65
by Arnold D. Robbins
Further code improvements and doc changes as diff until merge. |
342 |
if ((n->flags & USER_INPUT) != 0) { |
343 |
/* leave USER_INPUT set to indicate a strnum */
|
|
408.30.10
by Andrew J. Schorr
Modify MAYBE_NUM usage and typeof function to return "strnum" only for actual numeric strings. |
344 |
n->flags &= ~STRING; |
408.26.1
by Andrew J. Schorr
Fix usage of scalar type flag bits and fix some bugs in numeric conversions and lint checks. |
345 |
n->flags |= NUMBER; |
346 |
}
|
|
347 |
} else |
|
408.30.65
by Arnold D. Robbins
Further code improvements and doc changes as diff until merge. |
348 |
n->flags &= ~USER_INPUT; |
301
by john haque
New interpreter routine for MPFR. |
349 |
return n; |
350 |
}
|
|
351 |
||
302.1.1
by john haque
Finish MPFR changes and clean up code. |
352 |
/* mpg_format_val --- format a numeric value based on format */
|
301
by john haque
New interpreter routine for MPFR. |
353 |
|
354 |
static NODE * |
|
302.1.1
by john haque
Finish MPFR changes and clean up code. |
355 |
mpg_format_val(const char *format, int index, NODE *s) |
301
by john haque
New interpreter routine for MPFR. |
356 |
{
|
357 |
NODE *dummy[2], *r; |
|
358 |
unsigned int oflags; |
|
359 |
||
360 |
/* create dummy node for a sole use of format_tree */
|
|
361 |
dummy[1] = s; |
|
362 |
oflags = s->flags; |
|
363 |
||
306
by john haque
Add arbitrary-precision arithmetic on integers. |
364 |
if (is_mpg_integer(s) || mpfr_integer_p(s->mpg_numbr)) { |
301
by john haque
New interpreter routine for MPFR. |
365 |
/* integral value, use %d */
|
366 |
r = format_tree("%d", 2, dummy, 2); |
|
408.26.22
by Andrew J. Schorr
Use new STFMT_UNUSED define to improve code clarity, and fix some minor stfmt issues. |
367 |
s->stfmt = STFMT_UNUSED; |
301
by john haque
New interpreter routine for MPFR. |
368 |
} else { |
369 |
r = format_tree(format, fmt_list[index]->stlen, dummy, 2); |
|
370 |
assert(r != NULL); |
|
408.26.22
by Andrew J. Schorr
Use new STFMT_UNUSED define to improve code clarity, and fix some minor stfmt issues. |
371 |
s->stfmt = index; |
301
by john haque
New interpreter routine for MPFR. |
372 |
}
|
373 |
s->flags = oflags; |
|
374 |
s->stlen = r->stlen; |
|
731.8.1
by Andrew J. Schorr
Add some paranoid checks to make sure stptr was malloced before freeing it. |
375 |
if ((s->flags & (MALLOC|STRCUR)) == (MALLOC|STRCUR)) |
301
by john haque
New interpreter routine for MPFR. |
376 |
efree(s->stptr); |
377 |
s->stptr = r->stptr; |
|
731.8.42
by Arnold D. Robbins
Fix a memory leak in mpfr formatting values. |
378 |
s->flags |= STRCUR; |
731.11.254
by Arnold D. Robbins
Changes to ROUNDMODE now invalidate cached string values. |
379 |
s->strndmode = MPFR_round_mode; |
301
by john haque
New interpreter routine for MPFR. |
380 |
freenode(r); /* Do not unref(r)! We want to keep s->stptr == r->stpr. */ |
381 |
free_wstr(s); |
|
382 |
return s; |
|
383 |
}
|
|
384 |
||
306
by john haque
Add arbitrary-precision arithmetic on integers. |
385 |
/* mpg_cmp --- compare two numbers */
|
386 |
||
387 |
int
|
|
388 |
mpg_cmp(const NODE *t1, const NODE *t2) |
|
389 |
{
|
|
390 |
/*
|
|
391 |
* For the purposes of sorting, NaN is considered greater than
|
|
392 |
* any other value, and all NaN values are considered equivalent and equal.
|
|
393 |
*/
|
|
394 |
||
395 |
if (is_mpg_float(t1)) { |
|
396 |
if (is_mpg_float(t2)) { |
|
397 |
if (mpfr_nan_p(t1->mpg_numbr)) |
|
398 |
return ! mpfr_nan_p(t2->mpg_numbr); |
|
399 |
if (mpfr_nan_p(t2->mpg_numbr)) |
|
400 |
return -1; |
|
401 |
return mpfr_cmp(t1->mpg_numbr, t2->mpg_numbr); |
|
402 |
}
|
|
403 |
if (mpfr_nan_p(t1->mpg_numbr)) |
|
404 |
return 1; |
|
405 |
return mpfr_cmp_z(t1->mpg_numbr, t2->mpg_i); |
|
406 |
} else if (is_mpg_float(t2)) { |
|
407 |
int ret; |
|
408 |
if (mpfr_nan_p(t2->mpg_numbr)) |
|
409 |
return -1; |
|
410 |
ret = mpfr_cmp_z(t2->mpg_numbr, t1->mpg_i); |
|
411 |
return ret > 0 ? -1 : (ret < 0); |
|
412 |
} else if (is_mpg_integer(t1)) { |
|
413 |
return mpz_cmp(t1->mpg_i, t2->mpg_i); |
|
414 |
}
|
|
415 |
||
416 |
/* t1 and t2 are AWKNUMs */
|
|
417 |
return cmp_awknums(t1, t2); |
|
418 |
}
|
|
419 |
||
301
by john haque
New interpreter routine for MPFR. |
420 |
|
421 |
/*
|
|
408.26.83
by Arnold D. Robbins
Remove trailing whitespace everywhere. Fix Unicode into ASCII. |
422 |
* mpg_update_var --- update NR or FNR.
|
423 |
* NR_node->var_value(mpz_t) = MNR(mpz_t) * LONG_MAX + NR(long)
|
|
301
by john haque
New interpreter routine for MPFR. |
424 |
*/
|
425 |
||
306
by john haque
Add arbitrary-precision arithmetic on integers. |
426 |
NODE * |
302.1.1
by john haque
Finish MPFR changes and clean up code. |
427 |
mpg_update_var(NODE *n) |
301
by john haque
New interpreter routine for MPFR. |
428 |
{
|
429 |
NODE *val = n->var_value; |
|
311
by john haque
Placate gcc -Wall, minor doc updates. |
430 |
long nr = 0; |
431 |
mpz_ptr nq = 0; |
|
301
by john haque
New interpreter routine for MPFR. |
432 |
|
433 |
if (n == NR_node) { |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
434 |
nr = NR; |
435 |
nq = MNR; |
|
301
by john haque
New interpreter routine for MPFR. |
436 |
} else if (n == FNR_node) { |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
437 |
nr = FNR; |
438 |
nq = MFNR; |
|
301
by john haque
New interpreter routine for MPFR. |
439 |
} else |
440 |
cant_happen(); |
|
441 |
||
306
by john haque
Add arbitrary-precision arithmetic on integers. |
442 |
if (mpz_sgn(nq) == 0) { |
443 |
/* Efficiency hack similar to that for AWKNUM */
|
|
444 |
if (is_mpg_float(val) || mpz_get_si(val->mpg_i) != nr) { |
|
301
by john haque
New interpreter routine for MPFR. |
445 |
unref(n->var_value); |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
446 |
val = n->var_value = mpg_integer(); |
447 |
mpz_set_si(val->mpg_i, nr); |
|
301
by john haque
New interpreter routine for MPFR. |
448 |
}
|
449 |
} else { |
|
450 |
unref(n->var_value); |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
451 |
val = n->var_value = mpg_integer(); |
452 |
mpz_set_si(val->mpg_i, nr); |
|
453 |
mpz_addmul_ui(val->mpg_i, nq, LONG_MAX); /* val->mpg_i += nq * LONG_MAX */ |
|
301
by john haque
New interpreter routine for MPFR. |
454 |
}
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
455 |
return val; |
301
by john haque
New interpreter routine for MPFR. |
456 |
}
|
457 |
||
302.1.1
by john haque
Finish MPFR changes and clean up code. |
458 |
/* mpg_set_var --- set NR or FNR */
|
301
by john haque
New interpreter routine for MPFR. |
459 |
|
460 |
long
|
|
302.1.1
by john haque
Finish MPFR changes and clean up code. |
461 |
mpg_set_var(NODE *n) |
301
by john haque
New interpreter routine for MPFR. |
462 |
{
|
311
by john haque
Placate gcc -Wall, minor doc updates. |
463 |
long nr = 0; |
464 |
mpz_ptr nq = 0, r; |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
465 |
NODE *val = n->var_value; |
301
by john haque
New interpreter routine for MPFR. |
466 |
|
467 |
if (n == NR_node) |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
468 |
nq = MNR; |
301
by john haque
New interpreter routine for MPFR. |
469 |
else if (n == FNR_node) |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
470 |
nq = MFNR; |
301
by john haque
New interpreter routine for MPFR. |
471 |
else
|
472 |
cant_happen(); |
|
473 |
||
306
by john haque
Add arbitrary-precision arithmetic on integers. |
474 |
if (is_mpg_integer(val)) |
475 |
r = val->mpg_i; |
|
476 |
else { |
|
408.26.83
by Arnold D. Robbins
Remove trailing whitespace everywhere. Fix Unicode into ASCII. |
477 |
/* convert float to integer */
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
478 |
mpfr_get_z(mpzval, val->mpg_numbr, MPFR_RNDZ); |
479 |
r = mpzval; |
|
301
by john haque
New interpreter routine for MPFR. |
480 |
}
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
481 |
nr = mpz_fdiv_q_ui(nq, r, LONG_MAX); /* nq (MNR or MFNR) is quotient */ |
482 |
return nr; /* remainder (NR or FNR) */ |
|
301
by john haque
New interpreter routine for MPFR. |
483 |
}
|
484 |
||
300
by john haque
Add infrastructure for MPFR/GMP support. |
485 |
/* set_PREC --- update MPFR PRECISION related variables when PREC assigned to */
|
486 |
||
487 |
void
|
|
488 |
set_PREC() |
|
489 |
{
|
|
302.1.1
by john haque
Finish MPFR changes and clean up code. |
490 |
long prec = 0; |
491 |
NODE *val; |
|
492 |
static const struct ieee_fmt { |
|
493 |
const char *name; |
|
494 |
mpfr_prec_t precision; |
|
495 |
mpfr_exp_t emax; |
|
496 |
mpfr_exp_t emin; |
|
497 |
} ieee_fmts[] = { |
|
408.30.66
by Arnold D. Robbins
Audit use of stptr for NUL termination. Update doc before merge to master. |
498 |
{ "half", 11, 16, -23 }, /* binary16 */ |
499 |
{ "single", 24, 128, -148 }, /* binary32 */ |
|
500 |
{ "double", 53, 1024, -1073 }, /* binary64 */ |
|
501 |
{ "quad", 113, 16384, -16493 }, /* binary128 */ |
|
502 |
{ "oct", 237, 262144, -262377 }, /* binary256, not in the IEEE 754-2008 standard */ |
|
302.1.1
by john haque
Finish MPFR changes and clean up code. |
503 |
|
504 |
/*
|
|
505 |
* For any bitwidth = 32 * k ( k >= 4),
|
|
506 |
* precision = 13 + bitwidth - int(4 * log2(bitwidth))
|
|
507 |
* emax = 1 << bitwidth - precision - 1
|
|
508 |
* emin = 4 - emax - precision
|
|
509 |
*/
|
|
510 |
};
|
|
511 |
||
512 |
if (! do_mpfr) |
|
513 |
return; |
|
514 |
||
408.26.1
by Andrew J. Schorr
Fix usage of scalar type flag bits and fix some bugs in numeric conversions and lint checks. |
515 |
val = fixtype(PREC_node->var_value); |
302.1.1
by john haque
Finish MPFR changes and clean up code. |
516 |
|
408.26.1
by Andrew J. Schorr
Fix usage of scalar type flag bits and fix some bugs in numeric conversions and lint checks. |
517 |
if ((val->flags & STRING) != 0) { |
302.1.1
by john haque
Finish MPFR changes and clean up code. |
518 |
int i, j; |
519 |
||
305
by john haque
Bug fixes and tests for MPFR. |
520 |
/* emulate IEEE-754 binary format */
|
302.1.1
by john haque
Finish MPFR changes and clean up code. |
521 |
|
522 |
for (i = 0, j = sizeof(ieee_fmts)/sizeof(ieee_fmts[0]); i < j; i++) { |
|
305
by john haque
Bug fixes and tests for MPFR. |
523 |
if (strcasecmp(ieee_fmts[i].name, val->stptr) == 0) |
302.1.1
by john haque
Finish MPFR changes and clean up code. |
524 |
break; |
525 |
}
|
|
526 |
||
527 |
if (i < j) { |
|
528 |
prec = ieee_fmts[i].precision; |
|
305
by john haque
Bug fixes and tests for MPFR. |
529 |
|
530 |
/*
|
|
531 |
* We *DO NOT* change the MPFR exponent range using
|
|
532 |
* mpfr_set_{emin, emax} here. See format_ieee() for details.
|
|
533 |
*/
|
|
534 |
max_exp = ieee_fmts[i].emax; |
|
535 |
min_exp = ieee_fmts[i].emin; |
|
536 |
||
319.1.9
by Arnold D. Robbins
Move to use of bool type, true, false, everywhere. |
537 |
do_ieee_fmt = true; |
302.1.1
by john haque
Finish MPFR changes and clean up code. |
538 |
}
|
539 |
}
|
|
540 |
||
541 |
if (prec <= 0) { |
|
542 |
force_number(val); |
|
408.26.83
by Arnold D. Robbins
Remove trailing whitespace everywhere. Fix Unicode into ASCII. |
543 |
prec = get_number_si(val); |
302.1.1
by john haque
Finish MPFR changes and clean up code. |
544 |
if (prec < MPFR_PREC_MIN || prec > MPFR_PREC_MAX) { |
545 |
force_string(val); |
|
305
by john haque
Bug fixes and tests for MPFR. |
546 |
warning(_("PREC value `%.*s' is invalid"), (int) val->stlen, val->stptr); |
302.1.1
by john haque
Finish MPFR changes and clean up code. |
547 |
prec = 0; |
305
by john haque
Bug fixes and tests for MPFR. |
548 |
} else |
319.1.9
by Arnold D. Robbins
Move to use of bool type, true, false, everywhere. |
549 |
do_ieee_fmt = false; |
302.1.1
by john haque
Finish MPFR changes and clean up code. |
550 |
}
|
551 |
||
312
by john haque
Remove an unneeded define, more fixes for gcc -Wall. |
552 |
if (prec > 0) |
408.28.1
by Andrew J. Schorr
Fix MPFR bug where precision was reduced to that of the function argument. |
553 |
mpfr_set_default_prec(default_prec = prec); |
300
by john haque
Add infrastructure for MPFR/GMP support. |
554 |
}
|
555 |
||
302.1.1
by john haque
Finish MPFR changes and clean up code. |
556 |
|
557 |
/* get_rnd_mode --- convert string to MPFR rounding mode */
|
|
300
by john haque
Add infrastructure for MPFR/GMP support. |
558 |
|
559 |
static mpfr_rnd_t |
|
302.1.1
by john haque
Finish MPFR changes and clean up code. |
560 |
get_rnd_mode(const char rmode) |
300
by john haque
Add infrastructure for MPFR/GMP support. |
561 |
{
|
302.1.1
by john haque
Finish MPFR changes and clean up code. |
562 |
switch (rmode) { |
300
by john haque
Add infrastructure for MPFR/GMP support. |
563 |
case 'N': |
302.1.1
by john haque
Finish MPFR changes and clean up code. |
564 |
case 'n': |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
565 |
return MPFR_RNDN; /* round to nearest (IEEE-754 roundTiesToEven) */ |
300
by john haque
Add infrastructure for MPFR/GMP support. |
566 |
case 'Z': |
302.1.1
by john haque
Finish MPFR changes and clean up code. |
567 |
case 'z': |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
568 |
return MPFR_RNDZ; /* round toward zero (IEEE-754 roundTowardZero) */ |
300
by john haque
Add infrastructure for MPFR/GMP support. |
569 |
case 'U': |
302.1.1
by john haque
Finish MPFR changes and clean up code. |
570 |
case 'u': |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
571 |
return MPFR_RNDU; /* round toward plus infinity (IEEE-754 roundTowardPositive) */ |
300
by john haque
Add infrastructure for MPFR/GMP support. |
572 |
case 'D': |
302.1.1
by john haque
Finish MPFR changes and clean up code. |
573 |
case 'd': |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
574 |
return MPFR_RNDD; /* round toward minus infinity (IEEE-754 roundTowardNegative) */ |
305
by john haque
Bug fixes and tests for MPFR. |
575 |
#if defined(MPFR_VERSION_MAJOR) && MPFR_VERSION_MAJOR > 2
|
300
by john haque
Add infrastructure for MPFR/GMP support. |
576 |
case 'A': |
302.1.1
by john haque
Finish MPFR changes and clean up code. |
577 |
case 'a': |
731.11.225
by Andrew J. Schorr
Fix description of ROUNDMODE "A": it uses MPFR_RNDA to round away from zero. |
578 |
return MPFR_RNDA; /* round away from zero */ |
300
by john haque
Add infrastructure for MPFR/GMP support. |
579 |
#endif
|
580 |
default: |
|
581 |
break; |
|
582 |
}
|
|
583 |
return -1; |
|
584 |
}
|
|
585 |
||
314
by john haque
Change RNDMODE to ROUNDMODE and update doc. |
586 |
/*
|
587 |
* set_ROUNDMODE --- update MPFR rounding mode related variables
|
|
588 |
* when ROUNDMODE assigned to
|
|
589 |
*/
|
|
300
by john haque
Add infrastructure for MPFR/GMP support. |
590 |
|
591 |
void
|
|
314
by john haque
Change RNDMODE to ROUNDMODE and update doc. |
592 |
set_ROUNDMODE() |
300
by john haque
Add infrastructure for MPFR/GMP support. |
593 |
{
|
594 |
if (do_mpfr) { |
|
312
by john haque
Remove an unneeded define, more fixes for gcc -Wall. |
595 |
mpfr_rnd_t rndm = -1; |
300
by john haque
Add infrastructure for MPFR/GMP support. |
596 |
NODE *n; |
314
by john haque
Change RNDMODE to ROUNDMODE and update doc. |
597 |
n = force_string(ROUNDMODE_node->var_value); |
302.1.1
by john haque
Finish MPFR changes and clean up code. |
598 |
if (n->stlen == 1) |
312
by john haque
Remove an unneeded define, more fixes for gcc -Wall. |
599 |
rndm = get_rnd_mode(n->stptr[0]); |
600 |
if (rndm != -1) { |
|
601 |
mpfr_set_default_rounding_mode(rndm); |
|
316
by john haque
Change MPFR variable RND_MODE to ROUND_MODE. |
602 |
ROUND_MODE = rndm; |
731.11.254
by Arnold D. Robbins
Changes to ROUNDMODE now invalidate cached string values. |
603 |
MPFR_round_mode = n->stptr[0]; |
300
by john haque
Add infrastructure for MPFR/GMP support. |
604 |
} else |
305
by john haque
Bug fixes and tests for MPFR. |
605 |
warning(_("RNDMODE value `%.*s' is invalid"), (int) n->stlen, n->stptr); |
300
by john haque
Add infrastructure for MPFR/GMP support. |
606 |
}
|
607 |
}
|
|
608 |
||
305
by john haque
Bug fixes and tests for MPFR. |
609 |
|
610 |
/* format_ieee --- make sure a number follows IEEE-754 floating-point standard */
|
|
611 |
||
612 |
int
|
|
613 |
format_ieee(mpfr_ptr x, int tval) |
|
614 |
{
|
|
615 |
/*
|
|
616 |
* The MPFR doc says that it's our responsibility to make sure all numbers
|
|
617 |
* including those previously created are in range after we've changed the
|
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
618 |
* exponent range. Most MPFR operations and functions require
|
305
by john haque
Bug fixes and tests for MPFR. |
619 |
* the input arguments to have exponents within the current exponent range.
|
620 |
* Any argument outside the range results in a MPFR assertion failure
|
|
621 |
* like this:
|
|
622 |
*
|
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
623 |
* $ gawk -M 'BEGIN { x=1.0e-10000; print x+0; PREC="double"; print x+0}'
|
305
by john haque
Bug fixes and tests for MPFR. |
624 |
* 1e-10000
|
625 |
* init2.c:52: MPFR assertion failed ....
|
|
626 |
*
|
|
627 |
* A "naive" approach would be to keep track of the ternary state and
|
|
628 |
* the rounding mode for each number, and make sure it is in the current
|
|
629 |
* exponent range (using mpfr_check_range) before using it in an
|
|
630 |
* operation or function. Instead, we adopt the following strategy.
|
|
631 |
*
|
|
632 |
* When gawk starts, the exponent range is the MPFR default
|
|
633 |
* [MPFR_EMIN_DEFAULT, MPFR_EMAX_DEFAULT]. Any number that gawk
|
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
634 |
* creates must have exponent in this range (excluding infinities, NaNs and zeros).
|
305
by john haque
Bug fixes and tests for MPFR. |
635 |
* Each MPFR operation or function is performed with this default exponent
|
636 |
* range.
|
|
637 |
*
|
|
638 |
* When emulating IEEE-754 format, the exponents are *temporarily* changed,
|
|
639 |
* mpfr_check_range is called to make sure the number is in the new range,
|
|
640 |
* and mpfr_subnormalize is used to round following the rules of subnormal
|
|
641 |
* arithmetic. The exponent range is then *restored* to the original value
|
|
642 |
* [MPFR_EMIN_DEFAULT, MPFR_EMAX_DEFAULT].
|
|
643 |
*/
|
|
644 |
||
645 |
(void) mpfr_set_emin(min_exp); |
|
646 |
(void) mpfr_set_emax(max_exp); |
|
316
by john haque
Change MPFR variable RND_MODE to ROUND_MODE. |
647 |
tval = mpfr_check_range(x, tval, ROUND_MODE); |
648 |
tval = mpfr_subnormalize(x, tval, ROUND_MODE); |
|
305
by john haque
Bug fixes and tests for MPFR. |
649 |
(void) mpfr_set_emin(MPFR_EMIN_DEFAULT); |
650 |
(void) mpfr_set_emax(MPFR_EMAX_DEFAULT); |
|
651 |
return tval; |
|
652 |
}
|
|
653 |
||
654 |
||
302.1.1
by john haque
Finish MPFR changes and clean up code. |
655 |
/* do_mpfr_atan2 --- do the atan2 function */
|
300
by john haque
Add infrastructure for MPFR/GMP support. |
656 |
|
657 |
NODE * |
|
301
by john haque
New interpreter routine for MPFR. |
658 |
do_mpfr_atan2(int nargs) |
300
by john haque
Add infrastructure for MPFR/GMP support. |
659 |
{
|
301
by john haque
New interpreter routine for MPFR. |
660 |
NODE *t1, *t2, *res; |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
661 |
mpfr_ptr p1, p2; |
302.1.1
by john haque
Finish MPFR changes and clean up code. |
662 |
int tval; |
301
by john haque
New interpreter routine for MPFR. |
663 |
|
664 |
t2 = POP_SCALAR(); |
|
665 |
t1 = POP_SCALAR(); |
|
666 |
||
667 |
if (do_lint) { |
|
408.26.1
by Andrew J. Schorr
Fix usage of scalar type flag bits and fix some bugs in numeric conversions and lint checks. |
668 |
if ((fixtype(t1)->flags & NUMBER) == 0) |
301
by john haque
New interpreter routine for MPFR. |
669 |
lintwarn(_("atan2: received non-numeric first argument")); |
408.26.1
by Andrew J. Schorr
Fix usage of scalar type flag bits and fix some bugs in numeric conversions and lint checks. |
670 |
if ((fixtype(t2)->flags & NUMBER) == 0) |
301
by john haque
New interpreter routine for MPFR. |
671 |
lintwarn(_("atan2: received non-numeric second argument")); |
672 |
}
|
|
673 |
force_number(t1); |
|
674 |
force_number(t2); |
|
675 |
||
306
by john haque
Add arbitrary-precision arithmetic on integers. |
676 |
p1 = MP_FLOAT(t1); |
677 |
p2 = MP_FLOAT(t2); |
|
678 |
res = mpg_float(); |
|
408.26.83
by Arnold D. Robbins
Remove trailing whitespace everywhere. Fix Unicode into ASCII. |
679 |
/* See MPFR documentation for handling of special values like +inf as an argument */
|
316
by john haque
Change MPFR variable RND_MODE to ROUND_MODE. |
680 |
tval = mpfr_atan2(res->mpg_numbr, p1, p2, ROUND_MODE); |
305
by john haque
Bug fixes and tests for MPFR. |
681 |
IEEE_FMT(res->mpg_numbr, tval); |
300
by john haque
Add infrastructure for MPFR/GMP support. |
682 |
|
683 |
DEREF(t1); |
|
684 |
DEREF(t2); |
|
301
by john haque
New interpreter routine for MPFR. |
685 |
return res; |
300
by john haque
Add infrastructure for MPFR/GMP support. |
686 |
}
|
687 |
||
408.5.233
by Arnold D. Robbins
Bug fix in MPFR that manifested in sqrt(). |
688 |
/* do_mpfr_func --- run an MPFR function - not inline, for debugging */
|
689 |
||
690 |
static inline NODE * |
|
691 |
do_mpfr_func(const char *name, |
|
692 |
int (*mpfr_func)(), /* putting argument types just gets the compiler confused */ |
|
693 |
int nargs) |
|
694 |
{
|
|
695 |
NODE *t1, *res; |
|
696 |
mpfr_ptr p1; |
|
697 |
int tval; |
|
408.28.1
by Andrew J. Schorr
Fix MPFR bug where precision was reduced to that of the function argument. |
698 |
mpfr_prec_t argprec; |
408.5.233
by Arnold D. Robbins
Bug fix in MPFR that manifested in sqrt(). |
699 |
|
700 |
t1 = POP_SCALAR(); |
|
408.26.1
by Andrew J. Schorr
Fix usage of scalar type flag bits and fix some bugs in numeric conversions and lint checks. |
701 |
if (do_lint && (fixtype(t1)->flags & NUMBER) == 0) |
408.5.233
by Arnold D. Robbins
Bug fix in MPFR that manifested in sqrt(). |
702 |
lintwarn(_("%s: received non-numeric argument"), name); |
703 |
||
704 |
force_number(t1); |
|
705 |
p1 = MP_FLOAT(t1); |
|
706 |
res = mpg_float(); |
|
408.28.1
by Andrew J. Schorr
Fix MPFR bug where precision was reduced to that of the function argument. |
707 |
if ((argprec = mpfr_get_prec(p1)) > default_prec) |
708 |
mpfr_set_prec(res->mpg_numbr, argprec); /* needed at least for sqrt() */ |
|
408.5.233
by Arnold D. Robbins
Bug fix in MPFR that manifested in sqrt(). |
709 |
tval = mpfr_func(res->mpg_numbr, p1, ROUND_MODE); |
710 |
IEEE_FMT(res->mpg_numbr, tval); |
|
711 |
DEREF(t1); |
|
712 |
return res; |
|
713 |
}
|
|
714 |
||
715 |
#define SPEC_MATH(X) \
|
|
716 |
NODE *result; \
|
|
717 |
result = do_mpfr_func(#X, mpfr_##X, nargs); \
|
|
718 |
return result
|
|
302
by john haque
Finish builtins for MPFR. |
719 |
|
302.1.1
by john haque
Finish MPFR changes and clean up code. |
720 |
/* do_mpfr_sin --- do the sin function */
|
302
by john haque
Finish builtins for MPFR. |
721 |
|
722 |
NODE * |
|
723 |
do_mpfr_sin(int nargs) |
|
724 |
{
|
|
725 |
SPEC_MATH(sin); |
|
300
by john haque
Add infrastructure for MPFR/GMP support. |
726 |
}
|
727 |
||
302.1.1
by john haque
Finish MPFR changes and clean up code. |
728 |
/* do_mpfr_cos --- do the cos function */
|
300
by john haque
Add infrastructure for MPFR/GMP support. |
729 |
|
730 |
NODE * |
|
301
by john haque
New interpreter routine for MPFR. |
731 |
do_mpfr_cos(int nargs) |
300
by john haque
Add infrastructure for MPFR/GMP support. |
732 |
{
|
302
by john haque
Finish builtins for MPFR. |
733 |
SPEC_MATH(cos); |
300
by john haque
Add infrastructure for MPFR/GMP support. |
734 |
}
|
735 |
||
302.1.1
by john haque
Finish MPFR changes and clean up code. |
736 |
/* do_mpfr_exp --- exponential function */
|
300
by john haque
Add infrastructure for MPFR/GMP support. |
737 |
|
738 |
NODE * |
|
301
by john haque
New interpreter routine for MPFR. |
739 |
do_mpfr_exp(int nargs) |
300
by john haque
Add infrastructure for MPFR/GMP support. |
740 |
{
|
302
by john haque
Finish builtins for MPFR. |
741 |
SPEC_MATH(exp); |
742 |
}
|
|
743 |
||
302.1.1
by john haque
Finish MPFR changes and clean up code. |
744 |
/* do_mpfr_log --- the log function */
|
302
by john haque
Finish builtins for MPFR. |
745 |
|
746 |
NODE * |
|
747 |
do_mpfr_log(int nargs) |
|
748 |
{
|
|
749 |
SPEC_MATH(log); |
|
750 |
}
|
|
751 |
||
302.1.1
by john haque
Finish MPFR changes and clean up code. |
752 |
/* do_mpfr_sqrt --- do the sqrt function */
|
302
by john haque
Finish builtins for MPFR. |
753 |
|
754 |
NODE * |
|
755 |
do_mpfr_sqrt(int nargs) |
|
756 |
{
|
|
757 |
SPEC_MATH(sqrt); |
|
758 |
}
|
|
759 |
||
302.1.1
by john haque
Finish MPFR changes and clean up code. |
760 |
/* do_mpfr_int --- convert double to int for awk */
|
300
by john haque
Add infrastructure for MPFR/GMP support. |
761 |
|
762 |
NODE * |
|
301
by john haque
New interpreter routine for MPFR. |
763 |
do_mpfr_int(int nargs) |
300
by john haque
Add infrastructure for MPFR/GMP support. |
764 |
{
|
302
by john haque
Finish builtins for MPFR. |
765 |
NODE *tmp, *r; |
766 |
||
767 |
tmp = POP_SCALAR(); |
|
408.26.1
by Andrew J. Schorr
Fix usage of scalar type flag bits and fix some bugs in numeric conversions and lint checks. |
768 |
if (do_lint && (fixtype(tmp)->flags & NUMBER) == 0) |
302
by john haque
Finish builtins for MPFR. |
769 |
lintwarn(_("int: received non-numeric argument")); |
770 |
force_number(tmp); |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
771 |
|
772 |
if (is_mpg_integer(tmp)) { |
|
773 |
r = mpg_integer(); |
|
774 |
mpz_set(r->mpg_i, tmp->mpg_i); |
|
775 |
} else { |
|
776 |
if (! mpfr_number_p(tmp->mpg_numbr)) { |
|
777 |
/* [+-]inf or NaN */
|
|
778 |
return tmp; |
|
779 |
}
|
|
780 |
||
781 |
r = mpg_integer(); |
|
782 |
mpfr_get_z(r->mpg_i, tmp->mpg_numbr, MPFR_RNDZ); |
|
783 |
}
|
|
784 |
||
785 |
DEREF(tmp); |
|
786 |
return r; |
|
787 |
}
|
|
788 |
||
789 |
/* do_mpfr_compl --- perform a ~ operation */
|
|
790 |
||
791 |
NODE * |
|
792 |
do_mpfr_compl(int nargs) |
|
793 |
{
|
|
794 |
NODE *tmp, *r; |
|
795 |
mpz_ptr zptr; |
|
796 |
||
797 |
tmp = POP_SCALAR(); |
|
408.26.1
by Andrew J. Schorr
Fix usage of scalar type flag bits and fix some bugs in numeric conversions and lint checks. |
798 |
if (do_lint && (fixtype(tmp)->flags & NUMBER) == 0) |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
799 |
lintwarn(_("compl: received non-numeric argument")); |
800 |
||
801 |
force_number(tmp); |
|
802 |
if (is_mpg_float(tmp)) { |
|
803 |
mpfr_ptr p = tmp->mpg_numbr; |
|
804 |
||
805 |
if (! mpfr_number_p(p)) { |
|
806 |
/* [+-]inf or NaN */
|
|
807 |
return tmp; |
|
808 |
}
|
|
408.26.85
by Arnold D. Robbins
Disallow negative arguments to bitwise functions. Document same. |
809 |
if (mpfr_sgn(p) < 0) |
810 |
fatal("%s", |
|
811 |
mpg_fmt(_("compl(%Rg): negative value is not allowed"), p) |
|
812 |
);
|
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
813 |
if (do_lint) { |
814 |
if (! mpfr_integer_p(p)) |
|
815 |
lintwarn("%s", |
|
816 |
mpg_fmt(_("comp(%Rg): fractional value will be truncated"), p) |
|
817 |
);
|
|
818 |
}
|
|
408.26.83
by Arnold D. Robbins
Remove trailing whitespace everywhere. Fix Unicode into ASCII. |
819 |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
820 |
mpfr_get_z(mpzval, p, MPFR_RNDZ); /* float to integer conversion */ |
821 |
zptr = mpzval; |
|
822 |
} else { |
|
408.26.83
by Arnold D. Robbins
Remove trailing whitespace everywhere. Fix Unicode into ASCII. |
823 |
/* (tmp->flags & MPZN) != 0 */
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
824 |
zptr = tmp->mpg_i; |
408.26.85
by Arnold D. Robbins
Disallow negative arguments to bitwise functions. Document same. |
825 |
if (mpz_sgn(zptr) < 0) |
826 |
fatal("%s", |
|
731.11.113
by Arnold D. Robbins
Typo fix in do_compl_mpfr(). |
827 |
mpg_fmt(_("compl(%Zd): negative values are not allowed"), zptr) |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
828 |
);
|
829 |
}
|
|
830 |
||
831 |
r = mpg_integer(); |
|
832 |
mpz_com(r->mpg_i, zptr); |
|
833 |
DEREF(tmp); |
|
834 |
return r; |
|
835 |
}
|
|
836 |
||
367
by Arnold D. Robbins
Make mpfr and, or, xor, accept >= 2 arguments. |
837 |
/* get_intval --- get the (converted) integral operand of a binary function. */
|
838 |
||
839 |
static mpz_ptr |
|
840 |
get_intval(NODE *t1, int argnum, const char *op) |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
841 |
{
|
367
by Arnold D. Robbins
Make mpfr and, or, xor, accept >= 2 arguments. |
842 |
mpz_ptr pz; |
843 |
||
408.26.1
by Andrew J. Schorr
Fix usage of scalar type flag bits and fix some bugs in numeric conversions and lint checks. |
844 |
if (do_lint && (fixtype(t1)->flags & NUMBER) == 0) |
367
by Arnold D. Robbins
Make mpfr and, or, xor, accept >= 2 arguments. |
845 |
lintwarn(_("%s: received non-numeric argument #%d"), op, argnum); |
846 |
||
847 |
(void) force_number(t1); |
|
848 |
||
849 |
if (is_mpg_float(t1)) { |
|
850 |
mpfr_ptr left = t1->mpg_numbr; |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
851 |
if (! mpfr_number_p(left)) { |
852 |
/* inf or NaN */
|
|
367
by Arnold D. Robbins
Make mpfr and, or, xor, accept >= 2 arguments. |
853 |
if (do_lint) |
854 |
lintwarn("%s", |
|
855 |
mpg_fmt(_("%s: argument #%d has invalid value %Rg, using 0"), |
|
856 |
op, argnum, left) |
|
857 |
);
|
|
858 |
||
859 |
emalloc(pz, mpz_ptr, sizeof (mpz_t), "get_intval"); |
|
860 |
mpz_init(pz); |
|
861 |
return pz; /* should be freed */ |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
862 |
}
|
863 |
||
408.26.85
by Arnold D. Robbins
Disallow negative arguments to bitwise functions. Document same. |
864 |
if (mpfr_sgn(left) < 0) |
865 |
fatal("%s", |
|
866 |
mpg_fmt(_("%s: argument #%d negative value %Rg is not allowed"), |
|
367
by Arnold D. Robbins
Make mpfr and, or, xor, accept >= 2 arguments. |
867 |
op, argnum, left) |
868 |
);
|
|
869 |
||
408.26.85
by Arnold D. Robbins
Disallow negative arguments to bitwise functions. Document same. |
870 |
if (do_lint) { |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
871 |
if (! mpfr_integer_p(left)) |
872 |
lintwarn("%s", |
|
367
by Arnold D. Robbins
Make mpfr and, or, xor, accept >= 2 arguments. |
873 |
mpg_fmt(_("%s: argument #%d fractional value %Rg will be truncated"), |
874 |
op, argnum, left) |
|
875 |
);
|
|
876 |
}
|
|
877 |
||
878 |
emalloc(pz, mpz_ptr, sizeof (mpz_t), "get_intval"); |
|
879 |
mpz_init(pz); |
|
880 |
mpfr_get_z(pz, left, MPFR_RNDZ); /* float to integer conversion */ |
|
881 |
return pz; /* should be freed */ |
|
408.26.83
by Arnold D. Robbins
Remove trailing whitespace everywhere. Fix Unicode into ASCII. |
882 |
}
|
883 |
/* (t1->flags & MPZN) != 0 */
|
|
367
by Arnold D. Robbins
Make mpfr and, or, xor, accept >= 2 arguments. |
884 |
pz = t1->mpg_i; |
408.26.85
by Arnold D. Robbins
Disallow negative arguments to bitwise functions. Document same. |
885 |
if (mpz_sgn(pz) < 0) |
886 |
fatal("%s", |
|
887 |
mpg_fmt(_("%s: argument #%d negative value %Zd is not allowed"), |
|
367
by Arnold D. Robbins
Make mpfr and, or, xor, accept >= 2 arguments. |
888 |
op, argnum, pz) |
889 |
);
|
|
408.26.85
by Arnold D. Robbins
Disallow negative arguments to bitwise functions. Document same. |
890 |
|
367
by Arnold D. Robbins
Make mpfr and, or, xor, accept >= 2 arguments. |
891 |
return pz; /* must not be freed */ |
892 |
}
|
|
893 |
||
894 |
||
895 |
/* free_intval --- free the converted integer value returned by get_intval() */
|
|
896 |
||
897 |
static inline void |
|
898 |
free_intval(NODE *t, mpz_ptr pz) |
|
899 |
{
|
|
900 |
if ((t->flags & MPZN) == 0) { |
|
901 |
mpz_clear(pz); |
|
902 |
efree(pz); |
|
903 |
}
|
|
904 |
}
|
|
905 |
||
300
by john haque
Add infrastructure for MPFR/GMP support. |
906 |
|
302.1.1
by john haque
Finish MPFR changes and clean up code. |
907 |
/* do_mpfr_lshift --- perform a << operation */
|
300
by john haque
Add infrastructure for MPFR/GMP support. |
908 |
|
909 |
NODE * |
|
301
by john haque
New interpreter routine for MPFR. |
910 |
do_mpfr_lshift(int nargs) |
300
by john haque
Add infrastructure for MPFR/GMP support. |
911 |
{
|
367
by Arnold D. Robbins
Make mpfr and, or, xor, accept >= 2 arguments. |
912 |
NODE *t1, *t2, *res; |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
913 |
unsigned long shift; |
367
by Arnold D. Robbins
Make mpfr and, or, xor, accept >= 2 arguments. |
914 |
mpz_ptr pz1, pz2; |
408.26.83
by Arnold D. Robbins
Remove trailing whitespace everywhere. Fix Unicode into ASCII. |
915 |
|
367
by Arnold D. Robbins
Make mpfr and, or, xor, accept >= 2 arguments. |
916 |
t2 = POP_SCALAR(); |
917 |
t1 = POP_SCALAR(); |
|
918 |
||
919 |
pz1 = get_intval(t1, 1, "lshift"); |
|
920 |
pz2 = get_intval(t2, 2, "lshift"); |
|
921 |
||
922 |
/*
|
|
923 |
* mpz_get_ui: If op is too big to fit an unsigned long then just
|
|
924 |
* the least significant bits that do fit are returned.
|
|
925 |
* The sign of op is ignored, only the absolute value is used.
|
|
926 |
*/
|
|
927 |
||
928 |
shift = mpz_get_ui(pz2); /* GMP integer => unsigned long conversion */ |
|
929 |
res = mpg_integer(); |
|
930 |
mpz_mul_2exp(res->mpg_i, pz1, shift); /* res = pz1 * 2^shift */ |
|
931 |
||
932 |
free_intval(t1, pz1); |
|
933 |
free_intval(t2, pz2); |
|
934 |
DEREF(t2); |
|
935 |
DEREF(t1); |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
936 |
return res; |
937 |
}
|
|
938 |
||
939 |
/* do_mpfr_rshift --- perform a >> operation */
|
|
940 |
||
941 |
NODE * |
|
367
by Arnold D. Robbins
Make mpfr and, or, xor, accept >= 2 arguments. |
942 |
do_mpfr_rshift(int nargs) |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
943 |
{
|
367
by Arnold D. Robbins
Make mpfr and, or, xor, accept >= 2 arguments. |
944 |
NODE *t1, *t2, *res; |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
945 |
unsigned long shift; |
367
by Arnold D. Robbins
Make mpfr and, or, xor, accept >= 2 arguments. |
946 |
mpz_ptr pz1, pz2; |
408.26.83
by Arnold D. Robbins
Remove trailing whitespace everywhere. Fix Unicode into ASCII. |
947 |
|
367
by Arnold D. Robbins
Make mpfr and, or, xor, accept >= 2 arguments. |
948 |
t2 = POP_SCALAR(); |
949 |
t1 = POP_SCALAR(); |
|
950 |
||
951 |
pz1 = get_intval(t1, 1, "rshift"); |
|
952 |
pz2 = get_intval(t2, 2, "rshift"); |
|
953 |
||
954 |
/* N.B: See do_mpfp_lshift. */
|
|
955 |
shift = mpz_get_ui(pz2); /* GMP integer => unsigned long conversion */ |
|
956 |
res = mpg_integer(); |
|
408.26.83
by Arnold D. Robbins
Remove trailing whitespace everywhere. Fix Unicode into ASCII. |
957 |
mpz_fdiv_q_2exp(res->mpg_i, pz1, shift); /* res = pz1 / 2^shift, round towards -inf */ |
367
by Arnold D. Robbins
Make mpfr and, or, xor, accept >= 2 arguments. |
958 |
|
959 |
free_intval(t1, pz1); |
|
960 |
free_intval(t2, pz2); |
|
961 |
DEREF(t2); |
|
962 |
DEREF(t1); |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
963 |
return res; |
964 |
}
|
|
965 |
||
367
by Arnold D. Robbins
Make mpfr and, or, xor, accept >= 2 arguments. |
966 |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
967 |
/* do_mpfr_and --- perform an & operation */
|
968 |
||
969 |
NODE * |
|
970 |
do_mpfr_and(int nargs) |
|
971 |
{
|
|
367
by Arnold D. Robbins
Make mpfr and, or, xor, accept >= 2 arguments. |
972 |
NODE *t1, *t2, *res; |
973 |
mpz_ptr pz1, pz2; |
|
974 |
int i; |
|
975 |
||
976 |
if (nargs < 2) |
|
977 |
fatal(_("and: called with less than two arguments")); |
|
978 |
||
979 |
t2 = POP_SCALAR(); |
|
980 |
pz2 = get_intval(t2, nargs, "and"); |
|
981 |
||
982 |
res = mpg_integer(); |
|
983 |
for (i = 1; i < nargs; i++) { |
|
984 |
t1 = POP_SCALAR(); |
|
985 |
pz1 = get_intval(t1, nargs - i, "and"); |
|
986 |
mpz_and(res->mpg_i, pz1, pz2); |
|
987 |
free_intval(t1, pz1); |
|
988 |
DEREF(t1); |
|
989 |
if (i == 1) { |
|
990 |
free_intval(t2, pz2); |
|
991 |
DEREF(t2); |
|
992 |
}
|
|
993 |
pz2 = res->mpg_i; |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
994 |
}
|
995 |
return res; |
|
996 |
}
|
|
300
by john haque
Add infrastructure for MPFR/GMP support. |
997 |
|
367
by Arnold D. Robbins
Make mpfr and, or, xor, accept >= 2 arguments. |
998 |
|
302.1.1
by john haque
Finish MPFR changes and clean up code. |
999 |
/* do_mpfr_or --- perform an | operation */
|
300
by john haque
Add infrastructure for MPFR/GMP support. |
1000 |
|
1001 |
NODE * |
|
301
by john haque
New interpreter routine for MPFR. |
1002 |
do_mpfr_or(int nargs) |
300
by john haque
Add infrastructure for MPFR/GMP support. |
1003 |
{
|
367
by Arnold D. Robbins
Make mpfr and, or, xor, accept >= 2 arguments. |
1004 |
NODE *t1, *t2, *res; |
1005 |
mpz_ptr pz1, pz2; |
|
1006 |
int i; |
|
1007 |
||
1008 |
if (nargs < 2) |
|
1009 |
fatal(_("or: called with less than two arguments")); |
|
1010 |
||
1011 |
t2 = POP_SCALAR(); |
|
1012 |
pz2 = get_intval(t2, nargs, "or"); |
|
1013 |
||
1014 |
res = mpg_integer(); |
|
1015 |
for (i = 1; i < nargs; i++) { |
|
1016 |
t1 = POP_SCALAR(); |
|
1017 |
pz1 = get_intval(t1, nargs - i, "or"); |
|
1018 |
mpz_ior(res->mpg_i, pz1, pz2); |
|
1019 |
free_intval(t1, pz1); |
|
1020 |
DEREF(t1); |
|
1021 |
if (i == 1) { |
|
1022 |
free_intval(t2, pz2); |
|
1023 |
DEREF(t2); |
|
1024 |
}
|
|
1025 |
pz2 = res->mpg_i; |
|
1026 |
}
|
|
1027 |
return res; |
|
1028 |
}
|
|
1029 |
||
1030 |
/* do_mpfr_xor --- perform an ^ operation */
|
|
1031 |
||
1032 |
NODE * |
|
1033 |
do_mpfr_xor(int nargs) |
|
1034 |
{
|
|
1035 |
NODE *t1, *t2, *res; |
|
1036 |
mpz_ptr pz1, pz2; |
|
1037 |
int i; |
|
1038 |
||
1039 |
if (nargs < 2) |
|
1040 |
fatal(_("xor: called with less than two arguments")); |
|
1041 |
||
1042 |
t2 = POP_SCALAR(); |
|
1043 |
pz2 = get_intval(t2, nargs, "xor"); |
|
1044 |
||
1045 |
res = mpg_integer(); |
|
1046 |
for (i = 1; i < nargs; i++) { |
|
1047 |
t1 = POP_SCALAR(); |
|
1048 |
pz1 = get_intval(t1, nargs - i, "xor"); |
|
1049 |
mpz_xor(res->mpg_i, pz1, pz2); |
|
1050 |
free_intval(t1, pz1); |
|
1051 |
DEREF(t1); |
|
1052 |
if (i == 1) { |
|
1053 |
free_intval(t2, pz2); |
|
1054 |
DEREF(t2); |
|
1055 |
}
|
|
1056 |
pz2 = res->mpg_i; |
|
1057 |
}
|
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1058 |
return res; |
1059 |
}
|
|
302
by john haque
Finish builtins for MPFR. |
1060 |
|
302.1.1
by john haque
Finish MPFR changes and clean up code. |
1061 |
/* do_mpfr_strtonum --- the strtonum function */
|
302
by john haque
Finish builtins for MPFR. |
1062 |
|
1063 |
NODE * |
|
1064 |
do_mpfr_strtonum(int nargs) |
|
1065 |
{
|
|
1066 |
NODE *tmp, *r; |
|
1067 |
||
408.26.1
by Andrew J. Schorr
Fix usage of scalar type flag bits and fix some bugs in numeric conversions and lint checks. |
1068 |
tmp = fixtype(POP_SCALAR()); |
1069 |
if ((tmp->flags & NUMBER) == 0) { |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1070 |
r = mpg_integer(); /* will be changed to MPFR float if necessary in force_mpnum() */ |
1071 |
r->stptr = tmp->stptr; |
|
1072 |
r->stlen = tmp->stlen; |
|
319.1.9
by Arnold D. Robbins
Move to use of bool type, true, false, everywhere. |
1073 |
force_mpnum(r, true, use_lc_numeric); |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1074 |
r->stptr = NULL; |
1075 |
r->stlen = 0; |
|
408.30.66
by Arnold D. Robbins
Audit use of stptr for NUL termination. Update doc before merge to master. |
1076 |
r->wstptr = NULL; |
1077 |
r->wstlen = 0; |
|
408.26.14
by Arnold D. Robbins
Minor improvements after Andy's reworking of stuff. |
1078 |
} else if (is_mpg_float(tmp)) { |
1079 |
int tval; |
|
1080 |
r = mpg_float(); |
|
1081 |
tval = mpfr_set(r->mpg_numbr, tmp->mpg_numbr, ROUND_MODE); |
|
1082 |
IEEE_FMT(r->mpg_numbr, tval); |
|
302
by john haque
Finish builtins for MPFR. |
1083 |
} else { |
408.26.14
by Arnold D. Robbins
Minor improvements after Andy's reworking of stuff. |
1084 |
r = mpg_integer(); |
1085 |
mpz_set(r->mpg_i, tmp->mpg_i); |
|
302
by john haque
Finish builtins for MPFR. |
1086 |
}
|
1087 |
||
1088 |
DEREF(tmp); |
|
1089 |
return r; |
|
1090 |
}
|
|
1091 |
||
302.1.1
by john haque
Finish MPFR changes and clean up code. |
1092 |
|
319.1.9
by Arnold D. Robbins
Move to use of bool type, true, false, everywhere. |
1093 |
static bool firstrand = true; |
302
by john haque
Finish builtins for MPFR. |
1094 |
static gmp_randstate_t state; |
1095 |
static mpz_t seed; /* current seed */ |
|
1096 |
||
302.1.1
by john haque
Finish MPFR changes and clean up code. |
1097 |
/* do_mpfr_rand --- do the rand function */
|
302
by john haque
Finish builtins for MPFR. |
1098 |
|
1099 |
NODE * |
|
1100 |
do_mpfr_rand(int nargs ATTRIBUTE_UNUSED) |
|
1101 |
{
|
|
1102 |
NODE *res; |
|
302.1.1
by john haque
Finish MPFR changes and clean up code. |
1103 |
int tval; |
302
by john haque
Finish builtins for MPFR. |
1104 |
|
1105 |
if (firstrand) { |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1106 |
#if 0
|
302
by john haque
Finish builtins for MPFR. |
1107 |
/* Choose the default algorithm */
|
1108 |
gmp_randinit_default(state);
|
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1109 |
#endif
|
1110 |
/*
|
|
1111 |
* Choose a specific (Mersenne Twister) algorithm in case the default
|
|
1112 |
* changes in the future.
|
|
1113 |
*/
|
|
1114 |
||
1115 |
gmp_randinit_mt(state); |
|
1116 |
||
302
by john haque
Finish builtins for MPFR. |
1117 |
mpz_init(seed); |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1118 |
mpz_set_ui(seed, 1); |
302
by john haque
Finish builtins for MPFR. |
1119 |
/* seed state */
|
1120 |
gmp_randseed(state, seed); |
|
319.1.9
by Arnold D. Robbins
Move to use of bool type, true, false, everywhere. |
1121 |
firstrand = false; |
302
by john haque
Finish builtins for MPFR. |
1122 |
}
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1123 |
res = mpg_float(); |
302.1.1
by john haque
Finish MPFR changes and clean up code. |
1124 |
tval = mpfr_urandomb(res->mpg_numbr, state); |
305
by john haque
Bug fixes and tests for MPFR. |
1125 |
IEEE_FMT(res->mpg_numbr, tval); |
302
by john haque
Finish builtins for MPFR. |
1126 |
return res; |
1127 |
}
|
|
1128 |
||
300
by john haque
Add infrastructure for MPFR/GMP support. |
1129 |
|
302.1.1
by john haque
Finish MPFR changes and clean up code. |
1130 |
/* do_mpfr_srand --- seed the random number generator */
|
300
by john haque
Add infrastructure for MPFR/GMP support. |
1131 |
|
1132 |
NODE * |
|
301
by john haque
New interpreter routine for MPFR. |
1133 |
do_mpfr_srand(int nargs) |
300
by john haque
Add infrastructure for MPFR/GMP support. |
1134 |
{
|
302.1.1
by john haque
Finish MPFR changes and clean up code. |
1135 |
NODE *res; |
302
by john haque
Finish builtins for MPFR. |
1136 |
|
1137 |
if (firstrand) { |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1138 |
#if 0
|
302
by john haque
Finish builtins for MPFR. |
1139 |
/* Choose the default algorithm */
|
1140 |
gmp_randinit_default(state);
|
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1141 |
#endif
|
1142 |
/*
|
|
1143 |
* Choose a specific algorithm (Mersenne Twister) in case default
|
|
1144 |
* changes in the future.
|
|
1145 |
*/
|
|
1146 |
||
1147 |
gmp_randinit_mt(state); |
|
1148 |
||
302
by john haque
Finish builtins for MPFR. |
1149 |
mpz_init(seed); |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1150 |
mpz_set_ui(seed, 1); |
302
by john haque
Finish builtins for MPFR. |
1151 |
/* No need to seed state, will change it below */
|
319.1.9
by Arnold D. Robbins
Move to use of bool type, true, false, everywhere. |
1152 |
firstrand = false; |
302
by john haque
Finish builtins for MPFR. |
1153 |
}
|
1154 |
||
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1155 |
res = mpg_integer(); |
1156 |
mpz_set(res->mpg_i, seed); /* previous seed */ |
|
300
by john haque
Add infrastructure for MPFR/GMP support. |
1157 |
|
1158 |
if (nargs == 0) |
|
302
by john haque
Finish builtins for MPFR. |
1159 |
mpz_set_ui(seed, (unsigned long) time((time_t *) 0)); |
300
by john haque
Add infrastructure for MPFR/GMP support. |
1160 |
else { |
302.1.1
by john haque
Finish MPFR changes and clean up code. |
1161 |
NODE *tmp; |
300
by john haque
Add infrastructure for MPFR/GMP support. |
1162 |
tmp = POP_SCALAR(); |
408.26.1
by Andrew J. Schorr
Fix usage of scalar type flag bits and fix some bugs in numeric conversions and lint checks. |
1163 |
if (do_lint && (fixtype(tmp)->flags & NUMBER) == 0) |
302
by john haque
Finish builtins for MPFR. |
1164 |
lintwarn(_("srand: received non-numeric argument")); |
1165 |
force_number(tmp); |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1166 |
if (is_mpg_float(tmp)) |
1167 |
mpfr_get_z(seed, tmp->mpg_numbr, MPFR_RNDZ); |
|
1168 |
else /* MP integer */ |
|
1169 |
mpz_set(seed, tmp->mpg_i); |
|
300
by john haque
Add infrastructure for MPFR/GMP support. |
1170 |
DEREF(tmp); |
1171 |
}
|
|
1172 |
||
302
by john haque
Finish builtins for MPFR. |
1173 |
gmp_randseed(state, seed); |
1174 |
return res; |
|
300
by john haque
Add infrastructure for MPFR/GMP support. |
1175 |
}
|
1176 |
||
731.11.53
by Arnold D. Robbins
Rename intdiv to intdiv0, require it to be configured in. |
1177 |
#ifdef SUPPLY_INTDIV
|
408.12.64
by Arnold D. Robbins
Rename "div()" to "intdiv()". |
1178 |
/* do_mpfr_intdiv --- do integer division, return quotient and remainder in dest array */
|
408.2.342
by Arnold D. Robbins
Add div() function for integer division & remainder. |
1179 |
|
1180 |
/*
|
|
1181 |
* We define the semantics as:
|
|
1182 |
* numerator = int(numerator)
|
|
1183 |
* denominator = int(denonmator)
|
|
1184 |
* quotient = int(numerator / denomator)
|
|
1185 |
* remainder = int(numerator % denomator)
|
|
1186 |
*/
|
|
1187 |
||
1188 |
NODE * |
|
408.12.64
by Arnold D. Robbins
Rename "div()" to "intdiv()". |
1189 |
do_mpfr_intdiv(int nargs) |
408.2.342
by Arnold D. Robbins
Add div() function for integer division & remainder. |
1190 |
{
|
1191 |
NODE *numerator, *denominator, *result; |
|
1192 |
NODE *num, *denom; |
|
1193 |
NODE *quotient, *remainder; |
|
1194 |
NODE *sub, **lhs; |
|
1195 |
||
1196 |
result = POP_PARAM(); |
|
1197 |
if (result->type != Node_var_array) |
|
408.12.64
by Arnold D. Robbins
Rename "div()" to "intdiv()". |
1198 |
fatal(_("intdiv: third argument is not an array")); |
408.2.342
by Arnold D. Robbins
Add div() function for integer division & remainder. |
1199 |
assoc_clear(result); |
1200 |
||
1201 |
denominator = POP_SCALAR(); |
|
1202 |
numerator = POP_SCALAR(); |
|
1203 |
||
1204 |
if (do_lint) { |
|
408.26.1
by Andrew J. Schorr
Fix usage of scalar type flag bits and fix some bugs in numeric conversions and lint checks. |
1205 |
if ((fixtype(numerator)->flags & NUMBER) == 0) |
408.12.64
by Arnold D. Robbins
Rename "div()" to "intdiv()". |
1206 |
lintwarn(_("intdiv: received non-numeric first argument")); |
408.26.1
by Andrew J. Schorr
Fix usage of scalar type flag bits and fix some bugs in numeric conversions and lint checks. |
1207 |
if ((fixtype(denominator)->flags & NUMBER) == 0) |
408.12.64
by Arnold D. Robbins
Rename "div()" to "intdiv()". |
1208 |
lintwarn(_("intdiv: received non-numeric second argument")); |
408.2.342
by Arnold D. Robbins
Add div() function for integer division & remainder. |
1209 |
}
|
1210 |
||
1211 |
(void) force_number(numerator); |
|
1212 |
(void) force_number(denominator); |
|
1213 |
||
1214 |
/* convert numerator and denominator to integer */
|
|
1215 |
if (is_mpg_integer(numerator)) { |
|
1216 |
num = mpg_integer(); |
|
1217 |
mpz_set(num->mpg_i, numerator->mpg_i); |
|
1218 |
} else { |
|
1219 |
if (! mpfr_number_p(numerator->mpg_numbr)) { |
|
1220 |
/* [+-]inf or NaN */
|
|
731.8.44
by Arnold D. Robbins
Fixes for intdiv function, including documentation. |
1221 |
unref(numerator); |
1222 |
unref(denominator); |
|
1223 |
return make_number((AWKNUM) -1); |
|
408.2.342
by Arnold D. Robbins
Add div() function for integer division & remainder. |
1224 |
}
|
1225 |
||
1226 |
num = mpg_integer(); |
|
1227 |
mpfr_get_z(num->mpg_i, numerator->mpg_numbr, MPFR_RNDZ); |
|
1228 |
}
|
|
1229 |
||
1230 |
if (is_mpg_integer(denominator)) { |
|
1231 |
denom = mpg_integer(); |
|
1232 |
mpz_set(denom->mpg_i, denominator->mpg_i); |
|
1233 |
} else { |
|
1234 |
if (! mpfr_number_p(denominator->mpg_numbr)) { |
|
1235 |
/* [+-]inf or NaN */
|
|
731.8.44
by Arnold D. Robbins
Fixes for intdiv function, including documentation. |
1236 |
unref(numerator); |
1237 |
unref(denominator); |
|
1238 |
unref(num); |
|
1239 |
return make_number((AWKNUM) -1); |
|
408.2.342
by Arnold D. Robbins
Add div() function for integer division & remainder. |
1240 |
}
|
1241 |
||
1242 |
denom = mpg_integer(); |
|
1243 |
mpfr_get_z(denom->mpg_i, denominator->mpg_numbr, MPFR_RNDZ); |
|
1244 |
}
|
|
1245 |
||
1246 |
if (mpz_sgn(denom->mpg_i) == 0) |
|
408.12.64
by Arnold D. Robbins
Rename "div()" to "intdiv()". |
1247 |
fatal(_("intdiv: division by zero attempted")); |
408.2.342
by Arnold D. Robbins
Add div() function for integer division & remainder. |
1248 |
|
1249 |
quotient = mpg_integer(); |
|
1250 |
remainder = mpg_integer(); |
|
1251 |
||
1252 |
/* do the division */
|
|
1253 |
mpz_tdiv_qr(quotient->mpg_i, remainder->mpg_i, num->mpg_i, denom->mpg_i); |
|
1254 |
unref(num); |
|
1255 |
unref(denom); |
|
408.2.349
by Arnold D. Robbins
Fix memory leak in do_mpfr_div. |
1256 |
unref(numerator); |
1257 |
unref(denominator); |
|
408.2.342
by Arnold D. Robbins
Add div() function for integer division & remainder. |
1258 |
|
1259 |
sub = make_string("quotient", 8); |
|
1260 |
lhs = assoc_lookup(result, sub); |
|
1261 |
unref(*lhs); |
|
1262 |
*lhs = quotient; |
|
1263 |
||
1264 |
sub = make_string("remainder", 9); |
|
1265 |
lhs = assoc_lookup(result, sub); |
|
1266 |
unref(*lhs); |
|
1267 |
*lhs = remainder; |
|
1268 |
||
1269 |
return make_number((AWKNUM) 0.0); |
|
1270 |
}
|
|
731.11.53
by Arnold D. Robbins
Rename intdiv to intdiv0, require it to be configured in. |
1271 |
#endif /* SUPPLY_INTDIV */ |
408.2.342
by Arnold D. Robbins
Add div() function for integer division & remainder. |
1272 |
|
302.1.1
by john haque
Finish MPFR changes and clean up code. |
1273 |
/*
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1274 |
* mpg_tofloat --- convert an arbitrary-precision integer operand to
|
1275 |
* a float without loss of precision. It is assumed that the
|
|
1276 |
* MPFR variable has already been initialized.
|
|
1277 |
*/
|
|
1278 |
||
1279 |
static inline mpfr_ptr |
|
1280 |
mpg_tofloat(mpfr_ptr mf, mpz_ptr mz) |
|
1281 |
{
|
|
1282 |
size_t prec; |
|
1283 |
||
1284 |
/*
|
|
1285 |
* When implicitely converting a GMP integer operand to a MPFR float, use
|
|
1286 |
* a precision sufficiently large to hold the converted value exactly.
|
|
408.26.83
by Arnold D. Robbins
Remove trailing whitespace everywhere. Fix Unicode into ASCII. |
1287 |
*
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1288 |
* $ ./gawk -M 'BEGIN { print 13 % 2 }'
|
1289 |
* 1
|
|
1290 |
* If the user-specified precision is used to convert the integer 13 to a
|
|
1291 |
* float, one will get:
|
|
1292 |
* $ ./gawk -M 'BEGIN { PREC=2; print 13 % 2.0 }'
|
|
408.26.83
by Arnold D. Robbins
Remove trailing whitespace everywhere. Fix Unicode into ASCII. |
1293 |
* 0
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1294 |
*/
|
1295 |
||
1296 |
prec = mpz_sizeinbase(mz, 2); /* most significant 1 bit position starting at 1 */ |
|
1297 |
if (prec > PRECISION_MIN) { |
|
1298 |
prec -= (size_t) mpz_scan1(mz, 0); /* least significant 1 bit index starting at 0 */ |
|
1299 |
if (prec > MPFR_PREC_MAX) |
|
1300 |
prec = MPFR_PREC_MAX; |
|
408.28.2
by Andrew J. Schorr
Minor MPFR fix to avoid potential hysteresis effects resulting in higher-than-needed precision. |
1301 |
else if (prec < PRECISION_MIN) |
1302 |
prec = PRECISION_MIN; |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1303 |
}
|
408.28.2
by Andrew J. Schorr
Minor MPFR fix to avoid potential hysteresis effects resulting in higher-than-needed precision. |
1304 |
else
|
1305 |
prec = PRECISION_MIN; |
|
1306 |
/*
|
|
408.26.83
by Arnold D. Robbins
Remove trailing whitespace everywhere. Fix Unicode into ASCII. |
1307 |
* Always set the precision to avoid hysteresis, since do_mpfr_func
|
408.28.2
by Andrew J. Schorr
Minor MPFR fix to avoid potential hysteresis effects resulting in higher-than-needed precision. |
1308 |
* may copy our precision.
|
1309 |
*/
|
|
1310 |
if (prec != mpfr_get_prec(mf)) |
|
1311 |
mpfr_set_prec(mf, prec); |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1312 |
|
316
by john haque
Change MPFR variable RND_MODE to ROUND_MODE. |
1313 |
mpfr_set_z(mf, mz, ROUND_MODE); |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1314 |
return mf; |
1315 |
}
|
|
1316 |
||
1317 |
||
408.26.83
by Arnold D. Robbins
Remove trailing whitespace everywhere. Fix Unicode into ASCII. |
1318 |
/* mpg_add --- add arbitrary-precision numbers */
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1319 |
|
1320 |
static NODE * |
|
1321 |
mpg_add(NODE *t1, NODE *t2) |
|
1322 |
{
|
|
1323 |
NODE *r; |
|
1324 |
int tval; |
|
1325 |
||
1326 |
if (is_mpg_integer(t1) && is_mpg_integer(t2)) { |
|
1327 |
r = mpg_integer(); |
|
1328 |
mpz_add(r->mpg_i, t1->mpg_i, t2->mpg_i); |
|
1329 |
} else { |
|
1330 |
r = mpg_float(); |
|
1331 |
if (is_mpg_integer(t2)) |
|
316
by john haque
Change MPFR variable RND_MODE to ROUND_MODE. |
1332 |
tval = mpfr_add_z(r->mpg_numbr, t1->mpg_numbr, t2->mpg_i, ROUND_MODE); |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1333 |
else if (is_mpg_integer(t1)) |
316
by john haque
Change MPFR variable RND_MODE to ROUND_MODE. |
1334 |
tval = mpfr_add_z(r->mpg_numbr, t2->mpg_numbr, t1->mpg_i, ROUND_MODE); |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1335 |
else
|
316
by john haque
Change MPFR variable RND_MODE to ROUND_MODE. |
1336 |
tval = mpfr_add(r->mpg_numbr, t1->mpg_numbr, t2->mpg_numbr, ROUND_MODE); |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1337 |
IEEE_FMT(r->mpg_numbr, tval); |
1338 |
}
|
|
1339 |
return r; |
|
1340 |
}
|
|
1341 |
||
1342 |
/* mpg_sub --- subtract arbitrary-precision numbers */
|
|
1343 |
||
1344 |
static NODE * |
|
1345 |
mpg_sub(NODE *t1, NODE *t2) |
|
1346 |
{
|
|
1347 |
NODE *r; |
|
1348 |
int tval; |
|
1349 |
||
1350 |
if (is_mpg_integer(t1) && is_mpg_integer(t2)) { |
|
1351 |
r = mpg_integer(); |
|
1352 |
mpz_sub(r->mpg_i, t1->mpg_i, t2->mpg_i); |
|
1353 |
} else { |
|
1354 |
r = mpg_float(); |
|
1355 |
if (is_mpg_integer(t2)) |
|
316
by john haque
Change MPFR variable RND_MODE to ROUND_MODE. |
1356 |
tval = mpfr_sub_z(r->mpg_numbr, t1->mpg_numbr, t2->mpg_i, ROUND_MODE); |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1357 |
else if (is_mpg_integer(t1)) { |
1358 |
#if (!defined(MPFR_VERSION) || (MPFR_VERSION < MPFR_VERSION_NUM(3,1,0)))
|
|
1359 |
NODE *tmp = t1; |
|
1360 |
t1 = t2; |
|
1361 |
t2 = tmp; |
|
316
by john haque
Change MPFR variable RND_MODE to ROUND_MODE. |
1362 |
tval = mpfr_sub_z(r->mpg_numbr, t1->mpg_numbr, t2->mpg_i, ROUND_MODE); |
1363 |
tval = mpfr_neg(r->mpg_numbr, r->mpg_numbr, ROUND_MODE); |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1364 |
t2 = t1; |
1365 |
t1 = tmp; |
|
1366 |
#else
|
|
316
by john haque
Change MPFR variable RND_MODE to ROUND_MODE. |
1367 |
tval = mpfr_z_sub(r->mpg_numbr, t1->mpg_i, t2->mpg_numbr, ROUND_MODE); |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1368 |
#endif
|
1369 |
} else |
|
316
by john haque
Change MPFR variable RND_MODE to ROUND_MODE. |
1370 |
tval = mpfr_sub(r->mpg_numbr, t1->mpg_numbr, t2->mpg_numbr, ROUND_MODE); |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1371 |
IEEE_FMT(r->mpg_numbr, tval); |
1372 |
}
|
|
1373 |
return r; |
|
1374 |
}
|
|
1375 |
||
1376 |
/* mpg_mul --- multiply arbitrary-precision numbers */
|
|
1377 |
||
1378 |
static NODE * |
|
1379 |
mpg_mul(NODE *t1, NODE *t2) |
|
1380 |
{
|
|
1381 |
NODE *r; |
|
1382 |
int tval; |
|
1383 |
||
1384 |
if (is_mpg_integer(t1) && is_mpg_integer(t2)) { |
|
1385 |
r = mpg_integer(); |
|
1386 |
mpz_mul(r->mpg_i, t1->mpg_i, t2->mpg_i); |
|
1387 |
} else { |
|
1388 |
r = mpg_float(); |
|
1389 |
if (is_mpg_integer(t2)) |
|
316
by john haque
Change MPFR variable RND_MODE to ROUND_MODE. |
1390 |
tval = mpfr_mul_z(r->mpg_numbr, t1->mpg_numbr, t2->mpg_i, ROUND_MODE); |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1391 |
else if (is_mpg_integer(t1)) |
316
by john haque
Change MPFR variable RND_MODE to ROUND_MODE. |
1392 |
tval = mpfr_mul_z(r->mpg_numbr, t2->mpg_numbr, t1->mpg_i, ROUND_MODE); |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1393 |
else
|
316
by john haque
Change MPFR variable RND_MODE to ROUND_MODE. |
1394 |
tval = mpfr_mul(r->mpg_numbr, t1->mpg_numbr, t2->mpg_numbr, ROUND_MODE); |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1395 |
IEEE_FMT(r->mpg_numbr, tval); |
1396 |
}
|
|
1397 |
return r; |
|
1398 |
}
|
|
1399 |
||
1400 |
||
408.26.83
by Arnold D. Robbins
Remove trailing whitespace everywhere. Fix Unicode into ASCII. |
1401 |
/* mpg_pow --- exponentiation involving arbitrary-precision numbers */
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1402 |
|
1403 |
static NODE * |
|
1404 |
mpg_pow(NODE *t1, NODE *t2) |
|
1405 |
{
|
|
1406 |
NODE *r; |
|
1407 |
int tval; |
|
1408 |
||
1409 |
if (is_mpg_integer(t1) && is_mpg_integer(t2)) { |
|
1410 |
if (mpz_sgn(t2->mpg_i) >= 0 && mpz_fits_ulong_p(t2->mpg_i)) { |
|
1411 |
r = mpg_integer(); |
|
1412 |
mpz_pow_ui(r->mpg_i, t1->mpg_i, mpz_get_ui(t2->mpg_i)); |
|
1413 |
} else { |
|
1414 |
mpfr_ptr p1, p2; |
|
1415 |
p1 = MP_FLOAT(t1); |
|
1416 |
p2 = MP_FLOAT(t2); |
|
1417 |
r = mpg_float(); |
|
316
by john haque
Change MPFR variable RND_MODE to ROUND_MODE. |
1418 |
tval = mpfr_pow(r->mpg_numbr, p1, p2, ROUND_MODE); |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1419 |
IEEE_FMT(r->mpg_numbr, tval); |
1420 |
}
|
|
1421 |
} else { |
|
1422 |
r = mpg_float(); |
|
1423 |
if (is_mpg_integer(t2)) |
|
316
by john haque
Change MPFR variable RND_MODE to ROUND_MODE. |
1424 |
tval = mpfr_pow_z(r->mpg_numbr, t1->mpg_numbr, t2->mpg_i, ROUND_MODE); |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1425 |
else { |
1426 |
mpfr_ptr p1; |
|
1427 |
p1 = MP_FLOAT(t1); |
|
316
by john haque
Change MPFR variable RND_MODE to ROUND_MODE. |
1428 |
tval = mpfr_pow(r->mpg_numbr, p1, t2->mpg_numbr, ROUND_MODE); |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1429 |
}
|
1430 |
IEEE_FMT(r->mpg_numbr, tval); |
|
1431 |
}
|
|
1432 |
return r; |
|
1433 |
}
|
|
1434 |
||
1435 |
/* mpg_div --- arbitrary-precision division */
|
|
1436 |
||
1437 |
static NODE * |
|
1438 |
mpg_div(NODE *t1, NODE *t2) |
|
1439 |
{
|
|
1440 |
NODE *r; |
|
1441 |
int tval; |
|
1442 |
||
1443 |
if (is_mpg_integer(t1) && is_mpg_integer(t2) |
|
1444 |
&& (mpz_sgn(t2->mpg_i) != 0) /* not dividing by 0 */ |
|
1445 |
&& mpz_divisible_p(t1->mpg_i, t2->mpg_i) |
|
1446 |
) { |
|
1447 |
r = mpg_integer(); |
|
1448 |
mpz_divexact(r->mpg_i, t1->mpg_i, t2->mpg_i); |
|
1449 |
} else { |
|
1450 |
mpfr_ptr p1, p2; |
|
1451 |
p1 = MP_FLOAT(t1); |
|
1452 |
p2 = MP_FLOAT(t2); |
|
1453 |
r = mpg_float(); |
|
316
by john haque
Change MPFR variable RND_MODE to ROUND_MODE. |
1454 |
tval = mpfr_div(r->mpg_numbr, p1, p2, ROUND_MODE); |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1455 |
IEEE_FMT(r->mpg_numbr, tval); |
1456 |
}
|
|
1457 |
return r; |
|
1458 |
}
|
|
1459 |
||
1460 |
/* mpg_mod --- modulus operation with arbitrary-precision numbers */
|
|
1461 |
||
1462 |
static NODE * |
|
1463 |
mpg_mod(NODE *t1, NODE *t2) |
|
1464 |
{
|
|
1465 |
NODE *r; |
|
1466 |
int tval; |
|
1467 |
||
1468 |
if (is_mpg_integer(t1) && is_mpg_integer(t2)) { |
|
408.5.234
by Arnold D. Robbins
Bug fix to MPFR mod operation for negative numerator. |
1469 |
/*
|
1470 |
* 8/2014: Originally, this was just
|
|
1471 |
*
|
|
1472 |
* r = mpg_integer();
|
|
1473 |
* mpz_mod(r->mpg_i, t1->mpg_i, t2->mpg_i);
|
|
1474 |
*
|
|
1475 |
* But that gave very strange results with negative numerator:
|
|
1476 |
*
|
|
1477 |
* $ ./gawk -M 'BEGIN { print -15 % 7 }'
|
|
1478 |
* 6
|
|
1479 |
*
|
|
1480 |
* So instead we use mpz_tdiv_qr() to get the correct result
|
|
1481 |
* and just throw away the quotient. We could not find any
|
|
1482 |
* reason why mpz_mod() wasn't working correctly.
|
|
1483 |
*/
|
|
1484 |
NODE *dummy_quotient; |
|
1485 |
||
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1486 |
r = mpg_integer(); |
408.5.234
by Arnold D. Robbins
Bug fix to MPFR mod operation for negative numerator. |
1487 |
dummy_quotient = mpg_integer(); |
1488 |
mpz_tdiv_qr(dummy_quotient->mpg_i, r->mpg_i, t1->mpg_i, t2->mpg_i); |
|
1489 |
unref(dummy_quotient); |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1490 |
} else { |
1491 |
mpfr_ptr p1, p2; |
|
1492 |
p1 = MP_FLOAT(t1); |
|
1493 |
p2 = MP_FLOAT(t2); |
|
1494 |
r = mpg_float(); |
|
316
by john haque
Change MPFR variable RND_MODE to ROUND_MODE. |
1495 |
tval = mpfr_fmod(r->mpg_numbr, p1, p2, ROUND_MODE); |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1496 |
IEEE_FMT(r->mpg_numbr, tval); |
1497 |
}
|
|
1498 |
return r; |
|
1499 |
}
|
|
408.26.83
by Arnold D. Robbins
Remove trailing whitespace everywhere. Fix Unicode into ASCII. |
1500 |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1501 |
/*
|
302.1.1
by john haque
Finish MPFR changes and clean up code. |
1502 |
* mpg_interpret --- pre-exec hook in the interpreter. Handles
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1503 |
* arithmetic operations with MPFR/GMP numbers.
|
408.26.83
by Arnold D. Robbins
Remove trailing whitespace everywhere. Fix Unicode into ASCII. |
1504 |
*/
|
301
by john haque
New interpreter routine for MPFR. |
1505 |
|
302.1.1
by john haque
Finish MPFR changes and clean up code. |
1506 |
static int |
1507 |
mpg_interpret(INSTRUCTION **cp) |
|
301
by john haque
New interpreter routine for MPFR. |
1508 |
{
|
302.1.1
by john haque
Finish MPFR changes and clean up code. |
1509 |
INSTRUCTION *pc = *cp; /* current instruction */ |
1510 |
OPCODE op; /* current opcode */ |
|
1511 |
NODE *r = NULL; |
|
1512 |
NODE *t1, *t2; |
|
301
by john haque
New interpreter routine for MPFR. |
1513 |
NODE **lhs; |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1514 |
int tval; /* the ternary value returned by a MPFR function */ |
302.1.1
by john haque
Finish MPFR changes and clean up code. |
1515 |
|
1516 |
switch ((op = pc->opcode)) { |
|
1517 |
case Op_plus_i: |
|
1518 |
t2 = force_number(pc->memory); |
|
1519 |
goto plus; |
|
1520 |
case Op_plus: |
|
1521 |
t2 = POP_NUMBER(); |
|
1522 |
plus: |
|
1523 |
t1 = TOP_NUMBER(); |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1524 |
r = mpg_add(t1, t2); |
302.1.1
by john haque
Finish MPFR changes and clean up code. |
1525 |
DEREF(t1); |
1526 |
if (op == Op_plus) |
|
1527 |
DEREF(t2); |
|
1528 |
REPLACE(r); |
|
1529 |
break; |
|
1530 |
||
1531 |
case Op_minus_i: |
|
1532 |
t2 = force_number(pc->memory); |
|
1533 |
goto minus; |
|
1534 |
case Op_minus: |
|
1535 |
t2 = POP_NUMBER(); |
|
1536 |
minus: |
|
1537 |
t1 = TOP_NUMBER(); |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1538 |
r = mpg_sub(t1, t2); |
302.1.1
by john haque
Finish MPFR changes and clean up code. |
1539 |
DEREF(t1); |
1540 |
if (op == Op_minus) |
|
1541 |
DEREF(t2); |
|
1542 |
REPLACE(r); |
|
1543 |
break; |
|
1544 |
||
1545 |
case Op_times_i: |
|
1546 |
t2 = force_number(pc->memory); |
|
1547 |
goto times; |
|
1548 |
case Op_times: |
|
1549 |
t2 = POP_NUMBER(); |
|
1550 |
times: |
|
1551 |
t1 = TOP_NUMBER(); |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1552 |
r = mpg_mul(t1, t2); |
302.1.1
by john haque
Finish MPFR changes and clean up code. |
1553 |
DEREF(t1); |
1554 |
if (op == Op_times) |
|
1555 |
DEREF(t2); |
|
1556 |
REPLACE(r); |
|
1557 |
break; |
|
1558 |
||
1559 |
case Op_exp_i: |
|
1560 |
t2 = force_number(pc->memory); |
|
1561 |
goto exp; |
|
1562 |
case Op_exp: |
|
1563 |
t2 = POP_NUMBER(); |
|
1564 |
exp: |
|
1565 |
t1 = TOP_NUMBER(); |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1566 |
r = mpg_pow(t1, t2); |
302.1.1
by john haque
Finish MPFR changes and clean up code. |
1567 |
DEREF(t1); |
1568 |
if (op == Op_exp) |
|
1569 |
DEREF(t2); |
|
1570 |
REPLACE(r); |
|
1571 |
break; |
|
1572 |
||
1573 |
case Op_quotient_i: |
|
1574 |
t2 = force_number(pc->memory); |
|
1575 |
goto quotient; |
|
1576 |
case Op_quotient: |
|
1577 |
t2 = POP_NUMBER(); |
|
1578 |
quotient: |
|
1579 |
t1 = TOP_NUMBER(); |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1580 |
r = mpg_div(t1, t2); |
302.1.1
by john haque
Finish MPFR changes and clean up code. |
1581 |
DEREF(t1); |
1582 |
if (op == Op_quotient) |
|
1583 |
DEREF(t2); |
|
1584 |
REPLACE(r); |
|
408.26.83
by Arnold D. Robbins
Remove trailing whitespace everywhere. Fix Unicode into ASCII. |
1585 |
break; |
302.1.1
by john haque
Finish MPFR changes and clean up code. |
1586 |
|
1587 |
case Op_mod_i: |
|
1588 |
t2 = force_number(pc->memory); |
|
1589 |
goto mod; |
|
1590 |
case Op_mod: |
|
1591 |
t2 = POP_NUMBER(); |
|
1592 |
mod: |
|
1593 |
t1 = TOP_NUMBER(); |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1594 |
r = mpg_mod(t1, t2); |
302.1.1
by john haque
Finish MPFR changes and clean up code. |
1595 |
DEREF(t1); |
1596 |
if (op == Op_mod) |
|
1597 |
DEREF(t2); |
|
1598 |
REPLACE(r); |
|
1599 |
break; |
|
1600 |
||
1601 |
case Op_preincrement: |
|
1602 |
case Op_predecrement: |
|
1603 |
lhs = TOP_ADDRESS(); |
|
1604 |
t1 = *lhs; |
|
1605 |
force_number(t1); |
|
305
by john haque
Bug fixes and tests for MPFR. |
1606 |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1607 |
if (is_mpg_integer(t1)) { |
1608 |
if (t1->valref == 1 && t1->flags == (MALLOC|MPZN|NUMCUR|NUMBER)) |
|
1609 |
/* Efficiency hack. Big speed-up (> 30%) in a tight loop */
|
|
1610 |
r = t1; |
|
1611 |
else
|
|
1612 |
r = *lhs = mpg_integer(); |
|
1613 |
if (op == Op_preincrement) |
|
1614 |
mpz_add_ui(r->mpg_i, t1->mpg_i, 1); |
|
1615 |
else
|
|
1616 |
mpz_sub_ui(r->mpg_i, t1->mpg_i, 1); |
|
1617 |
} else { |
|
1618 |
||
1619 |
/*
|
|
1620 |
* An optimization like the one above is not going to work
|
|
1621 |
* for a floating-point number. With it,
|
|
1622 |
* gawk -M 'BEGIN { PREC=53; i=2^53+0.0; PREC=113; ++i; print i}'
|
|
1623 |
* will output 2^53 instead of 2^53+1.
|
|
1624 |
*/
|
|
1625 |
||
1626 |
r = *lhs = mpg_float(); |
|
1627 |
tval = mpfr_add_si(r->mpg_numbr, t1->mpg_numbr, |
|
1628 |
op == Op_preincrement ? 1 : -1, |
|
316
by john haque
Change MPFR variable RND_MODE to ROUND_MODE. |
1629 |
ROUND_MODE); |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1630 |
IEEE_FMT(r->mpg_numbr, tval); |
302.1.1
by john haque
Finish MPFR changes and clean up code. |
1631 |
}
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1632 |
if (r != t1) |
1633 |
unref(t1); |
|
302.1.1
by john haque
Finish MPFR changes and clean up code. |
1634 |
UPREF(r); |
1635 |
REPLACE(r); |
|
1636 |
break; |
|
1637 |
||
1638 |
case Op_postincrement: |
|
1639 |
case Op_postdecrement: |
|
1640 |
lhs = TOP_ADDRESS(); |
|
1641 |
t1 = *lhs; |
|
1642 |
force_number(t1); |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1643 |
|
1644 |
if (is_mpg_integer(t1)) { |
|
1645 |
r = mpg_integer(); |
|
1646 |
mpz_set(r->mpg_i, t1->mpg_i); |
|
1647 |
if (t1->valref == 1 && t1->flags == (MALLOC|MPZN|NUMCUR|NUMBER)) |
|
1648 |
/* Efficiency hack. Big speed-up (> 30%) in a tight loop */
|
|
1649 |
t2 = t1; |
|
1650 |
else
|
|
1651 |
t2 = *lhs = mpg_integer(); |
|
1652 |
if (op == Op_postincrement) |
|
1653 |
mpz_add_ui(t2->mpg_i, t1->mpg_i, 1); |
|
1654 |
else
|
|
1655 |
mpz_sub_ui(t2->mpg_i, t1->mpg_i, 1); |
|
1656 |
} else { |
|
1657 |
r = mpg_float(); |
|
316
by john haque
Change MPFR variable RND_MODE to ROUND_MODE. |
1658 |
tval = mpfr_set(r->mpg_numbr, t1->mpg_numbr, ROUND_MODE); |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1659 |
IEEE_FMT(r->mpg_numbr, tval); |
1660 |
t2 = *lhs = mpg_float(); |
|
1661 |
tval = mpfr_add_si(t2->mpg_numbr, t1->mpg_numbr, |
|
1662 |
op == Op_postincrement ? 1 : -1, |
|
316
by john haque
Change MPFR variable RND_MODE to ROUND_MODE. |
1663 |
ROUND_MODE); |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1664 |
IEEE_FMT(t2->mpg_numbr, tval); |
1665 |
}
|
|
1666 |
if (t2 != t1) |
|
1667 |
unref(t1); |
|
302.1.1
by john haque
Finish MPFR changes and clean up code. |
1668 |
REPLACE(r); |
1669 |
break; |
|
1670 |
||
1671 |
case Op_unary_minus: |
|
1672 |
t1 = TOP_NUMBER(); |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1673 |
if (is_mpg_float(t1)) { |
1674 |
r = mpg_float(); |
|
316
by john haque
Change MPFR variable RND_MODE to ROUND_MODE. |
1675 |
tval = mpfr_neg(r->mpg_numbr, t1->mpg_numbr, ROUND_MODE); |
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1676 |
IEEE_FMT(r->mpg_numbr, tval); |
1677 |
} else { |
|
1678 |
r = mpg_integer(); |
|
1679 |
mpz_neg(r->mpg_i, t1->mpg_i); |
|
1680 |
}
|
|
302.1.1
by john haque
Finish MPFR changes and clean up code. |
1681 |
DEREF(t1); |
1682 |
REPLACE(r); |
|
1683 |
break; |
|
1684 |
||
731.11.303
by Andrew J. Schorr
Fix bug printing +"01" in regular and MPFR mode. |
1685 |
case Op_unary_plus: |
1686 |
t1 = TOP_NUMBER(); |
|
1687 |
if (is_mpg_float(t1)) { |
|
1688 |
r = mpg_float(); |
|
1689 |
tval = mpfr_set(r->mpg_numbr, t1->mpg_numbr, ROUND_MODE); |
|
1690 |
IEEE_FMT(r->mpg_numbr, tval); |
|
1691 |
} else { |
|
1692 |
r = mpg_integer(); |
|
1693 |
mpz_set(r->mpg_i, t1->mpg_i); |
|
1694 |
}
|
|
1695 |
DEREF(t1); |
|
1696 |
REPLACE(r); |
|
1697 |
break; |
|
1698 |
||
301
by john haque
New interpreter routine for MPFR. |
1699 |
case Op_assign_plus: |
1700 |
case Op_assign_minus: |
|
1701 |
case Op_assign_times: |
|
1702 |
case Op_assign_quotient: |
|
1703 |
case Op_assign_mod: |
|
1704 |
case Op_assign_exp: |
|
302.1.1
by john haque
Finish MPFR changes and clean up code. |
1705 |
lhs = POP_ADDRESS(); |
1706 |
t1 = *lhs; |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1707 |
force_number(t1); |
302.1.1
by john haque
Finish MPFR changes and clean up code. |
1708 |
t2 = TOP_NUMBER(); |
1709 |
||
1710 |
switch (op) { |
|
1711 |
case Op_assign_plus: |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1712 |
r = mpg_add(t1, t2); |
302.1.1
by john haque
Finish MPFR changes and clean up code. |
1713 |
break; |
1714 |
case Op_assign_minus: |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1715 |
r = mpg_sub(t1, t2); |
302.1.1
by john haque
Finish MPFR changes and clean up code. |
1716 |
break; |
1717 |
case Op_assign_times: |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1718 |
r = mpg_mul(t1, t2); |
302.1.1
by john haque
Finish MPFR changes and clean up code. |
1719 |
break; |
1720 |
case Op_assign_quotient: |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1721 |
r = mpg_div(t1, t2); |
302.1.1
by john haque
Finish MPFR changes and clean up code. |
1722 |
break; |
1723 |
case Op_assign_mod: |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1724 |
r = mpg_mod(t1, t2); |
302.1.1
by john haque
Finish MPFR changes and clean up code. |
1725 |
break; |
1726 |
case Op_assign_exp: |
|
306
by john haque
Add arbitrary-precision arithmetic on integers. |
1727 |
r = mpg_pow(t1, t2); |
302.1.1
by john haque
Finish MPFR changes and clean up code. |
1728 |
break; |
1729 |
default: |
|
1730 |
cant_happen(); |
|
1731 |
}
|
|
305
by john haque
Bug fixes and tests for MPFR. |
1732 |
|
302.1.1
by john haque
Finish MPFR changes and clean up code. |
1733 |
DEREF(t2); |
1734 |
unref(*lhs); |
|
1735 |
*lhs = r; |
|
1736 |
UPREF(r); |
|
1737 |
REPLACE(r); |
|
301
by john haque
New interpreter routine for MPFR. |
1738 |
break; |
302.1.1
by john haque
Finish MPFR changes and clean up code. |
1739 |
|
301
by john haque
New interpreter routine for MPFR. |
1740 |
default: |
319.1.9
by Arnold D. Robbins
Move to use of bool type, true, false, everywhere. |
1741 |
return true; /* unhandled */ |
301
by john haque
New interpreter routine for MPFR. |
1742 |
}
|
1743 |
||
302.1.1
by john haque
Finish MPFR changes and clean up code. |
1744 |
*cp = pc->nexti; /* next instruction to execute */ |
319.1.9
by Arnold D. Robbins
Move to use of bool type, true, false, everywhere. |
1745 |
return false; |
301
by john haque
New interpreter routine for MPFR. |
1746 |
}
|
1747 |
||
1748 |
||
302.1.1
by john haque
Finish MPFR changes and clean up code. |
1749 |
/* mpg_fmt --- output formatted string with special MPFR/GMP conversion specifiers */
|
301
by john haque
New interpreter routine for MPFR. |
1750 |
|
1751 |
const char * |
|
302.1.1
by john haque
Finish MPFR changes and clean up code. |
1752 |
mpg_fmt(const char *mesg, ...) |
301
by john haque
New interpreter routine for MPFR. |
1753 |
{
|
1754 |
static char *tmp = NULL; |
|
1755 |
int ret; |
|
1756 |
va_list args; |
|
1757 |
||
302.1.1
by john haque
Finish MPFR changes and clean up code. |
1758 |
if (tmp != NULL) { |
301
by john haque
New interpreter routine for MPFR. |
1759 |
mpfr_free_str(tmp); |
302.1.1
by john haque
Finish MPFR changes and clean up code. |
1760 |
tmp = NULL; |
1761 |
}
|
|
301
by john haque
New interpreter routine for MPFR. |
1762 |
va_start(args, mesg); |
1763 |
ret = mpfr_vasprintf(& tmp, mesg, args); |
|
1764 |
va_end(args); |
|
1765 |
if (ret >= 0 && tmp != NULL) |
|
1766 |
return tmp; |
|
1767 |
return mesg; |
|
1768 |
}
|
|
1769 |
||
319.1.112
by Arnold D. Robbins
Minor cleanup in calls to mpfr routines. |
1770 |
/* mpfr_unset --- clear out the MPFR values */
|
1771 |
||
1772 |
void
|
|
1773 |
mpfr_unset(NODE *n) |
|
1774 |
{
|
|
1775 |
if (is_mpg_float(n)) |
|
1776 |
mpfr_clear(n->mpg_numbr); |
|
1777 |
else if (is_mpg_integer(n)) |
|
1778 |
mpz_clear(n->mpg_i); |
|
1779 |
}
|
|
1780 |
||
302.1.1
by john haque
Finish MPFR changes and clean up code. |
1781 |
#else
|
1782 |
||
1783 |
void
|
|
1784 |
set_PREC() |
|
1785 |
{
|
|
1786 |
/* dummy function */
|
|
1787 |
}
|
|
1788 |
||
1789 |
void
|
|
318
by john haque
MPFR fixes from Eli. |
1790 |
set_ROUNDMODE() |
302.1.1
by john haque
Finish MPFR changes and clean up code. |
1791 |
{
|
1792 |
/* dummy function */
|
|
1793 |
}
|
|
1794 |
||
319.1.112
by Arnold D. Robbins
Minor cleanup in calls to mpfr routines. |
1795 |
void
|
1796 |
mpfr_unset(NODE *n) |
|
1797 |
{
|
|
1798 |
/* dummy function */
|
|
1799 |
}
|
|
300
by john haque
Add infrastructure for MPFR/GMP support. |
1800 |
#endif
|