~vcs-imports/gawk/master

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