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