1*7f37b34dSShourya Goel //===-- Utils used by both MPCWrapper and MPFRWrapper----------------------===// 2*7f37b34dSShourya Goel // 3*7f37b34dSShourya Goel // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*7f37b34dSShourya Goel // See https://llvm.org/LICENSE.txt for license information. 5*7f37b34dSShourya Goel // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*7f37b34dSShourya Goel // 7*7f37b34dSShourya Goel //===----------------------------------------------------------------------===// 8*7f37b34dSShourya Goel 9*7f37b34dSShourya Goel #include "MPCommon.h" 10*7f37b34dSShourya Goel 11*7f37b34dSShourya Goel #include "src/__support/CPP/string_view.h" 12*7f37b34dSShourya Goel #include "src/__support/FPUtil/cast.h" 13*7f37b34dSShourya Goel #include "src/__support/macros/config.h" 14*7f37b34dSShourya Goel #include "src/__support/macros/properties/types.h" 15*7f37b34dSShourya Goel 16*7f37b34dSShourya Goel namespace LIBC_NAMESPACE_DECL { 17*7f37b34dSShourya Goel namespace testing { 18*7f37b34dSShourya Goel namespace mpfr { 19*7f37b34dSShourya Goel 20*7f37b34dSShourya Goel MPFRNumber::MPFRNumber() : mpfr_precision(256), mpfr_rounding(MPFR_RNDN) { 21*7f37b34dSShourya Goel mpfr_init2(value, mpfr_precision); 22*7f37b34dSShourya Goel } 23*7f37b34dSShourya Goel 24*7f37b34dSShourya Goel MPFRNumber::MPFRNumber(const MPFRNumber &other) 25*7f37b34dSShourya Goel : mpfr_precision(other.mpfr_precision), mpfr_rounding(other.mpfr_rounding) { 26*7f37b34dSShourya Goel mpfr_init2(value, mpfr_precision); 27*7f37b34dSShourya Goel mpfr_set(value, other.value, mpfr_rounding); 28*7f37b34dSShourya Goel } 29*7f37b34dSShourya Goel 30*7f37b34dSShourya Goel MPFRNumber::MPFRNumber(const MPFRNumber &other, unsigned int precision) 31*7f37b34dSShourya Goel : mpfr_precision(precision), mpfr_rounding(other.mpfr_rounding) { 32*7f37b34dSShourya Goel mpfr_init2(value, mpfr_precision); 33*7f37b34dSShourya Goel mpfr_set(value, other.value, mpfr_rounding); 34*7f37b34dSShourya Goel } 35*7f37b34dSShourya Goel 36*7f37b34dSShourya Goel MPFRNumber::MPFRNumber(const mpfr_t x, unsigned int precision, 37*7f37b34dSShourya Goel RoundingMode rounding) 38*7f37b34dSShourya Goel : mpfr_precision(precision), 39*7f37b34dSShourya Goel mpfr_rounding(get_mpfr_rounding_mode(rounding)) { 40*7f37b34dSShourya Goel mpfr_init2(value, mpfr_precision); 41*7f37b34dSShourya Goel mpfr_set(value, x, mpfr_rounding); 42*7f37b34dSShourya Goel } 43*7f37b34dSShourya Goel 44*7f37b34dSShourya Goel MPFRNumber::~MPFRNumber() { mpfr_clear(value); } 45*7f37b34dSShourya Goel 46*7f37b34dSShourya Goel MPFRNumber &MPFRNumber::operator=(const MPFRNumber &rhs) { 47*7f37b34dSShourya Goel mpfr_precision = rhs.mpfr_precision; 48*7f37b34dSShourya Goel mpfr_rounding = rhs.mpfr_rounding; 49*7f37b34dSShourya Goel mpfr_set(value, rhs.value, mpfr_rounding); 50*7f37b34dSShourya Goel return *this; 51*7f37b34dSShourya Goel } 52*7f37b34dSShourya Goel 53*7f37b34dSShourya Goel bool MPFRNumber::is_nan() const { return mpfr_nan_p(value); } 54*7f37b34dSShourya Goel 55*7f37b34dSShourya Goel MPFRNumber MPFRNumber::abs() const { 56*7f37b34dSShourya Goel MPFRNumber result(*this); 57*7f37b34dSShourya Goel mpfr_abs(result.value, value, mpfr_rounding); 58*7f37b34dSShourya Goel return result; 59*7f37b34dSShourya Goel } 60*7f37b34dSShourya Goel 61*7f37b34dSShourya Goel MPFRNumber MPFRNumber::acos() const { 62*7f37b34dSShourya Goel MPFRNumber result(*this); 63*7f37b34dSShourya Goel mpfr_acos(result.value, value, mpfr_rounding); 64*7f37b34dSShourya Goel return result; 65*7f37b34dSShourya Goel } 66*7f37b34dSShourya Goel 67*7f37b34dSShourya Goel MPFRNumber MPFRNumber::acosh() const { 68*7f37b34dSShourya Goel MPFRNumber result(*this); 69*7f37b34dSShourya Goel mpfr_acosh(result.value, value, mpfr_rounding); 70*7f37b34dSShourya Goel return result; 71*7f37b34dSShourya Goel } 72*7f37b34dSShourya Goel 73*7f37b34dSShourya Goel MPFRNumber MPFRNumber::add(const MPFRNumber &b) const { 74*7f37b34dSShourya Goel MPFRNumber result(*this); 75*7f37b34dSShourya Goel mpfr_add(result.value, value, b.value, mpfr_rounding); 76*7f37b34dSShourya Goel return result; 77*7f37b34dSShourya Goel } 78*7f37b34dSShourya Goel 79*7f37b34dSShourya Goel MPFRNumber MPFRNumber::asin() const { 80*7f37b34dSShourya Goel MPFRNumber result(*this); 81*7f37b34dSShourya Goel mpfr_asin(result.value, value, mpfr_rounding); 82*7f37b34dSShourya Goel return result; 83*7f37b34dSShourya Goel } 84*7f37b34dSShourya Goel 85*7f37b34dSShourya Goel MPFRNumber MPFRNumber::asinh() const { 86*7f37b34dSShourya Goel MPFRNumber result(*this); 87*7f37b34dSShourya Goel mpfr_asinh(result.value, value, mpfr_rounding); 88*7f37b34dSShourya Goel return result; 89*7f37b34dSShourya Goel } 90*7f37b34dSShourya Goel 91*7f37b34dSShourya Goel MPFRNumber MPFRNumber::atan() const { 92*7f37b34dSShourya Goel MPFRNumber result(*this); 93*7f37b34dSShourya Goel mpfr_atan(result.value, value, mpfr_rounding); 94*7f37b34dSShourya Goel return result; 95*7f37b34dSShourya Goel } 96*7f37b34dSShourya Goel 97*7f37b34dSShourya Goel MPFRNumber MPFRNumber::atan2(const MPFRNumber &b) { 98*7f37b34dSShourya Goel MPFRNumber result(*this); 99*7f37b34dSShourya Goel mpfr_atan2(result.value, value, b.value, mpfr_rounding); 100*7f37b34dSShourya Goel return result; 101*7f37b34dSShourya Goel } 102*7f37b34dSShourya Goel 103*7f37b34dSShourya Goel MPFRNumber MPFRNumber::atanh() const { 104*7f37b34dSShourya Goel MPFRNumber result(*this); 105*7f37b34dSShourya Goel mpfr_atanh(result.value, value, mpfr_rounding); 106*7f37b34dSShourya Goel return result; 107*7f37b34dSShourya Goel } 108*7f37b34dSShourya Goel 109*7f37b34dSShourya Goel MPFRNumber MPFRNumber::cbrt() const { 110*7f37b34dSShourya Goel MPFRNumber result(*this); 111*7f37b34dSShourya Goel mpfr_cbrt(result.value, value, mpfr_rounding); 112*7f37b34dSShourya Goel return result; 113*7f37b34dSShourya Goel } 114*7f37b34dSShourya Goel 115*7f37b34dSShourya Goel MPFRNumber MPFRNumber::ceil() const { 116*7f37b34dSShourya Goel MPFRNumber result(*this); 117*7f37b34dSShourya Goel mpfr_ceil(result.value, value); 118*7f37b34dSShourya Goel return result; 119*7f37b34dSShourya Goel } 120*7f37b34dSShourya Goel 121*7f37b34dSShourya Goel MPFRNumber MPFRNumber::cos() const { 122*7f37b34dSShourya Goel MPFRNumber result(*this); 123*7f37b34dSShourya Goel mpfr_cos(result.value, value, mpfr_rounding); 124*7f37b34dSShourya Goel return result; 125*7f37b34dSShourya Goel } 126*7f37b34dSShourya Goel 127*7f37b34dSShourya Goel MPFRNumber MPFRNumber::cosh() const { 128*7f37b34dSShourya Goel MPFRNumber result(*this); 129*7f37b34dSShourya Goel mpfr_cosh(result.value, value, mpfr_rounding); 130*7f37b34dSShourya Goel return result; 131*7f37b34dSShourya Goel } 132*7f37b34dSShourya Goel 133*7f37b34dSShourya Goel MPFRNumber MPFRNumber::cospi() const { 134*7f37b34dSShourya Goel MPFRNumber result(*this); 135*7f37b34dSShourya Goel 136*7f37b34dSShourya Goel #if MPFR_VERSION_MAJOR > 4 || \ 137*7f37b34dSShourya Goel (MPFR_VERSION_MAJOR == 4 && MPFR_VERSION_MINOR >= 2) 138*7f37b34dSShourya Goel mpfr_cospi(result.value, value, mpfr_rounding); 139*7f37b34dSShourya Goel return result; 140*7f37b34dSShourya Goel #else 141*7f37b34dSShourya Goel if (mpfr_integer_p(value)) { 142*7f37b34dSShourya Goel mpz_t integer; 143*7f37b34dSShourya Goel mpz_init(integer); 144*7f37b34dSShourya Goel mpfr_get_z(integer, value, mpfr_rounding); 145*7f37b34dSShourya Goel 146*7f37b34dSShourya Goel int d = mpz_tstbit(integer, 0); 147*7f37b34dSShourya Goel mpfr_set_si(result.value, d ? -1 : 1, mpfr_rounding); 148*7f37b34dSShourya Goel mpz_clear(integer); 149*7f37b34dSShourya Goel return result; 150*7f37b34dSShourya Goel } 151*7f37b34dSShourya Goel 152*7f37b34dSShourya Goel MPFRNumber value_pi(0.0, 1280); 153*7f37b34dSShourya Goel mpfr_const_pi(value_pi.value, MPFR_RNDN); 154*7f37b34dSShourya Goel mpfr_mul(value_pi.value, value_pi.value, value, MPFR_RNDN); 155*7f37b34dSShourya Goel mpfr_cos(result.value, value_pi.value, mpfr_rounding); 156*7f37b34dSShourya Goel 157*7f37b34dSShourya Goel return result; 158*7f37b34dSShourya Goel #endif 159*7f37b34dSShourya Goel } 160*7f37b34dSShourya Goel 161*7f37b34dSShourya Goel MPFRNumber MPFRNumber::erf() const { 162*7f37b34dSShourya Goel MPFRNumber result(*this); 163*7f37b34dSShourya Goel mpfr_erf(result.value, value, mpfr_rounding); 164*7f37b34dSShourya Goel return result; 165*7f37b34dSShourya Goel } 166*7f37b34dSShourya Goel 167*7f37b34dSShourya Goel MPFRNumber MPFRNumber::exp() const { 168*7f37b34dSShourya Goel MPFRNumber result(*this); 169*7f37b34dSShourya Goel mpfr_exp(result.value, value, mpfr_rounding); 170*7f37b34dSShourya Goel return result; 171*7f37b34dSShourya Goel } 172*7f37b34dSShourya Goel 173*7f37b34dSShourya Goel MPFRNumber MPFRNumber::exp2() const { 174*7f37b34dSShourya Goel MPFRNumber result(*this); 175*7f37b34dSShourya Goel mpfr_exp2(result.value, value, mpfr_rounding); 176*7f37b34dSShourya Goel return result; 177*7f37b34dSShourya Goel } 178*7f37b34dSShourya Goel 179*7f37b34dSShourya Goel MPFRNumber MPFRNumber::exp2m1() const { 180*7f37b34dSShourya Goel // TODO: Only use mpfr_exp2m1 once CI and buildbots get MPFR >= 4.2.0. 181*7f37b34dSShourya Goel #if MPFR_VERSION_MAJOR > 4 || \ 182*7f37b34dSShourya Goel (MPFR_VERSION_MAJOR == 4 && MPFR_VERSION_MINOR >= 2) 183*7f37b34dSShourya Goel MPFRNumber result(*this); 184*7f37b34dSShourya Goel mpfr_exp2m1(result.value, value, mpfr_rounding); 185*7f37b34dSShourya Goel return result; 186*7f37b34dSShourya Goel #else 187*7f37b34dSShourya Goel unsigned int prec = mpfr_precision * 3; 188*7f37b34dSShourya Goel MPFRNumber result(*this, prec); 189*7f37b34dSShourya Goel 190*7f37b34dSShourya Goel float f = mpfr_get_flt(abs().value, mpfr_rounding); 191*7f37b34dSShourya Goel if (f > 0.5f && f < 0x1.0p30f) { 192*7f37b34dSShourya Goel mpfr_exp2(result.value, value, mpfr_rounding); 193*7f37b34dSShourya Goel mpfr_sub_ui(result.value, result.value, 1, mpfr_rounding); 194*7f37b34dSShourya Goel return result; 195*7f37b34dSShourya Goel } 196*7f37b34dSShourya Goel 197*7f37b34dSShourya Goel MPFRNumber ln2(2.0f, prec); 198*7f37b34dSShourya Goel // log(2) 199*7f37b34dSShourya Goel mpfr_log(ln2.value, ln2.value, mpfr_rounding); 200*7f37b34dSShourya Goel // x * log(2) 201*7f37b34dSShourya Goel mpfr_mul(result.value, value, ln2.value, mpfr_rounding); 202*7f37b34dSShourya Goel // e^(x * log(2)) - 1 203*7f37b34dSShourya Goel int ex = mpfr_expm1(result.value, result.value, mpfr_rounding); 204*7f37b34dSShourya Goel mpfr_subnormalize(result.value, ex, mpfr_rounding); 205*7f37b34dSShourya Goel return result; 206*7f37b34dSShourya Goel #endif 207*7f37b34dSShourya Goel } 208*7f37b34dSShourya Goel 209*7f37b34dSShourya Goel MPFRNumber MPFRNumber::exp10() const { 210*7f37b34dSShourya Goel MPFRNumber result(*this); 211*7f37b34dSShourya Goel mpfr_exp10(result.value, value, mpfr_rounding); 212*7f37b34dSShourya Goel return result; 213*7f37b34dSShourya Goel } 214*7f37b34dSShourya Goel 215*7f37b34dSShourya Goel MPFRNumber MPFRNumber::exp10m1() const { 216*7f37b34dSShourya Goel // TODO: Only use mpfr_exp10m1 once CI and buildbots get MPFR >= 4.2.0. 217*7f37b34dSShourya Goel #if MPFR_VERSION_MAJOR > 4 || \ 218*7f37b34dSShourya Goel (MPFR_VERSION_MAJOR == 4 && MPFR_VERSION_MINOR >= 2) 219*7f37b34dSShourya Goel MPFRNumber result(*this); 220*7f37b34dSShourya Goel mpfr_exp10m1(result.value, value, mpfr_rounding); 221*7f37b34dSShourya Goel return result; 222*7f37b34dSShourya Goel #else 223*7f37b34dSShourya Goel unsigned int prec = mpfr_precision * 3; 224*7f37b34dSShourya Goel MPFRNumber result(*this, prec); 225*7f37b34dSShourya Goel 226*7f37b34dSShourya Goel MPFRNumber ln10(10.0f, prec); 227*7f37b34dSShourya Goel // log(10) 228*7f37b34dSShourya Goel mpfr_log(ln10.value, ln10.value, mpfr_rounding); 229*7f37b34dSShourya Goel // x * log(10) 230*7f37b34dSShourya Goel mpfr_mul(result.value, value, ln10.value, mpfr_rounding); 231*7f37b34dSShourya Goel // e^(x * log(10)) - 1 232*7f37b34dSShourya Goel int ex = mpfr_expm1(result.value, result.value, mpfr_rounding); 233*7f37b34dSShourya Goel mpfr_subnormalize(result.value, ex, mpfr_rounding); 234*7f37b34dSShourya Goel return result; 235*7f37b34dSShourya Goel #endif 236*7f37b34dSShourya Goel } 237*7f37b34dSShourya Goel 238*7f37b34dSShourya Goel MPFRNumber MPFRNumber::expm1() const { 239*7f37b34dSShourya Goel MPFRNumber result(*this); 240*7f37b34dSShourya Goel mpfr_expm1(result.value, value, mpfr_rounding); 241*7f37b34dSShourya Goel return result; 242*7f37b34dSShourya Goel } 243*7f37b34dSShourya Goel 244*7f37b34dSShourya Goel MPFRNumber MPFRNumber::div(const MPFRNumber &b) const { 245*7f37b34dSShourya Goel MPFRNumber result(*this); 246*7f37b34dSShourya Goel mpfr_div(result.value, value, b.value, mpfr_rounding); 247*7f37b34dSShourya Goel return result; 248*7f37b34dSShourya Goel } 249*7f37b34dSShourya Goel 250*7f37b34dSShourya Goel MPFRNumber MPFRNumber::floor() const { 251*7f37b34dSShourya Goel MPFRNumber result(*this); 252*7f37b34dSShourya Goel mpfr_floor(result.value, value); 253*7f37b34dSShourya Goel return result; 254*7f37b34dSShourya Goel } 255*7f37b34dSShourya Goel 256*7f37b34dSShourya Goel MPFRNumber MPFRNumber::fmod(const MPFRNumber &b) { 257*7f37b34dSShourya Goel MPFRNumber result(*this); 258*7f37b34dSShourya Goel mpfr_fmod(result.value, value, b.value, mpfr_rounding); 259*7f37b34dSShourya Goel return result; 260*7f37b34dSShourya Goel } 261*7f37b34dSShourya Goel 262*7f37b34dSShourya Goel MPFRNumber MPFRNumber::frexp(int &exp) { 263*7f37b34dSShourya Goel MPFRNumber result(*this); 264*7f37b34dSShourya Goel mpfr_exp_t resultExp; 265*7f37b34dSShourya Goel mpfr_frexp(&resultExp, result.value, value, mpfr_rounding); 266*7f37b34dSShourya Goel exp = resultExp; 267*7f37b34dSShourya Goel return result; 268*7f37b34dSShourya Goel } 269*7f37b34dSShourya Goel 270*7f37b34dSShourya Goel MPFRNumber MPFRNumber::hypot(const MPFRNumber &b) { 271*7f37b34dSShourya Goel MPFRNumber result(*this); 272*7f37b34dSShourya Goel mpfr_hypot(result.value, value, b.value, mpfr_rounding); 273*7f37b34dSShourya Goel return result; 274*7f37b34dSShourya Goel } 275*7f37b34dSShourya Goel 276*7f37b34dSShourya Goel MPFRNumber MPFRNumber::log() const { 277*7f37b34dSShourya Goel MPFRNumber result(*this); 278*7f37b34dSShourya Goel mpfr_log(result.value, value, mpfr_rounding); 279*7f37b34dSShourya Goel return result; 280*7f37b34dSShourya Goel } 281*7f37b34dSShourya Goel 282*7f37b34dSShourya Goel MPFRNumber MPFRNumber::log2() const { 283*7f37b34dSShourya Goel MPFRNumber result(*this); 284*7f37b34dSShourya Goel mpfr_log2(result.value, value, mpfr_rounding); 285*7f37b34dSShourya Goel return result; 286*7f37b34dSShourya Goel } 287*7f37b34dSShourya Goel 288*7f37b34dSShourya Goel MPFRNumber MPFRNumber::log10() const { 289*7f37b34dSShourya Goel MPFRNumber result(*this); 290*7f37b34dSShourya Goel mpfr_log10(result.value, value, mpfr_rounding); 291*7f37b34dSShourya Goel return result; 292*7f37b34dSShourya Goel } 293*7f37b34dSShourya Goel 294*7f37b34dSShourya Goel MPFRNumber MPFRNumber::log1p() const { 295*7f37b34dSShourya Goel MPFRNumber result(*this); 296*7f37b34dSShourya Goel mpfr_log1p(result.value, value, mpfr_rounding); 297*7f37b34dSShourya Goel return result; 298*7f37b34dSShourya Goel } 299*7f37b34dSShourya Goel 300*7f37b34dSShourya Goel MPFRNumber MPFRNumber::pow(const MPFRNumber &b) { 301*7f37b34dSShourya Goel MPFRNumber result(*this); 302*7f37b34dSShourya Goel mpfr_pow(result.value, value, b.value, mpfr_rounding); 303*7f37b34dSShourya Goel return result; 304*7f37b34dSShourya Goel } 305*7f37b34dSShourya Goel 306*7f37b34dSShourya Goel MPFRNumber MPFRNumber::remquo(const MPFRNumber &divisor, int "ient) { 307*7f37b34dSShourya Goel MPFRNumber remainder(*this); 308*7f37b34dSShourya Goel long q; 309*7f37b34dSShourya Goel mpfr_remquo(remainder.value, &q, value, divisor.value, mpfr_rounding); 310*7f37b34dSShourya Goel quotient = q; 311*7f37b34dSShourya Goel return remainder; 312*7f37b34dSShourya Goel } 313*7f37b34dSShourya Goel 314*7f37b34dSShourya Goel MPFRNumber MPFRNumber::round() const { 315*7f37b34dSShourya Goel MPFRNumber result(*this); 316*7f37b34dSShourya Goel mpfr_round(result.value, value); 317*7f37b34dSShourya Goel return result; 318*7f37b34dSShourya Goel } 319*7f37b34dSShourya Goel 320*7f37b34dSShourya Goel MPFRNumber MPFRNumber::roundeven() const { 321*7f37b34dSShourya Goel MPFRNumber result(*this); 322*7f37b34dSShourya Goel #if MPFR_VERSION_MAJOR >= 4 323*7f37b34dSShourya Goel mpfr_roundeven(result.value, value); 324*7f37b34dSShourya Goel #else 325*7f37b34dSShourya Goel mpfr_rint(result.value, value, MPFR_RNDN); 326*7f37b34dSShourya Goel #endif 327*7f37b34dSShourya Goel return result; 328*7f37b34dSShourya Goel } 329*7f37b34dSShourya Goel 330*7f37b34dSShourya Goel bool MPFRNumber::round_to_long(long &result) const { 331*7f37b34dSShourya Goel // We first calculate the rounded value. This way, when converting 332*7f37b34dSShourya Goel // to long using mpfr_get_si, the rounding direction of MPFR_RNDN 333*7f37b34dSShourya Goel // (or any other rounding mode), does not have an influence. 334*7f37b34dSShourya Goel MPFRNumber roundedValue = round(); 335*7f37b34dSShourya Goel mpfr_clear_erangeflag(); 336*7f37b34dSShourya Goel result = mpfr_get_si(roundedValue.value, MPFR_RNDN); 337*7f37b34dSShourya Goel return mpfr_erangeflag_p(); 338*7f37b34dSShourya Goel } 339*7f37b34dSShourya Goel 340*7f37b34dSShourya Goel bool MPFRNumber::round_to_long(mpfr_rnd_t rnd, long &result) const { 341*7f37b34dSShourya Goel MPFRNumber rint_result(*this); 342*7f37b34dSShourya Goel mpfr_rint(rint_result.value, value, rnd); 343*7f37b34dSShourya Goel return rint_result.round_to_long(result); 344*7f37b34dSShourya Goel } 345*7f37b34dSShourya Goel 346*7f37b34dSShourya Goel MPFRNumber MPFRNumber::rint(mpfr_rnd_t rnd) const { 347*7f37b34dSShourya Goel MPFRNumber result(*this); 348*7f37b34dSShourya Goel mpfr_rint(result.value, value, rnd); 349*7f37b34dSShourya Goel return result; 350*7f37b34dSShourya Goel } 351*7f37b34dSShourya Goel 352*7f37b34dSShourya Goel MPFRNumber MPFRNumber::mod_2pi() const { 353*7f37b34dSShourya Goel MPFRNumber result(0.0, 1280); 354*7f37b34dSShourya Goel MPFRNumber _2pi(0.0, 1280); 355*7f37b34dSShourya Goel mpfr_const_pi(_2pi.value, MPFR_RNDN); 356*7f37b34dSShourya Goel mpfr_mul_si(_2pi.value, _2pi.value, 2, MPFR_RNDN); 357*7f37b34dSShourya Goel mpfr_fmod(result.value, value, _2pi.value, MPFR_RNDN); 358*7f37b34dSShourya Goel return result; 359*7f37b34dSShourya Goel } 360*7f37b34dSShourya Goel 361*7f37b34dSShourya Goel MPFRNumber MPFRNumber::mod_pi_over_2() const { 362*7f37b34dSShourya Goel MPFRNumber result(0.0, 1280); 363*7f37b34dSShourya Goel MPFRNumber pi_over_2(0.0, 1280); 364*7f37b34dSShourya Goel mpfr_const_pi(pi_over_2.value, MPFR_RNDN); 365*7f37b34dSShourya Goel mpfr_mul_d(pi_over_2.value, pi_over_2.value, 0.5, MPFR_RNDN); 366*7f37b34dSShourya Goel mpfr_fmod(result.value, value, pi_over_2.value, MPFR_RNDN); 367*7f37b34dSShourya Goel return result; 368*7f37b34dSShourya Goel } 369*7f37b34dSShourya Goel 370*7f37b34dSShourya Goel MPFRNumber MPFRNumber::mod_pi_over_4() const { 371*7f37b34dSShourya Goel MPFRNumber result(0.0, 1280); 372*7f37b34dSShourya Goel MPFRNumber pi_over_4(0.0, 1280); 373*7f37b34dSShourya Goel mpfr_const_pi(pi_over_4.value, MPFR_RNDN); 374*7f37b34dSShourya Goel mpfr_mul_d(pi_over_4.value, pi_over_4.value, 0.25, MPFR_RNDN); 375*7f37b34dSShourya Goel mpfr_fmod(result.value, value, pi_over_4.value, MPFR_RNDN); 376*7f37b34dSShourya Goel return result; 377*7f37b34dSShourya Goel } 378*7f37b34dSShourya Goel 379*7f37b34dSShourya Goel MPFRNumber MPFRNumber::sin() const { 380*7f37b34dSShourya Goel MPFRNumber result(*this); 381*7f37b34dSShourya Goel mpfr_sin(result.value, value, mpfr_rounding); 382*7f37b34dSShourya Goel return result; 383*7f37b34dSShourya Goel } 384*7f37b34dSShourya Goel 385*7f37b34dSShourya Goel MPFRNumber MPFRNumber::sinpi() const { 386*7f37b34dSShourya Goel MPFRNumber result(*this); 387*7f37b34dSShourya Goel 388*7f37b34dSShourya Goel #if MPFR_VERSION_MAJOR > 4 || \ 389*7f37b34dSShourya Goel (MPFR_VERSION_MAJOR == 4 && MPFR_VERSION_MINOR >= 2) 390*7f37b34dSShourya Goel 391*7f37b34dSShourya Goel mpfr_sinpi(result.value, value, mpfr_rounding); 392*7f37b34dSShourya Goel return result; 393*7f37b34dSShourya Goel #else 394*7f37b34dSShourya Goel if (mpfr_integer_p(value)) { 395*7f37b34dSShourya Goel mpfr_set_si(result.value, 0, mpfr_rounding); 396*7f37b34dSShourya Goel return result; 397*7f37b34dSShourya Goel } 398*7f37b34dSShourya Goel 399*7f37b34dSShourya Goel MPFRNumber value_mul_two(*this); 400*7f37b34dSShourya Goel mpfr_mul_si(value_mul_two.value, value, 2, MPFR_RNDN); 401*7f37b34dSShourya Goel 402*7f37b34dSShourya Goel if (mpfr_integer_p(value_mul_two.value)) { 403*7f37b34dSShourya Goel auto d = mpfr_get_si(value, MPFR_RNDD); 404*7f37b34dSShourya Goel mpfr_set_si(result.value, (d & 1) ? -1 : 1, mpfr_rounding); 405*7f37b34dSShourya Goel return result; 406*7f37b34dSShourya Goel } 407*7f37b34dSShourya Goel 408*7f37b34dSShourya Goel MPFRNumber value_pi(0.0, 1280); 409*7f37b34dSShourya Goel mpfr_const_pi(value_pi.value, MPFR_RNDN); 410*7f37b34dSShourya Goel mpfr_mul(value_pi.value, value_pi.value, value, MPFR_RNDN); 411*7f37b34dSShourya Goel mpfr_sin(result.value, value_pi.value, mpfr_rounding); 412*7f37b34dSShourya Goel return result; 413*7f37b34dSShourya Goel #endif 414*7f37b34dSShourya Goel } 415*7f37b34dSShourya Goel 416*7f37b34dSShourya Goel MPFRNumber MPFRNumber::sinh() const { 417*7f37b34dSShourya Goel MPFRNumber result(*this); 418*7f37b34dSShourya Goel mpfr_sinh(result.value, value, mpfr_rounding); 419*7f37b34dSShourya Goel return result; 420*7f37b34dSShourya Goel } 421*7f37b34dSShourya Goel 422*7f37b34dSShourya Goel MPFRNumber MPFRNumber::sqrt() const { 423*7f37b34dSShourya Goel MPFRNumber result(*this); 424*7f37b34dSShourya Goel mpfr_sqrt(result.value, value, mpfr_rounding); 425*7f37b34dSShourya Goel return result; 426*7f37b34dSShourya Goel } 427*7f37b34dSShourya Goel 428*7f37b34dSShourya Goel MPFRNumber MPFRNumber::sub(const MPFRNumber &b) const { 429*7f37b34dSShourya Goel MPFRNumber result(*this); 430*7f37b34dSShourya Goel mpfr_sub(result.value, value, b.value, mpfr_rounding); 431*7f37b34dSShourya Goel return result; 432*7f37b34dSShourya Goel } 433*7f37b34dSShourya Goel 434*7f37b34dSShourya Goel MPFRNumber MPFRNumber::tan() const { 435*7f37b34dSShourya Goel MPFRNumber result(*this); 436*7f37b34dSShourya Goel mpfr_tan(result.value, value, mpfr_rounding); 437*7f37b34dSShourya Goel return result; 438*7f37b34dSShourya Goel } 439*7f37b34dSShourya Goel 440*7f37b34dSShourya Goel MPFRNumber MPFRNumber::tanh() const { 441*7f37b34dSShourya Goel MPFRNumber result(*this); 442*7f37b34dSShourya Goel mpfr_tanh(result.value, value, mpfr_rounding); 443*7f37b34dSShourya Goel return result; 444*7f37b34dSShourya Goel } 445*7f37b34dSShourya Goel 446*7f37b34dSShourya Goel MPFRNumber MPFRNumber::tanpi() const { 447*7f37b34dSShourya Goel MPFRNumber result(*this); 448*7f37b34dSShourya Goel 449*7f37b34dSShourya Goel #if MPFR_VERSION_MAJOR > 4 || \ 450*7f37b34dSShourya Goel (MPFR_VERSION_MAJOR == 4 && MPFR_VERSION_MINOR >= 2) 451*7f37b34dSShourya Goel 452*7f37b34dSShourya Goel mpfr_tanpi(result.value, value, mpfr_rounding); 453*7f37b34dSShourya Goel return result; 454*7f37b34dSShourya Goel #else 455*7f37b34dSShourya Goel MPFRNumber value_ret_exact(*this); 456*7f37b34dSShourya Goel MPFRNumber value_one(*this); 457*7f37b34dSShourya Goel mpfr_set_si(value_one.value, 1, MPFR_RNDN); 458*7f37b34dSShourya Goel mpfr_fmod(value_ret_exact.value, value, value_one.value, mpfr_rounding); 459*7f37b34dSShourya Goel mpfr_mul_si(value_ret_exact.value, value_ret_exact.value, 4, MPFR_RNDN); 460*7f37b34dSShourya Goel 461*7f37b34dSShourya Goel if (mpfr_integer_p(value_ret_exact.value)) { 462*7f37b34dSShourya Goel int mod = mpfr_get_si(value_ret_exact.value, MPFR_RNDN); 463*7f37b34dSShourya Goel mod = (mod < 0 ? -1 * mod : mod); 464*7f37b34dSShourya Goel 465*7f37b34dSShourya Goel switch (mod) { 466*7f37b34dSShourya Goel case 0: 467*7f37b34dSShourya Goel mpfr_set_si(result.value, 0, mpfr_rounding); 468*7f37b34dSShourya Goel break; 469*7f37b34dSShourya Goel case 1: 470*7f37b34dSShourya Goel mpfr_set_si(result.value, (mpfr_signbit(value) ? -1 : 1), mpfr_rounding); 471*7f37b34dSShourya Goel break; 472*7f37b34dSShourya Goel case 2: { 473*7f37b34dSShourya Goel auto d = mpfr_get_si(value, MPFR_RNDZ); 474*7f37b34dSShourya Goel d += mpfr_sgn(value) > 0 ? 0 : 1; 475*7f37b34dSShourya Goel mpfr_set_inf(result.value, (d & 1) ? -1 : 1); 476*7f37b34dSShourya Goel break; 477*7f37b34dSShourya Goel } 478*7f37b34dSShourya Goel case 3: 479*7f37b34dSShourya Goel mpfr_set_si(result.value, (mpfr_signbit(value) ? 1 : -1), mpfr_rounding); 480*7f37b34dSShourya Goel break; 481*7f37b34dSShourya Goel } 482*7f37b34dSShourya Goel 483*7f37b34dSShourya Goel return result; 484*7f37b34dSShourya Goel } 485*7f37b34dSShourya Goel 486*7f37b34dSShourya Goel MPFRNumber value_pi(0.0, 1280); 487*7f37b34dSShourya Goel mpfr_const_pi(value_pi.value, MPFR_RNDN); 488*7f37b34dSShourya Goel mpfr_mul(value_pi.value, value_pi.value, value, MPFR_RNDN); 489*7f37b34dSShourya Goel mpfr_tan(result.value, value_pi.value, mpfr_rounding); 490*7f37b34dSShourya Goel return result; 491*7f37b34dSShourya Goel #endif 492*7f37b34dSShourya Goel } 493*7f37b34dSShourya Goel 494*7f37b34dSShourya Goel MPFRNumber MPFRNumber::trunc() const { 495*7f37b34dSShourya Goel MPFRNumber result(*this); 496*7f37b34dSShourya Goel mpfr_trunc(result.value, value); 497*7f37b34dSShourya Goel return result; 498*7f37b34dSShourya Goel } 499*7f37b34dSShourya Goel 500*7f37b34dSShourya Goel MPFRNumber MPFRNumber::fma(const MPFRNumber &b, const MPFRNumber &c) { 501*7f37b34dSShourya Goel MPFRNumber result(*this); 502*7f37b34dSShourya Goel mpfr_fma(result.value, value, b.value, c.value, mpfr_rounding); 503*7f37b34dSShourya Goel return result; 504*7f37b34dSShourya Goel } 505*7f37b34dSShourya Goel 506*7f37b34dSShourya Goel MPFRNumber MPFRNumber::mul(const MPFRNumber &b) { 507*7f37b34dSShourya Goel MPFRNumber result(*this); 508*7f37b34dSShourya Goel mpfr_mul(result.value, value, b.value, mpfr_rounding); 509*7f37b34dSShourya Goel return result; 510*7f37b34dSShourya Goel } 511*7f37b34dSShourya Goel 512*7f37b34dSShourya Goel cpp::string MPFRNumber::str() const { 513*7f37b34dSShourya Goel // 200 bytes should be more than sufficient to hold a 100-digit number 514*7f37b34dSShourya Goel // plus additional bytes for the decimal point, '-' sign etc. 515*7f37b34dSShourya Goel constexpr size_t printBufSize = 200; 516*7f37b34dSShourya Goel char buffer[printBufSize]; 517*7f37b34dSShourya Goel mpfr_snprintf(buffer, printBufSize, "%100.50Rf", value); 518*7f37b34dSShourya Goel cpp::string_view view(buffer); 519*7f37b34dSShourya Goel // Trim whitespaces 520*7f37b34dSShourya Goel const char whitespace = ' '; 521*7f37b34dSShourya Goel while (!view.empty() && view.front() == whitespace) 522*7f37b34dSShourya Goel view.remove_prefix(1); 523*7f37b34dSShourya Goel while (!view.empty() && view.back() == whitespace) 524*7f37b34dSShourya Goel view.remove_suffix(1); 525*7f37b34dSShourya Goel return cpp::string(view.data()); 526*7f37b34dSShourya Goel } 527*7f37b34dSShourya Goel 528*7f37b34dSShourya Goel void MPFRNumber::dump(const char *msg) const { 529*7f37b34dSShourya Goel mpfr_printf("%s%.128g\n", msg, value); 530*7f37b34dSShourya Goel } 531*7f37b34dSShourya Goel 532*7f37b34dSShourya Goel template <> float MPFRNumber::as<float>() const { 533*7f37b34dSShourya Goel return mpfr_get_flt(value, mpfr_rounding); 534*7f37b34dSShourya Goel } 535*7f37b34dSShourya Goel 536*7f37b34dSShourya Goel template <> double MPFRNumber::as<double>() const { 537*7f37b34dSShourya Goel return mpfr_get_d(value, mpfr_rounding); 538*7f37b34dSShourya Goel } 539*7f37b34dSShourya Goel 540*7f37b34dSShourya Goel template <> long double MPFRNumber::as<long double>() const { 541*7f37b34dSShourya Goel return mpfr_get_ld(value, mpfr_rounding); 542*7f37b34dSShourya Goel } 543*7f37b34dSShourya Goel 544*7f37b34dSShourya Goel #ifdef LIBC_TYPES_HAS_FLOAT16 545*7f37b34dSShourya Goel template <> float16 MPFRNumber::as<float16>() const { 546*7f37b34dSShourya Goel // TODO: Either prove that this cast won't cause double-rounding errors, or 547*7f37b34dSShourya Goel // find a better way to get a float16. 548*7f37b34dSShourya Goel return fputil::cast<float16>(mpfr_get_d(value, mpfr_rounding)); 549*7f37b34dSShourya Goel } 550*7f37b34dSShourya Goel #endif 551*7f37b34dSShourya Goel 552*7f37b34dSShourya Goel #ifdef LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE 553*7f37b34dSShourya Goel template <> float128 MPFRNumber::as<float128>() const { 554*7f37b34dSShourya Goel return mpfr_get_float128(value, mpfr_rounding); 555*7f37b34dSShourya Goel } 556*7f37b34dSShourya Goel 557*7f37b34dSShourya Goel #endif // LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE 558*7f37b34dSShourya Goel 559*7f37b34dSShourya Goel } // namespace mpfr 560*7f37b34dSShourya Goel } // namespace testing 561*7f37b34dSShourya Goel } // namespace LIBC_NAMESPACE_DECL 562