sollya 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/ext/mpfr_rb.c ADDED
@@ -0,0 +1,4408 @@
1
+ /* Copyright (C) 2024 Théotime Bollengier <theotime.bollengier@ensta-bretagne.fr>
2
+ *
3
+ * This file is part of Sollya.rb. <https://gitlab.ensta-bretagne.fr/bollenth/sollya.rb>
4
+ *
5
+ * Sollya.rb is free software: you can redistribute it and/or modify it
6
+ * under the terms of the GNU General Public License as published
7
+ * by the Free Software Foundation, either version 3 of the License,
8
+ * or (at your option) any later version.
9
+ *
10
+ * Sollya.rb is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
+ * See the GNU General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU General Public License
16
+ * along with Sollya.rb. If not, see <https://www.gnu.org/licenses/>. 
17
+ */
18
+
19
+ #include <ruby.h>
20
+ #include <mpfr.h>
21
+
22
+
23
+ VALUE c_MPFR;
24
+
25
+ static ID id_rndn;
26
+ static ID id_rndz;
27
+ static ID id_rndu;
28
+ static ID id_rndd;
29
+ static ID id_rnda;
30
+ static ID id_rndf;
31
+ static ID id_rndna;
32
+ static ID id_round_nearest;
33
+ static ID id_toward_zero;
34
+ static ID id_round_up;
35
+ static ID id_round_down;
36
+ static ID id_away_from_zero;
37
+ static ID id_faithful_rounding;
38
+ static ID id_nearest;
39
+ static ID id_zero;
40
+ static ID id_up;
41
+ static ID id_down;
42
+ static ID id_away;
43
+ static ID id_faithful;
44
+ static ID id_nearest_ties_away;
45
+ static ID id_prec;
46
+ static ID id_conv;
47
+ static ID id_round;
48
+ static ID id_decimals;
49
+ static ID id_to_mpfr;
50
+ static ID id_chchleft;
51
+ static ID id_orpipe;
52
+
53
+ static mpfr_rnd_t mpfrrb_default_rounding = MPFR_RNDN;
54
+ static ID mpfrrb_default_rounding_id;
55
+ static gmp_randstate_t mpfrrb_gmp_randstate;
56
+
57
+
58
+
59
+ void mpfrrb_bignum_to_mpz(VALUE bignum, mpz_ptr mpz)
60
+ {
61
+ size_t byte_size = rb_absint_size(bignum, NULL);
62
+ mpz_realloc2(mpz, (byte_size+1)*8);
63
+ mpz->_mp_size = (byte_size + sizeof(mp_limb_t) - 1) / sizeof(mp_limb_t);
64
+ if (rb_integer_pack(bignum, mpz->_mp_d, mpz->_mp_alloc, sizeof(mp_limb_t), GMP_NAIL_BITS, INTEGER_PACK_LITTLE_ENDIAN) < 0) {
65
+ mpz->_mp_size = -mpz->_mp_size;
66
+ }
67
+ }
68
+
69
+
70
+ static VALUE mpfrrb_mpz_to_bignum(mpz_ptr mpz)
71
+ {
72
+ int is_neg = 0;
73
+ int nb_limbs = mpz->_mp_size;
74
+ if (nb_limbs < 0) {
75
+ is_neg = 1;
76
+ nb_limbs = -nb_limbs;
77
+ }
78
+ return rb_integer_unpack(mpz->_mp_d, nb_limbs, sizeof(mp_limb_t), GMP_NAIL_BITS,
79
+ INTEGER_PACK_LITTLE_ENDIAN | (is_neg ? INTEGER_PACK_NEGATIVE : 0));
80
+ }
81
+
82
+
83
+ void mpfrrb_rational_to_mpq(VALUE rational, mpq_ptr mpq)
84
+ {
85
+ mpfrrb_bignum_to_mpz(rb_rational_num(rational), &mpq->_mp_num);
86
+ mpfrrb_bignum_to_mpz(rb_rational_den(rational), &mpq->_mp_den);
87
+ }
88
+
89
+
90
+ static VALUE mpfrrb_mpq_to_rational(mpq_ptr mpq)
91
+ {
92
+ return rb_rational_new(mpfrrb_mpz_to_bignum(&mpq->_mp_num), mpfrrb_mpz_to_bignum(&mpq->_mp_den));
93
+ }
94
+
95
+
96
+ /* @return [self]
97
+ */
98
+ static VALUE mpfrrb_MPFR_to_mpfr(VALUE self)
99
+ {
100
+ return self;
101
+ }
102
+
103
+
104
+ /* Return the MPFR version
105
+ * @return [String]
106
+ */
107
+ static VALUE mpfrrb_get_version(VALUE self)
108
+ {
109
+ return rb_str_freeze(rb_str_new_cstr(mpfr_get_version()));
110
+ }
111
+
112
+
113
+ /* Return a string containing the ids of the patches applied to the MPFR library (contents of the PATCHES file), separated by spaces.
114
+ * @return [String]
115
+ */
116
+ static VALUE mpfrrb_get_patches(VALUE self)
117
+ {
118
+ return rb_str_freeze(rb_str_new_cstr(mpfr_get_patches()));
119
+ }
120
+
121
+
122
+ /* Set the default precision to be exactly `prec` bits, where `prec` can be any integer between {MPFR::PREC_MIN} and {MPFR::PREC_MAX}.
123
+ * The precision of a variable means the number of bits used to store its significand.
124
+ * All subsequent calls to `MPFR.new` will use this precision, but previously initialized variables are unaffected.
125
+ * The default precision is set to 53 bits initially.
126
+ * @return [Integer]
127
+ */
128
+ static VALUE mpfrrb_set_default_prec(VALUE self, VALUE prec)
129
+ {
130
+ mpfr_prec_t p = NUM2LL(prec);
131
+ if (p < MPFR_PREC_MIN || p > MPFR_PREC_MAX) {
132
+ rb_raise(rb_eRangeError, "precision must be between %d and %ld, %ld is invalid", MPFR_PREC_MIN, MPFR_PREC_MAX, p);
133
+ }
134
+ mpfr_set_default_prec(p);
135
+ return prec;
136
+ }
137
+
138
+
139
+ /* Return the current default MPFR precision in bits.
140
+ * @return [Integer]
141
+ * @see default_prec=
142
+ */
143
+ static VALUE mpfrrb_get_default_prec(VALUE self)
144
+ {
145
+ (void)self;
146
+ return LL2NUM(mpfr_get_default_prec());
147
+ }
148
+
149
+
150
+ static mpfr_rnd_t mpfrrb_sym2rnd(VALUE sym)
151
+ {
152
+ if (RB_NIL_P(sym)) {
153
+ return mpfrrb_default_rounding;
154
+ }
155
+
156
+ ID id = rb_sym2id(sym);
157
+ mpfr_rnd_t rnd;
158
+
159
+ if (id == id_rndn || id == id_round_nearest || id == id_nearest) {
160
+ rnd = MPFR_RNDN;
161
+ } else if (id == id_rndu || id == id_round_up || id == id_up) {
162
+ rnd = MPFR_RNDU;
163
+ } else if (id == id_rndd || id == id_round_down || id == id_down) {
164
+ rnd = MPFR_RNDD;
165
+ } else if (id == id_rndz || id == id_toward_zero || id == id_zero) {
166
+ rnd = MPFR_RNDZ;
167
+ } else if (id == id_rnda || id == id_away_from_zero || id == id_away) {
168
+ rnd = MPFR_RNDA;
169
+ } else if (id == id_rndf || id == id_faithful_rounding || id == id_faithful) {
170
+ rnd = MPFR_RNDF;
171
+ } else if (id == id_rndna || id == id_nearest_ties_away) {
172
+ rnd = MPFR_RNDNA;
173
+ } else {
174
+ rb_raise(rb_eArgError, "expecting :rndn, :rndu, :rndd, :rndz, :rnda, :rndf, :rndna, :round_up, :round_down, :toward_zero, :away_from_zero or :faithful_rounding, not %" PRIsVALUE, sym);
175
+ }
176
+
177
+ return rnd;
178
+ }
179
+
180
+
181
+ static mpfr_rnd_t mpfrrb_get_round_single_keword(int argc, VALUE *argv)
182
+ {
183
+ mpfr_rnd_t rnd = mpfrrb_default_rounding;
184
+ if (argc > 0) {
185
+ VALUE kw;
186
+ const ID kwkeys[1] = {id_round};
187
+ VALUE kwvalues[1] = {Qundef};
188
+ rb_scan_args(argc, argv, ":", &kw);
189
+ if (!NIL_P(kw)) {
190
+ rb_get_kwargs(kw, kwkeys, 0, 1, kwvalues);
191
+ if (kwvalues[0] != Qundef) {
192
+ rnd = mpfrrb_sym2rnd(kwvalues[0]);
193
+ }
194
+ }
195
+ }
196
+ return rnd;
197
+ }
198
+
199
+
200
+ static mpfr_rnd_t mpfrrb_get_4_args_and_round(int argc, VALUE *argv, VALUE *values)
201
+ {
202
+ mpfr_rnd_t rnd = mpfrrb_default_rounding;
203
+ VALUE kw;
204
+ const ID kwkeys[1] = {id_round};
205
+ VALUE kwvalues[1] = {Qundef};
206
+ rb_scan_args(argc, argv, "4:", &values[0], &values[1], &values[2], &values[3], &kw);
207
+ if (!NIL_P(kw)) {
208
+ rb_get_kwargs(kw, kwkeys, 0, 1, kwvalues);
209
+ if (kwvalues[0] != Qundef) {
210
+ rnd = mpfrrb_sym2rnd(kwvalues[0]);
211
+ }
212
+ }
213
+ return rnd;
214
+ }
215
+
216
+
217
+ static mpfr_rnd_t mpfrrb_get_a_b_c_round(int argc, VALUE *argv, VALUE *a, VALUE *b, VALUE *c)
218
+ {
219
+ mpfr_rnd_t rnd = mpfrrb_default_rounding;
220
+ VALUE kw;
221
+ const ID kwkeys[1] = {id_round};
222
+ VALUE kwvalues[1] = {Qundef};
223
+ rb_scan_args(argc, argv, "3:", a, b, c, &kw);
224
+ if (!NIL_P(kw)) {
225
+ rb_get_kwargs(kw, kwkeys, 0, 1, kwvalues);
226
+ if (kwvalues[0] != Qundef) {
227
+ rnd = mpfrrb_sym2rnd(kwvalues[0]);
228
+ }
229
+ }
230
+ return rnd;
231
+ }
232
+
233
+
234
+ static mpfr_rnd_t mpfrrb_get_a_b_round(int argc, VALUE *argv, VALUE *a, VALUE *b)
235
+ {
236
+ mpfr_rnd_t rnd = mpfrrb_default_rounding;
237
+ VALUE kw;
238
+ const ID kwkeys[1] = {id_round};
239
+ VALUE kwvalues[1] = {Qundef};
240
+ rb_scan_args(argc, argv, "2:", a, b, &kw);
241
+ if (!NIL_P(kw)) {
242
+ rb_get_kwargs(kw, kwkeys, 0, 1, kwvalues);
243
+ if (kwvalues[0] != Qundef) {
244
+ rnd = mpfrrb_sym2rnd(kwvalues[0]);
245
+ }
246
+ }
247
+ return rnd;
248
+ }
249
+
250
+
251
+ static mpfr_rnd_t mpfrrb_get_b_round(int argc, VALUE *argv, VALUE *b)
252
+ {
253
+ mpfr_rnd_t rnd = mpfrrb_default_rounding;
254
+ VALUE kw;
255
+ const ID kwkeys[1] = {id_round};
256
+ VALUE kwvalues[1] = {Qundef};
257
+ rb_scan_args(argc, argv, "1:", b, &kw);
258
+ if (!NIL_P(kw)) {
259
+ rb_get_kwargs(kw, kwkeys, 0, 1, kwvalues);
260
+ if (kwvalues[0] != Qundef) {
261
+ rnd = mpfrrb_sym2rnd(kwvalues[0]);
262
+ }
263
+ }
264
+ return rnd;
265
+ }
266
+
267
+
268
+ /* Set the default rounding used when the `:round` keyword is not set.
269
+ * The value can be:
270
+ * - `:rndn`, `:round_nearest`, `:nearest` : round to nearest, with the even rounding rule (roundTiesToEven in IEEE 754).
271
+ * - `:rndu`, `:round_up`, `:up` : round toward positive infinity (roundTowardPositive in IEEE 754). In case the number to be rounded lies exactly in the middle between two consecutive representable numbers, it is rounded to the one with an even significand; in radix 2, this means that the least significant bit is 0.
272
+ * - `:rndd`, `:round_down`, `:down` : round toward negative infinity (roundTowardNegative in IEEE 754).
273
+ * - `:rndz`, `:toward_zero`, `:zero` : round toward zero (roundTowardZero in IEEE 754).
274
+ * - `:rnda`, `:away_from_zero`, `:away` : round away from zero.
275
+ * - `:rndf`, `:faithful_rounding`, `:faithful` : faithful rounding. This feature is currently experimental.
276
+ * - `:rndna`, `:nearest_ties_away`
277
+ * @param rounding [Symbol]
278
+ * @return [Symbol]
279
+ */
280
+ static VALUE mpfrrb_set_default_rounding(VALUE self, VALUE rounding)
281
+ {
282
+ if (!RB_SYMBOL_P(rounding))
283
+ rb_raise(rb_eTypeError, "expecting a symbol, not a %s", rb_obj_classname(rounding));
284
+
285
+ mpfrrb_default_rounding = mpfrrb_sym2rnd(rounding);
286
+ mpfrrb_default_rounding_id = rb_sym2id(rounding);
287
+
288
+ return rounding;
289
+ }
290
+
291
+
292
+ /* Return the default rounding used when the `:round` keyword is not set.
293
+ * @return [Symbol]
294
+ * @see default_rounding=
295
+ */
296
+ static VALUE mpfrrb_get_default_rounding(VALUE self)
297
+ {
298
+ (void)self;
299
+ return rb_id2sym(mpfrrb_default_rounding_id);
300
+ }
301
+
302
+
303
+ static void mpfrrb_free(void *p)
304
+ {
305
+ mpfr_ptr mp = (mpfr_ptr)p;
306
+ if (mp) {
307
+ mpfr_clear(mp);
308
+ free(mp);
309
+ }
310
+ }
311
+
312
+
313
+ static size_t mpfrrb_size(const void *p)
314
+ {
315
+ mpfr_ptr mp = (mpfr_ptr)p;
316
+ mpfr_prec_t prec = mp->_mpfr_prec;
317
+ size_t limb_size;
318
+ if (prec >= 1) {
319
+ limb_size = ((prec - 1) / GMP_NUMB_BITS + 1 + 1)*sizeof(mp_limb_t);
320
+ } else {
321
+ limb_size = 0;
322
+ }
323
+ return sizeof(__mpfr_struct) + limb_size;
324
+ }
325
+
326
+
327
+ const rb_data_type_t mpfrrb_type = {
328
+ .wrap_struct_name = "MPFR",
329
+ .function = {
330
+ .dmark = NULL,
331
+ .dfree = mpfrrb_free,
332
+ .dsize = mpfrrb_size,
333
+ },
334
+ .parent = NULL,
335
+ .data = NULL,
336
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY
337
+ };
338
+
339
+
340
+ mpfr_ptr mpfrrb_rb2ref_ext(VALUE obj) {
341
+ mpfr_ptr p;
342
+ TypedData_Get_Struct(obj, __mpfr_struct, &mpfrrb_type, p);
343
+ return p;
344
+ }
345
+
346
+
347
+ static inline mpfr_ptr mpfrrb_rb2ref(VALUE obj) {
348
+ mpfr_ptr p;
349
+ TypedData_Get_Struct(obj, __mpfr_struct, &mpfrrb_type, p);
350
+ return p;
351
+ }
352
+
353
+
354
+ VALUE mpfrrb_alloc(VALUE klass)
355
+ {
356
+ mpfr_ptr mp = malloc(sizeof(__mpfr_struct));
357
+ memset(mp, 0, sizeof(__mpfr_struct));
358
+ return TypedData_Wrap_Struct(klass, &mpfrrb_type, mp);
359
+ }
360
+
361
+
362
+ static int mpfrrb_set_internal(mpfr_ptr mp, mpfr_rnd_t rnd, VALUE valrb, VALUE self)
363
+ {
364
+ int r;
365
+ if (RB_FLOAT_TYPE_P(valrb)) {
366
+ r = mpfr_set_d(mp, NUM2DBL(valrb), rnd);
367
+ } else if (RB_FIXNUM_P(valrb)) {
368
+ r = mpfr_set_si(mp, NUM2LL(valrb), rnd);
369
+ } else if (RB_TYPE_P(valrb, T_BIGNUM)) {
370
+ mpz_t mpz;
371
+ mpz_init(mpz);
372
+ mpfrrb_bignum_to_mpz(valrb, mpz);
373
+ r = mpfr_set_z(mp, mpz, rnd);
374
+ mpz_clear(mpz);
375
+ } else if (RB_TYPE_P(valrb, T_RATIONAL)) {
376
+ mpq_t mpq;
377
+ mpq_init(mpq);
378
+ mpfrrb_rational_to_mpq(valrb, mpq);
379
+ r = mpfr_set_q(mp, mpq, rnd);
380
+ mpq_clear(mpq);
381
+ } else if (RB_TYPE_P(valrb, T_STRING)) {
382
+ const char *str = rb_string_value_cstr(&valrb);
383
+ char *endptr;
384
+ r = mpfr_strtofr(mp, str, &endptr, 0, rnd);
385
+ if (*endptr != '\0') {
386
+ rb_raise(rb_eRuntimeError, "cannot convert \"%" PRIsVALUE "\" into an MPFR object", valrb);
387
+ }
388
+ } else if (rb_obj_is_kind_of(valrb, c_MPFR)) {
389
+ r = mpfr_set(mp, mpfrrb_rb2ref(valrb), rnd);
390
+ } else {
391
+ rb_raise(rb_eTypeError, "expecting a float, an integer, a rational, a string or a %s, not a %s", rb_obj_classname(self), rb_obj_classname(valrb));
392
+ }
393
+ return r;
394
+ }
395
+
396
+ /* Create a new MPFR object of a given precision (number of bits), and optionaly initializes it with the given value in the rounding direction.
397
+ * @return [MPFR]
398
+ * @overload new(value = Float::NAN, round: MPFR.default_rounding, prec: MPFR.default_prec)
399
+ * @param value [Float, Integer, Rational, String, MPFR]
400
+ * @param round [Symbol] rounding direction, used only if `value` is given
401
+ * @param prec [Integer] the precision of the MPFR object, that is the size in bits of the significand
402
+ */
403
+ static VALUE mpfrrb_initialize(int argc, VALUE *argv, VALUE self)
404
+ {
405
+ if (argc == 0) {
406
+ mpfr_init(mpfrrb_rb2ref(self));
407
+ return self;
408
+ }
409
+
410
+ VALUE valrb;
411
+ VALUE kw;
412
+ const ID kwkeys[2] = {id_prec, id_round};
413
+ VALUE kwvalues[2] = {Qundef, Qundef};
414
+ mpfr_rnd_t rnd = mpfrrb_default_rounding;
415
+ mpfr_prec_t prec = mpfr_get_default_prec();
416
+ rb_scan_args(argc, argv, "01:", &valrb, &kw);
417
+ if (!NIL_P(kw)) {
418
+ rb_get_kwargs(kw, kwkeys, 0, 2, kwvalues);
419
+ if (kwvalues[0] != Qundef) {
420
+ if (!rb_integer_type_p(kwvalues[0])) {
421
+ rb_raise(rb_eTypeError, "precision must be an integer, not a %s", rb_obj_classname(kwvalues[0]));
422
+ }
423
+ prec = NUM2ULL(kwvalues[0]);
424
+ if (prec < MPFR_PREC_MIN || prec > MPFR_PREC_MAX) {
425
+ rb_raise(rb_eRangeError, "precision must be between %d and %ld, %ld is invalid", MPFR_PREC_MIN, MPFR_PREC_MAX, prec);
426
+ }
427
+ }
428
+ if (kwvalues[1] != Qundef) {
429
+ rnd = mpfrrb_sym2rnd(kwvalues[1]);
430
+ }
431
+ }
432
+
433
+ mpfr_ptr mp = mpfrrb_rb2ref(self);
434
+ mpfr_init2(mp, prec);
435
+
436
+ if (!NIL_P(valrb)) {
437
+ mpfrrb_set_internal(mp, rnd, valrb, self);
438
+ }
439
+
440
+ return self;
441
+ }
442
+
443
+
444
+ /* Set the value of the MPFR object.
445
+ * @return [Integer]
446
+ * @overload set(value, round: MPFR.default_rounding)
447
+ * @param value [Float, Integer, Rational, String, MPFR]
448
+ * @param rnd [Symbol], either `:nearest`, `:up`, `:down`, `:zero`, `:rndn`, `:rndu`, `:rndd`, `:rndz`, `:rnda`, `:rndf`, `:rndna`, `:round_up`, `:round_down`, `:toward_zero`, `:away_from_zero` or `:faithful_rounding`
449
+ */
450
+ static VALUE mpfrrb_set(int argc, VALUE *argv, VALUE self)
451
+ {
452
+ VALUE valrb;
453
+ VALUE kw;
454
+ const ID kwkeys[1] = {id_round};
455
+ VALUE kwvalues[1] = {Qundef};
456
+ rb_scan_args(argc, argv, "1:", &valrb, &kw);
457
+ mpfr_rnd_t rnd = mpfrrb_default_rounding;
458
+ if (!NIL_P(kw)) {
459
+ rb_get_kwargs(kw, kwkeys, 0, 1, kwvalues);
460
+ if (kwvalues[0] != Qundef) {
461
+ rnd = mpfrrb_sym2rnd(kwvalues[0]);
462
+ }
463
+ }
464
+ mpfr_ptr mp = mpfrrb_rb2ref(self);
465
+ int r = mpfrrb_set_internal(mp, rnd, valrb, self);
466
+ return INT2NUM(r);
467
+ }
468
+
469
+
470
+ /* Return a MPFR object with a precision of 53 bits whose value is self.
471
+ * @return [MPFR]
472
+ */
473
+ static VALUE mpfrrb_Float_to_mpfr(VALUE self)
474
+ {
475
+ VALUE obj = mpfrrb_alloc(c_MPFR);
476
+ mpfr_ptr mp = mpfrrb_rb2ref(obj);
477
+ mpfr_init2(mp, 53);
478
+ mpfr_set_d(mp, NUM2DBL(self), MPFR_RNDN);
479
+ return obj;
480
+ }
481
+
482
+
483
+ /* Return a MPFR object with a just enough bits of precision to accomodate the value of self.
484
+ * @return [MPFR]
485
+ */
486
+ static VALUE mpfrrb_Integer_to_mpfr(VALUE self)
487
+ {
488
+ if (RB_FIXNUM_P(self)) {
489
+ long int v = NUM2LL(self);
490
+ mpfr_prec_t p;
491
+ if (v > 0) {
492
+ p = (mpfr_prec_t)ceil(log2((double)(v + 1)));
493
+ } else if (v < 0) {
494
+ p = (mpfr_prec_t)ceil(log2((double)(1 - v)));
495
+ } else {
496
+ p = 1;
497
+ }
498
+ VALUE obj = mpfrrb_alloc(c_MPFR);
499
+ mpfr_ptr mp = mpfrrb_rb2ref(obj);
500
+ mpfr_init2(mp, p);
501
+ mpfr_set_si(mp, v, MPFR_RNDN);
502
+ return obj;
503
+ } else {
504
+ mpz_t mpz;
505
+ mpz_init(mpz);
506
+ mpfrrb_bignum_to_mpz(self, mpz);
507
+ int nlz_bits_ret;
508
+ size_t nb_bytes = rb_absint_size(self, &nlz_bits_ret);
509
+ mpfr_prec_t p = nb_bytes*8 - nlz_bits_ret;
510
+ VALUE obj = mpfrrb_alloc(c_MPFR);
511
+ mpfr_ptr mp = mpfrrb_rb2ref(obj);
512
+ mpfr_init2(mp, p);
513
+ mpfr_set_z(mp, mpz, MPFR_RNDN);
514
+ mpz_clear(mpz);
515
+ return obj;
516
+ }
517
+ }
518
+
519
+
520
+ static VALUE mpfrrb_object_to_mpfr(VALUE obj)
521
+ {
522
+ if (RB_FLOAT_TYPE_P(obj)) {
523
+ return mpfrrb_Float_to_mpfr(obj);
524
+ } else if (RB_INTEGER_TYPE_P(obj)) {
525
+ return mpfrrb_Integer_to_mpfr(obj);
526
+ } else if (rb_obj_is_kind_of(obj, c_MPFR)) {
527
+ return obj;
528
+ }
529
+ return rb_funcallv(obj, id_to_mpfr, 0, NULL);
530
+ }
531
+
532
+
533
+ /* Return the precision of `self`, i.e., the number of bits used to store its significand.
534
+ * @return [Integer]
535
+ */
536
+ static VALUE mpfrrb_get_prec(VALUE self)
537
+ {
538
+ return LL2NUM(mpfr_get_prec(mpfrrb_rb2ref(self)));
539
+ }
540
+
541
+
542
+ /* Set the precision of `self` to be exactly `prec` bits, and set its value to NaN.
543
+ * The previous value stored in `self` is lost.
544
+ * In case you want to keep the previous value stored in `self`, use {#prec_round} instead.
545
+ * @see prec_round
546
+ */
547
+ static VALUE mpfrrb_set_prec(VALUE self, VALUE precrb)
548
+ {
549
+ mpfr_prec_t prec = NUM2LL(precrb);
550
+ if (prec < MPFR_PREC_MIN || prec > MPFR_PREC_MAX) {
551
+ rb_raise(rb_eRangeError, "precision must be between %d and %ld, %ld is invalid", MPFR_PREC_MIN, MPFR_PREC_MAX, prec);
552
+ }
553
+ mpfr_set_prec(mpfrrb_rb2ref(self), prec);
554
+ return precrb;
555
+ }
556
+
557
+
558
+ // static VALUE mpfrrb_to_s_autoprec(mpfr_ptr mp, char conv, mpfr_rnd_t rnd)
559
+ // {
560
+ // VALUE res;
561
+ // int ndigits = mpfr_get_str_ndigits(10, mpfr_get_prec(mp));
562
+ // char *str = NULL;
563
+ // char fmt[16];
564
+ // ruby_snprintf(fmt, sizeof(fmt), "%%.*R*%c", conv);
565
+ // int l = mpfr_asprintf(&str, fmt, ndigits, rnd, mp);
566
+ // // printf("ndigits = %d, str = \"%s\", l = %d\n", ndigits, str, l);
567
+ // if (l < 1 || str == NULL) {
568
+ // return Qnil;
569
+ // }
570
+ // int start_pos = -1;
571
+ // int point_pos = -1;
572
+ // int trail_pos = -1;
573
+ // int i = 0;
574
+ // char c;
575
+ // while ((c = str[i]) != '\0') {
576
+ // if (c >= '0' && c <= '9' && start_pos < 0) {
577
+ // start_pos = i;
578
+ // } else if (c == '.' && point_pos < 0) {
579
+ // point_pos = i;
580
+ // } else if (c != '-' && c != '+' && (c < '0' || c > '9') && trail_pos < 0) {
581
+ // trail_pos = i;
582
+ // }
583
+ // i++;
584
+ // }
585
+ // if (trail_pos < 0) {
586
+ // trail_pos = l;
587
+ // }
588
+ // // printf("start_pos = %d, point_pos = %d, trail_pos = %d\n", start_pos, point_pos, trail_pos);
589
+ // if (start_pos < 0 || point_pos < 0) {
590
+ // goto mpfrrb_to_s_autoprec_end;
591
+ // }
592
+ // int integer_len = point_pos - start_pos;
593
+ // int new_frac_len = ndigits - integer_len;
594
+ // // printf("integer_len = %d, new_frac_len = %d\n", integer_len, new_frac_len);
595
+ // if (new_frac_len < 1) {
596
+ // goto mpfrrb_to_s_autoprec_end;
597
+ // }
598
+ // int new_trail_pos = point_pos + new_frac_len + 1;
599
+ // // printf("new_trail_pos = %d\n", new_trail_pos);
600
+ // if (new_trail_pos >= trail_pos || new_trail_pos == l) {
601
+ // goto mpfrrb_to_s_autoprec_end;
602
+ // }
603
+ //
604
+ // while (1) {
605
+ // c = str[trail_pos++];
606
+ // str[new_trail_pos++] = c;
607
+ // if (c == '\0') {
608
+ // break;
609
+ // }
610
+ // }
611
+ //
612
+ // mpfrrb_to_s_autoprec_end:
613
+ // res = rb_str_new(str, l);
614
+ // mpfr_free_str(str);
615
+ // return res;
616
+ // }
617
+
618
+
619
+ /* Return a string representation of the number.
620
+ * @return [String]
621
+ * @overload to_s(conv: 'g', round: :nearest, decimals: nil)
622
+ * @param conf [String]
623
+ * The conversion specifier can be:
624
+ * - `'a'`, `'A'`: hex float, C99 style,
625
+ * - `'b'`: binary output,
626
+ * - `'e'`, `'E'`: scientific-format float,
627
+ * - `'f'`, `'F'`: fixed-point float,
628
+ * - `'g'`, `'G'`: fixed-point or scientific float.
629
+ * @param rnd [Symbol] Rounding direction, either `:rndn`, `:rndu`, `:rndd`, `:rndz`, `:rnda`, `:rndf`, `:rndna`, `:round_up`, `:round_down`, `:toward_zero`, `:away_from_zero` or `:faithful_rounding`
630
+ * @param decimals [Integer] number of digits to display.
631
+ */
632
+ static VALUE mpfrrb_to_s(int argc, VALUE *argv, VALUE self)
633
+ {
634
+ VALUE kw;
635
+ const ID kwkeys[3] = {id_conv, id_round, id_decimals};
636
+ VALUE kwvalues[3] = {Qundef, Qundef, Qundef};
637
+
638
+ mpfr_rnd_t rnd = MPFR_RNDN;
639
+ char conv = 'g';
640
+ int n_decimals = 0;
641
+
642
+ rb_scan_args(argc, argv, ":", &kw);
643
+ if (!NIL_P(kw)) {
644
+ rb_get_kwargs(kw, kwkeys, 0, 3, kwvalues);
645
+ if (kwvalues[0] != Qundef) {
646
+ Check_Type(kwvalues[0], T_STRING);
647
+ const char *convstr = RSTRING_PTR(kwvalues[0]);
648
+ int len = RSTRING_LEN(kwvalues[0]);
649
+ if (len != 1 || (convstr[0] != 'a' && convstr[0] != 'A' && convstr[0] != 'b' && convstr[0] != 'e' && convstr[0] != 'E' && convstr[0] != 'f' && convstr[0] != 'F' && convstr[0] != 'g' && convstr[0] != 'G')) {
650
+ rb_raise(rb_eArgError, "conv must be 'a', 'A', 'b', 'e', 'E', 'f', 'F', 'g' or 'G', \"%" PRIsVALUE "\" is invalid", kwvalues[0]);
651
+ }
652
+ conv = convstr[0];
653
+ }
654
+ if (kwvalues[1] != Qundef) {
655
+ rnd = mpfrrb_sym2rnd(kwvalues[1]);
656
+ }
657
+ if (kwvalues[2] != Qundef) {
658
+ n_decimals = NUM2INT(kwvalues[2]);
659
+ }
660
+ }
661
+
662
+ mpfr_ptr mp = mpfrrb_rb2ref(self);
663
+ if (mpfr_nan_p(mp)) {
664
+ return rb_sprintf("NaN");
665
+ } else if (mpfr_inf_p(mp)) {
666
+ if (mpfr_sgn(mp) < 0) {
667
+ return rb_sprintf("-Infinity");
668
+ } else {
669
+ return rb_sprintf("Infinity");
670
+ }
671
+ }
672
+
673
+ // if (n_decimals == 0 && conv != 'a' && conv != 'A' && conv != 'b' && conv != 'B') {
674
+ // return mpfrrb_to_s_autoprec(mp, conv, rnd);
675
+ // }
676
+ if (n_decimals == 0 && conv != 'a' && conv != 'A' && conv != 'b' && conv != 'B') {
677
+ n_decimals = mpfr_get_str_ndigits(10, mpfr_get_prec(mp));
678
+ }
679
+
680
+ char fmt[16];
681
+ char *str = NULL;
682
+ int s;
683
+ if (n_decimals > 0) {
684
+ ruby_snprintf(fmt, sizeof(fmt), "%%.*R*%c", conv);
685
+ s = mpfr_asprintf(&str, fmt, n_decimals, rnd, mp);
686
+ } else {
687
+ ruby_snprintf(fmt, sizeof(fmt), "%%R*%c", conv);
688
+ s = mpfr_asprintf(&str, fmt, rnd, mp);
689
+ }
690
+ if (s < 1 || str == NULL) {
691
+ return Qnil;
692
+ }
693
+ VALUE res = rb_str_new(str, s);
694
+ mpfr_free_str(str);
695
+ return res;
696
+ }
697
+
698
+
699
+ /* @return [Ingeger, nil] either -1 or 1
700
+ */
701
+ static VALUE mpfrrb_get_sign(VALUE self)
702
+ {
703
+ mpfr_ptr mp = mpfrrb_rb2ref(self);
704
+ if (mpfr_nan_p(mp)) {
705
+ return Qnil;
706
+ }
707
+ return INT2NUM(mpfr_sgn(mp) >= 0 ? 1 : -1);
708
+ }
709
+
710
+
711
+ /* Set the sign of `self` to the sign of the argument.
712
+ * @param s [Integer], either 1 or -1
713
+ */
714
+ static VALUE mpfrrb_set_sign(VALUE self, VALUE s)
715
+ {
716
+ int p = NUM2INT(s);
717
+ mpfr_ptr mp = mpfrrb_rb2ref(self);
718
+ mpfr_setsign(mp, mp, p < 0, MPFR_RNDN);
719
+ return s;
720
+ }
721
+
722
+
723
+ /* Return the exponent of `self`, assuming that `self` is a non-zero ordinary number and the significand is considered in [1, 2).
724
+ * @return [Integer,nil]
725
+ */
726
+ static VALUE mpfrrb_get_exponent(VALUE self)
727
+ {
728
+ mpfr_ptr mp = mpfrrb_rb2ref(self);
729
+ if (mpfr_nan_p(mp) || mpfr_inf_p(mp)) {
730
+ return Qnil;
731
+ } else if (mpfr_zero_p(mp)) {
732
+ return INT2NUM(0);
733
+ }
734
+ return LL2NUM(mpfr_get_exp(mp) - 1ll);
735
+ }
736
+
737
+
738
+ /* Set the exponent of `self` to `e`, assuming the significand in [1, 2).
739
+ * `self` must be an ordinary number (not nan, infinity nor zero).
740
+ * @param e [Integer]
741
+ */
742
+ static VALUE mpfrrb_set_exponent(VALUE self, VALUE e)
743
+ {
744
+ mpfr_exp_t p = NUM2LONG(e);
745
+ mpfr_ptr mp = mpfrrb_rb2ref(self);
746
+ if (!mpfr_regular_p(mp)) {
747
+ rb_raise(rb_eRuntimeError, "trying to set the exponent of a non-regular MPFR object");
748
+ }
749
+ p += 1;
750
+ mpfr_set_exp(mp, p);
751
+ return e;
752
+ }
753
+
754
+
755
+ /* Tels if self is zero.
756
+ * @return [Boolean]
757
+ */
758
+ static VALUE mpfrrb_is_zero(VALUE self)
759
+ {
760
+ return mpfr_zero_p(mpfrrb_rb2ref(self)) ? Qtrue : Qfalse;
761
+ }
762
+
763
+
764
+ /* Tels if self does not represent a number.
765
+ * @return [Boolean]
766
+ */
767
+ static VALUE mpfrrb_is_nan(VALUE self)
768
+ {
769
+ return mpfr_nan_p(mpfrrb_rb2ref(self)) ? Qtrue : Qfalse;
770
+ }
771
+
772
+
773
+ /* Tels if self is an infinity.
774
+ * @return [Boolean]
775
+ */
776
+ static VALUE mpfrrb_is_infinite(VALUE self)
777
+ {
778
+ return mpfr_inf_p(mpfrrb_rb2ref(self)) ? Qtrue : Qfalse;
779
+ }
780
+
781
+
782
+ /* Tels if self is neither an infinity nor NaN.
783
+ * @return [Boolean]
784
+ */
785
+ static VALUE mpfrrb_is_finite(VALUE self)
786
+ {
787
+ mpfr_ptr mp = mpfrrb_rb2ref(self);
788
+ return mpfr_number_p(mp) ? Qtrue : Qfalse;
789
+ }
790
+
791
+
792
+ /* Tels if the fractional part of self is null.
793
+ * @return [Boolean]
794
+ */
795
+ static VALUE mpfrrb_is_integer(VALUE self)
796
+ {
797
+ mpfr_ptr mp = mpfrrb_rb2ref(self);
798
+ return mpfr_integer_p(mp) ? Qtrue : Qfalse;
799
+ }
800
+
801
+
802
+ /* @return [Float]
803
+ * @overload to_f(round: MPFR.default_rounding)
804
+ * @param rnd [Symbol]
805
+ */
806
+ static VALUE mpfrrb_to_f(int argc, VALUE *argv, VALUE self)
807
+ {
808
+ mpfr_rnd_t rnd = mpfrrb_get_round_single_keword(argc, argv);
809
+ return DBL2NUM(mpfr_get_d(mpfrrb_rb2ref(self), rnd));
810
+ }
811
+
812
+
813
+ /* @return [Integer]
814
+ * @overload to_i(round: MPFR.default_rounding)
815
+ * @param rnd [Symbol]
816
+ */
817
+ static VALUE mpfrrb_to_i(int argc, VALUE *argv, VALUE self)
818
+ {
819
+ mpfr_ptr mp = mpfrrb_rb2ref(self);
820
+ if (mpfr_nan_p(mp)) {
821
+ rb_raise(rb_eFloatDomainError, "NaN");
822
+ } else if (mpfr_inf_p(mp)) {
823
+ rb_raise(rb_eFloatDomainError, "Infinity");
824
+ } else if (mpfr_zero_p(mp)) {
825
+ return INT2NUM(0);
826
+ }
827
+
828
+ mpfr_rnd_t rnd = mpfrrb_get_round_single_keword(argc, argv);
829
+
830
+ if (mpfr_fits_slong_p(mp, rnd)) {
831
+ return LL2NUM(mpfr_get_si(mp, rnd));
832
+ }
833
+
834
+ mpz_t mpz;
835
+ mpz_init(mpz);
836
+ mpfr_get_z(mpz, mp, rnd);
837
+ VALUE rbint = mpfrrb_mpz_to_bignum(mpz);
838
+ mpz_clear(mpz);
839
+ return rbint;
840
+ }
841
+
842
+
843
+ /* Convert the MPFR object to a rational.
844
+ * Conversion is always exact, no rounding has to be specified.
845
+ * @return [Rational]
846
+ */
847
+ static VALUE mpfrrb_to_r(VALUE self)
848
+ {
849
+ mpfr_ptr mp = mpfrrb_rb2ref(self);
850
+ if (mpfr_nan_p(mp)) {
851
+ rb_raise(rb_eFloatDomainError, "NaN");
852
+ } else if (mpfr_inf_p(mp)) {
853
+ rb_raise(rb_eFloatDomainError, "Infinity");
854
+ } else if (mpfr_zero_p(mp)) {
855
+ return rb_rational_new(INT2NUM(0), INT2NUM(1));
856
+ }
857
+
858
+ mpq_t mpq;
859
+ mpq_init(mpq);
860
+ mpfr_get_q(mpq, mp);
861
+ VALUE rat = mpfrrb_mpq_to_rational(mpq);
862
+ mpq_clear(mpq);
863
+ return rat;
864
+ }
865
+
866
+
867
+ /* Set `self` to NaN.
868
+ * @return [self]
869
+ */
870
+ static VALUE mpfrrb_set_nan(VALUE self)
871
+ {
872
+ mpfr_ptr mp = mpfrrb_rb2ref(self);
873
+ mpfr_set_nan(mp);
874
+ return self;
875
+ }
876
+
877
+
878
+ /* Set `self` to zero.
879
+ * @return [self]
880
+ * @overload set_zero(sign = 1)
881
+ * @param sign [Integer] the sign bit is set if `sign` < 0
882
+ */
883
+ static VALUE mpfrrb_set_zero(int argc, VALUE *argv, VALUE self)
884
+ {
885
+ VALUE signrb;
886
+ int sign = 1;
887
+ if (argc > 0) {
888
+ rb_scan_args(argc, argv, "01", &signrb);
889
+ if (!NIL_P(signrb)) {
890
+ sign = NUM2INT(signrb);
891
+ }
892
+ }
893
+ mpfr_ptr mp = mpfrrb_rb2ref(self);
894
+ mpfr_set_zero(mp, sign);
895
+ return self;
896
+ }
897
+
898
+
899
+ /* Set `self` to infinity.
900
+ * @return [self]
901
+ * @overload set_infinity(sign = 1)
902
+ * @param sign [Integer] the sign bit is set if `sign` < 0
903
+ */
904
+ static VALUE mpfrrb_set_infinity(int argc, VALUE *argv, VALUE self)
905
+ {
906
+ VALUE signrb;
907
+ int sign = 1;
908
+ if (argc > 0) {
909
+ rb_scan_args(argc, argv, "01", &signrb);
910
+ if (!NIL_P(signrb)) {
911
+ sign = NUM2INT(signrb);
912
+ }
913
+ }
914
+ mpfr_ptr mp = mpfrrb_rb2ref(self);
915
+ mpfr_set_inf(mp, sign);
916
+ return self;
917
+ }
918
+
919
+
920
+ /* Round `self` according to `round` with precision `prec`.
921
+ * If `prec` is greater than or equal to the precision of `self`, then new space is allocated for the significand, and it is filled with zeros.
922
+ * Otherwise, the significand is rounded to precision `prec` with the given direction; no memory reallocation to free the unused limbs is done.
923
+ * In both cases, the precision of `self` is changed to `prec`.
924
+ * @return [Integer]
925
+ * @overload prec_round(prec, round: MPFR.default_rounding)
926
+ * @param prec [Integer] The new precision. It must be an integer between MPFR::PREC_MIN and MPFR::PREC_MAX (otherwise the behavior is undefined).
927
+ * @param round [Symbol]
928
+ */
929
+ static VALUE mpfrrb_prec_round(int argc, VALUE *argv, VALUE self)
930
+ {
931
+ VALUE precrb;
932
+ VALUE kw;
933
+ const ID kwkeys[1] = {id_round};
934
+ VALUE kwvalues[1] = {Qundef};
935
+ rb_scan_args(argc, argv, "1:", &precrb, &kw);
936
+ mpfr_rnd_t rnd = mpfrrb_default_rounding;
937
+ mpfr_prec_t prec = NUM2LL(precrb);
938
+ if (prec < MPFR_PREC_MIN || prec > MPFR_PREC_MAX) {
939
+ rb_raise(rb_eRangeError, "precision must be between %d and %ld, %ld is invalid", MPFR_PREC_MIN, MPFR_PREC_MAX, prec);
940
+ }
941
+ if (!NIL_P(kw)) {
942
+ rb_get_kwargs(kw, kwkeys, 0, 1, kwvalues);
943
+ if (kwvalues[0] != Qundef) {
944
+ rnd = mpfrrb_sym2rnd(kwvalues[0]);
945
+ }
946
+ }
947
+ mpfr_ptr mp = mpfrrb_rb2ref(self);
948
+ int r = mpfr_prec_round(mp, prec, rnd);
949
+ return INT2NUM(r);
950
+ }
951
+
952
+
953
+ /* Set `self` to the logarithm of 2, rounded in the given direction.
954
+ * @return [Integer]
955
+ * @overload set_log2(round: MPFR.default_rounding)
956
+ */
957
+ static VALUE mpfrrb_set_log2(int argc, VALUE *argv, VALUE self)
958
+ {
959
+ mpfr_rnd_t rnd = mpfrrb_get_round_single_keword(argc, argv);
960
+ return INT2NUM(mpfr_const_log2(mpfrrb_rb2ref(self), rnd));
961
+ }
962
+
963
+
964
+ /* Set `self` to the value of Pi, rounded in the given direction.
965
+ * @return [Integer]
966
+ * @overload set_pi(round: MPFR.default_rounding)
967
+ */
968
+ static VALUE mpfrrb_set_pi(int argc, VALUE *argv, VALUE self)
969
+ {
970
+ mpfr_rnd_t rnd = mpfrrb_get_round_single_keword(argc, argv);
971
+ return INT2NUM(mpfr_const_pi(mpfrrb_rb2ref(self), rnd));
972
+ }
973
+
974
+
975
+ /* Set `self` to the value of of Euler's constant 0.577..., rounded in the given direction.
976
+ * @return [Integer]
977
+ * @overload set_euler(round: MPFR.default_rounding)
978
+ */
979
+ static VALUE mpfrrb_set_euler(int argc, VALUE *argv, VALUE self)
980
+ {
981
+ mpfr_rnd_t rnd = mpfrrb_get_round_single_keword(argc, argv);
982
+ return INT2NUM(mpfr_const_euler(mpfrrb_rb2ref(self), rnd));
983
+ }
984
+
985
+
986
+ /* Set `self` to the value of of Catalan's constant 0.915..., rounded in the given direction.
987
+ * @return [Integer]
988
+ * @overload set_catalan(round: MPFR.default_rounding)
989
+ */
990
+ static VALUE mpfrrb_set_catalan(int argc, VALUE *argv, VALUE self)
991
+ {
992
+ mpfr_rnd_t rnd = mpfrrb_get_round_single_keword(argc, argv);
993
+ return INT2NUM(mpfr_const_catalan(mpfrrb_rb2ref(self), rnd));
994
+ }
995
+
996
+
997
+ /* Return `[d, e]` such that 1 ≤ abs(d) < 2 and `d` times 2 raised to `e` equals `self` rounded to double precision,
998
+ * using the given rounding mode.
999
+ * @return [Array<Float, Integer>]
1000
+ * @overload get_d_2exp(round: MPFR.default_rounding)
1001
+ */
1002
+ static VALUE mpfrrb_get_d_2exp(int argc, VALUE *argv, VALUE self)
1003
+ {
1004
+ mpfr_rnd_t rnd = mpfrrb_get_round_single_keword(argc, argv);
1005
+ long e = 0;
1006
+ double d = mpfr_get_d_2exp(&e, mpfrrb_rb2ref(self), rnd);
1007
+ d *= 2.0;
1008
+ e -= 1;
1009
+ VALUE rbd = DBL2NUM(d);
1010
+ VALUE rbe = isfinite(d) ? LONG2NUM(e) : Qnil;
1011
+ return rb_ary_new_from_args(2, rbd, rbe);
1012
+ }
1013
+
1014
+
1015
+ /* Return `[i, e]` such that `self` exactly equals `i` times 2 raised to the power `e`.
1016
+ * @return [Array<Integer, Integer>]
1017
+ */
1018
+ static VALUE mpfrrb_get_i_2exp(VALUE self)
1019
+ {
1020
+ mpfr_ptr mp = mpfrrb_rb2ref(self);
1021
+ if (mpfr_nan_p(mp)) {
1022
+ rb_raise(rb_eFloatDomainError, "NaN");
1023
+ } else if (mpfr_inf_p(mp)) {
1024
+ rb_raise(rb_eFloatDomainError, "Infinity");
1025
+ } else if (mpfr_zero_p(mp)) {
1026
+ return rb_ary_new_from_args(2, INT2NUM(0), INT2NUM(0));
1027
+ }
1028
+
1029
+ mpz_t mpz;
1030
+ mpz_init(mpz);
1031
+ mpfr_exp_t e = mpfr_get_z_2exp(mpz, mpfrrb_rb2ref(self));
1032
+ VALUE rbi = mpfrrb_mpz_to_bignum(mpz);
1033
+ mpz_clear(mpz);
1034
+ return rb_ary_new_from_args(2, rbi, LL2NUM(e));
1035
+ }
1036
+
1037
+
1038
+ /* Return a new MPFR object from the value of `i` multiplied by two to the power `e`.
1039
+ * The precision of the returned object is set to accomodate `i` exactly.
1040
+ * @param i [Integer]
1041
+ * @param e [Integer]
1042
+ * @return [MPFR] i*2^e
1043
+ */
1044
+ static VALUE mpfrrb_i_2exp(VALUE self, VALUE i, VALUE e)
1045
+ {
1046
+ (void)self;
1047
+ mpfr_exp_t ve = NUM2LL(e);
1048
+ VALUE ret;
1049
+ if (RB_FIXNUM_P(i)) {
1050
+ long int v = NUM2LL(i);
1051
+ mpfr_prec_t p;
1052
+ if (v > 0) {
1053
+ p = (mpfr_prec_t)ceil(log2((double)(v + 1)));
1054
+ } else if (v < 0) {
1055
+ p = (mpfr_prec_t)ceil(log2((double)(1 - v)));
1056
+ } else {
1057
+ p = 1;
1058
+ }
1059
+ ret = mpfrrb_alloc(c_MPFR);
1060
+ mpfr_ptr mp = mpfrrb_rb2ref(ret);
1061
+ mpfr_init2(mp, p);
1062
+ mpfr_set_si_2exp(mp, v, ve, MPFR_RNDN);
1063
+ } else if (RB_INTEGER_TYPE_P(i)) {
1064
+ mpz_t mpz;
1065
+ mpz_init(mpz);
1066
+ mpfrrb_bignum_to_mpz(i, mpz);
1067
+ int nlz_bits_ret;
1068
+ size_t nb_bytes = rb_absint_size(i, &nlz_bits_ret);
1069
+ mpfr_prec_t p = nb_bytes*8 - nlz_bits_ret;
1070
+ ret = mpfrrb_alloc(c_MPFR);
1071
+ mpfr_ptr mp = mpfrrb_rb2ref(ret);
1072
+ mpfr_init2(mp, p);
1073
+ mpfr_set_z_2exp(mp, mpz, ve, MPFR_RNDN);
1074
+ mpz_clear(mpz);
1075
+ } else {
1076
+ rb_raise(rb_eTypeError, "expecting an integer, not a %s", rb_obj_classname(i));
1077
+ }
1078
+
1079
+ return ret;
1080
+ }
1081
+
1082
+
1083
+ /* Set the value of `self` to `a` + `b` rounded in the direction `round`.
1084
+ * @return [Integer]
1085
+ * @overload add(a, b, round: MPFR.default_rounding)
1086
+ * @param a [MPFR]
1087
+ * @param b [MPFR, Float, Integer, Rational]
1088
+ */
1089
+ static VALUE mpfrrb_add(int argc, VALUE *argv, VALUE self)
1090
+ {
1091
+ VALUE a, b;
1092
+ mpfr_rnd_t rnd = mpfrrb_get_a_b_round(argc, argv, &a, &b);
1093
+ a = mpfrrb_object_to_mpfr(a);
1094
+ mpfr_ptr mpr = mpfrrb_rb2ref(self);
1095
+ mpfr_ptr mpa = mpfrrb_rb2ref(a);
1096
+ int r;
1097
+ if (RB_FLOAT_TYPE_P(b)) {
1098
+ r = mpfr_add_d(mpr, mpa, NUM2DBL(b), rnd);
1099
+ } else if (RB_FIXNUM_P(b)) {
1100
+ r = mpfr_add_si(mpr, mpa, NUM2LL(b), rnd);
1101
+ } else if (RB_INTEGER_TYPE_P(b)) {
1102
+ mpz_t mpz;
1103
+ mpz_init(mpz);
1104
+ mpfrrb_bignum_to_mpz(b, mpz);
1105
+ r = mpfr_add_z(mpr, mpa, mpz, rnd);
1106
+ mpz_clear(mpz);
1107
+ } else if (RB_TYPE_P(b, T_RATIONAL)) {
1108
+ mpq_t mpq;
1109
+ mpq_init(mpq);
1110
+ mpfrrb_rational_to_mpq(b, mpq);
1111
+ r = mpfr_add_q(mpr, mpa, mpq, rnd);
1112
+ mpq_clear(mpq);
1113
+ } else {
1114
+ b = mpfrrb_object_to_mpfr(b);
1115
+ r = mpfr_add(mpr, mpa, mpfrrb_rb2ref(b), rnd);
1116
+ }
1117
+ return INT2NUM(r);
1118
+ }
1119
+
1120
+
1121
+ /* Set the value of `self` to `self` + `b` rounded in the direction `round`.
1122
+ * @return [Integer]
1123
+ * @overload add!(b, round: MPFR.default_rounding)
1124
+ * @param b [MPFR, Float, Integer, Rational]
1125
+ */
1126
+ static VALUE mpfrrb_add_B(int argc, VALUE *argv, VALUE self)
1127
+ {
1128
+ VALUE b;
1129
+ mpfr_rnd_t rnd = mpfrrb_get_b_round(argc, argv, &b);
1130
+ mpfr_ptr mpr = mpfrrb_rb2ref(self);
1131
+ int r;
1132
+ if (RB_FLOAT_TYPE_P(b)) {
1133
+ r = mpfr_add_d(mpr, mpr, NUM2DBL(b), rnd);
1134
+ } else if (RB_FIXNUM_P(b)) {
1135
+ r = mpfr_add_si(mpr, mpr, NUM2LL(b), rnd);
1136
+ } else if (RB_INTEGER_TYPE_P(b)) {
1137
+ mpz_t mpz;
1138
+ mpz_init(mpz);
1139
+ mpfrrb_bignum_to_mpz(b, mpz);
1140
+ r = mpfr_add_z(mpr, mpr, mpz, rnd);
1141
+ mpz_clear(mpz);
1142
+ } else if (RB_TYPE_P(b, T_RATIONAL)) {
1143
+ mpq_t mpq;
1144
+ mpq_init(mpq);
1145
+ mpfrrb_rational_to_mpq(b, mpq);
1146
+ r = mpfr_add_q(mpr, mpr, mpq, rnd);
1147
+ mpq_clear(mpq);
1148
+ } else {
1149
+ b = mpfrrb_object_to_mpfr(b);
1150
+ r = mpfr_add(mpr, mpr, mpfrrb_rb2ref(b), rnd);
1151
+ }
1152
+ return INT2NUM(r);
1153
+ }
1154
+
1155
+
1156
+ /* Set the value of `self` to `a` - `b` rounded in the direction `round`.
1157
+ * @return [Integer]
1158
+ * @overload sub(a, b, round: MPFR.default_rounding)
1159
+ * @param a [MPFR, Float, Integer]
1160
+ * @param b [MPFR, Float, Integer, Rational]
1161
+ */
1162
+ static VALUE mpfrrb_sub(int argc, VALUE *argv, VALUE self)
1163
+ {
1164
+ VALUE a, b;
1165
+ mpfr_rnd_t rnd = mpfrrb_get_a_b_round(argc, argv, &a, &b);
1166
+ a = mpfrrb_object_to_mpfr(a);
1167
+ mpfr_ptr mpr = mpfrrb_rb2ref(self);
1168
+ int r;
1169
+ if (rb_obj_is_kind_of(a, c_MPFR)) {
1170
+ mpfr_ptr mpa = mpfrrb_rb2ref(a);
1171
+ if (RB_FLOAT_TYPE_P(b)) {
1172
+ r = mpfr_sub_d(mpr, mpa, NUM2DBL(b), rnd);
1173
+ } else if (RB_FIXNUM_P(b)) {
1174
+ r = mpfr_sub_si(mpr, mpa, NUM2LL(b), rnd);
1175
+ } else if (RB_INTEGER_TYPE_P(b)) {
1176
+ mpz_t mpz;
1177
+ mpz_init(mpz);
1178
+ mpfrrb_bignum_to_mpz(b, mpz);
1179
+ r = mpfr_sub_z(mpr, mpa, mpz, rnd);
1180
+ mpz_clear(mpz);
1181
+ } else if (RB_TYPE_P(b, T_RATIONAL)) {
1182
+ mpq_t mpq;
1183
+ mpq_init(mpq);
1184
+ mpfrrb_rational_to_mpq(b, mpq);
1185
+ r = mpfr_sub_q(mpr, mpa, mpq, rnd);
1186
+ mpq_clear(mpq);
1187
+ } else {
1188
+ b = mpfrrb_object_to_mpfr(b);
1189
+ r = mpfr_sub(mpr, mpa, mpfrrb_rb2ref(b), rnd);
1190
+ }
1191
+ } else {
1192
+ b = mpfrrb_object_to_mpfr(b);
1193
+ mpfr_ptr mpb = mpfrrb_rb2ref(b);
1194
+ if (RB_FLOAT_TYPE_P(a)) {
1195
+ r = mpfr_d_sub(mpr, NUM2DBL(a), mpb, rnd);
1196
+ } else if (RB_FIXNUM_P(a)) {
1197
+ r = mpfr_si_sub(mpr, NUM2LL(a), mpb, rnd);
1198
+ } else if (RB_INTEGER_TYPE_P(a)) {
1199
+ mpz_t mpz;
1200
+ mpz_init(mpz);
1201
+ mpfrrb_bignum_to_mpz(a, mpz);
1202
+ r = mpfr_z_sub(mpr, mpz, mpb, rnd);
1203
+ mpz_clear(mpz);
1204
+ } else {
1205
+ a = mpfrrb_object_to_mpfr(a);
1206
+ r = mpfr_sub(mpr, mpfrrb_rb2ref(a), mpb, rnd);
1207
+ }
1208
+
1209
+ }
1210
+
1211
+ return INT2NUM(r);
1212
+ }
1213
+
1214
+
1215
+ /* Set the value of `self` to `self` - `b` rounded in the direction `round`.
1216
+ * @return [Integer]
1217
+ * @overload sub!(b, round: MPFR.default_rounding)
1218
+ * @param b [MPFR, Float, Integer, Rational]
1219
+ */
1220
+ static VALUE mpfrrb_sub_B(int argc, VALUE *argv, VALUE self)
1221
+ {
1222
+ VALUE b;
1223
+ mpfr_rnd_t rnd = mpfrrb_get_b_round(argc, argv, &b);
1224
+ mpfr_ptr mpr = mpfrrb_rb2ref(self);
1225
+ int r;
1226
+ if (RB_FLOAT_TYPE_P(b)) {
1227
+ r = mpfr_sub_d(mpr, mpr, NUM2DBL(b), rnd);
1228
+ } else if (RB_FIXNUM_P(b)) {
1229
+ r = mpfr_sub_si(mpr, mpr, NUM2LL(b), rnd);
1230
+ } else if (RB_INTEGER_TYPE_P(b)) {
1231
+ mpz_t mpz;
1232
+ mpz_init(mpz);
1233
+ mpfrrb_bignum_to_mpz(b, mpz);
1234
+ r = mpfr_sub_z(mpr, mpr, mpz, rnd);
1235
+ mpz_clear(mpz);
1236
+ } else if (RB_TYPE_P(b, T_RATIONAL)) {
1237
+ mpq_t mpq;
1238
+ mpq_init(mpq);
1239
+ mpfrrb_rational_to_mpq(b, mpq);
1240
+ r = mpfr_sub_q(mpr, mpr, mpq, rnd);
1241
+ mpq_clear(mpq);
1242
+ } else {
1243
+ b = mpfrrb_object_to_mpfr(b);
1244
+ r = mpfr_sub(mpr, mpr, mpfrrb_rb2ref(b), rnd);
1245
+ }
1246
+ return INT2NUM(r);
1247
+ }
1248
+
1249
+
1250
+ /* Set the value of `self` to `a` times `b` rounded in the direction `round`.
1251
+ * @return [Integer]
1252
+ * @overload mul(a, b, round: MPFR.default_rounding)
1253
+ * @param a [MPFR]
1254
+ * @param b [MPFR, Float, Integer, Rational]
1255
+ */
1256
+ static VALUE mpfrrb_mul(int argc, VALUE *argv, VALUE self)
1257
+ {
1258
+ VALUE a, b;
1259
+ mpfr_rnd_t rnd = mpfrrb_get_a_b_round(argc, argv, &a, &b);
1260
+ a = mpfrrb_object_to_mpfr(a);
1261
+ mpfr_ptr mpr = mpfrrb_rb2ref(self);
1262
+ mpfr_ptr mpa = mpfrrb_rb2ref(a);
1263
+ int r;
1264
+ if (RB_FLOAT_TYPE_P(b)) {
1265
+ r = mpfr_mul_d(mpr, mpa, NUM2DBL(b), rnd);
1266
+ } else if (RB_FIXNUM_P(b)) {
1267
+ r = mpfr_mul_si(mpr, mpa, NUM2LL(b), rnd);
1268
+ } else if (RB_INTEGER_TYPE_P(b)) {
1269
+ mpz_t mpz;
1270
+ mpz_init(mpz);
1271
+ mpfrrb_bignum_to_mpz(b, mpz);
1272
+ r = mpfr_mul_z(mpr, mpa, mpz, rnd);
1273
+ mpz_clear(mpz);
1274
+ } else if (RB_TYPE_P(b, T_RATIONAL)) {
1275
+ mpq_t mpq;
1276
+ mpq_init(mpq);
1277
+ mpfrrb_rational_to_mpq(b, mpq);
1278
+ r = mpfr_mul_q(mpr, mpa, mpq, rnd);
1279
+ mpq_clear(mpq);
1280
+ } else {
1281
+ b = mpfrrb_object_to_mpfr(b);
1282
+ r = mpfr_mul(mpr, mpa, mpfrrb_rb2ref(b), rnd);
1283
+ }
1284
+ return INT2NUM(r);
1285
+ }
1286
+
1287
+
1288
+ /* Set the value of `self` to `self` times `b` rounded in the direction `round`.
1289
+ * @return [Integer]
1290
+ * @overload mul!(b, round: MPFR.default_rounding)
1291
+ * @param b [MPFR, Float, Integer, Rational]
1292
+ */
1293
+ static VALUE mpfrrb_mul_B(int argc, VALUE *argv, VALUE self)
1294
+ {
1295
+ VALUE b;
1296
+ mpfr_rnd_t rnd = mpfrrb_get_b_round(argc, argv, &b);
1297
+ mpfr_ptr mpr = mpfrrb_rb2ref(self);
1298
+ int r;
1299
+ if (RB_FLOAT_TYPE_P(b)) {
1300
+ r = mpfr_mul_d(mpr, mpr, NUM2DBL(b), rnd);
1301
+ } else if (RB_FIXNUM_P(b)) {
1302
+ r = mpfr_mul_si(mpr, mpr, NUM2LL(b), rnd);
1303
+ } else if (RB_INTEGER_TYPE_P(b)) {
1304
+ mpz_t mpz;
1305
+ mpz_init(mpz);
1306
+ mpfrrb_bignum_to_mpz(b, mpz);
1307
+ r = mpfr_mul_z(mpr, mpr, mpz, rnd);
1308
+ mpz_clear(mpz);
1309
+ } else if (RB_TYPE_P(b, T_RATIONAL)) {
1310
+ mpq_t mpq;
1311
+ mpq_init(mpq);
1312
+ mpfrrb_rational_to_mpq(b, mpq);
1313
+ r = mpfr_mul_q(mpr, mpr, mpq, rnd);
1314
+ mpq_clear(mpq);
1315
+ } else {
1316
+ b = mpfrrb_object_to_mpfr(b);
1317
+ r = mpfr_mul(mpr, mpr, mpfrrb_rb2ref(b), rnd);
1318
+ }
1319
+ return INT2NUM(r);
1320
+ }
1321
+
1322
+
1323
+ /* Set the value of `self` to `a` / `b` rounded in the direction `round`.
1324
+ * @return [Integer]
1325
+ * @overload div(a, b, round: MPFR.default_rounding)
1326
+ * @param a [MPFR, Float, Integer]
1327
+ * @param b [MPFR, Float, Integer, Rational]
1328
+ */
1329
+ static VALUE mpfrrb_div(int argc, VALUE *argv, VALUE self)
1330
+ {
1331
+ VALUE a, b;
1332
+ mpfr_rnd_t rnd = mpfrrb_get_a_b_round(argc, argv, &a, &b);
1333
+ a = mpfrrb_object_to_mpfr(a);
1334
+ mpfr_ptr mpr = mpfrrb_rb2ref(self);
1335
+ int r;
1336
+ if (rb_obj_is_kind_of(a, c_MPFR)) {
1337
+ mpfr_ptr mpa = mpfrrb_rb2ref(a);
1338
+ if (RB_FLOAT_TYPE_P(b)) {
1339
+ r = mpfr_div_d(mpr, mpa, NUM2DBL(b), rnd);
1340
+ } else if (RB_FIXNUM_P(b)) {
1341
+ r = mpfr_div_si(mpr, mpa, NUM2LL(b), rnd);
1342
+ } else if (RB_INTEGER_TYPE_P(b)) {
1343
+ mpz_t mpz;
1344
+ mpz_init(mpz);
1345
+ mpfrrb_bignum_to_mpz(b, mpz);
1346
+ r = mpfr_div_z(mpr, mpa, mpz, rnd);
1347
+ mpz_clear(mpz);
1348
+ } else if (RB_TYPE_P(b, T_RATIONAL)) {
1349
+ mpq_t mpq;
1350
+ mpq_init(mpq);
1351
+ mpfrrb_rational_to_mpq(b, mpq);
1352
+ r = mpfr_div_q(mpr, mpa, mpq, rnd);
1353
+ mpq_clear(mpq);
1354
+ } else {
1355
+ b = mpfrrb_object_to_mpfr(b);
1356
+ r = mpfr_div(mpr, mpa, mpfrrb_rb2ref(b), rnd);
1357
+ }
1358
+ } else {
1359
+ b = mpfrrb_object_to_mpfr(b);
1360
+ mpfr_ptr mpb = mpfrrb_rb2ref(b);
1361
+ if (RB_FLOAT_TYPE_P(a)) {
1362
+ r = mpfr_d_div(mpr, NUM2DBL(a), mpb, rnd);
1363
+ } else if (RB_FIXNUM_P(a)) {
1364
+ r = mpfr_si_div(mpr, NUM2LL(a), mpb, rnd);
1365
+ } else {
1366
+ a = mpfrrb_object_to_mpfr(a);
1367
+ r = mpfr_div(mpr, mpfrrb_rb2ref(a), mpb, rnd);
1368
+ }
1369
+
1370
+ }
1371
+
1372
+ return INT2NUM(r);
1373
+ }
1374
+
1375
+
1376
+ /* Set the value of `self` to `self` / `b` rounded in the direction `round`.
1377
+ * @return [Integer]
1378
+ * @overload div!(b, round: MPFR.default_rounding)
1379
+ * @param b [MPFR, Float, Integer, Rational]
1380
+ */
1381
+ static VALUE mpfrrb_div_B(int argc, VALUE *argv, VALUE self)
1382
+ {
1383
+ VALUE b;
1384
+ mpfr_rnd_t rnd = mpfrrb_get_b_round(argc, argv, &b);
1385
+ mpfr_ptr mpr = mpfrrb_rb2ref(self);
1386
+ int r;
1387
+ if (RB_FLOAT_TYPE_P(b)) {
1388
+ r = mpfr_div_d(mpr, mpr, NUM2DBL(b), rnd);
1389
+ } else if (RB_FIXNUM_P(b)) {
1390
+ r = mpfr_div_si(mpr, mpr, NUM2LL(b), rnd);
1391
+ } else if (RB_INTEGER_TYPE_P(b)) {
1392
+ mpz_t mpz;
1393
+ mpz_init(mpz);
1394
+ mpfrrb_bignum_to_mpz(b, mpz);
1395
+ r = mpfr_div_z(mpr, mpr, mpz, rnd);
1396
+ mpz_clear(mpz);
1397
+ } else if (RB_TYPE_P(b, T_RATIONAL)) {
1398
+ mpq_t mpq;
1399
+ mpq_init(mpq);
1400
+ mpfrrb_rational_to_mpq(b, mpq);
1401
+ r = mpfr_div_q(mpr, mpr, mpq, rnd);
1402
+ mpq_clear(mpq);
1403
+ } else {
1404
+ b = mpfrrb_object_to_mpfr(b);
1405
+ r = mpfr_div(mpr, mpr, mpfrrb_rb2ref(b), rnd);
1406
+ }
1407
+ return INT2NUM(r);
1408
+ }
1409
+
1410
+
1411
+ /* Set self to the square of `a`, rounded int the direction `round`.
1412
+ * @return [Integer]
1413
+ * @overload sqr(a, round: MPFR.default_rounding)
1414
+ * @param a [MPFR]
1415
+ * @param round [Symbol]
1416
+ */
1417
+ static VALUE mpfrrb_sqr(int argc, VALUE *argv, VALUE self)
1418
+ {
1419
+ VALUE a;
1420
+ mpfr_rnd_t rnd = mpfrrb_get_b_round(argc, argv, &a);
1421
+ mpfr_ptr mpr = mpfrrb_rb2ref(self);
1422
+ int r;
1423
+ if (RB_FLOAT_TYPE_P(a)) {
1424
+ MPFR_DECL_INIT(mpa, 53);
1425
+ mpfr_set_d(mpa, NUM2DBL(a), MPFR_RNDN);
1426
+ r = mpfr_sqr(mpr, mpa, rnd);
1427
+ } else if (RB_FIXNUM_P(a)) {
1428
+ MPFR_DECL_INIT(mpa, 64);
1429
+ mpfr_set_si(mpa, NUM2LL(a), MPFR_RNDN);
1430
+ r = mpfr_sqr(mpr, mpa, rnd);
1431
+ } else {
1432
+ a = mpfrrb_object_to_mpfr(a);
1433
+ r = mpfr_sqr(mpr, mpfrrb_rb2ref(a), rnd);
1434
+ }
1435
+ return INT2NUM(r);
1436
+ }
1437
+
1438
+
1439
+ /* Set self to the square of `self`, rounded int the direction `round`.
1440
+ * @return [Integer]
1441
+ * @overload sqr!(round: MPFR.default_rounding)
1442
+ * @param round [Symbol]
1443
+ */
1444
+ static VALUE mpfrrb_sqr_B(int argc, VALUE *argv, VALUE self)
1445
+ {
1446
+ mpfr_rnd_t rnd = mpfrrb_get_round_single_keword(argc, argv);
1447
+ mpfr_ptr mp = mpfrrb_rb2ref(self);
1448
+ int r = mpfr_sqr(mp, mp, rnd);
1449
+ return INT2NUM(r);
1450
+ }
1451
+
1452
+
1453
+ /* Set self to the square root of `a`, rounded int the direction `round`.
1454
+ * @return [Integer]
1455
+ * @overload sqrt(a, round: MPFR.default_rounding)
1456
+ * @param a [MPFR]
1457
+ * @param round [Symbol]
1458
+ */
1459
+ static VALUE mpfrrb_sqrt(int argc, VALUE *argv, VALUE self)
1460
+ {
1461
+ VALUE a;
1462
+ mpfr_rnd_t rnd = mpfrrb_get_b_round(argc, argv, &a);
1463
+ mpfr_ptr mpr = mpfrrb_rb2ref(self);
1464
+ int r;
1465
+ if (RB_FLOAT_TYPE_P(a)) {
1466
+ MPFR_DECL_INIT(mpa, 53);
1467
+ mpfr_set_d(mpa, NUM2DBL(a), MPFR_RNDN);
1468
+ r = mpfr_sqrt(mpr, mpa, rnd);
1469
+ } else if (RB_FIXNUM_P(a)) {
1470
+ long int i = NUM2LL(a);
1471
+ if (i < 0) {
1472
+ mpfr_set_nan(mpr);
1473
+ r = 0;
1474
+ } else {
1475
+ r = mpfr_sqrt_ui(mpr, i, rnd);
1476
+ }
1477
+ } else {
1478
+ a = mpfrrb_object_to_mpfr(a);
1479
+ r = mpfr_sqrt(mpr, mpfrrb_rb2ref(a), rnd);
1480
+ }
1481
+ return INT2NUM(r);
1482
+ }
1483
+
1484
+
1485
+ /* Set self to the square root of `self`, rounded int the direction `round`.
1486
+ * @return [Integer]
1487
+ * @overload sqrt!(round: MPFR.default_rounding)
1488
+ * @param round [Symbol]
1489
+ */
1490
+ static VALUE mpfrrb_sqrt_B(int argc, VALUE *argv, VALUE self)
1491
+ {
1492
+ mpfr_rnd_t rnd = mpfrrb_get_round_single_keword(argc, argv);
1493
+ mpfr_ptr mp = mpfrrb_rb2ref(self);
1494
+ int r = mpfr_sqrt(mp, mp, rnd);
1495
+ return INT2NUM(r);
1496
+ }
1497
+
1498
+
1499
+ /* Set self to the reciprocal square root of `a`, rounded int the direction `round`.
1500
+ * @return [Integer]
1501
+ * @overload rec_sqrt(a, round: MPFR.default_rounding)
1502
+ * @param a [MPFR]
1503
+ * @param round [Symbol]
1504
+ */
1505
+ static VALUE mpfrrb_rec_sqrt(int argc, VALUE *argv, VALUE self)
1506
+ {
1507
+ VALUE a;
1508
+ mpfr_rnd_t rnd = mpfrrb_get_b_round(argc, argv, &a);
1509
+ mpfr_ptr mpr = mpfrrb_rb2ref(self);
1510
+ int r;
1511
+ if (RB_FLOAT_TYPE_P(a)) {
1512
+ MPFR_DECL_INIT(mpa, 53);
1513
+ mpfr_set_d(mpa, NUM2DBL(a), MPFR_RNDN);
1514
+ r = mpfr_rec_sqrt(mpr, mpa, rnd);
1515
+ } else if (RB_FIXNUM_P(a)) {
1516
+ MPFR_DECL_INIT(mpa, 64);
1517
+ mpfr_set_si(mpa, NUM2LL(a), MPFR_RNDN);
1518
+ r = mpfr_rec_sqrt(mpr, mpa, rnd);
1519
+ } else {
1520
+ a = mpfrrb_object_to_mpfr(a);
1521
+ r = mpfr_rec_sqrt(mpr, mpfrrb_rb2ref(a), rnd);
1522
+ }
1523
+ return INT2NUM(r);
1524
+ }
1525
+
1526
+
1527
+ /* Set self to the reciprocal square root of `self`, rounded int the direction `round`.
1528
+ * @return [Integer]
1529
+ * @overload rec_sqrt!(round: MPFR.default_rounding)
1530
+ * @param round [Symbol]
1531
+ */
1532
+ static VALUE mpfrrb_rec_sqrt_B(int argc, VALUE *argv, VALUE self)
1533
+ {
1534
+ mpfr_rnd_t rnd = mpfrrb_get_round_single_keword(argc, argv);
1535
+ mpfr_ptr mp = mpfrrb_rb2ref(self);
1536
+ int r = mpfr_rec_sqrt(mp, mp, rnd);
1537
+ return INT2NUM(r);
1538
+ }
1539
+
1540
+
1541
+ /* Set self to the cubic root of `a`, rounded int the direction `round`.
1542
+ * @return [Integer]
1543
+ * @overload cbrt(a, round: MPFR.default_rounding)
1544
+ * @param a [MPFR]
1545
+ * @param round [Symbol]
1546
+ */
1547
+ static VALUE mpfrrb_cbrt(int argc, VALUE *argv, VALUE self)
1548
+ {
1549
+ VALUE a;
1550
+ mpfr_rnd_t rnd = mpfrrb_get_b_round(argc, argv, &a);
1551
+ mpfr_ptr mpr = mpfrrb_rb2ref(self);
1552
+ int r;
1553
+ if (RB_FLOAT_TYPE_P(a)) {
1554
+ MPFR_DECL_INIT(mpa, 53);
1555
+ mpfr_set_d(mpa, NUM2DBL(a), MPFR_RNDN);
1556
+ r = mpfr_cbrt(mpr, mpa, rnd);
1557
+ } else if (RB_FIXNUM_P(a)) {
1558
+ MPFR_DECL_INIT(mpa, 64);
1559
+ mpfr_set_si(mpa, NUM2LL(a), MPFR_RNDN);
1560
+ r = mpfr_cbrt(mpr, mpa, rnd);
1561
+ } else {
1562
+ a = mpfrrb_object_to_mpfr(a);
1563
+ r = mpfr_cbrt(mpr, mpfrrb_rb2ref(a), rnd);
1564
+ }
1565
+ return INT2NUM(r);
1566
+ }
1567
+
1568
+
1569
+ /* Set self to the cubic root of `self`, rounded int the direction `round`.
1570
+ * @return [Integer]
1571
+ * @overload cbrt!(round: MPFR.default_rounding)
1572
+ * @param round [Symbol]
1573
+ */
1574
+ static VALUE mpfrrb_cbrt_B(int argc, VALUE *argv, VALUE self)
1575
+ {
1576
+ mpfr_rnd_t rnd = mpfrrb_get_round_single_keword(argc, argv);
1577
+ mpfr_ptr mp = mpfrrb_rb2ref(self);
1578
+ int r = mpfr_cbrt(mp, mp, rnd);
1579
+ return INT2NUM(r);
1580
+ }
1581
+
1582
+
1583
+ /* Set self to the nth root of `a`, rounded int the direction `round`.
1584
+ * @return [Integer]
1585
+ * @overload rootn(a, n, round: MPFR.default_rounding)
1586
+ * @param a [MPFR]
1587
+ * @param n [Integer]
1588
+ * @param round [Symbol]
1589
+ */
1590
+ static VALUE mpfrrb_rootn(int argc, VALUE *argv, VALUE self)
1591
+ {
1592
+ VALUE a, n;
1593
+ mpfr_rnd_t rnd = mpfrrb_get_a_b_round(argc, argv, &a, &n);
1594
+ long long i = NUM2LL(n);
1595
+ mpfr_ptr mpr = mpfrrb_rb2ref(self);
1596
+ int r;
1597
+ if (RB_FLOAT_TYPE_P(a)) {
1598
+ MPFR_DECL_INIT(mpa, 53);
1599
+ mpfr_set_d(mpa, NUM2DBL(a), MPFR_RNDN);
1600
+ r = mpfr_rootn_si(mpr, mpa, i, rnd);
1601
+ } else if (RB_FIXNUM_P(a)) {
1602
+ MPFR_DECL_INIT(mpa, 64);
1603
+ mpfr_set_si(mpa, NUM2LL(a), MPFR_RNDN);
1604
+ r = mpfr_rootn_si(mpr, mpa, i, rnd);
1605
+ } else {
1606
+ a = mpfrrb_object_to_mpfr(a);
1607
+ r = mpfr_rootn_si(mpr, mpfrrb_rb2ref(a), i, rnd);
1608
+ }
1609
+ return INT2NUM(r);
1610
+ }
1611
+
1612
+
1613
+ /* Set self to the nth root of `self`, rounded int the direction `round`.
1614
+ * @return [Integer]
1615
+ * @overload rootn!(n, round: MPFR.default_rounding)
1616
+ * @param n [Integer]
1617
+ * @param round [Symbol]
1618
+ */
1619
+ static VALUE mpfrrb_rootn_B(int argc, VALUE *argv, VALUE self)
1620
+ {
1621
+ VALUE n;
1622
+ mpfr_rnd_t rnd = mpfrrb_get_b_round(argc, argv, &n);
1623
+ long long i = NUM2LL(n);
1624
+ mpfr_ptr mp = mpfrrb_rb2ref(self);
1625
+ int r = mpfr_rootn_si(mp, mp, i, rnd);
1626
+ return INT2NUM(r);
1627
+ }
1628
+
1629
+
1630
+ /* Set self to `-a`, rounded int the direction `round`.
1631
+ * @return [Integer]
1632
+ * @overload neg(a, round: MPFR.default_rounding)
1633
+ * @param a [MPFR]
1634
+ * @param round [Symbol]
1635
+ */
1636
+ static VALUE mpfrrb_neg(int argc, VALUE *argv, VALUE self)
1637
+ {
1638
+ VALUE a;
1639
+ mpfr_rnd_t rnd = mpfrrb_get_b_round(argc, argv, &a);
1640
+ mpfr_ptr mpr = mpfrrb_rb2ref(self);
1641
+ int r;
1642
+ if (RB_FLOAT_TYPE_P(a)) {
1643
+ MPFR_DECL_INIT(mpa, 53);
1644
+ mpfr_set_d(mpa, NUM2DBL(a), MPFR_RNDN);
1645
+ r = mpfr_neg(mpr, mpa, rnd);
1646
+ } else if (RB_FIXNUM_P(a)) {
1647
+ MPFR_DECL_INIT(mpa, 64);
1648
+ mpfr_set_si(mpa, NUM2LL(a), MPFR_RNDN);
1649
+ r = mpfr_neg(mpr, mpa, rnd);
1650
+ } else {
1651
+ a = mpfrrb_object_to_mpfr(a);
1652
+ r = mpfr_neg(mpr, mpfrrb_rb2ref(a), rnd);
1653
+ }
1654
+ return INT2NUM(r);
1655
+ }
1656
+
1657
+
1658
+ /* Set self `-self`.
1659
+ * @return [Integer]
1660
+ */
1661
+ static VALUE mpfrrb_neg_B(VALUE self)
1662
+ {
1663
+ mpfr_ptr mp = mpfrrb_rb2ref(self);
1664
+ int r = mpfr_neg(mp, mp, MPFR_RNDN);
1665
+ return INT2NUM(r);
1666
+ }
1667
+
1668
+
1669
+ /* Set self to the absolute value of `a`, rounded int the direction `round`.
1670
+ * @return [Integer]
1671
+ * @overload abs(a, round: MPFR.default_rounding)
1672
+ * @param a [MPFR]
1673
+ * @param round [Symbol]
1674
+ */
1675
+ static VALUE mpfrrb_abs(int argc, VALUE *argv, VALUE self)
1676
+ {
1677
+ VALUE a;
1678
+ mpfr_rnd_t rnd = mpfrrb_get_b_round(argc, argv, &a);
1679
+ mpfr_ptr mpr = mpfrrb_rb2ref(self);
1680
+ int r;
1681
+ if (RB_FLOAT_TYPE_P(a)) {
1682
+ MPFR_DECL_INIT(mpa, 53);
1683
+ mpfr_set_d(mpa, NUM2DBL(a), MPFR_RNDN);
1684
+ r = mpfr_abs(mpr, mpa, rnd);
1685
+ } else if (RB_FIXNUM_P(a)) {
1686
+ MPFR_DECL_INIT(mpa, 64);
1687
+ mpfr_set_si(mpa, NUM2LL(a), MPFR_RNDN);
1688
+ r = mpfr_abs(mpr, mpa, rnd);
1689
+ } else {
1690
+ a = mpfrrb_object_to_mpfr(a);
1691
+ r = mpfr_abs(mpr, mpfrrb_rb2ref(a), rnd);
1692
+ }
1693
+ return INT2NUM(r);
1694
+ }
1695
+
1696
+
1697
+ /* Set self to the absolute value of `self`.
1698
+ * @return [Integer]
1699
+ */
1700
+ static VALUE mpfrrb_abs_B(VALUE self)
1701
+ {
1702
+ mpfr_ptr mp = mpfrrb_rb2ref(self);
1703
+ int r = mpfr_abs(mp, mp, MPFR_RNDN);
1704
+ return INT2NUM(r);
1705
+ }
1706
+
1707
+
1708
+ /* Set `self` to the positive difference of `a` and `b`.
1709
+ * That is: `a` - `b` rounded in the direction `round` if `a` > `b`, +0 if `a` ≤ `b`, and NaN if `a` or `b` is NaN.
1710
+ * @return [Integer]
1711
+ * @overload dim(a, b, round: MPFR.default_rounding)
1712
+ * @param a [MPFR]
1713
+ * @param b [MPFR]
1714
+ * @param round [Symbol]
1715
+ */
1716
+ static VALUE mpfrrb_dim(int argc, VALUE *argv, VALUE self)
1717
+ {
1718
+ VALUE a, b;
1719
+ mpfr_rnd_t rnd = mpfrrb_get_a_b_round(argc, argv, &a, &b);
1720
+ a = mpfrrb_object_to_mpfr(a);
1721
+ b = mpfrrb_object_to_mpfr(b);
1722
+ int r = mpfr_dim(mpfrrb_rb2ref(self), mpfrrb_rb2ref(a), mpfrrb_rb2ref(b), rnd);
1723
+ return INT2NUM(r);
1724
+ }
1725
+
1726
+
1727
+ /* Set self to `a` times 2 raised to `n`, rounded int the direction `round`.
1728
+ * @return [Integer]
1729
+ * @overload mul_2i(a, n, round: MPFR.default_rounding)
1730
+ * @param a [MPFR]
1731
+ * @param n [Integer]
1732
+ * @param round [Symbol]
1733
+ */
1734
+ static VALUE mpfrrb_mul_2i(int argc, VALUE *argv, VALUE self)
1735
+ {
1736
+ VALUE a, n;
1737
+ mpfr_rnd_t rnd = mpfrrb_get_a_b_round(argc, argv, &a, &n);
1738
+ long long i = NUM2LL(n);
1739
+ mpfr_ptr mpr = mpfrrb_rb2ref(self);
1740
+ int r;
1741
+ if (RB_FLOAT_TYPE_P(a)) {
1742
+ MPFR_DECL_INIT(mpa, 53);
1743
+ mpfr_set_d(mpa, NUM2DBL(a), MPFR_RNDN);
1744
+ r = mpfr_mul_2si(mpr, mpa, i, rnd);
1745
+ } else if (RB_FIXNUM_P(a)) {
1746
+ MPFR_DECL_INIT(mpa, 64);
1747
+ mpfr_set_si(mpa, NUM2LL(a), MPFR_RNDN);
1748
+ r = mpfr_mul_2si(mpr, mpa, i, rnd);
1749
+ } else {
1750
+ a = mpfrrb_object_to_mpfr(a);
1751
+ r = mpfr_mul_2si(mpr, mpfrrb_rb2ref(a), i, rnd);
1752
+ }
1753
+ return INT2NUM(r);
1754
+ }
1755
+
1756
+
1757
+ /* Set self to `self` times 2 raised to `n`, rounded int the direction `round`.
1758
+ * @return [Integer]
1759
+ * @overload mul_2i!(n, round: MPFR.default_rounding)
1760
+ * @param n [Integer]
1761
+ * @param round [Symbol]
1762
+ */
1763
+ static VALUE mpfrrb_mul_2i_B(int argc, VALUE *argv, VALUE self)
1764
+ {
1765
+ VALUE n;
1766
+ mpfr_rnd_t rnd = mpfrrb_get_b_round(argc, argv, &n);
1767
+ long long i = NUM2LL(n);
1768
+ mpfr_ptr mp = mpfrrb_rb2ref(self);
1769
+ int r = mpfr_mul_2si(mp, mp, i, rnd);
1770
+ return INT2NUM(r);
1771
+ }
1772
+
1773
+
1774
+ /* Set self to `a` divided by 2 raised to `n`, rounded int the direction `round`.
1775
+ * @return [Integer]
1776
+ * @overload div_2i(a, n, round: MPFR.default_rounding)
1777
+ * @param a [MPFR]
1778
+ * @param n [Integer]
1779
+ * @param round [Symbol]
1780
+ */
1781
+ static VALUE mpfrrb_div_2i(int argc, VALUE *argv, VALUE self)
1782
+ {
1783
+ VALUE a, n;
1784
+ mpfr_rnd_t rnd = mpfrrb_get_a_b_round(argc, argv, &a, &n);
1785
+ long long i = NUM2LL(n);
1786
+ mpfr_ptr mpr = mpfrrb_rb2ref(self);
1787
+ int r;
1788
+ if (RB_FLOAT_TYPE_P(a)) {
1789
+ MPFR_DECL_INIT(mpa, 53);
1790
+ mpfr_set_d(mpa, NUM2DBL(a), MPFR_RNDN);
1791
+ r = mpfr_div_2si(mpr, mpa, i, rnd);
1792
+ } else if (RB_FIXNUM_P(a)) {
1793
+ MPFR_DECL_INIT(mpa, 64);
1794
+ mpfr_set_si(mpa, NUM2LL(a), MPFR_RNDN);
1795
+ r = mpfr_div_2si(mpr, mpa, i, rnd);
1796
+ } else {
1797
+ a = mpfrrb_object_to_mpfr(a);
1798
+ r = mpfr_div_2si(mpr, mpfrrb_rb2ref(a), i, rnd);
1799
+ }
1800
+ return INT2NUM(r);
1801
+ }
1802
+
1803
+
1804
+ /* Set self to `self` divided by 2 raised to `n`, rounded int the direction `round`.
1805
+ * @return [Integer]
1806
+ * @overload div_2i!(n, round: MPFR.default_rounding)
1807
+ * @param n [Integer]
1808
+ * @param round [Symbol]
1809
+ */
1810
+ static VALUE mpfrrb_div_2i_B(int argc, VALUE *argv, VALUE self)
1811
+ {
1812
+ VALUE n;
1813
+ mpfr_rnd_t rnd = mpfrrb_get_b_round(argc, argv, &n);
1814
+ long long i = NUM2LL(n);
1815
+ mpfr_ptr mp = mpfrrb_rb2ref(self);
1816
+ int r = mpfr_div_2si(mp, mp, i, rnd);
1817
+ return INT2NUM(r);
1818
+ }
1819
+
1820
+
1821
+ /* Set self to the factorial of `n`, rounded int the direction `round`.
1822
+ * @return [Integer]
1823
+ * @overload fac(n, round: MPFR.default_rounding)
1824
+ * @param n [Integer]
1825
+ * @param round [Symbol]
1826
+ */
1827
+ static VALUE mpfrrb_fac(int argc, VALUE *argv, VALUE self)
1828
+ {
1829
+ VALUE n;
1830
+ mpfr_rnd_t rnd = mpfrrb_get_b_round(argc, argv, &n);
1831
+ long long i = NUM2LL(n);
1832
+ mpfr_ptr mp = mpfrrb_rb2ref(self);
1833
+ if (i < 0) {
1834
+ rb_raise(rb_eRangeError, "factorial of negative value");
1835
+ }
1836
+ int r = mpfr_fac_ui(mp, i, rnd);
1837
+ return INT2NUM(r);
1838
+ }
1839
+
1840
+
1841
+ /* Set self to (`a` times `b`) plus `c`, rounded in the direction `round`.
1842
+ * Concerning special values (signed zeros, infinities, NaN),
1843
+ * these functions behave like a multiplication followed by a separate addition or subtraction.
1844
+ * That is, the fused operation matters only for rounding.
1845
+ * @return [Integer]
1846
+ * @overload fma(a, b, c, round: MPFR.default_rounding)
1847
+ * @param a, b, c [MPFR]
1848
+ * @param round [Symbol]
1849
+ */
1850
+ static VALUE mpfrrb_fma(int argc, VALUE *argv, VALUE self)
1851
+ {
1852
+ VALUE a, b, c;
1853
+ mpfr_rnd_t rnd = mpfrrb_get_a_b_c_round(argc, argv, &a, &b, &c);
1854
+ mpfr_ptr mpr = mpfrrb_rb2ref(self);
1855
+ mpfr_ptr mpa = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(a));
1856
+ mpfr_ptr mpb = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(b));
1857
+ mpfr_ptr mpc = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(c));
1858
+ int r = mpfr_fma(mpr, mpa, mpb, mpc, rnd);
1859
+ return INT2NUM(r);
1860
+ }
1861
+
1862
+
1863
+ /* Set self to (`a` times `b`) plus `self`, rounded in the direction `round`.
1864
+ * Concerning special values (signed zeros, infinities, NaN),
1865
+ * these functions behave like a multiplication followed by a separate addition or subtraction.
1866
+ * That is, the fused operation matters only for rounding.
1867
+ * @return [Integer]
1868
+ * @overload fma!(a, b, round: MPFR.default_rounding)
1869
+ * @param a, b [MPFR]
1870
+ * @param round [Symbol]
1871
+ */
1872
+ static VALUE mpfrrb_fma_B(int argc, VALUE *argv, VALUE self)
1873
+ {
1874
+ VALUE a, b;
1875
+ mpfr_rnd_t rnd = mpfrrb_get_a_b_round(argc, argv, &a, &b);
1876
+ mpfr_ptr mpr = mpfrrb_rb2ref(self);
1877
+ mpfr_ptr mpa = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(a));
1878
+ mpfr_ptr mpb = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(b));
1879
+ int r = mpfr_fma(mpr, mpa, mpb, mpr, rnd);
1880
+ return INT2NUM(r);
1881
+ }
1882
+
1883
+
1884
+ /* Set self to (`a` times `b`) minus `c`, rounded in the direction `round`.
1885
+ * Concerning special values (signed zeros, infinities, NaN),
1886
+ * these functions behave like a multiplication followed by a separate addition or subtraction.
1887
+ * That is, the fused operation matters only for rounding.
1888
+ * @return [Integer]
1889
+ * @overload fms(a, b, c, round: MPFR.default_rounding)
1890
+ * @param a, b, c [MPFR]
1891
+ * @param round [Symbol]
1892
+ */
1893
+ static VALUE mpfrrb_fms(int argc, VALUE *argv, VALUE self)
1894
+ {
1895
+ VALUE a, b, c;
1896
+ mpfr_rnd_t rnd = mpfrrb_get_a_b_c_round(argc, argv, &a, &b, &c);
1897
+ mpfr_ptr mpr = mpfrrb_rb2ref(self);
1898
+ mpfr_ptr mpa = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(a));
1899
+ mpfr_ptr mpb = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(b));
1900
+ mpfr_ptr mpc = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(c));
1901
+ int r = mpfr_fms(mpr, mpa, mpb, mpc, rnd);
1902
+ return INT2NUM(r);
1903
+ }
1904
+
1905
+
1906
+ /* Set self to (`a` times `b`) minus `self`, rounded in the direction `round`.
1907
+ * Concerning special values (signed zeros, infinities, NaN),
1908
+ * these functions behave like a multiplication followed by a separate addition or subtraction.
1909
+ * That is, the fused operation matters only for rounding.
1910
+ * @return [Integer]
1911
+ * @overload fms!(a, b, round: MPFR.default_rounding)
1912
+ * @param a, b [MPFR]
1913
+ * @param round [Symbol]
1914
+ */
1915
+ static VALUE mpfrrb_fms_B(int argc, VALUE *argv, VALUE self)
1916
+ {
1917
+ VALUE a, b;
1918
+ mpfr_rnd_t rnd = mpfrrb_get_a_b_round(argc, argv, &a, &b);
1919
+ mpfr_ptr mpr = mpfrrb_rb2ref(self);
1920
+ mpfr_ptr mpa = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(a));
1921
+ mpfr_ptr mpb = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(b));
1922
+ int r = mpfr_fms(mpr, mpa, mpb, mpr, rnd);
1923
+ return INT2NUM(r);
1924
+ }
1925
+
1926
+
1927
+ /* Set self to (`a` times `b`) plus (`c` times `d`), rounded in the direction `round`.
1928
+ * In case the computation of `a` times `b` overflows or underflows (or that of `c` times `d`),
1929
+ * the result is computed as if the two intermediate products were computed with rounding toward zero.
1930
+ * @return [Integer]
1931
+ * @overload fmma(a, b, c, d, round: MPFR.default_rounding)
1932
+ * @param a, b, c, d [MPFR]
1933
+ * @param round [Symbol]
1934
+ */
1935
+ static VALUE mpfrrb_fmma(int argc, VALUE *argv, VALUE self)
1936
+ {
1937
+ VALUE v[4];
1938
+ mpfr_rnd_t rnd = mpfrrb_get_4_args_and_round(argc, argv, v);
1939
+ mpfr_ptr mpr = mpfrrb_rb2ref(self);
1940
+ mpfr_ptr mpa = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(v[0]));
1941
+ mpfr_ptr mpb = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(v[1]));
1942
+ mpfr_ptr mpc = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(v[2]));
1943
+ mpfr_ptr mpd = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(v[3]));
1944
+ int r = mpfr_fmma(mpr, mpa, mpb, mpc, mpd, rnd);
1945
+ return INT2NUM(r);
1946
+ }
1947
+
1948
+
1949
+ /* Set self to (`a` times `b`) minus (`c` times `d`), rounded in the direction `round`.
1950
+ * In case the computation of `a` times `b` overflows or underflows (or that of `c` times `d`),
1951
+ * the result is computed as if the two intermediate products were computed with rounding toward zero.
1952
+ * @return [Integer]
1953
+ * @overload fmms(a, b, c, d, round: MPFR.default_rounding)
1954
+ * @param a, b, c, d [MPFR]
1955
+ * @param round [Symbol]
1956
+ */
1957
+ static VALUE mpfrrb_fmms(int argc, VALUE *argv, VALUE self)
1958
+ {
1959
+ VALUE v[4];
1960
+ mpfr_rnd_t rnd = mpfrrb_get_4_args_and_round(argc, argv, v);
1961
+ mpfr_ptr mpr = mpfrrb_rb2ref(self);
1962
+ mpfr_ptr mpa = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(v[0]));
1963
+ mpfr_ptr mpb = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(v[1]));
1964
+ mpfr_ptr mpc = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(v[2]));
1965
+ mpfr_ptr mpd = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(v[3]));
1966
+ int r = mpfr_fmms(mpr, mpa, mpb, mpc, mpd, rnd);
1967
+ return INT2NUM(r);
1968
+ }
1969
+
1970
+
1971
+ /* Set self to the Euclidean norm of `x` and `y`, i.e. the square root to the sum of the squares of `x` and `y`, rounded in the direction `round`.
1972
+ * @return [Integer]
1973
+ * @overload hypot(x, y, round: MPFR.default_rounding)
1974
+ * @param x, y [MPFR]
1975
+ * @param round [Symbol]
1976
+ */
1977
+ static VALUE mpfrrb_hypot(int argc, VALUE *argv, VALUE self)
1978
+ {
1979
+ VALUE a, b;
1980
+ mpfr_rnd_t rnd = mpfrrb_get_a_b_round(argc, argv, &a, &b);
1981
+ mpfr_ptr mpr = mpfrrb_rb2ref(self);
1982
+ mpfr_ptr mpa = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(a));
1983
+ mpfr_ptr mpb = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(b));
1984
+ int r = mpfr_hypot(mpr, mpa, mpb, rnd);
1985
+ return INT2NUM(r);
1986
+ }
1987
+
1988
+
1989
+ /* Return a positive value if `self` > `other`, zero if `self` = `other`, and a negative value if `self` < `other`.
1990
+ * Returns `nil` if `other` is not comparable with `self`.
1991
+ * @return [Integer, nil]
1992
+ */
1993
+ static VALUE mpfrrb_cmp(VALUE self, VALUE other)
1994
+ {
1995
+ mpfr_ptr mp = mpfrrb_rb2ref(self);
1996
+ int r;
1997
+
1998
+ if (mpfr_nan_p(mp)) {
1999
+ return Qnil;
2000
+ }
2001
+ if (RB_FLOAT_TYPE_P(other)) {
2002
+ r = mpfr_cmp_d(mp, NUM2DBL(other));
2003
+ } else if (RB_FIXNUM_P(other)) {
2004
+ r = mpfr_cmp_si(mp, NUM2LL(other));
2005
+ } else if (RB_TYPE_P(other, T_BIGNUM)) {
2006
+ mpz_t mpz;
2007
+ mpz_init(mpz);
2008
+ mpfrrb_bignum_to_mpz(other, mpz);
2009
+ r = mpfr_cmp_z(mp, mpz);
2010
+ mpz_clear(mpz);
2011
+ } else if (RB_TYPE_P(other, T_RATIONAL)) {
2012
+ mpq_t mpq;
2013
+ mpq_init(mpq);
2014
+ mpfrrb_rational_to_mpq(other, mpq);
2015
+ r = mpfr_cmp_q(mp, mpq);
2016
+ mpq_clear(mpq);
2017
+ } else if (rb_obj_is_kind_of(other, c_MPFR)) {
2018
+ r = mpfr_cmp(mp, mpfrrb_rb2ref(other));
2019
+ } else {
2020
+ return Qnil;
2021
+ }
2022
+ return INT2NUM(r);
2023
+ }
2024
+
2025
+
2026
+ /* Returns an array with both `num` and `self` represented as MPFR objects.
2027
+ * If `num` is a Rational, the returned array contains both `num` and `self` as rationals.
2028
+ * @return [Array<MPFR,Rational>] `[num.to_mpfr, self]`
2029
+ */
2030
+ static VALUE mpfrrb_coerce(VALUE self, VALUE num)
2031
+ {
2032
+ if (RB_FLOAT_TYPE_P(num)) {
2033
+ return rb_ary_new_from_args(2, mpfrrb_Float_to_mpfr(num), self);
2034
+ } else if (RB_INTEGER_TYPE_P(num)) {
2035
+ return rb_ary_new_from_args(2, mpfrrb_Integer_to_mpfr(num), self);
2036
+ } else if (RB_TYPE_P(num, T_RATIONAL)) {
2037
+ return rb_ary_new_from_args(2, num, mpfrrb_to_r(self));
2038
+ } else {
2039
+ rb_raise(rb_eArgError, "invalid value: %" PRIsVALUE, num);
2040
+ }
2041
+ }
2042
+
2043
+
2044
+ /* Set self to the natural logarithm of `v`, rounded in the direction `round`.
2045
+ * Set self to +0 if `v` is 1 (in all rounding modes), for consistency with the ISO C99 and IEEE 754 standards.
2046
+ * Set self to -Inf if `v` is ±0 (i.e., the sign of the zero has no influence on the result).
2047
+ * @return [Integer]
2048
+ * @overload log(v, round: MPFR.default_rounding)
2049
+ */
2050
+ static VALUE mpfrrb_log(int argc, VALUE *argv, VALUE self)
2051
+ {
2052
+ VALUE a;
2053
+ mpfr_rnd_t rnd = mpfrrb_get_b_round(argc, argv, &a);
2054
+ mpfr_ptr mpr = mpfrrb_rb2ref(self);
2055
+ int r;
2056
+
2057
+ if (RB_FLOAT_TYPE_P(a)) {
2058
+ MPFR_DECL_INIT(mpa, 53);
2059
+ mpfr_set_d(mpa, NUM2DBL(a), MPFR_RNDN);
2060
+ r = mpfr_log(mpr, mpa, rnd);
2061
+ } else if (RB_FIXNUM_P(a)) {
2062
+ long int i = NUM2LL(a);
2063
+ if (i < 0) {
2064
+ mpfr_set_nan(mpr);
2065
+ r = 0;
2066
+ } else {
2067
+ r = mpfr_log_ui(mpr, i, rnd);
2068
+ }
2069
+ } else if (RB_TYPE_P(a, T_BIGNUM)) {
2070
+ mpz_t mpz;
2071
+ mpz_init(mpz);
2072
+ mpfrrb_bignum_to_mpz(a, mpz);
2073
+ int nlz_bits_ret;
2074
+ size_t nb_bytes = rb_absint_size(a, &nlz_bits_ret);
2075
+ mpfr_prec_t p = nb_bytes*8 - nlz_bits_ret;
2076
+ mpfr_t mpa;
2077
+ mpfr_init2(mpa, p);
2078
+ mpfr_set_z(mpa, mpz, MPFR_RNDN);
2079
+ mpz_clear(mpz);
2080
+ r = mpfr_log(mpr, mpa, rnd);
2081
+ mpfr_clear(mpa);
2082
+ } else {
2083
+ mpfr_ptr mpa = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(a));
2084
+ r = mpfr_log(mpr, mpa, rnd);
2085
+ }
2086
+ return INT2NUM(r);
2087
+ }
2088
+
2089
+
2090
+ /* Set self to the base 2 logarithm of `v`, rounded in the direction `round`.
2091
+ * Set self to +0 if `v` is 1 (in all rounding modes), for consistency with the ISO C99 and IEEE 754 standards.
2092
+ * Set self to -Inf if `v` is ±0 (i.e., the sign of the zero has no influence on the result).
2093
+ * @return [Integer]
2094
+ * @overload log2(v, round: MPFR.default_rounding)
2095
+ */
2096
+ static VALUE mpfrrb_log2(int argc, VALUE *argv, VALUE self)
2097
+ {
2098
+ VALUE a;
2099
+ mpfr_rnd_t rnd = mpfrrb_get_b_round(argc, argv, &a);
2100
+ mpfr_ptr mpr = mpfrrb_rb2ref(self);
2101
+ int r;
2102
+
2103
+ if (RB_FLOAT_TYPE_P(a)) {
2104
+ MPFR_DECL_INIT(mpa, 53);
2105
+ mpfr_set_d(mpa, NUM2DBL(a), MPFR_RNDN);
2106
+ r = mpfr_log2(mpr, mpa, rnd);
2107
+ } else if (RB_FIXNUM_P(a)) {
2108
+ MPFR_DECL_INIT(mpa, 64);
2109
+ mpfr_set_si(mpa, NUM2LL(a), MPFR_RNDN);
2110
+ r = mpfr_log2(mpr, mpa, rnd);
2111
+ } else if (RB_TYPE_P(a, T_BIGNUM)) {
2112
+ mpz_t mpz; mpz_init(mpz); mpfrrb_bignum_to_mpz(a, mpz);
2113
+ int nlz_bits_ret; size_t nb_bytes = rb_absint_size(a, &nlz_bits_ret);
2114
+ mpfr_prec_t p = nb_bytes*8 - nlz_bits_ret; mpfr_t mpa; mpfr_init2(mpa, p);
2115
+ mpfr_set_z(mpa, mpz, MPFR_RNDN); mpz_clear(mpz);
2116
+ r = mpfr_log2(mpr, mpa, rnd); mpfr_clear(mpa);
2117
+ } else {
2118
+ mpfr_ptr mpa = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(a));
2119
+ r = mpfr_log2(mpr, mpa, rnd);
2120
+ }
2121
+ return INT2NUM(r);
2122
+ }
2123
+
2124
+
2125
+ #define MPFRRB_ONE_ARG_FUNC_BODY(func) \
2126
+ VALUE a; \
2127
+ mpfr_rnd_t rnd = mpfrrb_get_b_round(argc, argv, &a); \
2128
+ mpfr_ptr mpr = mpfrrb_rb2ref(self); \
2129
+ int r; \
2130
+ if (RB_FLOAT_TYPE_P(a)) { \
2131
+ MPFR_DECL_INIT(mpa, 53); \
2132
+ mpfr_set_d(mpa, NUM2DBL(a), MPFR_RNDN); \
2133
+ r = mpfr_##func(mpr, mpa, rnd); \
2134
+ } else if (RB_FIXNUM_P(a)) { \
2135
+ MPFR_DECL_INIT(mpa, 64); \
2136
+ mpfr_set_si(mpa, NUM2LL(a), MPFR_RNDN); \
2137
+ r = mpfr_##func(mpr, mpa, rnd); \
2138
+ } else if (RB_TYPE_P(a, T_BIGNUM)) { \
2139
+ mpz_t mpz; mpz_init(mpz); mpfrrb_bignum_to_mpz(a, mpz); \
2140
+ int nlz_bits_ret; size_t nb_bytes = rb_absint_size(a, &nlz_bits_ret); \
2141
+ mpfr_prec_t p = nb_bytes*8 - nlz_bits_ret; mpfr_t mpa; mpfr_init2(mpa, p); \
2142
+ mpfr_set_z(mpa, mpz, MPFR_RNDN); mpz_clear(mpz); \
2143
+ r = mpfr_##func(mpr, mpa, rnd); mpfr_clear(mpa); \
2144
+ } else { \
2145
+ mpfr_ptr mpa = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(a)); \
2146
+ r = mpfr_##func(mpr, mpa, rnd); \
2147
+ } \
2148
+ return INT2NUM(r)
2149
+
2150
+
2151
+ #define MPFRRB_TWO_ARG_FUNC_BODY(func) \
2152
+ VALUE x, y; \
2153
+ mpfr_rnd_t rnd = mpfrrb_get_a_b_round(argc, argv, &x, &y); \
2154
+ mpfr_ptr mpr = mpfrrb_rb2ref(self); \
2155
+ int r; \
2156
+ if (RB_FLOAT_TYPE_P(x)) { \
2157
+ MPFR_DECL_INIT(mpx, 53); \
2158
+ mpfr_set_d(mpx, NUM2DBL(x), MPFR_RNDN); \
2159
+ if (RB_FLOAT_TYPE_P(y)) { \
2160
+ MPFR_DECL_INIT(mpy, 53); \
2161
+ mpfr_set_d(mpy, NUM2DBL(y), MPFR_RNDN); \
2162
+ r = mpfr_##func(mpr, mpx, mpy, rnd); \
2163
+ } else if (RB_FIXNUM_P(y)) { \
2164
+ MPFR_DECL_INIT(mpy, 64); \
2165
+ mpfr_set_si(mpy, NUM2LL(y), MPFR_RNDN); \
2166
+ r = mpfr_##func(mpr, mpx, mpy, rnd); \
2167
+ } else if (RB_TYPE_P(y, T_BIGNUM)) { \
2168
+ mpz_t mpzy; mpz_init(mpzy); mpfrrb_bignum_to_mpz(y, mpzy); \
2169
+ int nlz_bits_ret; size_t nb_bytes = rb_absint_size(y, &nlz_bits_ret); \
2170
+ mpfr_prec_t p = nb_bytes*8 - nlz_bits_ret; mpfr_t mpy; mpfr_init2(mpy, p); \
2171
+ mpfr_set_z(mpy, mpzy, MPFR_RNDN); mpz_clear(mpzy); \
2172
+ r = mpfr_##func(mpr, mpx, mpy, rnd); mpfr_clear(mpy); \
2173
+ } else { \
2174
+ mpfr_ptr mpy = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(y)); \
2175
+ r = mpfr_##func(mpr, mpx, mpy, rnd); \
2176
+ } \
2177
+ } else if (RB_FIXNUM_P(x)) { \
2178
+ MPFR_DECL_INIT(mpx, 64); \
2179
+ mpfr_set_si(mpx, NUM2LL(x), MPFR_RNDN); \
2180
+ if (RB_FLOAT_TYPE_P(y)) { \
2181
+ MPFR_DECL_INIT(mpy, 53); \
2182
+ mpfr_set_d(mpy, NUM2DBL(y), MPFR_RNDN); \
2183
+ r = mpfr_##func(mpr, mpx, mpy, rnd); \
2184
+ } else if (RB_FIXNUM_P(y)) { \
2185
+ MPFR_DECL_INIT(mpy, 64); \
2186
+ mpfr_set_si(mpy, NUM2LL(y), MPFR_RNDN); \
2187
+ r = mpfr_##func(mpr, mpx, mpy, rnd); \
2188
+ } else if (RB_TYPE_P(y, T_BIGNUM)) { \
2189
+ mpz_t mpzy; mpz_init(mpzy); mpfrrb_bignum_to_mpz(y, mpzy); \
2190
+ int nlz_bits_ret; size_t nb_bytes = rb_absint_size(y, &nlz_bits_ret); \
2191
+ mpfr_prec_t p = nb_bytes*8 - nlz_bits_ret; mpfr_t mpy; mpfr_init2(mpy, p); \
2192
+ mpfr_set_z(mpy, mpzy, MPFR_RNDN); mpz_clear(mpzy); \
2193
+ r = mpfr_##func(mpr, mpx, mpy, rnd); mpfr_clear(mpy); \
2194
+ } else { \
2195
+ mpfr_ptr mpy = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(y)); \
2196
+ r = mpfr_##func(mpr, mpx, mpy, rnd); \
2197
+ } \
2198
+ } else if (RB_TYPE_P(x, T_BIGNUM)) { \
2199
+ mpz_t mpz; mpz_init(mpz); mpfrrb_bignum_to_mpz(x, mpz); \
2200
+ int nlz_bits_ret; size_t nb_bytes = rb_absint_size(x, &nlz_bits_ret); \
2201
+ mpfr_prec_t p = nb_bytes*8 - nlz_bits_ret; mpfr_t mpx; mpfr_init2(mpx, p); \
2202
+ mpfr_set_z(mpx, mpz, MPFR_RNDN); mpz_clear(mpz); \
2203
+ if (RB_FLOAT_TYPE_P(y)) { \
2204
+ MPFR_DECL_INIT(mpy, 53); \
2205
+ mpfr_set_d(mpy, NUM2DBL(y), MPFR_RNDN); \
2206
+ r = mpfr_##func(mpr, mpx, mpy, rnd); \
2207
+ } else if (RB_FIXNUM_P(y)) { \
2208
+ MPFR_DECL_INIT(mpy, 64); \
2209
+ mpfr_set_si(mpy, NUM2LL(y), MPFR_RNDN); \
2210
+ r = mpfr_##func(mpr, mpx, mpy, rnd); \
2211
+ } else if (RB_TYPE_P(y, T_BIGNUM)) { \
2212
+ mpz_t mpzy; mpz_init(mpzy); mpfrrb_bignum_to_mpz(y, mpzy); \
2213
+ int nlz_bits_ret; size_t nb_bytes = rb_absint_size(y, &nlz_bits_ret); \
2214
+ mpfr_prec_t p = nb_bytes*8 - nlz_bits_ret; mpfr_t mpy; mpfr_init2(mpy, p); \
2215
+ mpfr_set_z(mpy, mpzy, MPFR_RNDN); mpz_clear(mpzy); \
2216
+ r = mpfr_##func(mpr, mpx, mpy, rnd); mpfr_clear(mpy); \
2217
+ } else { \
2218
+ mpfr_ptr mpy = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(y)); \
2219
+ r = mpfr_##func(mpr, mpx, mpy, rnd); \
2220
+ } \
2221
+ mpfr_clear(mpx); \
2222
+ } else { \
2223
+ mpfr_ptr mpx = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(x)); \
2224
+ if (RB_FLOAT_TYPE_P(y)) { \
2225
+ MPFR_DECL_INIT(mpy, 53); \
2226
+ mpfr_set_d(mpy, NUM2DBL(y), MPFR_RNDN); \
2227
+ r = mpfr_##func(mpr, mpx, mpy, rnd); \
2228
+ } else if (RB_FIXNUM_P(y)) { \
2229
+ MPFR_DECL_INIT(mpy, 64); \
2230
+ mpfr_set_si(mpy, NUM2LL(y), MPFR_RNDN); \
2231
+ r = mpfr_##func(mpr, mpx, mpy, rnd); \
2232
+ } else if (RB_TYPE_P(y, T_BIGNUM)) { \
2233
+ mpz_t mpzy; mpz_init(mpzy); mpfrrb_bignum_to_mpz(y, mpzy); \
2234
+ int nlz_bits_ret; size_t nb_bytes = rb_absint_size(y, &nlz_bits_ret); \
2235
+ mpfr_prec_t p = nb_bytes*8 - nlz_bits_ret; mpfr_t mpy; mpfr_init2(mpy, p); \
2236
+ mpfr_set_z(mpy, mpzy, MPFR_RNDN); mpz_clear(mpzy); \
2237
+ r = mpfr_##func(mpr, mpx, mpy, rnd); mpfr_clear(mpy); \
2238
+ } else { \
2239
+ mpfr_ptr mpy = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(y)); \
2240
+ r = mpfr_##func(mpr, mpx, mpy, rnd); \
2241
+ } \
2242
+ } \
2243
+ return INT2NUM(r)
2244
+
2245
+
2246
+ #define MPFRRB_ONE_ARG_SL_FUNC_BODY(func) \
2247
+ VALUE a, urb; \
2248
+ mpfr_rnd_t rnd = mpfrrb_get_a_b_round(argc, argv, &a, &urb); \
2249
+ long int n = NUM2LL(urb); \
2250
+ mpfr_ptr mpr = mpfrrb_rb2ref(self); \
2251
+ int r; \
2252
+ if (RB_FLOAT_TYPE_P(a)) { \
2253
+ MPFR_DECL_INIT(mpa, 53); \
2254
+ mpfr_set_d(mpa, NUM2DBL(a), MPFR_RNDN); \
2255
+ r = mpfr_##func(mpr, mpa, n, rnd); \
2256
+ } else if (RB_FIXNUM_P(a)) { \
2257
+ MPFR_DECL_INIT(mpa, 64); \
2258
+ mpfr_set_si(mpa, NUM2LL(a), MPFR_RNDN); \
2259
+ r = mpfr_##func(mpr, mpa, n, rnd); \
2260
+ } else if (RB_TYPE_P(a, T_BIGNUM)) { \
2261
+ mpz_t mpz; mpz_init(mpz); mpfrrb_bignum_to_mpz(a, mpz); \
2262
+ int nlz_bits_ret; size_t nb_bytes = rb_absint_size(a, &nlz_bits_ret); \
2263
+ mpfr_prec_t p = nb_bytes*8 - nlz_bits_ret; mpfr_t mpa; mpfr_init2(mpa, p); \
2264
+ mpfr_set_z(mpa, mpz, MPFR_RNDN); mpz_clear(mpz); \
2265
+ r = mpfr_##func(mpr, mpa, n, rnd); mpfr_clear(mpa); \
2266
+ } else { \
2267
+ mpfr_ptr mpa = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(a)); \
2268
+ r = mpfr_##func(mpr, mpa, n, rnd); \
2269
+ } \
2270
+ return INT2NUM(r)
2271
+
2272
+
2273
+ #define MPFRRB_ONE_ARG_UL_FUNC_BODY(func) \
2274
+ VALUE a, urb; \
2275
+ mpfr_rnd_t rnd = mpfrrb_get_a_b_round(argc, argv, &a, &urb); \
2276
+ unsigned long int u = NUM2ULONG(urb); \
2277
+ mpfr_ptr mpr = mpfrrb_rb2ref(self); \
2278
+ int r; \
2279
+ if (RB_FLOAT_TYPE_P(a)) { \
2280
+ MPFR_DECL_INIT(mpa, 53); \
2281
+ mpfr_set_d(mpa, NUM2DBL(a), MPFR_RNDN); \
2282
+ r = mpfr_##func(mpr, mpa, u, rnd); \
2283
+ } else if (RB_FIXNUM_P(a)) { \
2284
+ MPFR_DECL_INIT(mpa, 64); \
2285
+ mpfr_set_si(mpa, NUM2LL(a), MPFR_RNDN); \
2286
+ r = mpfr_##func(mpr, mpa, u, rnd); \
2287
+ } else if (RB_TYPE_P(a, T_BIGNUM)) { \
2288
+ mpz_t mpz; mpz_init(mpz); mpfrrb_bignum_to_mpz(a, mpz); \
2289
+ int nlz_bits_ret; size_t nb_bytes = rb_absint_size(a, &nlz_bits_ret); \
2290
+ mpfr_prec_t p = nb_bytes*8 - nlz_bits_ret; mpfr_t mpa; mpfr_init2(mpa, p); \
2291
+ mpfr_set_z(mpa, mpz, MPFR_RNDN); mpz_clear(mpz); \
2292
+ r = mpfr_##func(mpr, mpa, u, rnd); mpfr_clear(mpa); \
2293
+ } else { \
2294
+ mpfr_ptr mpa = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(a)); \
2295
+ r = mpfr_##func(mpr, mpa, u, rnd); \
2296
+ } \
2297
+ return INT2NUM(r)
2298
+
2299
+
2300
+ #define MPFRRB_TWO_ARG_UL_FUNC_BODY(func) \
2301
+ VALUE x, y, urb; \
2302
+ mpfr_rnd_t rnd = mpfrrb_get_a_b_c_round(argc, argv, &x, &y, &urb); \
2303
+ unsigned long int u = NUM2ULONG(urb); \
2304
+ mpfr_ptr mpr = mpfrrb_rb2ref(self); \
2305
+ int r; \
2306
+ if (RB_FLOAT_TYPE_P(x)) { \
2307
+ MPFR_DECL_INIT(mpx, 53); \
2308
+ mpfr_set_d(mpx, NUM2DBL(x), MPFR_RNDN); \
2309
+ if (RB_FLOAT_TYPE_P(y)) { \
2310
+ MPFR_DECL_INIT(mpy, 53); \
2311
+ mpfr_set_d(mpy, NUM2DBL(y), MPFR_RNDN); \
2312
+ r = mpfr_##func(mpr, mpx, mpy, u, rnd); \
2313
+ } else if (RB_FIXNUM_P(y)) { \
2314
+ MPFR_DECL_INIT(mpy, 64); \
2315
+ mpfr_set_si(mpy, NUM2LL(y), MPFR_RNDN); \
2316
+ r = mpfr_##func(mpr, mpx, mpy, u, rnd); \
2317
+ } else if (RB_TYPE_P(y, T_BIGNUM)) { \
2318
+ mpz_t mpzy; mpz_init(mpzy); mpfrrb_bignum_to_mpz(y, mpzy); \
2319
+ int nlz_bits_ret; size_t nb_bytes = rb_absint_size(y, &nlz_bits_ret); \
2320
+ mpfr_prec_t p = nb_bytes*8 - nlz_bits_ret; mpfr_t mpy; mpfr_init2(mpy, p); \
2321
+ mpfr_set_z(mpy, mpzy, MPFR_RNDN); mpz_clear(mpzy); \
2322
+ r = mpfr_##func(mpr, mpx, mpy, u, rnd); mpfr_clear(mpy); \
2323
+ } else { \
2324
+ mpfr_ptr mpy = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(y)); \
2325
+ r = mpfr_##func(mpr, mpx, mpy, u, rnd); \
2326
+ } \
2327
+ } else if (RB_FIXNUM_P(x)) { \
2328
+ MPFR_DECL_INIT(mpx, 64); \
2329
+ mpfr_set_si(mpx, NUM2LL(x), MPFR_RNDN); \
2330
+ if (RB_FLOAT_TYPE_P(y)) { \
2331
+ MPFR_DECL_INIT(mpy, 53); \
2332
+ mpfr_set_d(mpy, NUM2DBL(y), MPFR_RNDN); \
2333
+ r = mpfr_##func(mpr, mpx, mpy, u, rnd); \
2334
+ } else if (RB_FIXNUM_P(y)) { \
2335
+ MPFR_DECL_INIT(mpy, 64); \
2336
+ mpfr_set_si(mpy, NUM2LL(y), MPFR_RNDN); \
2337
+ r = mpfr_##func(mpr, mpx, mpy, u, rnd); \
2338
+ } else if (RB_TYPE_P(y, T_BIGNUM)) { \
2339
+ mpz_t mpzy; mpz_init(mpzy); mpfrrb_bignum_to_mpz(y, mpzy); \
2340
+ int nlz_bits_ret; size_t nb_bytes = rb_absint_size(y, &nlz_bits_ret); \
2341
+ mpfr_prec_t p = nb_bytes*8 - nlz_bits_ret; mpfr_t mpy; mpfr_init2(mpy, p); \
2342
+ mpfr_set_z(mpy, mpzy, MPFR_RNDN); mpz_clear(mpzy); \
2343
+ r = mpfr_##func(mpr, mpx, mpy, u, rnd); mpfr_clear(mpy); \
2344
+ } else { \
2345
+ mpfr_ptr mpy = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(y)); \
2346
+ r = mpfr_##func(mpr, mpx, mpy, u, rnd); \
2347
+ } \
2348
+ } else if (RB_TYPE_P(x, T_BIGNUM)) { \
2349
+ mpz_t mpz; mpz_init(mpz); mpfrrb_bignum_to_mpz(x, mpz); \
2350
+ int nlz_bits_ret; size_t nb_bytes = rb_absint_size(x, &nlz_bits_ret); \
2351
+ mpfr_prec_t p = nb_bytes*8 - nlz_bits_ret; mpfr_t mpx; mpfr_init2(mpx, p); \
2352
+ mpfr_set_z(mpx, mpz, MPFR_RNDN); mpz_clear(mpz); \
2353
+ if (RB_FLOAT_TYPE_P(y)) { \
2354
+ MPFR_DECL_INIT(mpy, 53); \
2355
+ mpfr_set_d(mpy, NUM2DBL(y), MPFR_RNDN); \
2356
+ r = mpfr_##func(mpr, mpx, mpy, u, rnd); \
2357
+ } else if (RB_FIXNUM_P(y)) { \
2358
+ MPFR_DECL_INIT(mpy, 64); \
2359
+ mpfr_set_si(mpy, NUM2LL(y), MPFR_RNDN); \
2360
+ r = mpfr_##func(mpr, mpx, mpy, u, rnd); \
2361
+ } else if (RB_TYPE_P(y, T_BIGNUM)) { \
2362
+ mpz_t mpzy; mpz_init(mpzy); mpfrrb_bignum_to_mpz(y, mpzy); \
2363
+ int nlz_bits_ret; size_t nb_bytes = rb_absint_size(y, &nlz_bits_ret); \
2364
+ mpfr_prec_t p = nb_bytes*8 - nlz_bits_ret; mpfr_t mpy; mpfr_init2(mpy, p); \
2365
+ mpfr_set_z(mpy, mpzy, MPFR_RNDN); mpz_clear(mpzy); \
2366
+ r = mpfr_##func(mpr, mpx, mpy, u, rnd); mpfr_clear(mpy); \
2367
+ } else { \
2368
+ mpfr_ptr mpy = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(y)); \
2369
+ r = mpfr_##func(mpr, mpx, mpy, u, rnd); \
2370
+ } \
2371
+ mpfr_clear(mpx); \
2372
+ } else { \
2373
+ mpfr_ptr mpx = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(x)); \
2374
+ if (RB_FLOAT_TYPE_P(y)) { \
2375
+ MPFR_DECL_INIT(mpy, 53); \
2376
+ mpfr_set_d(mpy, NUM2DBL(y), MPFR_RNDN); \
2377
+ r = mpfr_##func(mpr, mpx, mpy, u, rnd); \
2378
+ } else if (RB_FIXNUM_P(y)) { \
2379
+ MPFR_DECL_INIT(mpy, 64); \
2380
+ mpfr_set_si(mpy, NUM2LL(y), MPFR_RNDN); \
2381
+ r = mpfr_##func(mpr, mpx, mpy, u, rnd); \
2382
+ } else if (RB_TYPE_P(y, T_BIGNUM)) { \
2383
+ mpz_t mpzy; mpz_init(mpzy); mpfrrb_bignum_to_mpz(y, mpzy); \
2384
+ int nlz_bits_ret; size_t nb_bytes = rb_absint_size(y, &nlz_bits_ret); \
2385
+ mpfr_prec_t p = nb_bytes*8 - nlz_bits_ret; mpfr_t mpy; mpfr_init2(mpy, p); \
2386
+ mpfr_set_z(mpy, mpzy, MPFR_RNDN); mpz_clear(mpzy); \
2387
+ r = mpfr_##func(mpr, mpx, mpy, u, rnd); mpfr_clear(mpy); \
2388
+ } else { \
2389
+ mpfr_ptr mpy = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(y)); \
2390
+ r = mpfr_##func(mpr, mpx, mpy, u, rnd); \
2391
+ } \
2392
+ } \
2393
+ return INT2NUM(r)
2394
+
2395
+
2396
+ #define MPFRRB_ONE_ARG_NO_RND_FUNC_BODY(func) \
2397
+ mpfr_ptr mpr = mpfrrb_rb2ref(self); \
2398
+ int r; \
2399
+ if (RB_FLOAT_TYPE_P(op)) { \
2400
+ MPFR_DECL_INIT(mpa, 53); \
2401
+ mpfr_set_d(mpa, NUM2DBL(op), MPFR_RNDN); \
2402
+ r = mpfr_##func(mpr, mpa); \
2403
+ } else if (RB_FIXNUM_P(op)) { \
2404
+ MPFR_DECL_INIT(mpa, 64); \
2405
+ mpfr_set_si(mpa, NUM2LL(op), MPFR_RNDN); \
2406
+ r = mpfr_##func(mpr, mpa); \
2407
+ } else if (RB_TYPE_P(op, T_BIGNUM)) { \
2408
+ mpz_t mpz; mpz_init(mpz); mpfrrb_bignum_to_mpz(op, mpz); \
2409
+ int nlz_bits_ret; size_t nb_bytes = rb_absint_size(op, &nlz_bits_ret); \
2410
+ mpfr_prec_t p = nb_bytes*8 - nlz_bits_ret; mpfr_t mpa; mpfr_init2(mpa, p); \
2411
+ mpfr_set_z(mpa, mpz, MPFR_RNDN); mpz_clear(mpz); \
2412
+ r = mpfr_##func(mpr, mpa); mpfr_clear(mpa); \
2413
+ } else { \
2414
+ mpfr_ptr mpa = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(op)); \
2415
+ r = mpfr_##func(mpr, mpa); \
2416
+ } \
2417
+ return INT2NUM(r)
2418
+
2419
+
2420
+ #define MPFRRB_INT_MP_RND_FUNC_BODY(func) \
2421
+ VALUE x, i; \
2422
+ mpfr_rnd_t rnd = mpfrrb_get_a_b_round(argc, argv, &i, &x); \
2423
+ long int n = NUM2LL(i); \
2424
+ mpfr_ptr mpr = mpfrrb_rb2ref(self); \
2425
+ int r; \
2426
+ if (RB_FLOAT_TYPE_P(x)) { \
2427
+ MPFR_DECL_INIT(mpx, 53); \
2428
+ mpfr_set_d(mpx, NUM2DBL(x), MPFR_RNDN); \
2429
+ r = mpfr_##func(mpr, n, mpx, rnd); \
2430
+ } else if (RB_FIXNUM_P(x)) { \
2431
+ MPFR_DECL_INIT(mpx, 64); \
2432
+ mpfr_set_si(mpx, NUM2LL(x), MPFR_RNDN); \
2433
+ r = mpfr_##func(mpr, n, mpx, rnd); \
2434
+ } else if (RB_TYPE_P(x, T_BIGNUM)) { \
2435
+ mpz_t mpz; mpz_init(mpz); mpfrrb_bignum_to_mpz(x, mpz); \
2436
+ int nlz_bits_ret; size_t nb_bytes = rb_absint_size(x, &nlz_bits_ret); \
2437
+ mpfr_prec_t p = nb_bytes*8 - nlz_bits_ret; mpfr_t mpx; mpfr_init2(mpx, p); \
2438
+ mpfr_set_z(mpx, mpz, MPFR_RNDN); mpz_clear(mpz); \
2439
+ r = mpfr_##func(mpr, n, mpx, rnd); mpfr_clear(mpx); \
2440
+ } else { \
2441
+ mpfr_ptr mpx = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(x)); \
2442
+ r = mpfr_##func(mpr, n, mpx, rnd); \
2443
+ } \
2444
+ return INT2NUM(r)
2445
+
2446
+
2447
+ /* Set self to the base ten logarithm of `v`, rounded in the direction `round`.
2448
+ * Set self to +0 if `v` is 1 (in all rounding modes), for consistency with the ISO C99 and IEEE 754 standards.
2449
+ * Set self to -Inf if `v` is ±0 (i.e., the sign of the zero has no influence on the result).
2450
+ * @return [Integer]
2451
+ * @overload log10(v, round: MPFR.default_rounding)
2452
+ */
2453
+ static VALUE mpfrrb_log10(int argc, VALUE *argv, VALUE self)
2454
+ {
2455
+ MPFRRB_ONE_ARG_FUNC_BODY(log10);
2456
+ }
2457
+
2458
+
2459
+ /* Set self to the logarithm of one plus `v`, rounded in the direction `round`.
2460
+ * Set self to -Inf if `v` is -1.
2461
+ * @return [Integer]
2462
+ * @overload logp1(v, round: MPFR.default_rounding)
2463
+ */
2464
+ static VALUE mpfrrb_log1p(int argc, VALUE *argv, VALUE self)
2465
+ {
2466
+ MPFRRB_ONE_ARG_FUNC_BODY(log1p);
2467
+ }
2468
+
2469
+
2470
+ /* Set self to the logarithm of one plus `v` in radix two, rounded in the direction `round`.
2471
+ * Set self to -Inf if `v` is -1.
2472
+ * @return [Integer]
2473
+ * @overload log2p1(v, round: MPFR.default_rounding)
2474
+ */
2475
+ static VALUE mpfrrb_log2p1(int argc, VALUE *argv, VALUE self)
2476
+ {
2477
+ MPFRRB_ONE_ARG_FUNC_BODY(log2p1);
2478
+ }
2479
+
2480
+
2481
+ /* Set self to the logarithm of one plus `v` in radix ten, rounded in the direction `round`.
2482
+ * Set self to -Inf if `v` is -1.
2483
+ * @return [Integer]
2484
+ * @overload log10p1(v, round: MPFR.default_rounding)
2485
+ */
2486
+ static VALUE mpfrrb_log10p1(int argc, VALUE *argv, VALUE self)
2487
+ {
2488
+ MPFRRB_ONE_ARG_FUNC_BODY(log10p1);
2489
+ }
2490
+
2491
+
2492
+ /* Set self to the exponential of `v`, rounded in the direction `round`.
2493
+ * @return [Integer]
2494
+ * @overload exp(v, round: MPFR.default_rounding)
2495
+ */
2496
+ static VALUE mpfrrb_exp(int argc, VALUE *argv, VALUE self)
2497
+ {
2498
+ MPFRRB_ONE_ARG_FUNC_BODY(exp);
2499
+ }
2500
+
2501
+
2502
+ /* Set self to 2 power of `v`, rounded in the direction `round`.
2503
+ * @return [Integer]
2504
+ * @overload exp2(v, round: MPFR.default_rounding)
2505
+ */
2506
+ static VALUE mpfrrb_exp2(int argc, VALUE *argv, VALUE self)
2507
+ {
2508
+ MPFRRB_ONE_ARG_FUNC_BODY(exp2);
2509
+ }
2510
+
2511
+
2512
+ /* Set self to 10 power of `v`, rounded in the direction `round`.
2513
+ * @return [Integer]
2514
+ * @overload exp10(v, round: MPFR.default_rounding)
2515
+ */
2516
+ static VALUE mpfrrb_exp10(int argc, VALUE *argv, VALUE self)
2517
+ {
2518
+ MPFRRB_ONE_ARG_FUNC_BODY(exp10);
2519
+ }
2520
+
2521
+
2522
+ /* Set self to the exponential of `v` followed by a subtraction by one, rounded in the direction `round`.
2523
+ * @return [Integer]
2524
+ * @overload expm1(v, round: MPFR.default_rounding)
2525
+ */
2526
+ static VALUE mpfrrb_expm1(int argc, VALUE *argv, VALUE self)
2527
+ {
2528
+ MPFRRB_ONE_ARG_FUNC_BODY(expm1);
2529
+ }
2530
+
2531
+
2532
+ /* Set self to 2 power of `v` followed by a subtraction by one, rounded in the direction `round`.
2533
+ * @return [Integer]
2534
+ * @overload exp2m1(v, round: MPFR.default_rounding)
2535
+ */
2536
+ static VALUE mpfrrb_exp2m1(int argc, VALUE *argv, VALUE self)
2537
+ {
2538
+ MPFRRB_ONE_ARG_FUNC_BODY(exp2m1);
2539
+ }
2540
+
2541
+
2542
+ /* Set self to 10 power of `v` followed by a subtraction by one, rounded in the direction `round`.
2543
+ * @return [Integer]
2544
+ * @overload exp10m1(v, round: MPFR.default_rounding)
2545
+ */
2546
+ static VALUE mpfrrb_exp10m1(int argc, VALUE *argv, VALUE self)
2547
+ {
2548
+ MPFRRB_ONE_ARG_FUNC_BODY(exp10m1);
2549
+ }
2550
+
2551
+
2552
+ /* Set _self_ to `x` raised to `y`, rounded in the direction `round`.
2553
+ *
2554
+ * Special values are handled as described in the ISO C99 and IEEE 754 standards for the _pow_ function:
2555
+ * - pow(±0, _y_) returns ±Inf for _y_ a negative odd integer.
2556
+ * - pow(±0, _y_) returns +Inf for _y_ negative and not an odd integer.
2557
+ * - pow(±0, _y_) returns ±0 for _y_ a positive odd integer.
2558
+ * - pow(±0, _y_) returns +0 for _y_ positive and not an odd integer.
2559
+ * - pow(-1, ±Inf) returns 1.
2560
+ * - pow(+1, _y_) returns 1 for any _y_, even a NaN.
2561
+ * - pow(_x_, ±0) returns 1 for any _x_, even a NaN.
2562
+ * - pow(_x_, _y_) returns NaN for finite negative _x_ and finite non-integer _y_.
2563
+ * - pow(_x_, -Inf) returns +Inf for 0 < abs(_x_) < 1, and +0 for abs(_x_) > 1.
2564
+ * - pow(_x_, +Inf) returns +0 for 0 < abs(_x_) < 1, and +Inf for abs(_x_) > 1.
2565
+ * - pow(-Inf, _y_) returns -0 for _y_ a negative odd integer.
2566
+ * - pow(-Inf, _y_) returns +0 for _y_ negative and not an odd integer.
2567
+ * - pow(-Inf, _y_) returns -Inf for _y_ a positive odd integer.
2568
+ * - pow(-Inf, _y_) returns +Inf for _y_ positive and not an odd integer.
2569
+ * - pow(+Inf, _y_) returns +0 for _y_ negative, and +Inf for _y_ positive.
2570
+ * @note When 0 is of integer type, it is regarded as +0 by these functions. We do not use the usual limit rules in this case, as these rules are not used for _pow_.
2571
+ * @return [Integer]
2572
+ * @overload pow(x, y, round: MPFR.default_rounding)
2573
+ * @param x [MPFR, Float, Integer]
2574
+ * @param y [MPFR, Float, Integer]
2575
+ */
2576
+ static VALUE mpfrrb_pow(int argc, VALUE *argv, VALUE self)
2577
+ {
2578
+ VALUE x, y;
2579
+ mpfr_rnd_t rnd = mpfrrb_get_a_b_round(argc, argv, &x, &y);
2580
+ mpfr_ptr mpr = mpfrrb_rb2ref(self);
2581
+ int r;
2582
+ if (RB_FLOAT_TYPE_P(x)) {
2583
+ MPFR_DECL_INIT(mpx, 53);
2584
+ mpfr_set_d(mpx, NUM2DBL(x), MPFR_RNDN);
2585
+ if (RB_FLOAT_TYPE_P(y)) {
2586
+ MPFR_DECL_INIT(mpy, 53);
2587
+ mpfr_set_d(mpy, NUM2DBL(y), MPFR_RNDN);
2588
+ r = mpfr_pow(mpr, mpx, mpy, rnd);
2589
+ } else if (RB_FIXNUM_P(y)) {
2590
+ long long n = NUM2LL(y);
2591
+ r = mpfr_pow_si(mpr, mpx, n, rnd);
2592
+ } else if (RB_TYPE_P(y, T_BIGNUM)) {
2593
+ mpz_t mpzy;
2594
+ mpz_init(mpzy);
2595
+ mpfrrb_bignum_to_mpz(y, mpzy);
2596
+ r = mpfr_pow_z(mpr, mpx, mpzy, rnd);
2597
+ mpz_clear(mpzy);
2598
+ } else {
2599
+ mpfr_ptr mpy = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(y));
2600
+ r = mpfr_pow(mpr, mpx, mpy, rnd);
2601
+ }
2602
+ } else if (RB_FIXNUM_P(x)) {
2603
+ long long xn = NUM2LL(x);
2604
+ if (xn >= 0) {
2605
+ if (RB_FLOAT_TYPE_P(y)) {
2606
+ MPFR_DECL_INIT(mpy, 53);
2607
+ mpfr_set_d(mpy, NUM2DBL(y), MPFR_RNDN);
2608
+ r = mpfr_ui_pow(mpr, xn, mpy, rnd);
2609
+ } else if (RB_FIXNUM_P(y)) {
2610
+ long long yn = NUM2LL(y);
2611
+ if (yn >= 0) {
2612
+ r = mpfr_ui_pow_ui(mpr, xn, yn, rnd);
2613
+ } else {
2614
+ MPFR_DECL_INIT(mpx, 64);
2615
+ mpfr_set_si(mpx, NUM2LL(x), MPFR_RNDN);
2616
+ r = mpfr_pow_si(mpr, mpx, yn, rnd);
2617
+ }
2618
+ } else if (RB_TYPE_P(y, T_BIGNUM)) {
2619
+ MPFR_DECL_INIT(mpx, 64);
2620
+ mpfr_set_si(mpx, NUM2LL(x), MPFR_RNDN);
2621
+ mpz_t mpzy;
2622
+ mpz_init(mpzy);
2623
+ mpfrrb_bignum_to_mpz(y, mpzy);
2624
+ r = mpfr_pow_z(mpr, mpx, mpzy, rnd);
2625
+ mpz_clear(mpzy);
2626
+ } else {
2627
+ mpfr_ptr mpy = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(y));
2628
+ r = mpfr_ui_pow(mpr, xn, mpy, rnd);
2629
+ }
2630
+ } else {
2631
+ MPFR_DECL_INIT(mpx, 64);
2632
+ mpfr_set_si(mpx, NUM2LL(x), MPFR_RNDN);
2633
+ if (RB_FLOAT_TYPE_P(y)) {
2634
+ MPFR_DECL_INIT(mpy, 53);
2635
+ mpfr_set_d(mpy, NUM2DBL(y), MPFR_RNDN);
2636
+ r = mpfr_pow(mpr, mpx, mpy, rnd);
2637
+ } else if (RB_FIXNUM_P(y)) {
2638
+ long long n = NUM2LL(y);
2639
+ r = mpfr_pow_si(mpr, mpx, n, rnd);
2640
+ } else if (RB_TYPE_P(y, T_BIGNUM)) {
2641
+ mpz_t mpzy;
2642
+ mpz_init(mpzy);
2643
+ mpfrrb_bignum_to_mpz(y, mpzy);
2644
+ r = mpfr_pow_z(mpr, mpx, mpzy, rnd);
2645
+ mpz_clear(mpzy);
2646
+ } else {
2647
+ mpfr_ptr mpy = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(y));
2648
+ r = mpfr_pow(mpr, mpx, mpy, rnd);
2649
+ }
2650
+ }
2651
+ } else if (RB_TYPE_P(x, T_BIGNUM)) {
2652
+ mpz_t mpz; mpz_init(mpz); mpfrrb_bignum_to_mpz(x, mpz);
2653
+ int nlz_bits_ret; size_t nb_bytes = rb_absint_size(x, &nlz_bits_ret);
2654
+ mpfr_prec_t p = nb_bytes*8 - nlz_bits_ret; mpfr_t mpx; mpfr_init2(mpx, p);
2655
+ mpfr_set_z(mpx, mpz, MPFR_RNDN); mpz_clear(mpz);
2656
+ if (RB_FLOAT_TYPE_P(y)) {
2657
+ MPFR_DECL_INIT(mpy, 53);
2658
+ mpfr_set_d(mpy, NUM2DBL(y), MPFR_RNDN);
2659
+ r = mpfr_pow(mpr, mpx, mpy, rnd);
2660
+ } else if (RB_FIXNUM_P(y)) {
2661
+ long long n = NUM2LL(y);
2662
+ r = mpfr_pow_si(mpr, mpx, n, rnd);
2663
+ } else if (RB_TYPE_P(y, T_BIGNUM)) {
2664
+ mpz_t mpzy;
2665
+ mpz_init(mpzy);
2666
+ mpfrrb_bignum_to_mpz(y, mpzy);
2667
+ r = mpfr_pow_z(mpr, mpx, mpzy, rnd);
2668
+ mpz_clear(mpzy);
2669
+ } else {
2670
+ mpfr_ptr mpy = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(y));
2671
+ r = mpfr_pow(mpr, mpx, mpy, rnd);
2672
+ }
2673
+ mpfr_clear(mpx);
2674
+ } else {
2675
+ mpfr_ptr mpx = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(x));
2676
+ if (RB_FLOAT_TYPE_P(y)) {
2677
+ MPFR_DECL_INIT(mpy, 53);
2678
+ mpfr_set_d(mpy, NUM2DBL(y), MPFR_RNDN);
2679
+ r = mpfr_pow(mpr, mpx, mpy, rnd);
2680
+ } else if (RB_FIXNUM_P(y)) {
2681
+ long long n = NUM2LL(y);
2682
+ r = mpfr_pow_si(mpr, mpx, n, rnd);
2683
+ } else if (RB_TYPE_P(y, T_BIGNUM)) {
2684
+ mpz_t mpzy;
2685
+ mpz_init(mpzy);
2686
+ mpfrrb_bignum_to_mpz(y, mpzy);
2687
+ r = mpfr_pow_z(mpr, mpx, mpzy, rnd);
2688
+ mpz_clear(mpzy);
2689
+ } else {
2690
+ mpfr_ptr mpy = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(y));
2691
+ r = mpfr_pow(mpr, mpx, mpy, rnd);
2692
+ }
2693
+ }
2694
+ return INT2NUM(r);
2695
+ }
2696
+
2697
+
2698
+ /* Set _self_ to the power `n` of one plus `x`, following IEEE 754 for the special cases and exceptions.
2699
+ * In particular:
2700
+ * - When `x` < -1, self is set to NaN.
2701
+ * - When `n` is zero and `x` is NaN (like any value greater or equal to -1), self is set to 1.
2702
+ * - When `x` = -1, self is set to +Inf for `n` < 0, and to +0 for `n` > 0.
2703
+ * The other special cases follow the usual rules.
2704
+ * @return [Integer]
2705
+ * @overload compound(x, n, round: MPFR.default_rounding);
2706
+ * @param n [Integer]
2707
+ */
2708
+ static VALUE mpfrrb_compound(int argc, VALUE *argv, VALUE self)
2709
+ {
2710
+ MPFRRB_ONE_ARG_SL_FUNC_BODY(compound_si);
2711
+ }
2712
+
2713
+
2714
+ /* Set self to the cosine of `v`, rounded in the direction `round`.
2715
+ * @return [Integer]
2716
+ * @overload cos(v, round: MPFR.default_rounding)
2717
+ */
2718
+ static VALUE mpfrrb_cos(int argc, VALUE *argv, VALUE self)
2719
+ {
2720
+ MPFRRB_ONE_ARG_FUNC_BODY(cos);
2721
+ }
2722
+
2723
+
2724
+ /* Set self to the sine of `v`, rounded in the direction `round`.
2725
+ * @return [Integer]
2726
+ * @overload sin(v, round: MPFR.default_rounding)
2727
+ */
2728
+ static VALUE mpfrrb_sin(int argc, VALUE *argv, VALUE self)
2729
+ {
2730
+ MPFRRB_ONE_ARG_FUNC_BODY(sin);
2731
+ }
2732
+
2733
+
2734
+ /* Set self to the tangent of `v`, rounded in the direction `round`.
2735
+ * @return [Integer]
2736
+ * @overload tan(v, round: MPFR.default_rounding)
2737
+ */
2738
+ static VALUE mpfrrb_tan(int argc, VALUE *argv, VALUE self)
2739
+ {
2740
+ MPFRRB_ONE_ARG_FUNC_BODY(tan);
2741
+ }
2742
+
2743
+
2744
+ /* Set self to the cosine of `x`, multiplied by 2 Pi and divided by `u`, rounded in the direction `round`.
2745
+ *
2746
+ * For example, if `u` equals 360, one gets the cosine for `x` in degrees.
2747
+ *
2748
+ * When op multiplied by 2 and divided by u is a half-integer, the result is +0, following IEEE 754 (cosPi), so that the function is even.
2749
+ * @return [Integer]
2750
+ * @overload cosu(x, u, round: MPFR.default_rounding)
2751
+ * @param u [Integer]
2752
+ */
2753
+ static VALUE mpfrrb_cosu(int argc, VALUE *argv, VALUE self)
2754
+ {
2755
+ MPFRRB_ONE_ARG_UL_FUNC_BODY(cosu);
2756
+ }
2757
+
2758
+
2759
+ /* Set self to the sine of `x`, multiplied by 2 Pi and divided by `u`, rounded in the direction `round`.
2760
+ *
2761
+ * For example, if `u` equals 360, one gets the osine for `x` in degrees.
2762
+ *
2763
+ * When `x` multiplied by 2 and divided by `u` is an integer, the result is zero with the same sign as `x`, following IEEE 754 (sinPi),
2764
+ * so that the function is odd.
2765
+ * @return [Integer]
2766
+ * @overload cosu(x, u, round: MPFR.default_rounding)
2767
+ * @param u [Integer]
2768
+ */
2769
+ static VALUE mpfrrb_sinu(int argc, VALUE *argv, VALUE self)
2770
+ {
2771
+ MPFRRB_ONE_ARG_UL_FUNC_BODY(sinu);
2772
+ }
2773
+
2774
+
2775
+ /* Set self to the tangent of `x`, multiplied by 2 Pi and divided by `u`, rounded in the direction `round`.
2776
+ *
2777
+ * For example, if `u` equals 360, one gets the tangent for `x` in degrees.
2778
+ *
2779
+ * The method {tanu} follows IEEE 754 (tanPi).
2780
+ * @return [Integer]
2781
+ * @overload cosu(x, u, round: MPFR.default_rounding)
2782
+ * @param u [Integer]
2783
+ */
2784
+ static VALUE mpfrrb_tanu(int argc, VALUE *argv, VALUE self)
2785
+ {
2786
+ MPFRRB_ONE_ARG_UL_FUNC_BODY(tanu);
2787
+ }
2788
+
2789
+
2790
+ /* Set self to the cosine of `v` multiplied by Pi, rounded in the direction `round`.
2791
+ * See the description of {#cosu} for special values.
2792
+ * @return [Integer]
2793
+ * @overload cospi(v, round: MPFR.default_rounding)
2794
+ */
2795
+ static VALUE mpfrrb_cospi(int argc, VALUE *argv, VALUE self)
2796
+ {
2797
+ MPFRRB_ONE_ARG_FUNC_BODY(cospi);
2798
+ }
2799
+
2800
+
2801
+ /* Set self to the sine of `v` multiplied by Pi, rounded in the direction `round`.
2802
+ * See the description of {#sinu} for special values.
2803
+ * @return [Integer]
2804
+ * @overload sinpi(v, round: MPFR.default_rounding)
2805
+ */
2806
+ static VALUE mpfrrb_sinpi(int argc, VALUE *argv, VALUE self)
2807
+ {
2808
+ MPFRRB_ONE_ARG_FUNC_BODY(sinpi);
2809
+ }
2810
+
2811
+
2812
+ /* Set self to the tangent of `v` multiplied by Pi, rounded in the direction `round`.
2813
+ * See the description of {#tanu} for special values.
2814
+ * @return [Integer]
2815
+ * @overload tanpi(v, round: MPFR.default_rounding)
2816
+ */
2817
+ static VALUE mpfrrb_tanpi(int argc, VALUE *argv, VALUE self)
2818
+ {
2819
+ MPFRRB_ONE_ARG_FUNC_BODY(tanpi);
2820
+ }
2821
+
2822
+
2823
+ /* Set self to the secant of `v`, rounded in the direction `round`.
2824
+ * @return [Integer]
2825
+ * @overload cot(v, round: MPFR.default_rounding)
2826
+ */
2827
+ static VALUE mpfrrb_sec(int argc, VALUE *argv, VALUE self)
2828
+ {
2829
+ MPFRRB_ONE_ARG_FUNC_BODY(sec);
2830
+ }
2831
+
2832
+
2833
+ /* Set self to the cosecant of `v`, rounded in the direction `round`.
2834
+ * @return [Integer]
2835
+ * @overload cot(v, round: MPFR.default_rounding)
2836
+ */
2837
+ static VALUE mpfrrb_csc(int argc, VALUE *argv, VALUE self)
2838
+ {
2839
+ MPFRRB_ONE_ARG_FUNC_BODY(csc);
2840
+ }
2841
+
2842
+
2843
+ /* Set self to the cotangent of `v`, rounded in the direction `round`.
2844
+ * @return [Integer]
2845
+ * @overload cot(v, round: MPFR.default_rounding)
2846
+ */
2847
+ static VALUE mpfrrb_cot(int argc, VALUE *argv, VALUE self)
2848
+ {
2849
+ MPFRRB_ONE_ARG_FUNC_BODY(cot);
2850
+ }
2851
+
2852
+
2853
+ /* Set self to the arc-cosine of `v`, rounded in the direction `round`.
2854
+ * Note that since acos(-1) returns the floating-point number closest to Pi according to the given rounding mode,
2855
+ * this number might not be in the output range 0 ≤ self < Pi of the arc-cosine function; still, the result lies in the image of the output range by the rounding function.
2856
+ * The same holds for asin(-1), asin(1), atan(-Inf), atan(+Inf) or for atan(`v`) with large `v` and small precision of self.
2857
+ * @return [Integer]
2858
+ * @overload acos(v, round: MPFR.default_rounding)
2859
+ */
2860
+ static VALUE mpfrrb_acos(int argc, VALUE *argv, VALUE self)
2861
+ {
2862
+ MPFRRB_ONE_ARG_FUNC_BODY(acos);
2863
+ }
2864
+
2865
+
2866
+ /* Set self to the arc-sine of `v`, rounded in the direction `round`.
2867
+ * Note that since acos(-1) returns the floating-point number closest to Pi according to the given rounding mode,
2868
+ * this number might not be in the output range 0 ≤ self < Pi of the arc-cosine function; still, the result lies in the image of the output range by the rounding function.
2869
+ * The same holds for asin(-1), asin(1), atan(-Inf), atan(+Inf) or for atan(`v`) with large `v` and small precision of self.
2870
+ * @return [Integer]
2871
+ * @overload asin(v, round: MPFR.default_rounding)
2872
+ */
2873
+ static VALUE mpfrrb_asin(int argc, VALUE *argv, VALUE self)
2874
+ {
2875
+ MPFRRB_ONE_ARG_FUNC_BODY(asin);
2876
+ }
2877
+
2878
+
2879
+ /* Set self to the arc-tangent of `v`, rounded in the direction `round`.
2880
+ * Note that since acos(-1) returns the floating-point number closest to Pi according to the given rounding mode,
2881
+ * this number might not be in the output range 0 ≤ self < Pi of the arc-cosine function; still, the result lies in the image of the output range by the rounding function.
2882
+ * The same holds for asin(-1), asin(1), atan(-Inf), atan(+Inf) or for atan(`v`) with large `v` and small precision of self.
2883
+ * @return [Integer]
2884
+ * @overload atan(v, round: MPFR.default_rounding)
2885
+ */
2886
+ static VALUE mpfrrb_atan(int argc, VALUE *argv, VALUE self)
2887
+ {
2888
+ MPFRRB_ONE_ARG_FUNC_BODY(atan);
2889
+ }
2890
+
2891
+
2892
+ /* Set _self_ to the arc-cosine(x) multiplied by u and divided by 2 Pi.
2893
+ * For example, if `u` equals 360, {acosu} yields the arc-cosine in degrees.
2894
+ * @return [Integer]
2895
+ * @overload acosu(x, u, round: MPFR.default_rounding)
2896
+ * @param u [Integer]
2897
+ */
2898
+ static VALUE mpfrrb_acosu(int argc, VALUE *argv, VALUE self)
2899
+ {
2900
+ MPFRRB_ONE_ARG_UL_FUNC_BODY(acosu);
2901
+ }
2902
+
2903
+
2904
+ /* Set _self_ to the arc-sine(x) multiplied by u and divided by 2 Pi.
2905
+ * For example, if `u` equals 360, {asinu} yields the arc-sine in degrees.
2906
+ * @return [Integer]
2907
+ * @overload asinu(x, u, round: MPFR.default_rounding)
2908
+ * @param u [Integer]
2909
+ */
2910
+ static VALUE mpfrrb_asinu(int argc, VALUE *argv, VALUE self)
2911
+ {
2912
+ MPFRRB_ONE_ARG_UL_FUNC_BODY(asinu);
2913
+ }
2914
+
2915
+
2916
+ /* Set _self_ to the arc-tangent(x) multiplied by u and divided by 2 Pi.
2917
+ * For example, if `u` equals 360, {asinu} yields the arc-tangent in degrees.
2918
+ * @return [Integer]
2919
+ * @overload atanu(x, u, round: MPFR.default_rounding)
2920
+ * @param u [Integer]
2921
+ */
2922
+ static VALUE mpfrrb_atanu(int argc, VALUE *argv, VALUE self)
2923
+ {
2924
+ MPFRRB_ONE_ARG_UL_FUNC_BODY(atanu);
2925
+ }
2926
+
2927
+
2928
+ /* Set self to acos(`v`) divided by Pi, rounded in the direction `round`.
2929
+ * @return [Integer]
2930
+ * @overload acos(v, round: MPFR.default_rounding)
2931
+ */
2932
+ static VALUE mpfrrb_acospi(int argc, VALUE *argv, VALUE self)
2933
+ {
2934
+ MPFRRB_ONE_ARG_FUNC_BODY(acospi);
2935
+ }
2936
+
2937
+
2938
+ /* Set self to asin(`v`) divided by Pi, rounded in the direction `round`.
2939
+ * @return [Integer]
2940
+ * @overload asin(v, round: MPFR.default_rounding)
2941
+ */
2942
+ static VALUE mpfrrb_asinpi(int argc, VALUE *argv, VALUE self)
2943
+ {
2944
+ MPFRRB_ONE_ARG_FUNC_BODY(asinpi);
2945
+ }
2946
+
2947
+
2948
+ /* Set self to atan(`v`) divided by Pi, rounded in the direction `round`.
2949
+ * @return [Integer]
2950
+ * @overload atanpi(v, round: MPFR.default_rounding)
2951
+ */
2952
+ static VALUE mpfrrb_atanpi(int argc, VALUE *argv, VALUE self)
2953
+ {
2954
+ MPFRRB_ONE_ARG_FUNC_BODY(atanpi);
2955
+ }
2956
+
2957
+
2958
+ /* Set _self_ to the arc-tangent2 of `y` and `x`, rounded in the direction `round`.
2959
+ * If `x` > 0, then `atan2(y, x)` returns `atan(y/x)`; if `x` < 0, then `atan2(y, x)` returns the sign of `y` multiplied
2960
+ * by Pi - atan(abs(y/x)), thus a number from -Pi to Pi.
2961
+ * As for {atan}, in case the exact mathematical result is +Pi or -Pi, its rounded result might be outside the function output range.
2962
+ *
2963
+ * Special values are handled as described in the ISO C99 and IEEE 754 standards for the atan2 function:
2964
+ * - atan2(+0, -0) returns +Pi.
2965
+ * - atan2(-0, -0) returns -Pi.
2966
+ * - atan2(+0, +0) returns +0.
2967
+ * - atan2(-0, +0) returns -0.
2968
+ * - atan2(+0, _x_) returns +Pi for _x_ < 0.
2969
+ * - atan2(-0, _x_) returns -Pi for _x_ < 0.
2970
+ * - atan2(+0, _x_) returns +0 for _x_ > 0.
2971
+ * - atan2(-0, _x_) returns -0 for _x_ > 0.
2972
+ * - atan2(_y_, 0) returns -Pi/2 for _y_ < 0.
2973
+ * - atan2(_y_, 0) returns +Pi/2 for _y_ > 0.
2974
+ * - atan2(+Inf, -Inf) returns +3*Pi/4.
2975
+ * - atan2(-Inf, -Inf) returns -3*Pi/4.
2976
+ * - atan2(+Inf, +Inf) returns +Pi/4.
2977
+ * - atan2(-Inf, +Inf) returns -Pi/4.
2978
+ * - atan2(+Inf, _x_) returns +Pi/2 for finite _x_.
2979
+ * - atan2(-Inf, _x_) returns -Pi/2 for finite _x_.
2980
+ * - atan2(_y_, -Inf) returns +Pi for finite _y_ > 0.
2981
+ * - atan2(_y_, -Inf) returns -Pi for finite _y_ < 0.
2982
+ * - atan2(_y_, +Inf) returns +0 for finite _y_ > 0.
2983
+ * - atan2(_y_, +Inf) returns -0 for finite _y_ < 0.
2984
+ * @return [Integer]
2985
+ * @overload atan2(y, x, round: MPFR.default_rounding)
2986
+ */
2987
+ static VALUE mpfrrb_atan2(int argc, VALUE *argv, VALUE self)
2988
+ {
2989
+ MPFRRB_TWO_ARG_FUNC_BODY(atan2);
2990
+ }
2991
+
2992
+
2993
+ /* Behaves similarly to {atan2} except the result is multiplied by `u` and divided by 2 Pi.
2994
+ * @return [Integer]
2995
+ * @overload atan2u(y, x, u, round: MPFR.default_rounding)
2996
+ * @param u [Integer]
2997
+ */
2998
+ static VALUE mpfrrb_atan2u(int argc, VALUE *argv, VALUE self)
2999
+ {
3000
+ MPFRRB_TWO_ARG_UL_FUNC_BODY(atan2u);
3001
+ }
3002
+
3003
+
3004
+ /* The same as {atan2u} with u = 2.
3005
+ * @return [Integer]
3006
+ * @overload atan2pi(y, x, round: MPFR.default_rounding)
3007
+ */
3008
+ static VALUE mpfrrb_atan2pi(int argc, VALUE *argv, VALUE self)
3009
+ {
3010
+ MPFRRB_TWO_ARG_FUNC_BODY(atan2pi);
3011
+ }
3012
+
3013
+
3014
+ /* Set self to the hyperbolic cosine of `v`, rounded in the direction `round`.
3015
+ * @return [Integer]
3016
+ * @overload cosh(v, round: MPFR.default_rounding)
3017
+ */
3018
+ static VALUE mpfrrb_cosh(int argc, VALUE *argv, VALUE self)
3019
+ {
3020
+ MPFRRB_ONE_ARG_FUNC_BODY(cosh);
3021
+ }
3022
+
3023
+
3024
+ /* Set self to the hyperbolic sine of `v`, rounded in the direction `round`.
3025
+ * @return [Integer]
3026
+ * @overload sinh(v, round: MPFR.default_rounding)
3027
+ */
3028
+ static VALUE mpfrrb_sinh(int argc, VALUE *argv, VALUE self)
3029
+ {
3030
+ MPFRRB_ONE_ARG_FUNC_BODY(sinh);
3031
+ }
3032
+
3033
+
3034
+ /* Set self to the hyperbolic tangent of `v`, rounded in the direction `round`.
3035
+ * @return [Integer]
3036
+ * @overload tanh(v, round: MPFR.default_rounding)
3037
+ */
3038
+ static VALUE mpfrrb_tanh(int argc, VALUE *argv, VALUE self)
3039
+ {
3040
+ MPFRRB_ONE_ARG_FUNC_BODY(tanh);
3041
+ }
3042
+
3043
+
3044
+ /* Set self to the hyperbolic secant of `v`, rounded in the direction `round`.
3045
+ * @return [Integer]
3046
+ * @overload sech(v, round: MPFR.default_rounding)
3047
+ */
3048
+ static VALUE mpfrrb_sech(int argc, VALUE *argv, VALUE self)
3049
+ {
3050
+ MPFRRB_ONE_ARG_FUNC_BODY(sech);
3051
+ }
3052
+
3053
+
3054
+ /* Set self to the hyperbolic cosecant of `v`, rounded in the direction `round`.
3055
+ * @return [Integer]
3056
+ * @overload csch(v, round: MPFR.default_rounding)
3057
+ */
3058
+ static VALUE mpfrrb_csch(int argc, VALUE *argv, VALUE self)
3059
+ {
3060
+ MPFRRB_ONE_ARG_FUNC_BODY(csch);
3061
+ }
3062
+
3063
+
3064
+ /* Set self to the hyperbolic cotangent of `v`, rounded in the direction `round`.
3065
+ * @return [Integer]
3066
+ * @overload coth(v, round: MPFR.default_rounding)
3067
+ */
3068
+ static VALUE mpfrrb_coth(int argc, VALUE *argv, VALUE self)
3069
+ {
3070
+ MPFRRB_ONE_ARG_FUNC_BODY(coth);
3071
+ }
3072
+
3073
+
3074
+ /* Set self to the inverse hyperbolic cossine of `v`, rounded in the direction `round`.
3075
+ * @return [Integer]
3076
+ * @overload acosh(v, round: MPFR.default_rounding)
3077
+ */
3078
+ static VALUE mpfrrb_acosh(int argc, VALUE *argv, VALUE self)
3079
+ {
3080
+ MPFRRB_ONE_ARG_FUNC_BODY(acosh);
3081
+ }
3082
+
3083
+
3084
+ /* Set self to the inverse hyperbolic sine of `v`, rounded in the direction `round`.
3085
+ * @return [Integer]
3086
+ * @overload asinh(v, round: MPFR.default_rounding)
3087
+ */
3088
+ static VALUE mpfrrb_asinh(int argc, VALUE *argv, VALUE self)
3089
+ {
3090
+ MPFRRB_ONE_ARG_FUNC_BODY(asinh);
3091
+ }
3092
+
3093
+
3094
+ /* Set self to the inverse hyperbolic tangent of `v`, rounded in the direction `round`.
3095
+ * @return [Integer]
3096
+ * @overload atanh(v, round: MPFR.default_rounding)
3097
+ */
3098
+ static VALUE mpfrrb_atanh(int argc, VALUE *argv, VALUE self)
3099
+ {
3100
+ MPFRRB_ONE_ARG_FUNC_BODY(atanh);
3101
+ }
3102
+
3103
+
3104
+ /* Set self to the exponential integral of `v`, rounded in the direction`round`.
3105
+ * This is the sum of Euler’s constant, of the logarithm of the absolute value of `v`, and of the sum for k from 1 to infinity of `v` to the power k, divided by k and the factorial of k.
3106
+ * For positive `v`, it corresponds to the Ei function at `v` (see formula 5.1.10 from the Handbook of Mathematical Functions from Abramowitz and Stegun),
3107
+ * and for negative `v`, to the opposite of the E1 function (sometimes called eint1) at -`v` (formula 5.1.1 from the same reference).
3108
+ * @return [Integer]
3109
+ * @overload eint(v, round: MPFR.default_rounding)
3110
+ */
3111
+ static VALUE mpfrrb_eint(int argc, VALUE *argv, VALUE self)
3112
+ {
3113
+ MPFRRB_ONE_ARG_FUNC_BODY(eint);
3114
+ }
3115
+
3116
+
3117
+ /* Set self to real part of the dilogarithm of `v`, rounded in the direction`round`.
3118
+ * MPFR defines the dilogarithm function as the integral of −log(1−t)/t from 0 to `v`.
3119
+ * @return [Integer]
3120
+ * @overload li2(v, round: MPFR.default_rounding)
3121
+ */
3122
+ static VALUE mpfrrb_li2(int argc, VALUE *argv, VALUE self)
3123
+ {
3124
+ MPFRRB_ONE_ARG_FUNC_BODY(li2);
3125
+ }
3126
+
3127
+
3128
+ /* Set self to the value of the Gamma function on `v`, , rounded in the direction`round`.
3129
+ * When `v` is a negative integer, self is set to NaN.
3130
+ * @return [Integer]
3131
+ * @overload gamma(v, round: MPFR.default_rounding)
3132
+ */
3133
+ static VALUE mpfrrb_gamma(int argc, VALUE *argv, VALUE self)
3134
+ {
3135
+ MPFRRB_ONE_ARG_FUNC_BODY(gamma);
3136
+ }
3137
+
3138
+
3139
+ /* Set self to the value of the incomplete Gamma function on `x` and `y`, rounded in the direction `round`.
3140
+ * (In the literature, `gamma_inc` is called upper incomplete Gamma function, or sometimes complementary incomplete Gamma function.)
3141
+ * When `y` is zero and `x` is a negative integer, self is set to NaN.
3142
+ *
3143
+ * @note The current implementation of `gamma_inc` is slow for large values of self or `x`, in which case some internal overflow might also occur.
3144
+ * @return [Integer]
3145
+ * @overload gamma_inc(x, y, round: MPFR.default_rounding)
3146
+ */
3147
+ static VALUE mpfrrb_gamma_inc(int argc, VALUE *argv, VALUE self)
3148
+ {
3149
+ MPFRRB_TWO_ARG_FUNC_BODY(gamma_inc);
3150
+ }
3151
+
3152
+
3153
+ /* Set self to the value of the logarithm of the Gamma function on `v`, rounded in the direction`round`.
3154
+ * When `v` is 1 or 2, set self to +0 (in all rounding modes).
3155
+ * When `v` is an infinity or a non-positive integer, set self to +Inf, following the general rules on special values.
3156
+ * When −2k − 1 < `v` < −2k, k being a non-negative integer, set self to NaN.
3157
+ * @return [Integer]
3158
+ * @overload lngamma(v, round: MPFR.default_rounding)
3159
+ */
3160
+ static VALUE mpfrrb_lngamma(int argc, VALUE *argv, VALUE self)
3161
+ {
3162
+ MPFRRB_ONE_ARG_FUNC_BODY(lngamma);
3163
+ }
3164
+
3165
+
3166
+ /* Set self to the value of the Digamma (sometimes also called Psi) function on `v`, rounded in the direction`round`.
3167
+ * When `v` is a negative integer, set self to NaN.
3168
+ * @return [Integer]
3169
+ * @overload digamma(v, round: MPFR.default_rounding)
3170
+ */
3171
+ static VALUE mpfrrb_digamma(int argc, VALUE *argv, VALUE self)
3172
+ {
3173
+ MPFRRB_ONE_ARG_FUNC_BODY(digamma);
3174
+ }
3175
+
3176
+
3177
+ /* Set _self_ to the value of the Beta function at arguments `x` and `x`.
3178
+ * @note The current code does not try to avoid internal overflow or underflow, and might use a huge internal precision in some cases.
3179
+ * @return [Integer]
3180
+ * @overload beta(x, y, round: MPFR.default_rounding)
3181
+ */
3182
+ static VALUE mpfrrb_beta(int argc, VALUE *argv, VALUE self)
3183
+ {
3184
+ MPFRRB_TWO_ARG_FUNC_BODY(beta);
3185
+ }
3186
+
3187
+
3188
+ /* Set self to the value of the Riemann Zeta function on `v`, rounded in the direction`round`.
3189
+ * @return [Integer]
3190
+ * @overload zeta(v, round: MPFR.default_rounding)
3191
+ */
3192
+ static VALUE mpfrrb_zeta(int argc, VALUE *argv, VALUE self)
3193
+ {
3194
+ MPFRRB_ONE_ARG_FUNC_BODY(zeta);
3195
+ }
3196
+
3197
+
3198
+ /* Set self to the value of the error function on 'v', rounded in the direction `round`.
3199
+ * @return [Integer]
3200
+ * @overload erf(v, round: MPFR.default_rounding)
3201
+ */
3202
+ static VALUE mpfrrb_erf(int argc, VALUE *argv, VALUE self)
3203
+ {
3204
+ MPFRRB_ONE_ARG_FUNC_BODY(erf);
3205
+ }
3206
+
3207
+
3208
+ /* Set self to the value of the complementary error function on 'v', rounded in the direction `round`.
3209
+ * @return [Integer]
3210
+ * @overload erfc(v, round: MPFR.default_rounding)
3211
+ */
3212
+ static VALUE mpfrrb_erfc(int argc, VALUE *argv, VALUE self)
3213
+ {
3214
+ MPFRRB_ONE_ARG_FUNC_BODY(erfc);
3215
+ }
3216
+
3217
+
3218
+ /* Set self to the value of the first kind Bessel function of order 0, on `v`, rounded in the direction `round`.
3219
+ * When `v` is NaN, self is always set to NaN.
3220
+ * When `v` is positive or negative infinity, self is set to +0.
3221
+ * When `v` is zero, and n is not zero, self is set to +0 or -0 depending on the parity and sign of n, and the sign of `v`.
3222
+ * @return [Integer]
3223
+ * @overload j0(v, round: MPFR.default_rounding)
3224
+ */
3225
+ static VALUE mpfrrb_j0(int argc, VALUE *argv, VALUE self)
3226
+ {
3227
+ MPFRRB_ONE_ARG_FUNC_BODY(j0);
3228
+ }
3229
+
3230
+
3231
+ /* Set self to the value of the first kind Bessel function of order 1, on `v`, rounded in the direction `round`.
3232
+ * When `v` is NaN, self is always set to NaN.
3233
+ * When `v` is positive or negative infinity, self is set to +0.
3234
+ * When `v` is zero, and n is not zero, self is set to +0 or -0 depending on the parity and sign of n, and the sign of `v`.
3235
+ * @return [Integer]
3236
+ * @overload j1(v, round: MPFR.default_rounding)
3237
+ */
3238
+ static VALUE mpfrrb_j1(int argc, VALUE *argv, VALUE self)
3239
+ {
3240
+ MPFRRB_ONE_ARG_FUNC_BODY(j1);
3241
+ }
3242
+
3243
+
3244
+ /* Set self to the value of the first kind Bessel function of order `n`, on `v`, rounded in the direction `round`.
3245
+ * When `v` is NaN, self is always set to NaN.
3246
+ * When `v` is positive or negative infinity, self is set to +0.
3247
+ * When `v` is zero, and n is not zero, self is set to +0 or -0 depending on the parity and sign of n, and the sign of `v`.
3248
+ * @return [Integer]
3249
+ * @overload jn(n, v, round: MPFR.default_rounding)
3250
+ * @param n [Integer]
3251
+ * @param v [MPFR]
3252
+ */
3253
+ static VALUE mpfrrb_jn(int argc, VALUE *argv, VALUE self)
3254
+ {
3255
+ MPFRRB_INT_MP_RND_FUNC_BODY(jn);
3256
+ }
3257
+
3258
+
3259
+ /* Set self to the value of the second kind Bessel function of order 0 on `v`, rounded in the direction `round`.
3260
+ * When `v` is NaN or negative, self is always set to NaN.
3261
+ * When `v` is +Inf, self is set to +0.
3262
+ * When `v` is zero, self is set to +Inf or -Inf depending on the parity and sign of `n`.
3263
+ * @return [Integer]
3264
+ * @overload y1(v, round: MPFR.default_rounding)
3265
+ */
3266
+ static VALUE mpfrrb_y0(int argc, VALUE *argv, VALUE self)
3267
+ {
3268
+ MPFRRB_ONE_ARG_FUNC_BODY(y0);
3269
+ }
3270
+
3271
+
3272
+ /* Set self to the value of the second kind Bessel function of order 1 on `v`, rounded in the direction `round`.
3273
+ * When `v` is NaN or negative, self is always set to NaN.
3274
+ * When `v` is +Inf, self is set to +0.
3275
+ * When `v` is zero, self is set to +Inf or -Inf depending on the parity and sign of `n`.
3276
+ * @return [Integer]
3277
+ * @overload y1(v, round: MPFR.default_rounding)
3278
+ */
3279
+ static VALUE mpfrrb_y1(int argc, VALUE *argv, VALUE self)
3280
+ {
3281
+ MPFRRB_ONE_ARG_FUNC_BODY(y1);
3282
+ }
3283
+
3284
+
3285
+ /* Set self to the value of the second kind Bessel function of order `n` on `v`, rounded in the direction `round`.
3286
+ * When `v` is NaN or negative, self is always set to NaN.
3287
+ * When `v` is +Inf, self is set to +0.
3288
+ * When `v` is zero, self is set to +Inf or -Inf depending on the parity and sign of `n`.
3289
+ * @return [Integer]
3290
+ * @overload yn(n, v, round: MPFR.default_rounding)
3291
+ * @param n [Integer]
3292
+ * @param v [MPFR]
3293
+ */
3294
+ static VALUE mpfrrb_yn(int argc, VALUE *argv, VALUE self)
3295
+ {
3296
+ MPFRRB_INT_MP_RND_FUNC_BODY(yn);
3297
+ }
3298
+
3299
+
3300
+ /* Set _self_ to the arithmetic-geometric mean of `x` and `y`, rounded in the direction `round`.
3301
+ * The arithmetic-geometric mean is the common limit of the sequences u_n and v_n, where u_0 = `x`, v_0 = `y`, u_(n+1)
3302
+ * is the arithmetic mean of u_n and v_n, and v_(n+1) is the geometric mean of u_n and v_n.
3303
+ *
3304
+ * If any operand is negative and the other one is not zero, set _self_ to NaN.
3305
+ *
3306
+ * If any operand is zero and the other one is finite (resp. infinite), set _self_ to +0 (resp. NaN).
3307
+ *
3308
+ * @return [Integer]
3309
+ * @overload agm(x, y, round: MPFR.default_rounding)
3310
+ */
3311
+ static VALUE mpfrrb_agm(int argc, VALUE *argv, VALUE self)
3312
+ {
3313
+ MPFRRB_TWO_ARG_FUNC_BODY(agm);
3314
+ }
3315
+
3316
+
3317
+ /* Set self to the value of the Airy function Ai on `x`, rounded in the direction `round`.
3318
+ *
3319
+ * When `x` is NaN, self is always set to NaN.
3320
+ * When `x` is +Inf or -Inf, self is set to +0.
3321
+ *
3322
+ * The current implementation is not intended to be used with large arguments.
3323
+ * It works with abs(x) typically smaller than 500.
3324
+ * For larger arguments, other methods should be used and will be implemented in a future version.
3325
+ * @return [Integer]
3326
+ * @overload ai(x, round: MPFR.default_rounding)
3327
+ */
3328
+ static VALUE mpfrrb_ai(int argc, VALUE *argv, VALUE self)
3329
+ {
3330
+ MPFRRB_ONE_ARG_FUNC_BODY(ai);
3331
+ }
3332
+
3333
+
3334
+ /* Set self to `op` rounded to the nearest representable integer in the direction `round`.
3335
+ * @return [Integer]
3336
+ * @overload rint(op, round: MPFR.default_rounding)
3337
+ */
3338
+ static VALUE mpfrrb_rint(int argc, VALUE *argv, VALUE self)
3339
+ {
3340
+ MPFRRB_ONE_ARG_FUNC_BODY(rint);
3341
+ }
3342
+
3343
+
3344
+ /* Set self to `op` rounded to the next higher or equal representable integer.
3345
+ * @return [Integer]
3346
+ */
3347
+ static VALUE mpfrrb_ceil(VALUE self, VALUE op)
3348
+ {
3349
+ MPFRRB_ONE_ARG_NO_RND_FUNC_BODY(ceil);
3350
+ }
3351
+
3352
+
3353
+ /* Set self to `op` rounded to the next lower or equal representable integer.
3354
+ * @return [Integer]
3355
+ */
3356
+ static VALUE mpfrrb_floor(VALUE self, VALUE op)
3357
+ {
3358
+ MPFRRB_ONE_ARG_NO_RND_FUNC_BODY(floor);
3359
+ }
3360
+
3361
+
3362
+ /* Set self to `op` rounded to the nearest representable integer, rounding halfway cases away from zero.
3363
+ * @return [Integer]
3364
+ */
3365
+ static VALUE mpfrrb_round(VALUE self, VALUE op)
3366
+ {
3367
+ MPFRRB_ONE_ARG_NO_RND_FUNC_BODY(round);
3368
+ }
3369
+
3370
+
3371
+ /* Set self to `op` rounded to the nearest representable integer, rounding halfway cases with the even-rounding rule.
3372
+ * @return [Integer]
3373
+ */
3374
+ static VALUE mpfrrb_roundeven(VALUE self, VALUE op)
3375
+ {
3376
+ MPFRRB_ONE_ARG_NO_RND_FUNC_BODY(roundeven);
3377
+ }
3378
+
3379
+
3380
+ /* Set self to `op` rounded to the next representable integer toward zero.
3381
+ * @return [Integer]
3382
+ */
3383
+ static VALUE mpfrrb_trunc(VALUE self, VALUE op)
3384
+ {
3385
+ MPFRRB_ONE_ARG_NO_RND_FUNC_BODY(trunc);
3386
+ }
3387
+
3388
+
3389
+ /* Set self to self rounded to the nearest representable integer in the direction `round`.
3390
+ * @return [Integer]
3391
+ * @overload rint!(round: MPFR.default_rounding)
3392
+ */
3393
+ static VALUE mpfrrb_rint_B(int argc, VALUE *argv, VALUE self)
3394
+ {
3395
+ mpfr_rnd_t rnd = mpfrrb_get_round_single_keword(argc, argv);
3396
+ mpfr_ptr mp = mpfrrb_rb2ref(self);
3397
+ return INT2NUM(mpfr_rint(mp, mp, rnd));
3398
+ }
3399
+
3400
+
3401
+ /* Set self to self rounded to the next higher or equal representable integer.
3402
+ * @return [Integer]
3403
+ */
3404
+ static VALUE mpfrrb_ceil_B(VALUE self)
3405
+ {
3406
+ mpfr_ptr mp = mpfrrb_rb2ref(self);
3407
+ return INT2NUM(mpfr_ceil(mp, mp));
3408
+ }
3409
+
3410
+
3411
+ /* Set self to self rounded to the next lower or equal representable integer.
3412
+ * @return [Integer]
3413
+ */
3414
+ static VALUE mpfrrb_floor_B(VALUE self)
3415
+ {
3416
+ mpfr_ptr mp = mpfrrb_rb2ref(self);
3417
+ return INT2NUM(mpfr_floor(mp, mp));
3418
+ }
3419
+
3420
+
3421
+ /* Set self to self rounded to the nearest representable integer, rounding halfway cases away from zero.
3422
+ * @return [Integer]
3423
+ */
3424
+ static VALUE mpfrrb_round_B(VALUE self)
3425
+ {
3426
+ mpfr_ptr mp = mpfrrb_rb2ref(self);
3427
+ return INT2NUM(mpfr_round(mp, mp));
3428
+ }
3429
+
3430
+
3431
+ /* Set self to self rounded to the nearest representable integer, rounding halfway cases with the even-rounding rule.
3432
+ * @return [Integer]
3433
+ */
3434
+ static VALUE mpfrrb_roundeven_B(VALUE self)
3435
+ {
3436
+ mpfr_ptr mp = mpfrrb_rb2ref(self);
3437
+ return INT2NUM(mpfr_roundeven(mp, mp));
3438
+ }
3439
+
3440
+
3441
+ /* Set self to self rounded to the next representable integer toward zero.
3442
+ * @return [Integer]
3443
+ */
3444
+ static VALUE mpfrrb_trunc_B(VALUE self)
3445
+ {
3446
+ mpfr_ptr mp = mpfrrb_rb2ref(self);
3447
+ return INT2NUM(mpfr_trunc(mp, mp));
3448
+ }
3449
+
3450
+
3451
+ /* Set self to `op` rounded to the next higher or equal integer.
3452
+ * If the result is not representable, it is rounded in the direction `round`.
3453
+ * This method do perform a double rounding:
3454
+ * first op is rounded to the nearest integer in the direction given by the method name,
3455
+ * then this nearest integer (if not representable) is rounded in the given direction `round`.
3456
+ * @return [Ingeger]
3457
+ * @overload rint_ceil(op, round: MPFR.default_rounding)
3458
+ */
3459
+ static VALUE mpfrrb_rint_ceil(int argc, VALUE *argv, VALUE self)
3460
+ {
3461
+ MPFRRB_ONE_ARG_FUNC_BODY(rint_ceil);
3462
+ }
3463
+
3464
+
3465
+ /* Set self to `op` rounded to the next lower or equal integer.
3466
+ * If the result is not representable, it is rounded in the direction `round`.
3467
+ * This method do perform a double rounding:
3468
+ * first op is rounded to the nearest integer in the direction given by the method name,
3469
+ * then this nearest integer (if not representable) is rounded in the given direction `round`.
3470
+ * @return [Ingeger]
3471
+ * @overload rint_floor(op, round: MPFR.default_rounding)
3472
+ */
3473
+ static VALUE mpfrrb_rint_floor(int argc, VALUE *argv, VALUE self)
3474
+ {
3475
+ MPFRRB_ONE_ARG_FUNC_BODY(rint_floor);
3476
+ }
3477
+
3478
+
3479
+ /* Set self to `op` rounded to the nearest integer, rounding halfway cases away from zero.
3480
+ * If the result is not representable, it is rounded in the direction `round`.
3481
+ * This method do perform a double rounding:
3482
+ * first op is rounded to the nearest integer in the direction given by the method name,
3483
+ * then this nearest integer (if not representable) is rounded in the given direction `round`.
3484
+ * @return [Ingeger]
3485
+ * @overload rint_round(op, round: MPFR.default_rounding)
3486
+ */
3487
+ static VALUE mpfrrb_rint_round(int argc, VALUE *argv, VALUE self)
3488
+ {
3489
+ MPFRRB_ONE_ARG_FUNC_BODY(rint_round);
3490
+ }
3491
+
3492
+
3493
+ /* Set self to `op` rounded to the nearest integer, rounding halfway cases to the nearest even integer.
3494
+ * If the result is not representable, it is rounded in the direction `round`.
3495
+ * This method do perform a double rounding:
3496
+ * first op is rounded to the nearest integer in the direction given by the method name,
3497
+ * then this nearest integer (if not representable) is rounded in the given direction `round`.
3498
+ * @return [Ingeger]
3499
+ * @overload rint_roundeven(op, round: MPFR.default_rounding)
3500
+ */
3501
+ static VALUE mpfrrb_rint_roundeven(int argc, VALUE *argv, VALUE self)
3502
+ {
3503
+ MPFRRB_ONE_ARG_FUNC_BODY(rint_roundeven);
3504
+ }
3505
+
3506
+
3507
+ /* Set self to `op` rounded to the next integer toward zero.
3508
+ * If the result is not representable, it is rounded in the direction `round`.
3509
+ * This method do perform a double rounding:
3510
+ * first op is rounded to the nearest integer in the direction given by the method name,
3511
+ * then this nearest integer (if not representable) is rounded in the given direction `round`.
3512
+ * @return [Ingeger]
3513
+ * @overload rint_trunc(op, round: MPFR.default_rounding)
3514
+ */
3515
+ static VALUE mpfrrb_rint_trunc(int argc, VALUE *argv, VALUE self)
3516
+ {
3517
+ MPFRRB_ONE_ARG_FUNC_BODY(rint_trunc);
3518
+ }
3519
+
3520
+
3521
+ /* Set self to the fractional part of `op`, having the same sign as `op`, rounded in the direction `round`.
3522
+ * Unlike in {#rint}, `round` affects only how the exact fractional part is rounded, not how the fractional part is generated.
3523
+ * When `op` is an integer or an infinity, set self to zero with the same sign as `op`.
3524
+ * @return [Integer]
3525
+ * @overload frac(op, round: MPFR.default_rounding)
3526
+ */
3527
+ static VALUE mpfrrb_frac(int argc, VALUE *argv, VALUE self)
3528
+ {
3529
+ MPFRRB_ONE_ARG_FUNC_BODY(frac);
3530
+ }
3531
+
3532
+
3533
+ /* Set simultaneously `ipart` to the integral part of `x` and `fpart` to the fractional part of `x`, rounded in the direction `round`
3534
+ * with the corresponding precision of `ipart` and `fpart`.
3535
+ * It is equivalent to `ipart.trunc(x, round: rnd)` and `fpart.frac(x, round: rnd)`.
3536
+ * The variables `ipart` and `fpart` must be different.
3537
+ * Return 0 iff both results are exact.
3538
+ * @return [Integer]
3539
+ * @overload modf(ipart, fpart, x, round: MPFR.default_rounding)
3540
+ * @param ipart [MPFR] output
3541
+ * @param fpart [MPFR] output
3542
+ * @param x [MPFR] input
3543
+ * @see trunc
3544
+ * @see frac
3545
+ */
3546
+ static VALUE mpfrrb_modf(int argc, VALUE *argv, VALUE self)
3547
+ {
3548
+ VALUE ipart, fpart, x;
3549
+ mpfr_rnd_t rnd = mpfrrb_get_a_b_c_round(argc, argv, &ipart, &fpart, &x);
3550
+ mpfr_ptr iop = mpfrrb_rb2ref(ipart);
3551
+ mpfr_ptr fop = mpfrrb_rb2ref(fpart);
3552
+ mpfr_ptr op = mpfrrb_rb2ref(x);
3553
+ int r = mpfr_modf(iop, fop, op, rnd);
3554
+ return INT2NUM(r);
3555
+ }
3556
+
3557
+
3558
+ /* Set _self_ the the value of `x - ny`, rounded according to the direction `round`.
3559
+ *
3560
+ * `n` is the integer quotient of `x` divided by `y`, rounded toward zero.
3561
+ *
3562
+ * Special values are handled as described in Section F.9.7.1 of the ISO C99 standard:
3563
+ * - If `x` is infinite or `y` is zero, _self_ is NaN.
3564
+ * - If `y` is infinite and `x` is finite, _self_ is `x` rounded to the precision of _self_.
3565
+ * - If _self_ is zero, it has the sign of `x`. The return value is the ternary value corresponding to _self_.
3566
+ * @return [Integer]
3567
+ * @overload fmod(x, y, round: MPFR.default_rounding)
3568
+ * @see remainder
3569
+ */
3570
+ static VALUE mpfrrb_fmod(int argc, VALUE *argv, VALUE self)
3571
+ {
3572
+ VALUE x, y;
3573
+ mpfr_rnd_t rnd = mpfrrb_get_a_b_round(argc, argv, &x, &y);
3574
+ mpfr_ptr mpr = mpfrrb_rb2ref(self);
3575
+ int r;
3576
+ if (RB_FLOAT_TYPE_P(x)) {
3577
+ MPFR_DECL_INIT(mpx, 53);
3578
+ mpfr_set_d(mpx, NUM2DBL(x), MPFR_RNDN);
3579
+ if (RB_FLOAT_TYPE_P(y)) {
3580
+ MPFR_DECL_INIT(mpy, 53);
3581
+ mpfr_set_d(mpy, NUM2DBL(y), MPFR_RNDN);
3582
+ r = mpfr_fmod(mpr, mpx, mpy, rnd);
3583
+ } else if (RB_FIXNUM_P(y)) {
3584
+ long long ly = NUM2LL(y);
3585
+ if (ly >= 0) {
3586
+ r = mpfr_fmod_ui(mpr, mpx, ly, rnd);
3587
+ } else {
3588
+ MPFR_DECL_INIT(mpy, 64);
3589
+ mpfr_set_si(mpy, NUM2LL(y), MPFR_RNDN);
3590
+ r = mpfr_fmod(mpr, mpx, mpy, rnd);
3591
+ }
3592
+ } else if (RB_TYPE_P(y, T_BIGNUM)) {
3593
+ mpz_t mpzy; mpz_init(mpzy); mpfrrb_bignum_to_mpz(y, mpzy);
3594
+ int nlz_bits_ret; size_t nb_bytes = rb_absint_size(y, &nlz_bits_ret);
3595
+ mpfr_prec_t p = nb_bytes*8 - nlz_bits_ret; mpfr_t mpy; mpfr_init2(mpy, p);
3596
+ mpfr_set_z(mpy, mpzy, MPFR_RNDN); mpz_clear(mpzy);
3597
+ r = mpfr_fmod(mpr, mpx, mpy, rnd); mpfr_clear(mpy);
3598
+ } else {
3599
+ mpfr_ptr mpy = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(y));
3600
+ r = mpfr_fmod(mpr, mpx, mpy, rnd);
3601
+ }
3602
+ } else if (RB_FIXNUM_P(x)) {
3603
+ MPFR_DECL_INIT(mpx, 64);
3604
+ mpfr_set_si(mpx, NUM2LL(x), MPFR_RNDN);
3605
+ if (RB_FLOAT_TYPE_P(y)) {
3606
+ MPFR_DECL_INIT(mpy, 53);
3607
+ mpfr_set_d(mpy, NUM2DBL(y), MPFR_RNDN);
3608
+ r = mpfr_fmod(mpr, mpx, mpy, rnd);
3609
+ } else if (RB_FIXNUM_P(y)) {
3610
+ long long ly = NUM2LL(y);
3611
+ if (ly >= 0) {
3612
+ r = mpfr_fmod_ui(mpr, mpx, ly, rnd);
3613
+ } else {
3614
+ MPFR_DECL_INIT(mpy, 64);
3615
+ mpfr_set_si(mpy, NUM2LL(y), MPFR_RNDN);
3616
+ r = mpfr_fmod(mpr, mpx, mpy, rnd);
3617
+ }
3618
+ } else if (RB_TYPE_P(y, T_BIGNUM)) {
3619
+ mpz_t mpzy; mpz_init(mpzy); mpfrrb_bignum_to_mpz(y, mpzy);
3620
+ int nlz_bits_ret; size_t nb_bytes = rb_absint_size(y, &nlz_bits_ret);
3621
+ mpfr_prec_t p = nb_bytes*8 - nlz_bits_ret; mpfr_t mpy; mpfr_init2(mpy, p);
3622
+ mpfr_set_z(mpy, mpzy, MPFR_RNDN); mpz_clear(mpzy);
3623
+ r = mpfr_fmod(mpr, mpx, mpy, rnd); mpfr_clear(mpy);
3624
+ } else {
3625
+ mpfr_ptr mpy = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(y));
3626
+ r = mpfr_fmod(mpr, mpx, mpy, rnd);
3627
+ }
3628
+ } else if (RB_TYPE_P(x, T_BIGNUM)) {
3629
+ mpz_t mpz; mpz_init(mpz); mpfrrb_bignum_to_mpz(x, mpz);
3630
+ int nlz_bits_ret; size_t nb_bytes = rb_absint_size(x, &nlz_bits_ret);
3631
+ mpfr_prec_t p = nb_bytes*8 - nlz_bits_ret; mpfr_t mpx; mpfr_init2(mpx, p);
3632
+ mpfr_set_z(mpx, mpz, MPFR_RNDN); mpz_clear(mpz);
3633
+ if (RB_FLOAT_TYPE_P(y)) {
3634
+ MPFR_DECL_INIT(mpy, 53);
3635
+ mpfr_set_d(mpy, NUM2DBL(y), MPFR_RNDN);
3636
+ r = mpfr_fmod(mpr, mpx, mpy, rnd);
3637
+ } else if (RB_FIXNUM_P(y)) {
3638
+ long long ly = NUM2LL(y);
3639
+ if (ly >= 0) {
3640
+ r = mpfr_fmod_ui(mpr, mpx, ly, rnd);
3641
+ } else {
3642
+ MPFR_DECL_INIT(mpy, 64);
3643
+ mpfr_set_si(mpy, NUM2LL(y), MPFR_RNDN);
3644
+ r = mpfr_fmod(mpr, mpx, mpy, rnd);
3645
+ }
3646
+ } else if (RB_TYPE_P(y, T_BIGNUM)) {
3647
+ mpz_t mpzy; mpz_init(mpzy); mpfrrb_bignum_to_mpz(y, mpzy);
3648
+ int nlz_bits_ret; size_t nb_bytes = rb_absint_size(y, &nlz_bits_ret);
3649
+ mpfr_prec_t p = nb_bytes*8 - nlz_bits_ret; mpfr_t mpy; mpfr_init2(mpy, p);
3650
+ mpfr_set_z(mpy, mpzy, MPFR_RNDN); mpz_clear(mpzy);
3651
+ r = mpfr_fmod(mpr, mpx, mpy, rnd); mpfr_clear(mpy);
3652
+ } else {
3653
+ mpfr_ptr mpy = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(y));
3654
+ r = mpfr_fmod(mpr, mpx, mpy, rnd);
3655
+ }
3656
+ mpfr_clear(mpx);
3657
+ } else {
3658
+ mpfr_ptr mpx = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(x));
3659
+ if (RB_FLOAT_TYPE_P(y)) {
3660
+ MPFR_DECL_INIT(mpy, 53);
3661
+ mpfr_set_d(mpy, NUM2DBL(y), MPFR_RNDN);
3662
+ r = mpfr_fmod(mpr, mpx, mpy, rnd);
3663
+ } else if (RB_FIXNUM_P(y)) {
3664
+ long long ly = NUM2LL(y);
3665
+ if (ly >= 0) {
3666
+ r = mpfr_fmod_ui(mpr, mpx, ly, rnd);
3667
+ } else {
3668
+ MPFR_DECL_INIT(mpy, 64);
3669
+ mpfr_set_si(mpy, NUM2LL(y), MPFR_RNDN);
3670
+ r = mpfr_fmod(mpr, mpx, mpy, rnd);
3671
+ }
3672
+ } else if (RB_TYPE_P(y, T_BIGNUM)) {
3673
+ mpz_t mpzy; mpz_init(mpzy); mpfrrb_bignum_to_mpz(y, mpzy);
3674
+ int nlz_bits_ret; size_t nb_bytes = rb_absint_size(y, &nlz_bits_ret);
3675
+ mpfr_prec_t p = nb_bytes*8 - nlz_bits_ret; mpfr_t mpy; mpfr_init2(mpy, p);
3676
+ mpfr_set_z(mpy, mpzy, MPFR_RNDN); mpz_clear(mpzy);
3677
+ r = mpfr_fmod(mpr, mpx, mpy, rnd); mpfr_clear(mpy);
3678
+ } else {
3679
+ mpfr_ptr mpy = mpfrrb_rb2ref(mpfrrb_object_to_mpfr(y));
3680
+ r = mpfr_fmod(mpr, mpx, mpy, rnd);
3681
+ }
3682
+ }
3683
+ return INT2NUM(r);
3684
+ }
3685
+
3686
+
3687
+ /* Set _self_ the the value of `x - ny`, rounded according to the direction `round`.
3688
+ *
3689
+ * `n` is the integer quotient of `x` divided by `y`, rounded to the nearest integer (ties rounded to even).
3690
+ *
3691
+ * Special values are handled as described in Section F.9.7.1 of the ISO C99 standard:
3692
+ * - If `x` is infinite or `y` is zero, _self_ is NaN.
3693
+ * - If `y` is infinite and `x` is finite, _self_ is `x` rounded to the precision of _self_.
3694
+ * - If _self_ is zero, it has the sign of `x`. The return value is the ternary value corresponding to _self_.
3695
+ * @return [Integer]
3696
+ * @overload remainder(x, y, round: MPFR.default_rounding)
3697
+ * @see fmod
3698
+ */
3699
+ static VALUE mpfrrb_remainder(int argc, VALUE *argv, VALUE self)
3700
+ {
3701
+ MPFRRB_TWO_ARG_FUNC_BODY(remainder);
3702
+ }
3703
+
3704
+
3705
+ /* Set self to the next (toward +Infinity) representable value.
3706
+ * @return [self]
3707
+ */
3708
+ static VALUE mpfrrb_nextabove_B(VALUE self)
3709
+ {
3710
+ mpfr_nextabove(mpfrrb_rb2ref(self));
3711
+ return self;
3712
+ }
3713
+
3714
+
3715
+ /* Set self to the previous (toward -Infinity) representable value.
3716
+ * @return [self]
3717
+ */
3718
+ static VALUE mpfrrb_nextbelow_B(VALUE self)
3719
+ {
3720
+ mpfr_nextbelow(mpfrrb_rb2ref(self));
3721
+ return self;
3722
+ }
3723
+
3724
+
3725
+ /* Free all caches and pools used by MPFR internally.
3726
+ */
3727
+ static VALUE mpfrrb_free_cache(VALUE self)
3728
+ {
3729
+ mpfr_free_cache();
3730
+ return self;
3731
+ }
3732
+
3733
+
3734
+ /* This function rounds _self_ emulating subnormal number arithmetic.
3735
+ * If _self_ is outside the subnormal exponent range of the emulated floating-point system,
3736
+ * this function just propagates the ternary value `t`;
3737
+ * otherwise, if `self.exponent` denotes the exponent of _self_,
3738
+ * it rounds _self_ to precision `self.exponent - emin + 1` according to rounding mode `round` and previous ternary value `t`,
3739
+ * avoiding double rounding problems.
3740
+ * More precisely in the subnormal domain, denoting by _e_ the value of _emin_,
3741
+ * _self_ is rounded in fixed-point arithmetic to an integer multiple of two to the power _e_ − 1;
3742
+ * as a consequence, 1.5 multiplied by two to the power _e_ − 1 when `t` is zero is rounded to
3743
+ * two to the power _e_ with rounding to nearest.
3744
+ *
3745
+ * The precision `self.prec` of _self_ is not modified by this function.
3746
+ * `round` and `t` must be the rounding mode and the returned ternary value used when computing _self_ (as in mpfr_check_range).
3747
+ * The subnormal exponent range is from _emin_ to `emin + self.prec - 1`.
3748
+ * If the result cannot be represented in the current exponent range of MPFR (due to a too small _emax_),
3749
+ * the behavior is undefined. Note that unlike most functions, the result is compared to the exact one,
3750
+ * not the input value _self_, i.e., the ternary value is propagated.
3751
+ *
3752
+ * As usual, if the returned ternary value is non zero, the inexact flag is set.
3753
+ * Moreover, if a second rounding occurred (because the input _self_ was in the subnormal range),
3754
+ * the underflow flag is set.
3755
+ *
3756
+ * Warning! If you change _emin_ (with {emin=}) just before calling mpfr_subnormalize,
3757
+ * you need to make sure that the value is in the current exponent range of MPFR.
3758
+ * But it is better to change _emin_ before any computation, if possible.
3759
+ *
3760
+ * This is an example of how to emulate binary64 IEEE 754 arithmetic (a.k.a. double precision) using MPFR:
3761
+ *
3762
+ * ```ruby
3763
+ * MPFR.default_prec = 53
3764
+ * MPFR.emin = -1073
3765
+ * MPFR.emax = 1024
3766
+ * xa = MPFR.new
3767
+ * xb = MPFR.new
3768
+ *
3769
+ * b = 34.3
3770
+ * xb.set(b, round: :nearest)
3771
+ * a = 0x11235.to_f * 2**-1037
3772
+ * xa.set(a, round: :nearest)
3773
+ *
3774
+ * a /= b
3775
+ * i = xa.div(xa, xb, round: :nearest)
3776
+ * i = xa.subnormalize(i, round: :nearest) # new ternary value
3777
+ * ```
3778
+ *
3779
+ * Note that {emin=} and {emax=} are called early enough in order to make sure that all computed values
3780
+ * are in the current exponent range.
3781
+ * Warning! This emulates a double IEEE 754 arithmetic with correct rounding in the subnormal range,
3782
+ * which may not be the case for your hardware.
3783
+ *
3784
+ * Below is another example showing how to emulate fixed-point arithmetic in a specific case.
3785
+ * Here we compute the sine of the integers 1 to 17 with a result in a fixed-point arithmetic rounded at two to the power -42
3786
+ * (using the fact that the result is at most 1 in absolute value):
3787
+ *
3788
+ * ```ruby
3789
+ * MPFR.emin = -41
3790
+ * x = MPFR.new(prec: 42)
3791
+ * (1..17).each do |i|
3792
+ * x.set(i, round: :nearest)
3793
+ * inex = x.sin(x, round: :toward_zero)
3794
+ * x.subnormalize(inex, round: :toward_zero)
3795
+ * puts x
3796
+ * end
3797
+ * ```
3798
+ *
3799
+ * @return [Integer]
3800
+ * @overload subnormalize(t, round: MPFR.default_rounding)
3801
+ * @param t [Integer]
3802
+ * @param round [Symbol]
3803
+ * @see emin=
3804
+ * @see emax=
3805
+ */
3806
+ static VALUE mpfrrb_subnormalize(int argc, VALUE *argv, VALUE self)
3807
+ {
3808
+ VALUE trb;
3809
+ mpfr_rnd_t rnd = mpfrrb_get_b_round(argc, argv, &trb);
3810
+ int t = NUM2INT(trb);
3811
+ mpfr_ptr mp = mpfrrb_rb2ref(self);
3812
+ int r = mpfr_subnormalize(mp, t, rnd);
3813
+ return INT2NUM(r);
3814
+ }
3815
+
3816
+
3817
+ /* Return the (current) smallest exponents allowed for a floating-point variable.
3818
+ * The smallest positive value of a floating-point variable is one half times 2 raised to the smallest exponent.
3819
+ * @return [Integer]
3820
+ * @see emin=
3821
+ */
3822
+ static VALUE mpfrrb_get_emin(VALUE self)
3823
+ {
3824
+ (void)self;
3825
+ return LL2NUM(mpfr_get_emin());
3826
+ }
3827
+
3828
+
3829
+ /* Set the smallest exponents allowed for a floating-point variable.
3830
+ *
3831
+ * For the subsequent operations, it is the user's responsibility to check that any floating-point value used as an input
3832
+ * is in the new exponent range (for example using {#check_range}).
3833
+ * If a floating-point value outside the new exponent range is used as an input, the default behavior is undefined.
3834
+ *
3835
+ * @note If `emin > emax` and a floating-point value needs to be produced as output, the behavior is undefined.
3836
+ * @return [Integer]
3837
+ */
3838
+ static VALUE mpfrrb_set_emin(VALUE self, VALUE e)
3839
+ {
3840
+ (void)self;
3841
+ mpfr_exp_t v = NUM2LL(e);
3842
+ if (v < mpfr_get_emin_min() || v > mpfr_get_emin_max()) {
3843
+ rb_raise(rb_eRangeError, "emin must be between %ld and %ld", mpfr_get_emin_min(), mpfr_get_emin_max());
3844
+ }
3845
+ mpfr_set_emin(v);
3846
+ return e;
3847
+ }
3848
+
3849
+
3850
+ /* Return the (current) largest exponents allowed for a floating-point variable.
3851
+ * The largest value has the form (1 − epsilon) times 2 raised to the largest exponent,
3852
+ * where epsilon depends on the precision of the considered variable.
3853
+ * @return [Integer]
3854
+ * @see emax=
3855
+ */
3856
+ static VALUE mpfrrb_get_emax(VALUE self)
3857
+ {
3858
+ (void)self;
3859
+ return LL2NUM(mpfr_get_emax());
3860
+ }
3861
+
3862
+
3863
+ /* Set the largest exponents allowed for a floating-point variable.
3864
+ *
3865
+ * For the subsequent operations, it is the user's responsibility to check that any floating-point value used as an input
3866
+ * is in the new exponent range (for example using {#check_range}).
3867
+ * If a floating-point value outside the new exponent range is used as an input, the default behavior is undefined.
3868
+ *
3869
+ * @note If `emin > emax` and a floating-point value needs to be produced as output, the behavior is undefined.
3870
+ * @return [Integer]
3871
+ */
3872
+ static VALUE mpfrrb_set_emax(VALUE self, VALUE e)
3873
+ {
3874
+ (void)self;
3875
+ mpfr_exp_t v = NUM2LL(e);
3876
+ if (v < mpfr_get_emax_min() || v > mpfr_get_emax_max()) {
3877
+ rb_raise(rb_eRangeError, "emax must be between %ld and %ld", mpfr_get_emax_min(), mpfr_get_emax_max());
3878
+ }
3879
+ mpfr_set_emax(v);
3880
+ return e;
3881
+ }
3882
+
3883
+
3884
+ /* Set self to the minimum of `x` and `y`.
3885
+ * If `x` and `y` are both NaN, then self is set to NaN.
3886
+ * If `x` or `y` is NaN, then self is set to the numeric value.
3887
+ * If `x` and `y` are zeros of different signs, then rop is set to -0.
3888
+ * @return [Integer]
3889
+ * @overload min(x, y, round: MPFR.default_rounding)
3890
+ */
3891
+ static VALUE mpfrrb_min(int argc, VALUE *argv, VALUE self)
3892
+ {
3893
+ VALUE x, y;
3894
+ mpfr_rnd_t rnd = mpfrrb_get_a_b_round(argc, argv, &x, &y);
3895
+ x = mpfrrb_object_to_mpfr(x);
3896
+ y = mpfrrb_object_to_mpfr(y);
3897
+ mpfr_ptr mp = mpfrrb_rb2ref(self);
3898
+ int r = mpfr_min(mp, mpfrrb_rb2ref(x), mpfrrb_rb2ref(y), rnd);
3899
+ return INT2NUM(r);
3900
+ }
3901
+
3902
+
3903
+ /* Set self to the maximum of `x` and `y`.
3904
+ * If `x` and `y` are both NaN, then self is set to NaN.
3905
+ * If `x` or `y` is NaN, then self is set to the numeric value.
3906
+ * If `x` and `y` are zeros of different signs, then rop is set to +0.
3907
+ * @return [Integer]
3908
+ * @overload max(x, y, round: MPFR.default_rounding)
3909
+ */
3910
+ static VALUE mpfrrb_max(int argc, VALUE *argv, VALUE self)
3911
+ {
3912
+ VALUE x, y;
3913
+ mpfr_rnd_t rnd = mpfrrb_get_a_b_round(argc, argv, &x, &y);
3914
+ x = mpfrrb_object_to_mpfr(x);
3915
+ y = mpfrrb_object_to_mpfr(y);
3916
+ mpfr_ptr mp = mpfrrb_rb2ref(self);
3917
+ int r = mpfr_max(mp, mpfrrb_rb2ref(x), mpfrrb_rb2ref(y), rnd);
3918
+ return INT2NUM(r);
3919
+ }
3920
+
3921
+
3922
+ /* Generate a uniformly distributed random float in the interval 0 ≤ _self_ < 1.
3923
+ * More precisely, the number can be seen as a float with a random non-normalized significand and exponent 0,
3924
+ * which is then normalized (thus if _e_ denotes the exponent after normalization,
3925
+ * then the least -_e_ significant bits of the significand are always 0).
3926
+ *
3927
+ * Return 0, unless the exponent is not in the current exponent range,
3928
+ * in which case _self_ is set to NaN and a non-zero value is returned
3929
+ * (this should never happen in practice, except in very specific cases).
3930
+ *
3931
+ * @return [Integer]
3932
+ */
3933
+ static VALUE mpfrrb_urandomb(VALUE self)
3934
+ {
3935
+ mpfr_ptr mp = mpfrrb_rb2ref(self);
3936
+ int r = mpfr_urandomb(mp, mpfrrb_gmp_randstate);
3937
+ return INT2NUM(r);
3938
+ }
3939
+
3940
+
3941
+ /* Generate a uniformly distributed random float.
3942
+ * The floating-point number _self_ can be seen as if a random real number is generated
3943
+ * according to the continuous uniform distribution on the interval [0, 1] and then rounded in the direction `round`.
3944
+ *
3945
+ * @return [Integer]
3946
+ * @overload urandom(round: MPFR.default_rounding)
3947
+ */
3948
+ static VALUE mpfrrb_urandom(int argc, VALUE *argv, VALUE self)
3949
+ {
3950
+ mpfr_rnd_t rnd = mpfrrb_get_round_single_keword(argc, argv);
3951
+ mpfr_ptr mp = mpfrrb_rb2ref(self);
3952
+ int r = mpfr_urandom(mp, mpfrrb_gmp_randstate, rnd);
3953
+ return INT2NUM(r);
3954
+ }
3955
+
3956
+
3957
+ /* Generate a random floating-point number according to a standard normal Gaussian distribution (with mean zero and variance one).
3958
+ *
3959
+ * The floating-point number _self_ can be seen as if a random real number were generated according to the standard normal
3960
+ * Gaussian distribution and then rounded in the direction rnd.
3961
+ *
3962
+ * @return [Integer]
3963
+ * @overload nrandom(round: MPFR.default_rounding)
3964
+ */
3965
+ static VALUE mpfrrb_nrandom(int argc, VALUE *argv, VALUE self)
3966
+ {
3967
+ mpfr_rnd_t rnd = mpfrrb_get_round_single_keword(argc, argv);
3968
+ mpfr_ptr mp = mpfrrb_rb2ref(self);
3969
+ int r = mpfr_nrandom(mp, mpfrrb_gmp_randstate, rnd);
3970
+ return INT2NUM(r);
3971
+ }
3972
+
3973
+
3974
+ /* Generate a random floating-point number according to an exponential distribution, with mean one.
3975
+ * Other characteristics are identical to {nrandom}.
3976
+ * @return [Integer]
3977
+ * @overload erandom(round: MPFR.default_rounding)
3978
+ */
3979
+ static VALUE mpfrrb_erandom(int argc, VALUE *argv, VALUE self)
3980
+ {
3981
+ mpfr_rnd_t rnd = mpfrrb_get_round_single_keword(argc, argv);
3982
+ mpfr_ptr mp = mpfrrb_rb2ref(self);
3983
+ int r = mpfr_erandom(mp, mpfrrb_gmp_randstate, rnd);
3984
+ return INT2NUM(r);
3985
+ }
3986
+
3987
+
3988
+ static VALUE mpfrrb_index_from_integer(mpfr_ptr mp, int index)
3989
+ {
3990
+ // printf("prec: %ld\n", mp->_mpfr_prec);
3991
+ // printf("sign: %d\n", mp->_mpfr_sign);
3992
+ // printf("exp: %ld\n", mp->_mpfr_exp);
3993
+ // printf("[-1]: 0x%016lx\n", mp->_mpfr_d[-1]);
3994
+ // printf("[0]: 0x%016lx\n", mp->_mpfr_d[0]);
3995
+ // if (mp->_mpfr_prec > GMP_NUMB_BITS) printf("[1]: 0x%016lx\n", mp->_mpfr_d[1]);
3996
+ // printf("mpfrrb_index_from_integer(%d)\n", index);
3997
+ int p = mpfr_get_prec(mp);
3998
+ if (index > 0 || index <= -p) return INT2NUM(0);
3999
+ index += p - 1 + (GMP_NUMB_BITS - p % GMP_NUMB_BITS) % GMP_NUMB_BITS;
4000
+ int limb_nb = index / GMP_NUMB_BITS;
4001
+ int bit_idx = index % GMP_NUMB_BITS;
4002
+ // printf("limb_nb = %d\n", limb_nb);
4003
+ // printf("bit_idx = %d\n", bit_idx);
4004
+ int r = (mp->_mpfr_d[limb_nb] >> bit_idx) & 1;
4005
+ return INT2NUM(r);
4006
+ }
4007
+
4008
+
4009
+ static VALUE mpfrrb_index_from_range(mpfr_ptr mp, int lsbpos, int msbpos)
4010
+ {
4011
+ int p = mpfr_get_prec(mp);
4012
+ if (lsbpos > msbpos) return Qnil;
4013
+ if (msbpos <= -p || lsbpos > 0) return INT2NUM(0);
4014
+ if (msbpos > 0) msbpos = 0;
4015
+ int len = msbpos - lsbpos + 1;
4016
+ int shift = 0;
4017
+ if (lsbpos <= -p) {
4018
+ shift = 1 - p - lsbpos;
4019
+ len -= shift;
4020
+ lsbpos = 1 - p;
4021
+ }
4022
+ if (len < 1) {
4023
+ return Qnil;
4024
+ } else if (len <= 64) {
4025
+ uint64_t n = 0;
4026
+ int i, j;
4027
+ const int offst = (GMP_NUMB_BITS - p % GMP_NUMB_BITS) % GMP_NUMB_BITS;
4028
+ for (i = 0, j = lsbpos; j <= msbpos; i++, j++) {
4029
+ int index = j + p - 1 + offst;
4030
+ int limb_nb = index / GMP_NUMB_BITS;
4031
+ int bit_idx = index % GMP_NUMB_BITS;
4032
+ int b = (mp->_mpfr_d[limb_nb] >> bit_idx) & 1;
4033
+ n |= (uint64_t)b << i;
4034
+ }
4035
+ VALUE num = ULL2NUM(n);
4036
+ if (shift) {
4037
+ VALUE sh = INT2NUM(shift);
4038
+ num = rb_funcallv(num, id_chchleft, 1, &sh);
4039
+ }
4040
+ return num;
4041
+ } else {
4042
+ VALUE num = INT2NUM(0);
4043
+ const int offst = (GMP_NUMB_BITS - p % GMP_NUMB_BITS) % GMP_NUMB_BITS;
4044
+ int c, nb_chunks = (len + 63) / 64;
4045
+ for (c = 0; c < nb_chunks; c++) {
4046
+ int lsb = lsbpos + c*64;
4047
+ int msb = (lsb + 63) > msbpos ? msbpos : (lsb + 63);
4048
+ uint64_t n = 0;
4049
+ int i, j;
4050
+ for (i = 0, j = lsb; j <= msb; i++, j++) {
4051
+ int index = j + p - 1 + offst;
4052
+ int limb_nb = index / GMP_NUMB_BITS;
4053
+ int bit_idx = index % GMP_NUMB_BITS;
4054
+ int b = (mp->_mpfr_d[limb_nb] >> bit_idx) & 1;
4055
+ n |= (uint64_t)b << i;
4056
+ }
4057
+ VALUE chunk = ULL2NUM(n);
4058
+ VALUE sh = INT2NUM(c*64);
4059
+ chunk = rb_funcallv(chunk, id_chchleft, 1, &sh);
4060
+ num = rb_funcallv(num, id_orpipe, 1, &chunk);
4061
+ }
4062
+ if (shift) {
4063
+ VALUE sh = INT2NUM(shift);
4064
+ num = rb_funcallv(num, id_chchleft, 1, &sh);
4065
+ }
4066
+ return num;
4067
+ }
4068
+ }
4069
+
4070
+
4071
+ /* Returns bits from the significand, ignoring the sign or the exponent.
4072
+ *
4073
+ * The most significand bit is indexed at 0, the least significand bit is indexed at 1 - _prec_.
4074
+ *
4075
+ * In case _self_ is not finite (an infinite or NaN), _nil_ is retured.
4076
+ *
4077
+ * @param index [Integer, Range<Integer>]
4078
+ * @return [Integer, nil]
4079
+ */
4080
+ static VALUE mpfrrb_index(VALUE self, VALUE index)
4081
+ {
4082
+ mpfr_ptr mp = mpfrrb_rb2ref(self);
4083
+ if (mpfr_zero_p(mp)) {
4084
+ return INT2NUM(0);
4085
+ } else if (!mpfr_regular_p(mp)) {
4086
+ return Qnil;
4087
+ }
4088
+ if (RB_FIXNUM_P(index)) {
4089
+ return mpfrrb_index_from_integer(mp, NUM2INT(index));
4090
+ } else if (rb_class_of(index) == rb_cRange) {
4091
+ VALUE begrb, endrb;
4092
+ int excl;
4093
+ rb_range_values(index, &begrb, &endrb, &excl);
4094
+ int beg = NUM2INT(begrb);
4095
+ int end = NUM2INT(endrb);
4096
+ int len = (end > beg ? end - beg : beg - end) + (excl ? 0 : 1);
4097
+ if (len < 1) {
4098
+ return Qnil;
4099
+ }
4100
+ if (beg < end) {
4101
+ end = beg + len - 1;
4102
+ } else {
4103
+ end = beg - len + 1;
4104
+ int t = end;
4105
+ end = beg;
4106
+ beg = t;
4107
+ }
4108
+ return mpfrrb_index_from_range(mp, beg, end);
4109
+ } else {
4110
+ rb_raise(rb_eTypeError, "expecging an integer or a range, got a %s", rb_obj_classname(index));
4111
+ }
4112
+ }
4113
+
4114
+
4115
+ /* Document-class: MPFR
4116
+ *
4117
+ * MPFR methods take as last argument a rounding mode, and have a return value of type integer, called the _ternary value_.
4118
+ * The value stored in the receiver is correctly rounded, i.e., MPFR behaves as if it computed the result with an infinite precision, then rounded it to the precision of this variable.
4119
+ * The input variables are regarded as exact (in particular, their precision does not affect the result).
4120
+ *
4121
+ * As a consequence, in case of a non-zero real rounded result,
4122
+ * the error on the result is less than or equal to 1/2 ulp (unit in the last place) of that result in the rounding to nearest mode,
4123
+ * and less than 1 ulp of that result in the directed rounding modes (a ulp is the weight of the least significant represented bit of the result after rounding).
4124
+ *
4125
+ * Unless documented otherwise, methods returning an integer return a ternary value.
4126
+ * If the ternary value is zero, it means that the value stored in the receiver is the exact result of the corresponding mathematical function.
4127
+ * If the ternary value is positive (resp. negative), it means the value stored in the receiver is greater (resp. lower) than the exact result.
4128
+ * For example with the `:round_up` rounding mode, the ternary value is usually positive, except when the result is exact, in which case it is zero.
4129
+ * In the case of an infinite result, it is considered as inexact when it was obtained by overflow, and exact otherwise.
4130
+ * A NaN result (Not-a-Number) always corresponds to an exact return value.
4131
+ * The opposite of a returned ternary value is guaranteed to be representable in an integer.
4132
+ */
4133
+
4134
+
4135
+ void Init_mpfr(void)
4136
+ {
4137
+ id_rndn = rb_intern("rndn");
4138
+ id_rndz = rb_intern("rndz");
4139
+ id_rndu = rb_intern("rndu");
4140
+ id_rndd = rb_intern("rndd");
4141
+ id_rnda = rb_intern("rnda");
4142
+ id_rndf = rb_intern("rndf");
4143
+ id_rndna = rb_intern("rndna");
4144
+ id_round_nearest = rb_intern("round_nearest");
4145
+ id_toward_zero = rb_intern("toward_zero");
4146
+ id_round_up = rb_intern("round_up");
4147
+ id_round_down = rb_intern("round_down");
4148
+ id_away_from_zero = rb_intern("away_from_zero");
4149
+ id_faithful_rounding = rb_intern("faithful_rounding");
4150
+ id_nearest = rb_intern("nearest");
4151
+ id_zero = rb_intern("zero");
4152
+ id_up = rb_intern("up");
4153
+ id_down = rb_intern("down");
4154
+ id_away = rb_intern("away");
4155
+ id_faithful = rb_intern("faithful");
4156
+ id_nearest_ties_away = rb_intern("nearest_ties_away");
4157
+ id_prec = rb_intern("prec");
4158
+ id_conv = rb_intern("conv");
4159
+ id_round = rb_intern("round");
4160
+ id_decimals = rb_intern("decimals");
4161
+ id_to_mpfr = rb_intern("to_mpfr");
4162
+ id_chchleft = rb_intern("<<");
4163
+ id_orpipe = rb_intern("|");
4164
+
4165
+ mpfrrb_default_rounding_id = id_round_nearest;
4166
+
4167
+ // c_MPFR = rb_define_class("MPFR", rb_cObject);
4168
+ c_MPFR = rb_define_class("MPFR", rb_cNumeric);
4169
+
4170
+ rb_define_module_function(c_MPFR, "version", mpfrrb_get_version, 0);
4171
+ rb_define_module_function(c_MPFR, "patches", mpfrrb_get_patches, 0);
4172
+ rb_define_module_function(c_MPFR, "default_prec", mpfrrb_get_default_prec, 0);
4173
+ rb_define_module_function(c_MPFR, "default_prec=", mpfrrb_set_default_prec, 1);
4174
+ rb_define_module_function(c_MPFR, "default_rounding", mpfrrb_get_default_rounding, 0);
4175
+ rb_define_module_function(c_MPFR, "default_rounding=", mpfrrb_set_default_rounding, 1);
4176
+ rb_define_module_function(c_MPFR, "emin", mpfrrb_get_emin, 0);
4177
+ rb_define_module_function(c_MPFR, "emin=", mpfrrb_set_emin, 1);
4178
+ rb_define_module_function(c_MPFR, "emax", mpfrrb_get_emax, 0);
4179
+ rb_define_module_function(c_MPFR, "emax=", mpfrrb_set_emax, 1);
4180
+ rb_define_module_function(c_MPFR, "i_2exp", mpfrrb_i_2exp, 2);
4181
+ rb_define_module_function(c_MPFR, "free_cache", mpfrrb_free_cache, 0);
4182
+
4183
+ /* The minimum precision that can be set for a MPFR object.
4184
+ * @return [Integer]
4185
+ */
4186
+ rb_define_const(c_MPFR, "PREC_MIN", INT2NUM(MPFR_PREC_MIN));
4187
+
4188
+ /* The maximum precision that can be set for a MPFR object.
4189
+ * @return [Integer]
4190
+ */
4191
+ rb_define_const(c_MPFR, "PREC_MAX", ULL2NUM(MPFR_PREC_MAX));
4192
+
4193
+ /* The minimum of the exponents allowed for {emin=}.
4194
+ * This value is implementation dependent, thus a program using `MPFR.emin = EMIN_MIN` may not be portable.
4195
+ * @return [Integer]
4196
+ */
4197
+ rb_define_const(c_MPFR, "EMIN_MIN", LL2NUM(mpfr_get_emin_min()));
4198
+
4199
+ /* The maximum of the exponents allowed for {emin=}.
4200
+ * @return [Integer]
4201
+ */
4202
+ rb_define_const(c_MPFR, "EMIN_MAX", LL2NUM(mpfr_get_emin_max()));
4203
+
4204
+ /* The minimum of the exponents allowed for {emax=}.
4205
+ * @return [Integer]
4206
+ */
4207
+ rb_define_const(c_MPFR, "EMAX_MIN", LL2NUM(mpfr_get_emin_min()));
4208
+
4209
+ /* The maximum of the exponents allowed for {emax=}.
4210
+ * This value is implementation dependent, thus a program using `MPFR.emax = EMAX_MAX` may not be portable.
4211
+ * @return [Integer]
4212
+ */
4213
+ rb_define_const(c_MPFR, "EMAX_MAX", LL2NUM(mpfr_get_emin_max()));
4214
+
4215
+ rb_define_alloc_func(c_MPFR, mpfrrb_alloc);
4216
+ rb_undef_method(rb_class_of(c_MPFR), "allocate");
4217
+ // rb_include_module(c_MPFR, rb_mComparable);
4218
+ rb_define_method(c_MPFR, "initialize", mpfrrb_initialize, -1);
4219
+
4220
+ rb_define_method(c_MPFR, "to_s", mpfrrb_to_s, -1);
4221
+ rb_define_method(c_MPFR, "to_f", mpfrrb_to_f, -1);
4222
+ rb_define_method(c_MPFR, "to_i", mpfrrb_to_i, -1);
4223
+ rb_define_method(c_MPFR, "to_r", mpfrrb_to_r, 0);
4224
+ rb_define_method(c_MPFR, "to_mpfr", mpfrrb_MPFR_to_mpfr, 0);
4225
+
4226
+ rb_define_method(c_MPFR, "prec_round", mpfrrb_prec_round, -1);
4227
+ rb_define_method(c_MPFR, "prec", mpfrrb_get_prec, 0);
4228
+ rb_define_method(c_MPFR, "prec=", mpfrrb_set_prec, 1);
4229
+ rb_define_method(c_MPFR, "sign", mpfrrb_get_sign, 0);
4230
+ rb_define_method(c_MPFR, "sign=", mpfrrb_set_sign, 1);
4231
+ rb_define_method(c_MPFR, "exponent", mpfrrb_get_exponent , 0);
4232
+ rb_define_method(c_MPFR, "exponent=", mpfrrb_set_exponent , 1);
4233
+
4234
+ rb_define_method(c_MPFR, "set", mpfrrb_set, -1);
4235
+ rb_define_method(c_MPFR, "set_nan", mpfrrb_set_nan, 0);
4236
+ rb_define_method(c_MPFR, "set_zero", mpfrrb_set_zero, -1);
4237
+ rb_define_method(c_MPFR, "set_infinity", mpfrrb_set_infinity, -1);
4238
+ rb_define_method(c_MPFR, "set_pi", mpfrrb_set_pi, -1);
4239
+ rb_define_method(c_MPFR, "set_log2", mpfrrb_set_log2, -1);
4240
+ rb_define_method(c_MPFR, "set_euler", mpfrrb_set_euler, -1);
4241
+ rb_define_method(c_MPFR, "set_catalan", mpfrrb_set_catalan, -1);
4242
+
4243
+ rb_define_method(c_MPFR, "get_d_2exp", mpfrrb_get_d_2exp, -1);
4244
+ rb_define_method(c_MPFR, "get_i_2exp", mpfrrb_get_i_2exp, 0);
4245
+
4246
+ rb_define_method(c_MPFR, "zero?", mpfrrb_is_zero, 0);
4247
+ rb_define_method(c_MPFR, "nan?", mpfrrb_is_nan, 0);
4248
+ rb_define_method(c_MPFR, "infinite?", mpfrrb_is_infinite, 0);
4249
+ rb_define_method(c_MPFR, "finite?", mpfrrb_is_finite, 0);
4250
+ rb_define_method(c_MPFR, "integer?", mpfrrb_is_integer, 0);
4251
+
4252
+ rb_define_method(c_MPFR, "add", mpfrrb_add, -1);
4253
+ rb_define_method(c_MPFR, "add!", mpfrrb_add_B, -1);
4254
+ rb_define_method(c_MPFR, "sub", mpfrrb_sub, -1);
4255
+ rb_define_method(c_MPFR, "sub!", mpfrrb_sub_B, -1);
4256
+ rb_define_method(c_MPFR, "mul", mpfrrb_mul, -1);
4257
+ rb_define_method(c_MPFR, "mul!", mpfrrb_mul_B, -1);
4258
+ rb_define_method(c_MPFR, "div", mpfrrb_div, -1);
4259
+ rb_define_method(c_MPFR, "div!", mpfrrb_div_B, -1);
4260
+ rb_define_method(c_MPFR, "sqr", mpfrrb_sqr, -1);
4261
+ rb_define_method(c_MPFR, "sqr!", mpfrrb_sqr_B, -1);
4262
+ rb_define_method(c_MPFR, "sqrt", mpfrrb_sqrt, -1);
4263
+ rb_define_method(c_MPFR, "sqrt!", mpfrrb_sqrt_B, -1);
4264
+ rb_define_method(c_MPFR, "rec_sqrt", mpfrrb_rec_sqrt, -1);
4265
+ rb_define_method(c_MPFR, "rec_sqrt!", mpfrrb_rec_sqrt_B, -1);
4266
+ rb_define_method(c_MPFR, "cbrt", mpfrrb_cbrt, -1);
4267
+ rb_define_method(c_MPFR, "cbrt!", mpfrrb_cbrt_B, -1);
4268
+ rb_define_method(c_MPFR, "rootn", mpfrrb_rootn, -1);
4269
+ rb_define_method(c_MPFR, "rootn!", mpfrrb_rootn_B, -1);
4270
+ rb_define_method(c_MPFR, "neg", mpfrrb_neg, -1);
4271
+ rb_define_method(c_MPFR, "neg!", mpfrrb_neg_B, 0);
4272
+ rb_define_method(c_MPFR, "abs", mpfrrb_abs, -1);
4273
+ rb_define_method(c_MPFR, "abs!", mpfrrb_abs_B, 0);
4274
+ rb_define_method(c_MPFR, "dim", mpfrrb_dim, -1);
4275
+ rb_define_method(c_MPFR, "mul_2i", mpfrrb_mul_2i, -1);
4276
+ rb_define_method(c_MPFR, "mul_2i!", mpfrrb_mul_2i_B, -1);
4277
+ rb_define_method(c_MPFR, "div_2i", mpfrrb_div_2i, -1);
4278
+ rb_define_method(c_MPFR, "div_2i!", mpfrrb_div_2i_B, -1);
4279
+ rb_define_method(c_MPFR, "fac", mpfrrb_fac, -1);
4280
+ rb_define_method(c_MPFR, "fma", mpfrrb_fma, -1);
4281
+ rb_define_method(c_MPFR, "fma!", mpfrrb_fma_B, -1);
4282
+ rb_define_method(c_MPFR, "fms", mpfrrb_fms, -1);
4283
+ rb_define_method(c_MPFR, "fms!", mpfrrb_fms_B, -1);
4284
+ rb_define_method(c_MPFR, "fmma", mpfrrb_fmma, -1);
4285
+ rb_define_method(c_MPFR, "fmms", mpfrrb_fmms, -1);
4286
+ rb_define_method(c_MPFR, "hypot", mpfrrb_hypot, -1);
4287
+
4288
+ rb_define_method(c_MPFR, "<=>", mpfrrb_cmp, 1);
4289
+ rb_define_method(c_MPFR, "coerce", mpfrrb_coerce, 1);
4290
+
4291
+ rb_define_method(c_MPFR, "log", mpfrrb_log, -1);
4292
+ rb_define_method(c_MPFR, "log2", mpfrrb_log2, -1);
4293
+ rb_define_method(c_MPFR, "log10", mpfrrb_log10, -1);
4294
+ rb_define_method(c_MPFR, "log1p", mpfrrb_log1p, -1);
4295
+ rb_define_method(c_MPFR, "log2p1", mpfrrb_log2p1, -1);
4296
+ rb_define_method(c_MPFR, "log10p1", mpfrrb_log10p1, -1);
4297
+ rb_define_method(c_MPFR, "exp", mpfrrb_exp, -1);
4298
+ rb_define_method(c_MPFR, "exp2", mpfrrb_exp2, -1);
4299
+ rb_define_method(c_MPFR, "exp10", mpfrrb_exp10, -1);
4300
+ rb_define_method(c_MPFR, "expm1", mpfrrb_expm1, -1);
4301
+ rb_define_method(c_MPFR, "exp2m1", mpfrrb_exp2m1, -1);
4302
+ rb_define_method(c_MPFR, "exp10m1", mpfrrb_exp10m1, -1);
4303
+ rb_define_method(c_MPFR, "pow", mpfrrb_pow, -1);
4304
+ rb_define_method(c_MPFR, "compound", mpfrrb_compound, -1);
4305
+ rb_define_method(c_MPFR, "cos", mpfrrb_cos, -1);
4306
+ rb_define_method(c_MPFR, "sin", mpfrrb_sin, -1);
4307
+ rb_define_method(c_MPFR, "tan", mpfrrb_tan, -1);
4308
+ rb_define_method(c_MPFR, "cosu", mpfrrb_cosu, -1);
4309
+ rb_define_method(c_MPFR, "sinu", mpfrrb_sinu, -1);
4310
+ rb_define_method(c_MPFR, "tanu", mpfrrb_tanu, -1);
4311
+ rb_define_method(c_MPFR, "cospi", mpfrrb_cospi, -1);
4312
+ rb_define_method(c_MPFR, "sinpi", mpfrrb_sinpi, -1);
4313
+ rb_define_method(c_MPFR, "tanpi", mpfrrb_tanpi, -1);
4314
+ rb_define_method(c_MPFR, "sec", mpfrrb_sec, -1);
4315
+ rb_define_method(c_MPFR, "csc", mpfrrb_csc, -1);
4316
+ rb_define_method(c_MPFR, "cot", mpfrrb_cot, -1);
4317
+ rb_define_method(c_MPFR, "acos", mpfrrb_acos, -1);
4318
+ rb_define_method(c_MPFR, "asin", mpfrrb_asin, -1);
4319
+ rb_define_method(c_MPFR, "atan", mpfrrb_atan, -1);
4320
+ rb_define_method(c_MPFR, "acosu", mpfrrb_acosu, -1);
4321
+ rb_define_method(c_MPFR, "asinu", mpfrrb_asinu, -1);
4322
+ rb_define_method(c_MPFR, "atanu", mpfrrb_atanu, -1);
4323
+ rb_define_method(c_MPFR, "acospi", mpfrrb_acospi, -1);
4324
+ rb_define_method(c_MPFR, "asinpi", mpfrrb_asinpi, -1);
4325
+ rb_define_method(c_MPFR, "atanpi", mpfrrb_atanpi, -1);
4326
+ rb_define_method(c_MPFR, "atan2", mpfrrb_atan2, -1);
4327
+ rb_define_method(c_MPFR, "atan2u", mpfrrb_atan2u, -1);
4328
+ rb_define_method(c_MPFR, "atan2pi", mpfrrb_atan2pi, -1);
4329
+ rb_define_method(c_MPFR, "cosh", mpfrrb_cosh, -1);
4330
+ rb_define_method(c_MPFR, "sinh", mpfrrb_sinh, -1);
4331
+ rb_define_method(c_MPFR, "tanh", mpfrrb_tanh, -1);
4332
+ rb_define_method(c_MPFR, "sech", mpfrrb_sech, -1);
4333
+ rb_define_method(c_MPFR, "csch", mpfrrb_csch, -1);
4334
+ rb_define_method(c_MPFR, "coth", mpfrrb_coth, -1);
4335
+ rb_define_method(c_MPFR, "acosh", mpfrrb_acosh, -1);
4336
+ rb_define_method(c_MPFR, "asinh", mpfrrb_asinh, -1);
4337
+ rb_define_method(c_MPFR, "atanh", mpfrrb_atanh, -1);
4338
+ rb_define_method(c_MPFR, "eint", mpfrrb_eint, -1);
4339
+ rb_define_method(c_MPFR, "li2", mpfrrb_li2, -1);
4340
+ rb_define_method(c_MPFR, "gamma", mpfrrb_gamma, -1);
4341
+ rb_define_method(c_MPFR, "gamma_inc", mpfrrb_gamma_inc, -1);
4342
+ rb_define_method(c_MPFR, "lngamma", mpfrrb_lngamma, -1);
4343
+ rb_define_method(c_MPFR, "digamma", mpfrrb_digamma, -1);
4344
+ rb_define_method(c_MPFR, "beta", mpfrrb_beta, -1);
4345
+ rb_define_method(c_MPFR, "zeta", mpfrrb_zeta, -1);
4346
+ rb_define_method(c_MPFR, "erf", mpfrrb_erf, -1);
4347
+ rb_define_method(c_MPFR, "erfc", mpfrrb_erfc, -1);
4348
+ rb_define_method(c_MPFR, "j0", mpfrrb_j0, -1);
4349
+ rb_define_method(c_MPFR, "j1", mpfrrb_j1, -1);
4350
+ rb_define_method(c_MPFR, "jn", mpfrrb_jn, -1);
4351
+ rb_define_method(c_MPFR, "y0", mpfrrb_y0, -1);
4352
+ rb_define_method(c_MPFR, "y1", mpfrrb_y1, -1);
4353
+ rb_define_method(c_MPFR, "yn", mpfrrb_yn, -1);
4354
+ rb_define_method(c_MPFR, "agm", mpfrrb_agm, -1);
4355
+ rb_define_method(c_MPFR, "ai", mpfrrb_ai, -1);
4356
+
4357
+ rb_define_method(c_MPFR, "rint", mpfrrb_rint, -1);
4358
+ rb_define_method(c_MPFR, "ceil", mpfrrb_ceil, 1);
4359
+ rb_define_method(c_MPFR, "floor", mpfrrb_floor, 1);
4360
+ rb_define_method(c_MPFR, "round", mpfrrb_round, 1);
4361
+ rb_define_method(c_MPFR, "roundeven", mpfrrb_roundeven, 1);
4362
+ rb_define_method(c_MPFR, "trunc", mpfrrb_trunc, 1);
4363
+ rb_define_method(c_MPFR, "rint!", mpfrrb_rint_B, -1);
4364
+ rb_define_method(c_MPFR, "ceil!", mpfrrb_ceil_B, 0);
4365
+ rb_define_method(c_MPFR, "floor!", mpfrrb_floor_B, 0);
4366
+ rb_define_method(c_MPFR, "round!", mpfrrb_round_B, 0);
4367
+ rb_define_method(c_MPFR, "roundeven!", mpfrrb_roundeven_B, 0);
4368
+ rb_define_method(c_MPFR, "trunc!", mpfrrb_trunc_B, 0);
4369
+ rb_define_method(c_MPFR, "rint_ceil", mpfrrb_rint_ceil, -1);
4370
+ rb_define_method(c_MPFR, "rint_floor", mpfrrb_rint_floor, -1);
4371
+ rb_define_method(c_MPFR, "rint_round", mpfrrb_rint_round, -1);
4372
+ rb_define_method(c_MPFR, "rint_roundeven", mpfrrb_rint_roundeven, -1);
4373
+ rb_define_method(c_MPFR, "rint_trunc", mpfrrb_rint_trunc, -1);
4374
+ rb_define_method(c_MPFR, "frac", mpfrrb_frac, -1);
4375
+ rb_define_module_function(c_MPFR, "modf", mpfrrb_modf, -1);
4376
+ rb_define_method(c_MPFR, "fmod", mpfrrb_fmod, -1);
4377
+ rb_define_method(c_MPFR, "remainder", mpfrrb_remainder, -1);
4378
+
4379
+ rb_define_method(c_MPFR, "nextabove!", mpfrrb_nextabove_B, 0);
4380
+ rb_define_method(c_MPFR, "nextbelow!", mpfrrb_nextbelow_B, 0);
4381
+
4382
+ /* @!group Random
4383
+ */
4384
+ rb_define_method(c_MPFR, "urandomb", mpfrrb_urandomb, 0);
4385
+ rb_define_method(c_MPFR, "urandom", mpfrrb_urandom, -1);
4386
+ rb_define_method(c_MPFR, "nrandom", mpfrrb_nrandom, -1);
4387
+ rb_define_method(c_MPFR, "erandom", mpfrrb_erandom, -1);
4388
+ /* @!endgroup
4389
+ */
4390
+
4391
+ rb_define_method(c_MPFR, "min", mpfrrb_min, -1);
4392
+ rb_define_method(c_MPFR, "max", mpfrrb_max, -1);
4393
+ rb_define_method(c_MPFR, "subnormalize", mpfrrb_subnormalize, -1);
4394
+
4395
+ rb_define_method(c_MPFR, "[]", mpfrrb_index, 1);
4396
+
4397
+ rb_define_alias(c_MPFR, "inspect", "to_s");
4398
+
4399
+ rb_define_method(rb_cFloat, "to_mpfr", mpfrrb_Float_to_mpfr, 0);
4400
+ rb_define_method(rb_cInteger, "to_mpfr", mpfrrb_Integer_to_mpfr, 0);
4401
+
4402
+ gmp_randinit_default(mpfrrb_gmp_randstate);
4403
+ gmp_randseed_ui(mpfrrb_gmp_randstate, rb_genrand_ulong_limited(0xffffffffffffffffULL));
4404
+
4405
+ // Init_sollya();
4406
+ }
4407
+
4408
+