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

source code of libc/utils/MPFRWrapper/MPCommon.cpp