1570af302Sopenharmony_ci#include <stdio.h>
2570af302Sopenharmony_ci#include <stdint.h>
3570af302Sopenharmony_ci#include <mpfr.h>
4570af302Sopenharmony_ci#include "gen.h"
5570af302Sopenharmony_ci
6570af302Sopenharmony_cistatic int rmap(int r)
7570af302Sopenharmony_ci{
8570af302Sopenharmony_ci	switch (r) {
9570af302Sopenharmony_ci	case RN: return MPFR_RNDN;
10570af302Sopenharmony_ci	case RZ: return MPFR_RNDZ;
11570af302Sopenharmony_ci	case RD: return MPFR_RNDD;
12570af302Sopenharmony_ci	case RU: return MPFR_RNDU;
13570af302Sopenharmony_ci	}
14570af302Sopenharmony_ci	return -1;
15570af302Sopenharmony_ci}
16570af302Sopenharmony_ci
17570af302Sopenharmony_cienum {FLT, DBL, LDBL};
18570af302Sopenharmony_cistatic const int emin[] = {
19570af302Sopenharmony_ci[FLT] = -148,
20570af302Sopenharmony_ci[DBL] = -1073,
21570af302Sopenharmony_ci[LDBL] = -16444
22570af302Sopenharmony_ci};
23570af302Sopenharmony_cistatic const int emax[] = {
24570af302Sopenharmony_ci[FLT] = 128,
25570af302Sopenharmony_ci[DBL] = 1024,
26570af302Sopenharmony_ci[LDBL] = 16384
27570af302Sopenharmony_ci};
28570af302Sopenharmony_ci
29570af302Sopenharmony_civoid debug(mpfr_t x)
30570af302Sopenharmony_ci{
31570af302Sopenharmony_ci	mpfr_out_str(stdout, 10, 0, x, MPFR_RNDN);
32570af302Sopenharmony_ci	printf("\n");
33570af302Sopenharmony_ci}
34570af302Sopenharmony_ci
35570af302Sopenharmony_ci/*
36570af302Sopenharmony_ciround x into y considering x is already rounded (t = up or down)
37570af302Sopenharmony_ci
38570af302Sopenharmony_cionly cases where adjustment is done:
39570af302Sopenharmony_ci	x=...|1...0, t=up    -> x=nextbelow(x)
40570af302Sopenharmony_ci	x=...|1...0, t=down  -> x=nextabove(x)
41570af302Sopenharmony_ciwhere | is the rounding point, ... is 0 or 1 bit patterns
42570af302Sopenharmony_ci*/
43570af302Sopenharmony_ci
44570af302Sopenharmony_ci// TODO: adjust(y, 0, 2, RN); when prec is 24 (0 vs 0x1p-149f), special case x=0
45570af302Sopenharmony_cistatic int adjust_round(mpfr_t y, mpfr_t x, int t, int r)
46570af302Sopenharmony_ci{
47570af302Sopenharmony_ci	mp_limb_t *p, *q;
48570af302Sopenharmony_ci	unsigned xp, yp;
49570af302Sopenharmony_ci	int t2;
50570af302Sopenharmony_ci
51570af302Sopenharmony_ci	xp = mpfr_get_prec(x);
52570af302Sopenharmony_ci	yp = mpfr_get_prec(y);
53570af302Sopenharmony_ci	if (yp >= xp || r != MPFR_RNDN || t == 0 || !mpfr_number_p(x) || mpfr_zero_p(x)) {
54570af302Sopenharmony_ci		t2 = mpfr_set(y, x, r);
55570af302Sopenharmony_ci		return t2 ? t2 : t;
56570af302Sopenharmony_ci	}
57570af302Sopenharmony_ci	p = x->_mpfr_d;
58570af302Sopenharmony_ci	yp++;
59570af302Sopenharmony_ci	q = p + (xp + mp_bits_per_limb - 1)/mp_bits_per_limb - (yp + mp_bits_per_limb - 1)/mp_bits_per_limb;
60570af302Sopenharmony_ci	if ((*p & 1 << -xp%mp_bits_per_limb) || !(*q & 1 << -yp%mp_bits_per_limb)) {
61570af302Sopenharmony_ci		t2 = mpfr_set(y, x, r);
62570af302Sopenharmony_ci		return t2 ? t2 : t;
63570af302Sopenharmony_ci	}
64570af302Sopenharmony_ci	if (t > 0)
65570af302Sopenharmony_ci		mpfr_nextbelow(x);
66570af302Sopenharmony_ci	else
67570af302Sopenharmony_ci		mpfr_nextabove(x);
68570af302Sopenharmony_ci	return mpfr_set(y, x, r);
69570af302Sopenharmony_ci}
70570af302Sopenharmony_ci
71570af302Sopenharmony_cistatic int adjust(mpfr_t mr, mpfr_t my, int t, int r, int type)
72570af302Sopenharmony_ci{
73570af302Sopenharmony_ci//	double d, dn, dp;
74570af302Sopenharmony_ci//printf("adj %d\n", t);
75570af302Sopenharmony_ci//debug(my);
76570af302Sopenharmony_ci	t = adjust_round(mr, my, t, r);
77570af302Sopenharmony_ci//printf("rnd %d\n", t);
78570af302Sopenharmony_ci//debug(mr);
79570af302Sopenharmony_ci	mpfr_set_emin(emin[type]);
80570af302Sopenharmony_ci	mpfr_set_emax(emax[type]);
81570af302Sopenharmony_ci	// mpfr could handle this in subnormlize easily but no it doesnt...
82570af302Sopenharmony_ci	t = mpfr_check_range(mr, t, r);
83570af302Sopenharmony_ci	t = mpfr_subnormalize(mr, t, r);
84570af302Sopenharmony_ci	mpfr_set_emax(MPFR_EMAX_DEFAULT);
85570af302Sopenharmony_ci	mpfr_set_emin(MPFR_EMIN_DEFAULT);
86570af302Sopenharmony_ci//printf("sub %d\n", t);
87570af302Sopenharmony_ci//debug(mr);
88570af302Sopenharmony_ci//	d = mpfr_get_d(mr, r);
89570af302Sopenharmony_ci//	dn = nextafter(d, INFINITY);
90570af302Sopenharmony_ci//	dp = nextafter(d, -INFINITY);
91570af302Sopenharmony_ci//printf("c\n %.21e %a\n %.21e %a\n %.21e %a\n",d,d,dn,dn,dp,dp);
92570af302Sopenharmony_ci//	dn = nextafterf(d, INFINITY);
93570af302Sopenharmony_ci//	dp = nextafterf(d, -INFINITY);
94570af302Sopenharmony_ci//printf("cf\n %.21e %a\n %.21e %a\n %.21e %a\n",d,d,dn,dn,dp,dp);
95570af302Sopenharmony_ci	return t;
96570af302Sopenharmony_ci}
97570af302Sopenharmony_ci
98570af302Sopenharmony_ci// TODO
99570af302Sopenharmony_ci//static int eflags(mpfr_t mr, mpfr_t my, int t)
100570af302Sopenharmony_cistatic int eflags(int naninput)
101570af302Sopenharmony_ci{
102570af302Sopenharmony_ci	int i = 0;
103570af302Sopenharmony_ci
104570af302Sopenharmony_ci	if (mpfr_inexflag_p())
105570af302Sopenharmony_ci		i |= FE_INEXACT;
106570af302Sopenharmony_ci//	if (mpfr_underflow_p() && (t || mpfr_cmp(mr, my) != 0))
107570af302Sopenharmony_ci	if (mpfr_underflow_p() && i)
108570af302Sopenharmony_ci		i |= FE_UNDERFLOW;
109570af302Sopenharmony_ci	if (mpfr_overflow_p())
110570af302Sopenharmony_ci		i |= FE_OVERFLOW;
111570af302Sopenharmony_ci	if (mpfr_divby0_p())
112570af302Sopenharmony_ci		i |= FE_DIVBYZERO;
113570af302Sopenharmony_ci	if (!naninput && (mpfr_nanflag_p() || mpfr_erangeflag_p()))
114570af302Sopenharmony_ci		i |= FE_INVALID;
115570af302Sopenharmony_ci	return i;
116570af302Sopenharmony_ci}
117570af302Sopenharmony_ci
118570af302Sopenharmony_cistatic void genf(struct t *p, mpfr_t my, int t, int r)
119570af302Sopenharmony_ci{
120570af302Sopenharmony_ci	MPFR_DECL_INIT(mr, 24);
121570af302Sopenharmony_ci	int i;
122570af302Sopenharmony_ci
123570af302Sopenharmony_ci	t = adjust(mr, my, t, r, FLT);
124570af302Sopenharmony_ci	p->y = mpfr_get_flt(mr, r);
125570af302Sopenharmony_ci	p->e = eflags(isnan(p->x) || isnan(p->x2) || isnan(p->x3));
126570af302Sopenharmony_ci	i = eulpf(p->y);
127570af302Sopenharmony_ci	if (!isfinite(p->y)) {
128570af302Sopenharmony_ci		p->dy = 0;
129570af302Sopenharmony_ci	} else {
130570af302Sopenharmony_ci		mpfr_sub(my, mr, my, MPFR_RNDN);
131570af302Sopenharmony_ci		mpfr_div_2si(my, my, i, MPFR_RNDN);
132570af302Sopenharmony_ci		p->dy = mpfr_get_flt(my, MPFR_RNDN);
133570af302Sopenharmony_ci		// happens in RU,RD,RZ modes when y is finite but outside the domain
134570af302Sopenharmony_ci		if (p->dy > 1)
135570af302Sopenharmony_ci			p->dy = 1;
136570af302Sopenharmony_ci		if (p->dy < -1)
137570af302Sopenharmony_ci			p->dy = -1;
138570af302Sopenharmony_ci	}
139570af302Sopenharmony_ci}
140570af302Sopenharmony_ci
141570af302Sopenharmony_cistatic int mpf1(struct t *p, int (*fmp)(mpfr_t, const mpfr_t, mpfr_rnd_t))
142570af302Sopenharmony_ci{
143570af302Sopenharmony_ci	int tn;
144570af302Sopenharmony_ci	int r = rmap(p->r);
145570af302Sopenharmony_ci	MPFR_DECL_INIT(mx, 24);
146570af302Sopenharmony_ci	MPFR_DECL_INIT(my, 128);
147570af302Sopenharmony_ci
148570af302Sopenharmony_ci	mpfr_clear_flags();
149570af302Sopenharmony_ci	mpfr_set_flt(mx, p->x, MPFR_RNDN);
150570af302Sopenharmony_ci	tn = fmp(my, mx, r);
151570af302Sopenharmony_ci	p->x2 = 0;
152570af302Sopenharmony_ci	genf(p, my, tn, r);
153570af302Sopenharmony_ci	return 0;
154570af302Sopenharmony_ci}
155570af302Sopenharmony_ci
156570af302Sopenharmony_cistatic int mpf2(struct t *p, int (*fmp)(mpfr_t, const mpfr_t, const mpfr_t, mpfr_rnd_t))
157570af302Sopenharmony_ci{
158570af302Sopenharmony_ci	int tn;
159570af302Sopenharmony_ci	int r = rmap(p->r);
160570af302Sopenharmony_ci	MPFR_DECL_INIT(mx, 24);
161570af302Sopenharmony_ci	MPFR_DECL_INIT(mx2, 24);
162570af302Sopenharmony_ci	MPFR_DECL_INIT(my, 128);
163570af302Sopenharmony_ci
164570af302Sopenharmony_ci	mpfr_clear_flags();
165570af302Sopenharmony_ci	mpfr_set_flt(mx, p->x, MPFR_RNDN);
166570af302Sopenharmony_ci	mpfr_set_flt(mx2, p->x2, MPFR_RNDN);
167570af302Sopenharmony_ci	tn = fmp(my, mx, mx2, r);
168570af302Sopenharmony_ci	genf(p, my, tn, r);
169570af302Sopenharmony_ci	return 0;
170570af302Sopenharmony_ci}
171570af302Sopenharmony_ci
172570af302Sopenharmony_cistatic void gend(struct t *p, mpfr_t my, int t, int r)
173570af302Sopenharmony_ci{
174570af302Sopenharmony_ci	MPFR_DECL_INIT(mr, 53);
175570af302Sopenharmony_ci	int i;
176570af302Sopenharmony_ci
177570af302Sopenharmony_ci	t = adjust(mr, my, t, r, DBL);
178570af302Sopenharmony_ci	p->y = mpfr_get_d(mr, r);
179570af302Sopenharmony_ci	p->e = eflags(isnan(p->x) || isnan(p->x2) || isnan(p->x3));
180570af302Sopenharmony_ci	i = eulp(p->y);
181570af302Sopenharmony_ci	if (!isfinite(p->y)) {
182570af302Sopenharmony_ci		p->dy = 0;
183570af302Sopenharmony_ci	} else {
184570af302Sopenharmony_ci		mpfr_sub(my, mr, my, MPFR_RNDN);
185570af302Sopenharmony_ci		mpfr_div_2si(my, my, i, MPFR_RNDN);
186570af302Sopenharmony_ci		p->dy = mpfr_get_flt(my, MPFR_RNDN);
187570af302Sopenharmony_ci		// happens in RU,RD,RZ modes when y is finite but outside the domain
188570af302Sopenharmony_ci		if (p->dy > 1)
189570af302Sopenharmony_ci			p->dy = 1;
190570af302Sopenharmony_ci		if (p->dy < -1)
191570af302Sopenharmony_ci			p->dy = -1;
192570af302Sopenharmony_ci	}
193570af302Sopenharmony_ci}
194570af302Sopenharmony_ci
195570af302Sopenharmony_cistatic int mpd1(struct t *p, int (*fmp)(mpfr_t, const mpfr_t, mpfr_rnd_t))
196570af302Sopenharmony_ci{
197570af302Sopenharmony_ci	int tn;
198570af302Sopenharmony_ci	int r = rmap(p->r);
199570af302Sopenharmony_ci	MPFR_DECL_INIT(mx, 53);
200570af302Sopenharmony_ci	MPFR_DECL_INIT(my, 128);
201570af302Sopenharmony_ci
202570af302Sopenharmony_ci	mpfr_clear_flags();
203570af302Sopenharmony_ci	mpfr_set_d(mx, p->x, MPFR_RNDN);
204570af302Sopenharmony_ci	tn = fmp(my, mx, r);
205570af302Sopenharmony_ci	p->x2 = 0;
206570af302Sopenharmony_ci	gend(p, my, tn, r);
207570af302Sopenharmony_ci	return 0;
208570af302Sopenharmony_ci}
209570af302Sopenharmony_ci
210570af302Sopenharmony_cistatic int mpd2(struct t *p, int (*fmp)(mpfr_t, const mpfr_t, const mpfr_t, mpfr_rnd_t))
211570af302Sopenharmony_ci{
212570af302Sopenharmony_ci	int tn;
213570af302Sopenharmony_ci	int r = rmap(p->r);
214570af302Sopenharmony_ci	MPFR_DECL_INIT(mx, 53);
215570af302Sopenharmony_ci	MPFR_DECL_INIT(mx2, 53);
216570af302Sopenharmony_ci	MPFR_DECL_INIT(my, 128);
217570af302Sopenharmony_ci
218570af302Sopenharmony_ci	mpfr_clear_flags();
219570af302Sopenharmony_ci	mpfr_set_d(mx, p->x, MPFR_RNDN);
220570af302Sopenharmony_ci	mpfr_set_d(mx2, p->x2, MPFR_RNDN);
221570af302Sopenharmony_ci	tn = fmp(my, mx, mx2, r);
222570af302Sopenharmony_ci	gend(p, my, tn, r);
223570af302Sopenharmony_ci	return 0;
224570af302Sopenharmony_ci}
225570af302Sopenharmony_ci
226570af302Sopenharmony_ci#if LDBL_MANT_DIG == 64
227570af302Sopenharmony_cistatic void genl(struct t *p, mpfr_t my, int t, int r)
228570af302Sopenharmony_ci{
229570af302Sopenharmony_ci	MPFR_DECL_INIT(mr, 64);
230570af302Sopenharmony_ci	int i;
231570af302Sopenharmony_ci
232570af302Sopenharmony_ci	t = adjust(mr, my, t, r, LDBL);
233570af302Sopenharmony_ci	p->y = mpfr_get_ld(mr, r);
234570af302Sopenharmony_ci	p->e = eflags(isnan(p->x) || isnan(p->x2) || isnan(p->x3));
235570af302Sopenharmony_ci	i = eulpl(p->y);
236570af302Sopenharmony_ci	if (!isfinite(p->y)) {
237570af302Sopenharmony_ci		p->dy = 0;
238570af302Sopenharmony_ci	} else {
239570af302Sopenharmony_ci		mpfr_sub(my, mr, my, MPFR_RNDN);
240570af302Sopenharmony_ci		mpfr_div_2si(my, my, i, MPFR_RNDN);
241570af302Sopenharmony_ci		p->dy = mpfr_get_flt(my, MPFR_RNDN);
242570af302Sopenharmony_ci		// happens in RU,RD,RZ modes when y is finite but outside the domain
243570af302Sopenharmony_ci		if (p->dy > 1)
244570af302Sopenharmony_ci			p->dy = 1;
245570af302Sopenharmony_ci		if (p->dy < -1)
246570af302Sopenharmony_ci			p->dy = -1;
247570af302Sopenharmony_ci	}
248570af302Sopenharmony_ci}
249570af302Sopenharmony_ci#endif
250570af302Sopenharmony_ci
251570af302Sopenharmony_cistatic int mpl1(struct t *p, int (*fmp)(mpfr_t, const mpfr_t, mpfr_rnd_t))
252570af302Sopenharmony_ci{
253570af302Sopenharmony_ci#if LDBL_MANT_DIG == 53
254570af302Sopenharmony_ci	return mpd1(p, fmp);
255570af302Sopenharmony_ci#elif LDBL_MANT_DIG == 64
256570af302Sopenharmony_ci	int tn;
257570af302Sopenharmony_ci	int r = rmap(p->r);
258570af302Sopenharmony_ci	MPFR_DECL_INIT(mx, 64);
259570af302Sopenharmony_ci	MPFR_DECL_INIT(my, 128);
260570af302Sopenharmony_ci
261570af302Sopenharmony_ci	mpfr_clear_flags();
262570af302Sopenharmony_ci	mpfr_set_ld(mx, p->x, MPFR_RNDN);
263570af302Sopenharmony_ci	tn = fmp(my, mx, r);
264570af302Sopenharmony_ci	p->x2 = 0;
265570af302Sopenharmony_ci	genl(p, my, tn, r);
266570af302Sopenharmony_ci	return 0;
267570af302Sopenharmony_ci#else
268570af302Sopenharmony_ci	return -1;
269570af302Sopenharmony_ci#endif
270570af302Sopenharmony_ci}
271570af302Sopenharmony_ci
272570af302Sopenharmony_cistatic int mpl2(struct t *p, int (*fmp)(mpfr_t, const mpfr_t, const mpfr_t, mpfr_rnd_t))
273570af302Sopenharmony_ci{
274570af302Sopenharmony_ci#if LDBL_MANT_DIG == 53
275570af302Sopenharmony_ci	return mpd2(p, fmp);
276570af302Sopenharmony_ci#elif LDBL_MANT_DIG == 64
277570af302Sopenharmony_ci	int tn;
278570af302Sopenharmony_ci	int r = rmap(p->r);
279570af302Sopenharmony_ci	MPFR_DECL_INIT(mx, 64);
280570af302Sopenharmony_ci	MPFR_DECL_INIT(mx2, 64);
281570af302Sopenharmony_ci	MPFR_DECL_INIT(my, 128);
282570af302Sopenharmony_ci
283570af302Sopenharmony_ci	mpfr_clear_flags();
284570af302Sopenharmony_ci	mpfr_set_ld(mx, p->x, MPFR_RNDN);
285570af302Sopenharmony_ci	mpfr_set_ld(mx2, p->x2, MPFR_RNDN);
286570af302Sopenharmony_ci	tn = fmp(my, mx, mx2, r);
287570af302Sopenharmony_ci	genl(p, my, tn, r);
288570af302Sopenharmony_ci	return 0;
289570af302Sopenharmony_ci#else
290570af302Sopenharmony_ci	return -1;
291570af302Sopenharmony_ci#endif
292570af302Sopenharmony_ci}
293570af302Sopenharmony_ci
294570af302Sopenharmony_ci// TODO
295570af302Sopenharmony_cistatic int mplgamma_sign;
296570af302Sopenharmony_cistatic int wrap_lgamma(mpfr_t my, const mpfr_t mx, mpfr_rnd_t r)
297570af302Sopenharmony_ci{
298570af302Sopenharmony_ci	return mpfr_lgamma(my, &mplgamma_sign, mx, r);
299570af302Sopenharmony_ci}
300570af302Sopenharmony_cistatic long mpremquo_q;
301570af302Sopenharmony_cistatic int wrap_remquo(mpfr_t my, const mpfr_t mx, const mpfr_t mx2, mpfr_rnd_t r)
302570af302Sopenharmony_ci{
303570af302Sopenharmony_ci	return mpfr_remquo(my, &mpremquo_q, mx, mx2, r);
304570af302Sopenharmony_ci}
305570af302Sopenharmony_cistatic int mpbessel_n;
306570af302Sopenharmony_cistatic int wrap_jn(mpfr_t my, const mpfr_t mx, mpfr_rnd_t r)
307570af302Sopenharmony_ci{
308570af302Sopenharmony_ci	return mpfr_jn(my, mpbessel_n, mx, r);
309570af302Sopenharmony_ci}
310570af302Sopenharmony_cistatic int wrap_yn(mpfr_t my, const mpfr_t mx, mpfr_rnd_t r)
311570af302Sopenharmony_ci{
312570af302Sopenharmony_ci	return mpfr_yn(my, mpbessel_n, mx, r);
313570af302Sopenharmony_ci}
314570af302Sopenharmony_cistatic int wrap_ceil(mpfr_t my, const mpfr_t mx, mpfr_rnd_t r)
315570af302Sopenharmony_ci{
316570af302Sopenharmony_ci	return mpfr_ceil(my, mx);
317570af302Sopenharmony_ci}
318570af302Sopenharmony_cistatic int wrap_floor(mpfr_t my, const mpfr_t mx, mpfr_rnd_t r)
319570af302Sopenharmony_ci{
320570af302Sopenharmony_ci	return mpfr_floor(my, mx);
321570af302Sopenharmony_ci}
322570af302Sopenharmony_cistatic int wrap_round(mpfr_t my, const mpfr_t mx, mpfr_rnd_t r)
323570af302Sopenharmony_ci{
324570af302Sopenharmony_ci	return mpfr_round(my, mx);
325570af302Sopenharmony_ci}
326570af302Sopenharmony_cistatic int wrap_trunc(mpfr_t my, const mpfr_t mx, mpfr_rnd_t r)
327570af302Sopenharmony_ci{
328570af302Sopenharmony_ci	return mpfr_trunc(my, mx);
329570af302Sopenharmony_ci}
330570af302Sopenharmony_cistatic int wrap_nearbyint(mpfr_t my, const mpfr_t mx, mpfr_rnd_t r)
331570af302Sopenharmony_ci{
332570af302Sopenharmony_ci	int i = mpfr_rint(my, mx, r);
333570af302Sopenharmony_ci	mpfr_clear_inexflag();
334570af302Sopenharmony_ci	return i;
335570af302Sopenharmony_ci}
336570af302Sopenharmony_cistatic int wrap_pow10(mpfr_t my, const mpfr_t mx, mpfr_rnd_t r)
337570af302Sopenharmony_ci{
338570af302Sopenharmony_ci	return mpfr_ui_pow(my, 10, mx, r);
339570af302Sopenharmony_ci}
340570af302Sopenharmony_ci
341570af302Sopenharmony_ci
342570af302Sopenharmony_cistatic int wrap_sinpi(mpfr_t my, const mpfr_t mx, mpfr_rnd_t r)
343570af302Sopenharmony_ci{
344570af302Sopenharmony_ci	// hack because mpfr has no sinpi
345570af302Sopenharmony_ci	MPFR_DECL_INIT(mz, 4096);
346570af302Sopenharmony_ci	mpfr_const_pi(mz, r);
347570af302Sopenharmony_ci	mpfr_mul(mz,mz,mx,r);
348570af302Sopenharmony_ci	return mpfr_sin(my, mz, r);
349570af302Sopenharmony_ci}
350570af302Sopenharmony_ciint mpsinpi(struct t *t) { return mpd1(t, wrap_sinpi); }
351570af302Sopenharmony_ci
352570af302Sopenharmony_ciint mpadd(struct t *t) { return mpd2(t, mpfr_add); }
353570af302Sopenharmony_ciint mpaddf(struct t *t) { return mpf2(t, mpfr_add); }
354570af302Sopenharmony_ciint mpaddl(struct t *t) { return mpl2(t, mpfr_add); }
355570af302Sopenharmony_ciint mpmul(struct t *t) { return mpd2(t, mpfr_mul); }
356570af302Sopenharmony_ciint mpmulf(struct t *t) { return mpf2(t, mpfr_mul); }
357570af302Sopenharmony_ciint mpmull(struct t *t) { return mpl2(t, mpfr_mul); }
358570af302Sopenharmony_ciint mpdiv(struct t *t) { return mpd2(t, mpfr_div); }
359570af302Sopenharmony_ciint mpdivf(struct t *t) { return mpf2(t, mpfr_div); }
360570af302Sopenharmony_ciint mpdivl(struct t *t) { return mpl2(t, mpfr_div); }
361570af302Sopenharmony_ci
362570af302Sopenharmony_ciint mpacos(struct t *t) { return mpd1(t, mpfr_acos); }
363570af302Sopenharmony_ciint mpacosf(struct t *t) { return mpf1(t, mpfr_acos); }
364570af302Sopenharmony_ciint mpacosl(struct t *t) { return mpl1(t, mpfr_acos); }
365570af302Sopenharmony_ciint mpacosh(struct t *t) { return mpd1(t, mpfr_acosh); }
366570af302Sopenharmony_ciint mpacoshf(struct t *t) { return mpf1(t, mpfr_acosh); }
367570af302Sopenharmony_ciint mpacoshl(struct t *t) { return mpl1(t, mpfr_acosh); }
368570af302Sopenharmony_ciint mpasin(struct t *t) { return mpd1(t, mpfr_asin); }
369570af302Sopenharmony_ciint mpasinf(struct t *t) { return mpf1(t, mpfr_asin); }
370570af302Sopenharmony_ciint mpasinl(struct t *t) { return mpl1(t, mpfr_asin); }
371570af302Sopenharmony_ciint mpasinh(struct t *t) { return mpd1(t, mpfr_asinh); }
372570af302Sopenharmony_ciint mpasinhf(struct t *t) { return mpf1(t, mpfr_asinh); }
373570af302Sopenharmony_ciint mpasinhl(struct t *t) { return mpl1(t, mpfr_asinh); }
374570af302Sopenharmony_ciint mpatan(struct t *t) { return mpd1(t, mpfr_atan); }
375570af302Sopenharmony_ciint mpatanf(struct t *t) { return mpf1(t, mpfr_atan); }
376570af302Sopenharmony_ciint mpatanl(struct t *t) { return mpl1(t, mpfr_atan); }
377570af302Sopenharmony_ciint mpatan2(struct t *t) { return mpd2(t, mpfr_atan2); }
378570af302Sopenharmony_ciint mpatan2f(struct t *t) { return mpf2(t, mpfr_atan2); }
379570af302Sopenharmony_ciint mpatan2l(struct t *t) { return mpl2(t, mpfr_atan2); }
380570af302Sopenharmony_ciint mpatanh(struct t *t) { return mpd1(t, mpfr_atanh); }
381570af302Sopenharmony_ciint mpatanhf(struct t *t) { return mpf1(t, mpfr_atanh); }
382570af302Sopenharmony_ciint mpatanhl(struct t *t) { return mpl1(t, mpfr_atanh); }
383570af302Sopenharmony_ciint mpcbrt(struct t *t) { return mpd1(t, mpfr_cbrt); }
384570af302Sopenharmony_ciint mpcbrtf(struct t *t) { return mpf1(t, mpfr_cbrt); }
385570af302Sopenharmony_ciint mpcbrtl(struct t *t) { return mpl1(t, mpfr_cbrt); }
386570af302Sopenharmony_ciint mpceil(struct t *t) { return mpd1(t, wrap_ceil); }
387570af302Sopenharmony_ciint mpceilf(struct t *t) { return mpf1(t, wrap_ceil); }
388570af302Sopenharmony_ciint mpceill(struct t *t) { return mpl1(t, wrap_ceil); }
389570af302Sopenharmony_ciint mpcopysign(struct t *t) { return mpd2(t, mpfr_copysign); }
390570af302Sopenharmony_ciint mpcopysignf(struct t *t) { return mpf2(t, mpfr_copysign); }
391570af302Sopenharmony_ciint mpcopysignl(struct t *t) { return mpl2(t, mpfr_copysign); }
392570af302Sopenharmony_ciint mpcos(struct t *t) { return mpd1(t, mpfr_cos); }
393570af302Sopenharmony_ciint mpcosf(struct t *t) { return mpf1(t, mpfr_cos); }
394570af302Sopenharmony_ciint mpcosl(struct t *t) { return mpl1(t, mpfr_cos); }
395570af302Sopenharmony_ciint mpcosh(struct t *t) { return mpd1(t, mpfr_cosh); }
396570af302Sopenharmony_ciint mpcoshf(struct t *t) { return mpf1(t, mpfr_cosh); }
397570af302Sopenharmony_ciint mpcoshl(struct t *t) { return mpl1(t, mpfr_cosh); }
398570af302Sopenharmony_ciint mperf(struct t *t) { return mpd1(t, mpfr_erf); }
399570af302Sopenharmony_ciint mperff(struct t *t) { return mpf1(t, mpfr_erf); }
400570af302Sopenharmony_ciint mperfl(struct t *t) { return mpl1(t, mpfr_erf); }
401570af302Sopenharmony_ciint mperfc(struct t *t) { return mpd1(t, mpfr_erfc); }
402570af302Sopenharmony_ciint mperfcf(struct t *t) { return mpf1(t, mpfr_erfc); }
403570af302Sopenharmony_ciint mperfcl(struct t *t) { return mpl1(t, mpfr_erfc); }
404570af302Sopenharmony_ciint mpexp(struct t *t) { return mpd1(t, mpfr_exp); }
405570af302Sopenharmony_ciint mpexpf(struct t *t) { return mpf1(t, mpfr_exp); }
406570af302Sopenharmony_ciint mpexpl(struct t *t) { return mpl1(t, mpfr_exp); }
407570af302Sopenharmony_ciint mpexp2(struct t *t) { return mpd1(t, mpfr_exp2); }
408570af302Sopenharmony_ciint mpexp2f(struct t *t) { return mpf1(t, mpfr_exp2); }
409570af302Sopenharmony_ciint mpexp2l(struct t *t) { return mpl1(t, mpfr_exp2); }
410570af302Sopenharmony_ciint mpexpm1(struct t *t) { return mpd1(t, mpfr_expm1); }
411570af302Sopenharmony_ciint mpexpm1f(struct t *t) { return mpf1(t, mpfr_expm1); }
412570af302Sopenharmony_ciint mpexpm1l(struct t *t) { return mpl1(t, mpfr_expm1); }
413570af302Sopenharmony_ciint mpfabs(struct t *t) { return mpd1(t, mpfr_abs); }
414570af302Sopenharmony_ciint mpfabsf(struct t *t) { return mpf1(t, mpfr_abs); }
415570af302Sopenharmony_ciint mpfabsl(struct t *t) { return mpl1(t, mpfr_abs); }
416570af302Sopenharmony_ciint mpfdim(struct t *t) { return mpd2(t, mpfr_dim); }
417570af302Sopenharmony_ciint mpfdimf(struct t *t) { return mpf2(t, mpfr_dim); }
418570af302Sopenharmony_ciint mpfdiml(struct t *t) { return mpl2(t, mpfr_dim); }
419570af302Sopenharmony_ciint mpfloor(struct t *t) { return mpd1(t, wrap_floor); }
420570af302Sopenharmony_ciint mpfloorf(struct t *t) { return mpf1(t, wrap_floor); }
421570af302Sopenharmony_ciint mpfloorl(struct t *t) { return mpl1(t, wrap_floor); }
422570af302Sopenharmony_ciint mpfmax(struct t *t) { return mpd2(t, mpfr_max); }
423570af302Sopenharmony_ciint mpfmaxf(struct t *t) { return mpf2(t, mpfr_max); }
424570af302Sopenharmony_ciint mpfmaxl(struct t *t) { return mpl2(t, mpfr_max); }
425570af302Sopenharmony_ciint mpfmin(struct t *t) { return mpd2(t, mpfr_min); }
426570af302Sopenharmony_ciint mpfminf(struct t *t) { return mpf2(t, mpfr_min); }
427570af302Sopenharmony_ciint mpfminl(struct t *t) { return mpl2(t, mpfr_min); }
428570af302Sopenharmony_ciint mpfmod(struct t *t) { return mpd2(t, mpfr_fmod); }
429570af302Sopenharmony_ciint mpfmodf(struct t *t) { return mpf2(t, mpfr_fmod); }
430570af302Sopenharmony_ciint mpfmodl(struct t *t) { return mpl2(t, mpfr_fmod); }
431570af302Sopenharmony_ciint mphypot(struct t *t) { return mpd2(t, mpfr_hypot); }
432570af302Sopenharmony_ciint mphypotf(struct t *t) { return mpf2(t, mpfr_hypot); }
433570af302Sopenharmony_ciint mphypotl(struct t *t) { return mpl2(t, mpfr_hypot); }
434570af302Sopenharmony_ciint mplgamma(struct t *t) { return mpd1(t, wrap_lgamma) || (t->i = mplgamma_sign, 0); }
435570af302Sopenharmony_ciint mplgammaf(struct t *t) { return mpf1(t, wrap_lgamma) || (t->i = mplgamma_sign, 0); }
436570af302Sopenharmony_ciint mplgammal(struct t *t) { return mpl1(t, wrap_lgamma) || (t->i = mplgamma_sign, 0); }
437570af302Sopenharmony_ciint mplog(struct t *t) { return mpd1(t, mpfr_log); }
438570af302Sopenharmony_ciint mplogf(struct t *t) { return mpf1(t, mpfr_log); }
439570af302Sopenharmony_ciint mplogl(struct t *t) { return mpl1(t, mpfr_log); }
440570af302Sopenharmony_ciint mplog10(struct t *t) { return mpd1(t, mpfr_log10); }
441570af302Sopenharmony_ciint mplog10f(struct t *t) { return mpf1(t, mpfr_log10); }
442570af302Sopenharmony_ciint mplog10l(struct t *t) { return mpl1(t, mpfr_log10); }
443570af302Sopenharmony_ciint mplog1p(struct t *t) { return mpd1(t, mpfr_log1p); }
444570af302Sopenharmony_ciint mplog1pf(struct t *t) { return mpf1(t, mpfr_log1p); }
445570af302Sopenharmony_ciint mplog1pl(struct t *t) { return mpl1(t, mpfr_log1p); }
446570af302Sopenharmony_ciint mplog2(struct t *t) { return mpd1(t, mpfr_log2); }
447570af302Sopenharmony_ciint mplog2f(struct t *t) { return mpf1(t, mpfr_log2); }
448570af302Sopenharmony_ciint mplog2l(struct t *t) { return mpl1(t, mpfr_log2); }
449570af302Sopenharmony_ciint mplogb(struct t *t)
450570af302Sopenharmony_ci{
451570af302Sopenharmony_ci	MPFR_DECL_INIT(mx, 53);
452570af302Sopenharmony_ci
453570af302Sopenharmony_ci	t->dy = 0;
454570af302Sopenharmony_ci	t->e = 0;
455570af302Sopenharmony_ci	if (t->x == 0) {
456570af302Sopenharmony_ci		t->y = -INFINITY;
457570af302Sopenharmony_ci		t->e |= DIVBYZERO;
458570af302Sopenharmony_ci		return 0;
459570af302Sopenharmony_ci	}
460570af302Sopenharmony_ci	if (isinf(t->x)) {
461570af302Sopenharmony_ci		t->y = INFINITY;
462570af302Sopenharmony_ci		return 0;
463570af302Sopenharmony_ci	}
464570af302Sopenharmony_ci	if (isnan(t->x)) {
465570af302Sopenharmony_ci		t->y = t->x;
466570af302Sopenharmony_ci		return 0;
467570af302Sopenharmony_ci	}
468570af302Sopenharmony_ci	mpfr_set_d(mx, t->x, MPFR_RNDN);
469570af302Sopenharmony_ci	t->y = mpfr_get_exp(mx) - 1;
470570af302Sopenharmony_ci	return 0;
471570af302Sopenharmony_ci}
472570af302Sopenharmony_ciint mplogbf(struct t *t)
473570af302Sopenharmony_ci{
474570af302Sopenharmony_ci	MPFR_DECL_INIT(mx, 24);
475570af302Sopenharmony_ci
476570af302Sopenharmony_ci	t->dy = 0;
477570af302Sopenharmony_ci	t->e = 0;
478570af302Sopenharmony_ci	if (t->x == 0) {
479570af302Sopenharmony_ci		t->y = -INFINITY;
480570af302Sopenharmony_ci		t->e |= DIVBYZERO;
481570af302Sopenharmony_ci		return 0;
482570af302Sopenharmony_ci	}
483570af302Sopenharmony_ci	if (isinf(t->x)) {
484570af302Sopenharmony_ci		t->y = INFINITY;
485570af302Sopenharmony_ci		return 0;
486570af302Sopenharmony_ci	}
487570af302Sopenharmony_ci	if (isnan(t->x)) {
488570af302Sopenharmony_ci		t->y = t->x;
489570af302Sopenharmony_ci		return 0;
490570af302Sopenharmony_ci	}
491570af302Sopenharmony_ci	mpfr_set_flt(mx, t->x, MPFR_RNDN);
492570af302Sopenharmony_ci	t->y = mpfr_get_exp(mx) - 1;
493570af302Sopenharmony_ci	return 0;
494570af302Sopenharmony_ci}
495570af302Sopenharmony_ciint mplogbl(struct t *t)
496570af302Sopenharmony_ci{
497570af302Sopenharmony_ci	MPFR_DECL_INIT(mx, 64);
498570af302Sopenharmony_ci
499570af302Sopenharmony_ci	t->dy = 0;
500570af302Sopenharmony_ci	t->e = 0;
501570af302Sopenharmony_ci	if (t->x == 0) {
502570af302Sopenharmony_ci		t->y = -INFINITY;
503570af302Sopenharmony_ci		t->e |= DIVBYZERO;
504570af302Sopenharmony_ci		return 0;
505570af302Sopenharmony_ci	}
506570af302Sopenharmony_ci	if (isinf(t->x)) {
507570af302Sopenharmony_ci		t->y = INFINITY;
508570af302Sopenharmony_ci		return 0;
509570af302Sopenharmony_ci	}
510570af302Sopenharmony_ci	if (isnan(t->x)) {
511570af302Sopenharmony_ci		t->y = t->x;
512570af302Sopenharmony_ci		return 0;
513570af302Sopenharmony_ci	}
514570af302Sopenharmony_ci	mpfr_set_ld(mx, t->x, MPFR_RNDN);
515570af302Sopenharmony_ci	t->y = mpfr_get_exp(mx) - 1;
516570af302Sopenharmony_ci	return 0;
517570af302Sopenharmony_ci}
518570af302Sopenharmony_ciint mpnearbyint(struct t *t) { return mpd1(t, wrap_nearbyint) || (t->e&=~INEXACT, 0); }
519570af302Sopenharmony_ciint mpnearbyintf(struct t *t) { return mpf1(t, wrap_nearbyint) || (t->e&=~INEXACT, 0); }
520570af302Sopenharmony_ciint mpnearbyintl(struct t *t) { return mpl1(t, wrap_nearbyint) || (t->e&=~INEXACT, 0); }
521570af302Sopenharmony_ci// TODO: hard to implement with mpfr
522570af302Sopenharmony_ciint mpnextafter(struct t *t)
523570af302Sopenharmony_ci{
524570af302Sopenharmony_ci	feclearexcept(FE_ALL_EXCEPT);
525570af302Sopenharmony_ci	t->y = nextafter(t->x, t->x2);
526570af302Sopenharmony_ci	t->e = getexcept();
527570af302Sopenharmony_ci	t->dy = 0;
528570af302Sopenharmony_ci	return 0;
529570af302Sopenharmony_ci}
530570af302Sopenharmony_ciint mpnextafterf(struct t *t)
531570af302Sopenharmony_ci{
532570af302Sopenharmony_ci	feclearexcept(FE_ALL_EXCEPT);
533570af302Sopenharmony_ci	t->y = nextafterf(t->x, t->x2);
534570af302Sopenharmony_ci	t->e = getexcept();
535570af302Sopenharmony_ci	t->dy = 0;
536570af302Sopenharmony_ci	return 0;
537570af302Sopenharmony_ci}
538570af302Sopenharmony_ciint mpnextafterl(struct t *t)
539570af302Sopenharmony_ci{
540570af302Sopenharmony_ci	feclearexcept(FE_ALL_EXCEPT);
541570af302Sopenharmony_ci	t->y = nextafterl(t->x, t->x2);
542570af302Sopenharmony_ci	t->e = getexcept();
543570af302Sopenharmony_ci	t->dy = 0;
544570af302Sopenharmony_ci	return 0;
545570af302Sopenharmony_ci}
546570af302Sopenharmony_ciint mpnexttoward(struct t *t)
547570af302Sopenharmony_ci{
548570af302Sopenharmony_ci	feclearexcept(FE_ALL_EXCEPT);
549570af302Sopenharmony_ci	t->y = nexttoward(t->x, t->x2);
550570af302Sopenharmony_ci	t->e = getexcept();
551570af302Sopenharmony_ci	t->dy = 0;
552570af302Sopenharmony_ci	return 0;
553570af302Sopenharmony_ci}
554570af302Sopenharmony_ciint mpnexttowardf(struct t *t)
555570af302Sopenharmony_ci{
556570af302Sopenharmony_ci	feclearexcept(FE_ALL_EXCEPT);
557570af302Sopenharmony_ci	t->y = nexttowardf(t->x, t->x2);
558570af302Sopenharmony_ci	t->e = getexcept();
559570af302Sopenharmony_ci	t->dy = 0;
560570af302Sopenharmony_ci	return 0;
561570af302Sopenharmony_ci}
562570af302Sopenharmony_ciint mpnexttowardl(struct t *t) { return mpnextafterl(t); }
563570af302Sopenharmony_ciint mppow(struct t *t) { return mpd2(t, mpfr_pow); }
564570af302Sopenharmony_ciint mppowf(struct t *t) { return mpf2(t, mpfr_pow); }
565570af302Sopenharmony_ciint mppowl(struct t *t) { return mpl2(t, mpfr_pow); }
566570af302Sopenharmony_ciint mpremainder(struct t *t) { return mpd2(t, mpfr_remainder); }
567570af302Sopenharmony_ciint mpremainderf(struct t *t) { return mpf2(t, mpfr_remainder); }
568570af302Sopenharmony_ciint mpremainderl(struct t *t) { return mpl2(t, mpfr_remainder); }
569570af302Sopenharmony_ciint mprint(struct t *t) { return mpd1(t, mpfr_rint); }
570570af302Sopenharmony_ciint mprintf(struct t *t) { return mpf1(t, mpfr_rint); }
571570af302Sopenharmony_ciint mprintl(struct t *t) { return mpl1(t, mpfr_rint); }
572570af302Sopenharmony_ciint mpround(struct t *t) { return mpd1(t, wrap_round); }
573570af302Sopenharmony_ciint mproundf(struct t *t) { return mpf1(t, wrap_round); }
574570af302Sopenharmony_ciint mproundl(struct t *t) { return mpl1(t, wrap_round); }
575570af302Sopenharmony_ciint mpsin(struct t *t) { return mpd1(t, mpfr_sin); }
576570af302Sopenharmony_ciint mpsinf(struct t *t) { return mpf1(t, mpfr_sin); }
577570af302Sopenharmony_ciint mpsinl(struct t *t) { return mpl1(t, mpfr_sin); }
578570af302Sopenharmony_ciint mpsinh(struct t *t) { return mpd1(t, mpfr_sinh); }
579570af302Sopenharmony_ciint mpsinhf(struct t *t) { return mpf1(t, mpfr_sinh); }
580570af302Sopenharmony_ciint mpsinhl(struct t *t) { return mpl1(t, mpfr_sinh); }
581570af302Sopenharmony_ciint mpsqrt(struct t *t) { return mpd1(t, mpfr_sqrt); }
582570af302Sopenharmony_ciint mpsqrtf(struct t *t) { return mpf1(t, mpfr_sqrt); }
583570af302Sopenharmony_ciint mpsqrtl(struct t *t) { return mpl1(t, mpfr_sqrt); }
584570af302Sopenharmony_ciint mptan(struct t *t) { return mpd1(t, mpfr_tan); }
585570af302Sopenharmony_ciint mptanf(struct t *t) { return mpf1(t, mpfr_tan); }
586570af302Sopenharmony_ciint mptanl(struct t *t) { return mpl1(t, mpfr_tan); }
587570af302Sopenharmony_ciint mptanh(struct t *t) { return mpd1(t, mpfr_tanh); }
588570af302Sopenharmony_ciint mptanhf(struct t *t) { return mpf1(t, mpfr_tanh); }
589570af302Sopenharmony_ciint mptanhl(struct t *t) { return mpl1(t, mpfr_tanh); }
590570af302Sopenharmony_ci// TODO: tgamma(2) raises wrong flags
591570af302Sopenharmony_ciint mptgamma(struct t *t) { return mpd1(t, mpfr_gamma); }
592570af302Sopenharmony_ciint mptgammaf(struct t *t) { return mpf1(t, mpfr_gamma); }
593570af302Sopenharmony_ciint mptgammal(struct t *t) { return mpl1(t, mpfr_gamma); }
594570af302Sopenharmony_ciint mptrunc(struct t *t) { return mpd1(t, wrap_trunc); }
595570af302Sopenharmony_ciint mptruncf(struct t *t) { return mpf1(t, wrap_trunc); }
596570af302Sopenharmony_ciint mptruncl(struct t *t) { return mpl1(t, wrap_trunc); }
597570af302Sopenharmony_ciint mpj0(struct t *t) { return mpd1(t, mpfr_j0); }
598570af302Sopenharmony_ciint mpj1(struct t *t) { return mpd1(t, mpfr_j1); }
599570af302Sopenharmony_ciint mpy0(struct t *t) { return mpd1(t, mpfr_y0); }
600570af302Sopenharmony_ciint mpy1(struct t *t) { return mpd1(t, mpfr_y1); }
601570af302Sopenharmony_ci// TODO: non standard functions
602570af302Sopenharmony_ciint mpscalb(struct t *t)
603570af302Sopenharmony_ci{
604570af302Sopenharmony_ci	setupfenv(t->r);
605570af302Sopenharmony_ci	t->y = scalb(t->x, t->x2);
606570af302Sopenharmony_ci	t->e = getexcept();
607570af302Sopenharmony_ci	t->dy = 0; // wrong
608570af302Sopenharmony_ci	return 0;
609570af302Sopenharmony_ci}
610570af302Sopenharmony_ciint mpscalbf(struct t *t)
611570af302Sopenharmony_ci{
612570af302Sopenharmony_ci	setupfenv(t->r);
613570af302Sopenharmony_ci	t->y = scalbf(t->x, t->x2);
614570af302Sopenharmony_ci	t->e = getexcept();
615570af302Sopenharmony_ci	t->dy = 0; // wrong
616570af302Sopenharmony_ci	return 0;
617570af302Sopenharmony_ci}
618570af302Sopenharmony_ciint mpj0f(struct t *t) { return mpf1(t, mpfr_j0); }
619570af302Sopenharmony_ciint mpj0l(struct t *t) { return mpl1(t, mpfr_j0); }
620570af302Sopenharmony_ciint mpj1f(struct t *t) { return mpf1(t, mpfr_j1); }
621570af302Sopenharmony_ciint mpj1l(struct t *t) { return mpl1(t, mpfr_j1); }
622570af302Sopenharmony_ciint mpy0f(struct t *t) { return mpf1(t, mpfr_y0); }
623570af302Sopenharmony_ciint mpy0l(struct t *t) { return mpl1(t, mpfr_y0); }
624570af302Sopenharmony_ciint mpy1f(struct t *t) { return mpf1(t, mpfr_y1); }
625570af302Sopenharmony_ciint mpy1l(struct t *t) { return mpl1(t, mpfr_y1); }
626570af302Sopenharmony_ciint mpexp10(struct t *t) { return mpd1(t, wrap_pow10); }
627570af302Sopenharmony_ciint mpexp10f(struct t *t) { return mpf1(t, wrap_pow10); }
628570af302Sopenharmony_ciint mpexp10l(struct t *t) { return mpl1(t, wrap_pow10); }
629570af302Sopenharmony_ciint mppow10(struct t *t) { return mpd1(t, wrap_pow10); }
630570af302Sopenharmony_ciint mppow10f(struct t *t) { return mpf1(t, wrap_pow10); }
631570af302Sopenharmony_ciint mppow10l(struct t *t) { return mpl1(t, wrap_pow10); }
632570af302Sopenharmony_ci
633570af302Sopenharmony_ciint mpfrexp(struct t *t)
634570af302Sopenharmony_ci{
635570af302Sopenharmony_ci	mpfr_exp_t e;
636570af302Sopenharmony_ci	int k;
637570af302Sopenharmony_ci	MPFR_DECL_INIT(mx, 53);
638570af302Sopenharmony_ci
639570af302Sopenharmony_ci	t->dy = 0;
640570af302Sopenharmony_ci	t->y = 0;
641570af302Sopenharmony_ci	mpfr_clear_flags();
642570af302Sopenharmony_ci	mpfr_set_d(mx, t->x, MPFR_RNDN);
643570af302Sopenharmony_ci	k = mpfr_frexp(&e, mx, mx, t->r);
644570af302Sopenharmony_ci	t->y = mpfr_get_d(mx, MPFR_RNDN);
645570af302Sopenharmony_ci	t->i = e;
646570af302Sopenharmony_ci	t->e = eflags(isnan(t->x));
647570af302Sopenharmony_ci	return 0;
648570af302Sopenharmony_ci}
649570af302Sopenharmony_ci
650570af302Sopenharmony_ciint mpfrexpf(struct t *t)
651570af302Sopenharmony_ci{
652570af302Sopenharmony_ci	mpfr_exp_t e;
653570af302Sopenharmony_ci	int k;
654570af302Sopenharmony_ci	MPFR_DECL_INIT(mx, 24);
655570af302Sopenharmony_ci
656570af302Sopenharmony_ci	t->dy = 0;
657570af302Sopenharmony_ci	t->y = 0;
658570af302Sopenharmony_ci	mpfr_clear_flags();
659570af302Sopenharmony_ci	mpfr_set_flt(mx, t->x, MPFR_RNDN);
660570af302Sopenharmony_ci	k = mpfr_frexp(&e, mx, mx, t->r);
661570af302Sopenharmony_ci	t->y = mpfr_get_flt(mx, MPFR_RNDN);
662570af302Sopenharmony_ci	t->i = e;
663570af302Sopenharmony_ci	t->e = eflags(isnan(t->x));
664570af302Sopenharmony_ci	return 0;
665570af302Sopenharmony_ci}
666570af302Sopenharmony_ci
667570af302Sopenharmony_ciint mpfrexpl(struct t *t)
668570af302Sopenharmony_ci{
669570af302Sopenharmony_ci	mpfr_exp_t e;
670570af302Sopenharmony_ci	int k;
671570af302Sopenharmony_ci	MPFR_DECL_INIT(mx, 64);
672570af302Sopenharmony_ci
673570af302Sopenharmony_ci	t->dy = 0;
674570af302Sopenharmony_ci	t->y = 0;
675570af302Sopenharmony_ci	mpfr_clear_flags();
676570af302Sopenharmony_ci	mpfr_set_ld(mx, t->x, MPFR_RNDN);
677570af302Sopenharmony_ci	k = mpfr_frexp(&e, mx, mx, t->r);
678570af302Sopenharmony_ci	t->y = mpfr_get_ld(mx, MPFR_RNDN);
679570af302Sopenharmony_ci	t->i = e;
680570af302Sopenharmony_ci	t->e = eflags(isnan(t->x));
681570af302Sopenharmony_ci	return 0;
682570af302Sopenharmony_ci}
683570af302Sopenharmony_ci
684570af302Sopenharmony_ciint mpldexp(struct t *t)
685570af302Sopenharmony_ci{
686570af302Sopenharmony_ci	int k;
687570af302Sopenharmony_ci	MPFR_DECL_INIT(mx, 53);
688570af302Sopenharmony_ci
689570af302Sopenharmony_ci	t->dy = 0;
690570af302Sopenharmony_ci	t->y = 0;
691570af302Sopenharmony_ci	mpfr_clear_flags();
692570af302Sopenharmony_ci	mpfr_set_d(mx, t->x, MPFR_RNDN);
693570af302Sopenharmony_ci	k = mpfr_mul_2si(mx, mx, t->i, t->r);
694570af302Sopenharmony_ci	adjust(mx, mx, k, t->r, DBL);
695570af302Sopenharmony_ci	t->y = mpfr_get_d(mx, MPFR_RNDN);
696570af302Sopenharmony_ci	t->e = eflags(isnan(t->x));
697570af302Sopenharmony_ci	return 0;
698570af302Sopenharmony_ci}
699570af302Sopenharmony_ci
700570af302Sopenharmony_ciint mpldexpf(struct t *t)
701570af302Sopenharmony_ci{
702570af302Sopenharmony_ci	int k;
703570af302Sopenharmony_ci	MPFR_DECL_INIT(mx, 24);
704570af302Sopenharmony_ci
705570af302Sopenharmony_ci	t->dy = 0;
706570af302Sopenharmony_ci	t->y = 0;
707570af302Sopenharmony_ci	mpfr_clear_flags();
708570af302Sopenharmony_ci	mpfr_set_flt(mx, t->x, MPFR_RNDN);
709570af302Sopenharmony_ci	k = mpfr_mul_2si(mx, mx, t->i, t->r);
710570af302Sopenharmony_ci	adjust(mx, mx, k, t->r, FLT);
711570af302Sopenharmony_ci	t->y = mpfr_get_flt(mx, MPFR_RNDN);
712570af302Sopenharmony_ci	t->e = eflags(isnan(t->x));
713570af302Sopenharmony_ci	return 0;
714570af302Sopenharmony_ci}
715570af302Sopenharmony_ci
716570af302Sopenharmony_ciint mpldexpl(struct t *t)
717570af302Sopenharmony_ci{
718570af302Sopenharmony_ci	int k;
719570af302Sopenharmony_ci	MPFR_DECL_INIT(mx, 64);
720570af302Sopenharmony_ci
721570af302Sopenharmony_ci	t->dy = 0;
722570af302Sopenharmony_ci	t->y = 0;
723570af302Sopenharmony_ci	mpfr_clear_flags();
724570af302Sopenharmony_ci	mpfr_set_ld(mx, t->x, MPFR_RNDN);
725570af302Sopenharmony_ci	k = mpfr_mul_2si(mx, mx, t->i, t->r);
726570af302Sopenharmony_ci	adjust(mx, mx, k, t->r, LDBL);
727570af302Sopenharmony_ci	t->y = mpfr_get_ld(mx, MPFR_RNDN);
728570af302Sopenharmony_ci	t->e = eflags(isnan(t->x));
729570af302Sopenharmony_ci	return 0;
730570af302Sopenharmony_ci}
731570af302Sopenharmony_ci
732570af302Sopenharmony_ciint mpscalbn(struct t *t) { return mpldexp(t); }
733570af302Sopenharmony_ciint mpscalbnf(struct t *t) { return mpldexpf(t); }
734570af302Sopenharmony_ciint mpscalbnl(struct t *t) { return mpldexpl(t); }
735570af302Sopenharmony_ciint mpscalbln(struct t *t) { return mpldexp(t); }
736570af302Sopenharmony_ciint mpscalblnf(struct t *t) { return mpldexpf(t); }
737570af302Sopenharmony_ciint mpscalblnl(struct t *t) { return mpldexpl(t); }
738570af302Sopenharmony_ci
739570af302Sopenharmony_ciint mplgamma_r(struct t *t) { return mplgamma(t); }
740570af302Sopenharmony_ciint mplgammaf_r(struct t *t) { return mplgammaf(t); }
741570af302Sopenharmony_ciint mplgammal_r(struct t *t) { return mplgammal(t); }
742570af302Sopenharmony_ci
743570af302Sopenharmony_ciint mpilogb(struct t *t)
744570af302Sopenharmony_ci{
745570af302Sopenharmony_ci	MPFR_DECL_INIT(mx, 53);
746570af302Sopenharmony_ci
747570af302Sopenharmony_ci	mpfr_set_d(mx, t->x, MPFR_RNDN);
748570af302Sopenharmony_ci	t->i = mpfr_get_exp(mx) - 1;
749570af302Sopenharmony_ci	t->e = 0;
750570af302Sopenharmony_ci	if (isinf(t->x) || isnan(t->x) || t->x == 0)
751570af302Sopenharmony_ci		t->e = INVALID;
752570af302Sopenharmony_ci	return 0;
753570af302Sopenharmony_ci}
754570af302Sopenharmony_ciint mpilogbf(struct t *t)
755570af302Sopenharmony_ci{
756570af302Sopenharmony_ci	MPFR_DECL_INIT(mx, 24);
757570af302Sopenharmony_ci
758570af302Sopenharmony_ci	mpfr_set_flt(mx, t->x, MPFR_RNDN);
759570af302Sopenharmony_ci	t->i = mpfr_get_exp(mx) - 1;
760570af302Sopenharmony_ci	t->e = 0;
761570af302Sopenharmony_ci	if (isinf(t->x) || isnan(t->x) || t->x == 0)
762570af302Sopenharmony_ci		t->e = INVALID;
763570af302Sopenharmony_ci	return 0;
764570af302Sopenharmony_ci}
765570af302Sopenharmony_ciint mpilogbl(struct t *t)
766570af302Sopenharmony_ci{
767570af302Sopenharmony_ci	MPFR_DECL_INIT(mx, 64);
768570af302Sopenharmony_ci
769570af302Sopenharmony_ci	mpfr_set_ld(mx, t->x, MPFR_RNDN);
770570af302Sopenharmony_ci	t->i = mpfr_get_exp(mx) - 1;
771570af302Sopenharmony_ci	t->e = 0;
772570af302Sopenharmony_ci	if (isinf(t->x) || isnan(t->x) || t->x == 0)
773570af302Sopenharmony_ci		t->e = INVALID;
774570af302Sopenharmony_ci	return 0;
775570af302Sopenharmony_ci}
776570af302Sopenharmony_ci
777570af302Sopenharmony_ci// TODO: ll* is hard to do with mpfr
778570af302Sopenharmony_ci#define mp_f_i(n) \
779570af302Sopenharmony_ciint mp##n(struct t *t) \
780570af302Sopenharmony_ci{ \
781570af302Sopenharmony_ci	setupfenv(t->r); \
782570af302Sopenharmony_ci	t->i = n(t->x); \
783570af302Sopenharmony_ci	t->e = getexcept(); \
784570af302Sopenharmony_ci	if (t->e & INVALID) \
785570af302Sopenharmony_ci		t->i = 0; \
786570af302Sopenharmony_ci	return 0; \
787570af302Sopenharmony_ci}
788570af302Sopenharmony_ci
789570af302Sopenharmony_cimp_f_i(llrint)
790570af302Sopenharmony_cimp_f_i(llrintf)
791570af302Sopenharmony_cimp_f_i(llrintl)
792570af302Sopenharmony_cimp_f_i(lrint)
793570af302Sopenharmony_cimp_f_i(lrintf)
794570af302Sopenharmony_cimp_f_i(lrintl)
795570af302Sopenharmony_cimp_f_i(llround)
796570af302Sopenharmony_cimp_f_i(llroundf)
797570af302Sopenharmony_cimp_f_i(llroundl)
798570af302Sopenharmony_cimp_f_i(lround)
799570af302Sopenharmony_cimp_f_i(lroundf)
800570af302Sopenharmony_cimp_f_i(lroundl)
801570af302Sopenharmony_ci
802570af302Sopenharmony_ciint mpmodf(struct t *t)
803570af302Sopenharmony_ci{
804570af302Sopenharmony_ci	int e, r;
805570af302Sopenharmony_ci
806570af302Sopenharmony_ci	r = mpd1(t, wrap_trunc);
807570af302Sopenharmony_ci	if (r)
808570af302Sopenharmony_ci		return r;
809570af302Sopenharmony_ci	t->y2 = t->y;
810570af302Sopenharmony_ci	t->dy2 = t->dy;
811570af302Sopenharmony_ci	e = t->e & ~INEXACT;
812570af302Sopenharmony_ci	r = mpd1(t, mpfr_frac);
813570af302Sopenharmony_ci	t->e |= e;
814570af302Sopenharmony_ci	return r;
815570af302Sopenharmony_ci}
816570af302Sopenharmony_ci
817570af302Sopenharmony_ciint mpmodff(struct t *t)
818570af302Sopenharmony_ci{
819570af302Sopenharmony_ci	int e, r;
820570af302Sopenharmony_ci
821570af302Sopenharmony_ci	r = mpf1(t, wrap_trunc);
822570af302Sopenharmony_ci	if (r)
823570af302Sopenharmony_ci		return r;
824570af302Sopenharmony_ci	t->y2 = t->y;
825570af302Sopenharmony_ci	t->dy2 = t->dy;
826570af302Sopenharmony_ci	e = t->e & ~INEXACT;
827570af302Sopenharmony_ci	r = mpf1(t, mpfr_frac);
828570af302Sopenharmony_ci	t->e |= e;
829570af302Sopenharmony_ci	return r;
830570af302Sopenharmony_ci}
831570af302Sopenharmony_ci
832570af302Sopenharmony_ciint mpmodfl(struct t *t)
833570af302Sopenharmony_ci{
834570af302Sopenharmony_ci	int e, r;
835570af302Sopenharmony_ci
836570af302Sopenharmony_ci	r = mpl1(t, wrap_trunc);
837570af302Sopenharmony_ci	if (r)
838570af302Sopenharmony_ci		return r;
839570af302Sopenharmony_ci	t->y2 = t->y;
840570af302Sopenharmony_ci	t->dy2 = t->dy;
841570af302Sopenharmony_ci	e = t->e & ~INEXACT;
842570af302Sopenharmony_ci	r = mpl1(t, mpfr_frac);
843570af302Sopenharmony_ci	t->e |= e;
844570af302Sopenharmony_ci	return r;
845570af302Sopenharmony_ci}
846570af302Sopenharmony_ci
847570af302Sopenharmony_ciint mpsincos(struct t *t)
848570af302Sopenharmony_ci{
849570af302Sopenharmony_ci	int e, r;
850570af302Sopenharmony_ci
851570af302Sopenharmony_ci	r = mpd1(t, mpfr_cos);
852570af302Sopenharmony_ci	if (r)
853570af302Sopenharmony_ci		return r;
854570af302Sopenharmony_ci	t->y2 = t->y;
855570af302Sopenharmony_ci	t->dy2 = t->dy;
856570af302Sopenharmony_ci	e = t->e;
857570af302Sopenharmony_ci	r = mpd1(t, mpfr_sin);
858570af302Sopenharmony_ci	t->e |= e;
859570af302Sopenharmony_ci	return r;
860570af302Sopenharmony_ci}
861570af302Sopenharmony_ci
862570af302Sopenharmony_ciint mpsincosf(struct t *t)
863570af302Sopenharmony_ci{
864570af302Sopenharmony_ci	int e, r;
865570af302Sopenharmony_ci
866570af302Sopenharmony_ci	r = mpf1(t, mpfr_cos);
867570af302Sopenharmony_ci	if (r)
868570af302Sopenharmony_ci		return r;
869570af302Sopenharmony_ci	t->y2 = t->y;
870570af302Sopenharmony_ci	t->dy2 = t->dy;
871570af302Sopenharmony_ci	e = t->e;
872570af302Sopenharmony_ci	r = mpf1(t, mpfr_sin);
873570af302Sopenharmony_ci	t->e |= e;
874570af302Sopenharmony_ci	return r;
875570af302Sopenharmony_ci}
876570af302Sopenharmony_ci
877570af302Sopenharmony_ciint mpsincosl(struct t *t)
878570af302Sopenharmony_ci{
879570af302Sopenharmony_ci	int e, r;
880570af302Sopenharmony_ci
881570af302Sopenharmony_ci	r = mpl1(t, mpfr_cos);
882570af302Sopenharmony_ci	if (r)
883570af302Sopenharmony_ci		return r;
884570af302Sopenharmony_ci	t->y2 = t->y;
885570af302Sopenharmony_ci	t->dy2 = t->dy;
886570af302Sopenharmony_ci	e = t->e;
887570af302Sopenharmony_ci	r = mpl1(t, mpfr_sin);
888570af302Sopenharmony_ci	t->e |= e;
889570af302Sopenharmony_ci	return r;
890570af302Sopenharmony_ci}
891570af302Sopenharmony_ci
892570af302Sopenharmony_ciint mpremquo(struct t *t) { return mpd2(t, wrap_remquo) || (t->i = mpremquo_q, 0); }
893570af302Sopenharmony_ciint mpremquof(struct t *t) { return mpf2(t, wrap_remquo) || (t->i = mpremquo_q, 0); }
894570af302Sopenharmony_ciint mpremquol(struct t *t) { return mpl2(t, wrap_remquo) || (t->i = mpremquo_q, 0); }
895570af302Sopenharmony_ci
896570af302Sopenharmony_ciint mpfma(struct t *t)
897570af302Sopenharmony_ci{
898570af302Sopenharmony_ci	int tn;
899570af302Sopenharmony_ci	int r = rmap(t->r);
900570af302Sopenharmony_ci	MPFR_DECL_INIT(mx, 53);
901570af302Sopenharmony_ci	MPFR_DECL_INIT(mx2, 53);
902570af302Sopenharmony_ci	MPFR_DECL_INIT(mx3, 53);
903570af302Sopenharmony_ci	MPFR_DECL_INIT(my, 128);
904570af302Sopenharmony_ci
905570af302Sopenharmony_ci	mpfr_clear_flags();
906570af302Sopenharmony_ci	mpfr_set_d(mx, t->x, MPFR_RNDN);
907570af302Sopenharmony_ci	mpfr_set_d(mx2, t->x2, MPFR_RNDN);
908570af302Sopenharmony_ci	mpfr_set_d(mx3, t->x3, MPFR_RNDN);
909570af302Sopenharmony_ci	tn = mpfr_fma(my, mx, mx2, mx3, r);
910570af302Sopenharmony_ci	gend(t, my, tn, r);
911570af302Sopenharmony_ci	return 0;
912570af302Sopenharmony_ci}
913570af302Sopenharmony_ci
914570af302Sopenharmony_ciint mpfmaf(struct t *t)
915570af302Sopenharmony_ci{
916570af302Sopenharmony_ci	int tn;
917570af302Sopenharmony_ci	int r = rmap(t->r);
918570af302Sopenharmony_ci	MPFR_DECL_INIT(mx, 24);
919570af302Sopenharmony_ci	MPFR_DECL_INIT(mx2, 24);
920570af302Sopenharmony_ci	MPFR_DECL_INIT(mx3, 24);
921570af302Sopenharmony_ci	MPFR_DECL_INIT(my, 128);
922570af302Sopenharmony_ci
923570af302Sopenharmony_ci	mpfr_clear_flags();
924570af302Sopenharmony_ci	mpfr_set_flt(mx, t->x, MPFR_RNDN);
925570af302Sopenharmony_ci	mpfr_set_flt(mx2, t->x2, MPFR_RNDN);
926570af302Sopenharmony_ci	mpfr_set_flt(mx3, t->x3, MPFR_RNDN);
927570af302Sopenharmony_ci	tn = mpfr_fma(my, mx, mx2, mx3, r);
928570af302Sopenharmony_ci	genf(t, my, tn, r);
929570af302Sopenharmony_ci	return 0;
930570af302Sopenharmony_ci}
931570af302Sopenharmony_ci
932570af302Sopenharmony_ciint mpfmal(struct t *t)
933570af302Sopenharmony_ci{
934570af302Sopenharmony_ci#if LDBL_MANT_DIG == 53
935570af302Sopenharmony_ci	return mpfma(t);
936570af302Sopenharmony_ci#elif LDBL_MANT_DIG == 64
937570af302Sopenharmony_ci	int tn;
938570af302Sopenharmony_ci	int r = rmap(t->r);
939570af302Sopenharmony_ci	MPFR_DECL_INIT(mx, 64);
940570af302Sopenharmony_ci	MPFR_DECL_INIT(mx2, 64);
941570af302Sopenharmony_ci	MPFR_DECL_INIT(mx3, 64);
942570af302Sopenharmony_ci	MPFR_DECL_INIT(my, 128);
943570af302Sopenharmony_ci
944570af302Sopenharmony_ci	mpfr_clear_flags();
945570af302Sopenharmony_ci	mpfr_set_ld(mx, t->x, MPFR_RNDN);
946570af302Sopenharmony_ci	mpfr_set_ld(mx2, t->x2, MPFR_RNDN);
947570af302Sopenharmony_ci	mpfr_set_ld(mx3, t->x3, MPFR_RNDN);
948570af302Sopenharmony_ci	tn = mpfr_fma(my, mx, mx2, mx3, r);
949570af302Sopenharmony_ci	genl(t, my, tn, r);
950570af302Sopenharmony_ci	return 0;
951570af302Sopenharmony_ci#else
952570af302Sopenharmony_ci	return -1;
953570af302Sopenharmony_ci#endif
954570af302Sopenharmony_ci}
955570af302Sopenharmony_ci
956570af302Sopenharmony_ciint mpjn(struct t *t) { mpbessel_n = t->i; return mpd1(t, wrap_jn); }
957570af302Sopenharmony_ciint mpjnf(struct t *t) { mpbessel_n = t->i; return mpf1(t, wrap_jn); }
958570af302Sopenharmony_ciint mpjnl(struct t *t) { mpbessel_n = t->i; return mpl1(t, wrap_jn); }
959570af302Sopenharmony_ciint mpyn(struct t *t) { mpbessel_n = t->i; return mpd1(t, wrap_yn); }
960570af302Sopenharmony_ciint mpynf(struct t *t) { mpbessel_n = t->i; return mpf1(t, wrap_yn); }
961570af302Sopenharmony_ciint mpynl(struct t *t) { mpbessel_n = t->i; return mpl1(t, wrap_yn); }
962570af302Sopenharmony_ci
963