crmf 0.1.1
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.
- checksums.yaml +7 -0
- data/.yardopts +10 -0
- data/LICENSE +674 -0
- data/README.md +35 -0
- data/crmf.gemspec +29 -0
- data/ext/crlibm-1.0beta4.tar.gz +0 -0
- data/ext/crmf/crmf.c +1966 -0
- data/ext/crmf/crmf.h +29 -0
- data/ext/crmf/crmf.map +7 -0
- data/ext/crmf/extconf.rb +68 -0
- data/lib/crmf/version.rb +4 -0
- data/lib/crmf.rb +19 -0
- data/tests/perf.rb +354 -0
- metadata +57 -0
data/ext/crmf/crmf.c
ADDED
@@ -0,0 +1,1966 @@
|
|
1
|
+
/* Copyright (C) 2022 Théotime Bollengier <theotime.bollengier@ensta-bretagne.fr>
|
2
|
+
*
|
3
|
+
* This file is part of CRMF. <https://gitlab.ensta-bretagne.fr/bollenth/crmf>
|
4
|
+
*
|
5
|
+
* CRMF 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
|
+
* CRMF 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 CRMF. If not, see <https://www.gnu.org/licenses/>.
|
17
|
+
*/
|
18
|
+
|
19
|
+
#include <ruby.h>
|
20
|
+
#include "crmf.h"
|
21
|
+
#include <mpfr.h>
|
22
|
+
#include "crlibm.h"
|
23
|
+
#include <fenv.h>
|
24
|
+
|
25
|
+
static VALUE m_CRMF;
|
26
|
+
static ID id_to_f;
|
27
|
+
static ID id_to_s;
|
28
|
+
static ID id_nearest;
|
29
|
+
static ID id_down;
|
30
|
+
static ID id_up;
|
31
|
+
static ID id_zero;
|
32
|
+
static ID id_away;
|
33
|
+
static ID id_syminf;
|
34
|
+
static ID id_sign;
|
35
|
+
static ID id_sign_bit;
|
36
|
+
static ID id_exponent_bits;
|
37
|
+
static ID id_fraction_bits;
|
38
|
+
static ID id_exponent;
|
39
|
+
static ID id_significand;
|
40
|
+
static ID id_isignificand;
|
41
|
+
static ID id_flag;
|
42
|
+
static ID id_infinity;
|
43
|
+
static ID id_nan;
|
44
|
+
static ID id_subnormal;
|
45
|
+
static ID id_zero;
|
46
|
+
|
47
|
+
|
48
|
+
/* Returns a hash containing the components of the float.
|
49
|
+
*
|
50
|
+
* The returned hash contains the folowing fields:
|
51
|
+
*
|
52
|
+
* - **:sign_bit** An integer: 0 for positive, 1 for negative. Corresponds to bit 63.
|
53
|
+
* - **:exponent_bits** The biased exponent as an integer. Corresponds to bits 62 downto 52.
|
54
|
+
* - **:fraction_bits** The stored fraction bits (without the implicit leading 1). Corresponds to bits 51 downto 0.
|
55
|
+
* - **:sign** An integer: 1 for positive, -1 for negative
|
56
|
+
* - **:flag** A symbol, either _:nan_, _:infinite_, _:zero_, _:subnormal_ or _nil_.
|
57
|
+
* - **:exponent** The unbiased exponent as an integer.
|
58
|
+
* - **:isignificand** An integer corresponding to _fraction\_bits_ plus the leading implicit 1 if not a subnormal.
|
59
|
+
* - **:significand** The significand part as a float, in the range [1.0, 2.0[, or less than 1.0 if the number is subnormal.
|
60
|
+
*
|
61
|
+
* The number can be retreived with `sign * 2**exponent * significand`
|
62
|
+
* @return [Hash{Symbol => Object}]
|
63
|
+
* @see build_up
|
64
|
+
*/
|
65
|
+
static VALUE crmf_float_break_down(VALUE self)
|
66
|
+
{
|
67
|
+
union {
|
68
|
+
double d;
|
69
|
+
unsigned long long l;
|
70
|
+
} dudul;
|
71
|
+
dudul.d = NUM2DBL(self);
|
72
|
+
unsigned long long sign = (dudul.l >> 63) & 1;
|
73
|
+
unsigned long long expo = (dudul.l >> 52) & 0x7ff;
|
74
|
+
unsigned long long frac = dudul.l & 0x000fffffffffffffULL;
|
75
|
+
VALUE h = rb_hash_new();
|
76
|
+
rb_hash_aset(h, rb_id2sym(id_sign_bit), ULL2NUM(sign));
|
77
|
+
rb_hash_aset(h, rb_id2sym(id_exponent_bits), RB_ULL2NUM(expo));
|
78
|
+
rb_hash_aset(h, rb_id2sym(id_fraction_bits), RB_ULL2NUM(frac));
|
79
|
+
rb_hash_aset(h, rb_id2sym(id_sign), INT2NUM((sign == 0) ? 1 : -1));
|
80
|
+
|
81
|
+
if (expo == 0x7ffULL) {
|
82
|
+
if (frac == 0ULL) // Infinity
|
83
|
+
rb_hash_aset(h, rb_id2sym(id_flag), rb_id2sym(id_infinity));
|
84
|
+
else // NaN
|
85
|
+
rb_hash_aset(h, rb_id2sym(id_flag), rb_id2sym(id_nan));
|
86
|
+
}
|
87
|
+
else if (expo == 0ULL) {
|
88
|
+
if (frac == 0ULL) { // Zero
|
89
|
+
rb_hash_aset(h, rb_id2sym(id_flag), rb_id2sym(id_zero));
|
90
|
+
rb_hash_aset(h, rb_id2sym(id_isignificand), INT2NUM(0));
|
91
|
+
rb_hash_aset(h, rb_id2sym(id_exponent), INT2NUM(-1022));
|
92
|
+
rb_hash_aset(h, rb_id2sym(id_significand), DBL2NUM(0.0));
|
93
|
+
}
|
94
|
+
else { // Subnormal
|
95
|
+
rb_hash_aset(h, rb_id2sym(id_flag), rb_id2sym(id_subnormal));
|
96
|
+
rb_hash_aset(h, rb_id2sym(id_isignificand), RB_ULL2NUM(frac));
|
97
|
+
rb_hash_aset(h, rb_id2sym(id_exponent), INT2NUM(-1022));
|
98
|
+
expo = 1023;
|
99
|
+
while ((frac & 0x0010000000000000ULL) == 0ULL) {
|
100
|
+
frac <<= 1;
|
101
|
+
expo -= 1;
|
102
|
+
}
|
103
|
+
dudul.l = (expo << 52) | (frac & 0x000fffffffffffffULL);
|
104
|
+
rb_hash_aset(h, rb_id2sym(id_significand), DBL2NUM(dudul.d));
|
105
|
+
}
|
106
|
+
}
|
107
|
+
else {
|
108
|
+
rb_hash_aset(h, rb_id2sym(id_flag), Qnil);
|
109
|
+
rb_hash_aset(h, rb_id2sym(id_isignificand), ULL2NUM(frac | 0x10000000000000ULL));
|
110
|
+
rb_hash_aset(h, rb_id2sym(id_exponent), INT2NUM((int)expo - 1023));
|
111
|
+
dudul.l &= 0x000fffffffffffffULL;
|
112
|
+
dudul.l |= 0x3ff0000000000000ULL;
|
113
|
+
rb_hash_aset(h, rb_id2sym(id_significand), DBL2NUM(dudul.d));
|
114
|
+
}
|
115
|
+
|
116
|
+
return h;
|
117
|
+
}
|
118
|
+
|
119
|
+
|
120
|
+
/* Build a float from its bit fields.
|
121
|
+
* @param sign_bit [Integer] 0 for positive, 1 for negative.
|
122
|
+
* @param exponent_bits [Integer] the biased exponent (exponent + 1023), from 0 to 2047.
|
123
|
+
* @param fraction_bits [Integer] the fraction bits of the significand, without the implicit leading 1. From 0 to 4503599627370495.
|
124
|
+
* @return [Float]
|
125
|
+
* @see Float#break_down
|
126
|
+
* @example
|
127
|
+
* Float.build_up(0, 1023, 0) #=> 1.0
|
128
|
+
* Float.build_up(1, 1024, 0) #=> -2.0
|
129
|
+
* Float.build_up(0, 2047, 0) #=> Infinity
|
130
|
+
* Float.build_up(1, 2047, 0) #=> -Infinity
|
131
|
+
* Float.build_up(0, 2047, 42) #=> NaN
|
132
|
+
* Float.build_up(0, 0, 0) #=> 0.0
|
133
|
+
* Float.build_up(0, 0, 1) #=> 5.0e-324
|
134
|
+
*/
|
135
|
+
static VALUE crmf_float_build_up(VALUE self, VALUE sign_bit, VALUE exponent_bits, VALUE fraction_bits)
|
136
|
+
{
|
137
|
+
long long sb, eb, fb;
|
138
|
+
union {
|
139
|
+
double d;
|
140
|
+
unsigned long long l;
|
141
|
+
} dudul;
|
142
|
+
|
143
|
+
if (!rb_integer_type_p(sign_bit))
|
144
|
+
rb_raise(rb_eTypeError, "expecting an integer as sign bit, not a %s", rb_obj_classname(sign_bit));
|
145
|
+
sb = NUM2LL(sign_bit);
|
146
|
+
if ((sb & 0xfffffffffffffffeULL) != 0)
|
147
|
+
rb_raise(rb_eArgError, "sign bit must be 0 or 1");
|
148
|
+
|
149
|
+
if (!rb_integer_type_p(exponent_bits))
|
150
|
+
rb_raise(rb_eTypeError, "expecting an integer as exponent bits, not a %s", rb_obj_classname(exponent_bits));
|
151
|
+
eb = NUM2LL(exponent_bits);
|
152
|
+
if ((eb & 0xfffffffffffff800ULL) != 0)
|
153
|
+
rb_raise(rb_eArgError, "exponent bits must be between 0 and 2047");
|
154
|
+
|
155
|
+
if (!rb_integer_type_p(fraction_bits))
|
156
|
+
rb_raise(rb_eTypeError, "expecting an integer as fraction bits, not a %s", rb_obj_classname(fraction_bits));
|
157
|
+
fb = NUM2LL(fraction_bits);
|
158
|
+
if ((fb & 0xfff0000000000000ULL) != 0)
|
159
|
+
rb_raise(rb_eArgError, "fraction bits must be between 0 and 4503599627370495");
|
160
|
+
|
161
|
+
dudul.l = (sb << 63) | (eb << 52) | fb;
|
162
|
+
|
163
|
+
return DBL2NUM(dudul.d);
|
164
|
+
}
|
165
|
+
|
166
|
+
|
167
|
+
/* Tels if the float is subnormal.
|
168
|
+
* That is, if its biased exponent is 0 and its fraction part is not null.
|
169
|
+
* @return [Boolean]
|
170
|
+
*/
|
171
|
+
static VALUE crmf_float_is_subnormal(VALUE self)
|
172
|
+
{
|
173
|
+
union dul {
|
174
|
+
double d;
|
175
|
+
unsigned long long l;
|
176
|
+
} dudul;
|
177
|
+
dudul.d = NUM2DBL(self);
|
178
|
+
unsigned long long expo = (dudul.l >> 52) & 0x7ff;
|
179
|
+
unsigned long long frac = dudul.l & 0x000fffffffffffffULL;
|
180
|
+
if (expo == 0ULL && frac != 0ULL)
|
181
|
+
return Qtrue;
|
182
|
+
return Qfalse;
|
183
|
+
}
|
184
|
+
|
185
|
+
|
186
|
+
static mpfr_rnd_t crmf_sym_to_rnd(VALUE s)
|
187
|
+
{
|
188
|
+
if (!RB_TYPE_P(s, RUBY_T_SYMBOL))
|
189
|
+
rb_raise(rb_eTypeError, "expecting a symbol, not %s", rb_obj_classname(s));
|
190
|
+
ID sym = rb_sym2id(s);
|
191
|
+
mpfr_rnd_t rnd;
|
192
|
+
if (sym == id_nearest)
|
193
|
+
rnd = MPFR_RNDN;
|
194
|
+
else if (sym == id_down)
|
195
|
+
rnd = MPFR_RNDD;
|
196
|
+
else if (sym == id_up)
|
197
|
+
rnd = MPFR_RNDU;
|
198
|
+
else if (sym == id_zero)
|
199
|
+
rnd = MPFR_RNDZ;
|
200
|
+
else if (sym == id_away)
|
201
|
+
rnd = MPFR_RNDA;
|
202
|
+
else
|
203
|
+
rb_raise(rb_eArgError, "expecting :nearest, :down, :up, :zero or :away, not %" PRIsVALUE, s);
|
204
|
+
return rnd;
|
205
|
+
}
|
206
|
+
|
207
|
+
|
208
|
+
/* Convert _obj_ to a Float, rounding according to _rnd_.
|
209
|
+
* @return [Float]
|
210
|
+
* @overload to_float(obj, rnd = :nearest)
|
211
|
+
* @param obj [Float, Integer, String, #to_f] object to convert
|
212
|
+
* @param rnd [Symbol] :nearest, :down, :up, :zero or :away
|
213
|
+
*/
|
214
|
+
static VALUE crmf_object_to_float(int argc, VALUE *argv, VALUE self)
|
215
|
+
{
|
216
|
+
VALUE obj = Qnil, rnd = Qnil;
|
217
|
+
mpfr_rnd_t rndt = MPFR_RNDN;
|
218
|
+
rb_scan_args(argc, argv, "11", &obj, &rnd);
|
219
|
+
if (rnd != Qnil)
|
220
|
+
rndt = crmf_sym_to_rnd(rnd);
|
221
|
+
MPFR_DECL_INIT(mpfra, 53);
|
222
|
+
int type = rb_type(obj);
|
223
|
+
int t = 0;
|
224
|
+
if (type == RUBY_T_FLOAT) {
|
225
|
+
printf("RUBY_T_FLOAT\n");
|
226
|
+
double d = NUM2DBL(obj);
|
227
|
+
t = mpfr_set_d(mpfra, d, rndt);
|
228
|
+
}
|
229
|
+
else if (type == RUBY_T_FIXNUM) {
|
230
|
+
printf("RUBY_T_FIXNUM\n");
|
231
|
+
long int li = NUM2LL(obj);
|
232
|
+
t = mpfr_set_si(mpfra, li, rndt);
|
233
|
+
}
|
234
|
+
else if (type == RUBY_T_BIGNUM) {
|
235
|
+
printf("RUBY_T_BIGNUM\n");
|
236
|
+
obj = rb_funcallv(obj, id_to_s, 0, NULL);
|
237
|
+
const char *strptr = StringValuePtr(obj);
|
238
|
+
t = mpfr_set_str(mpfra, strptr, 10, rndt);
|
239
|
+
}
|
240
|
+
else if (type == RUBY_T_STRING) {
|
241
|
+
printf("RUBY_T_STRING\n");
|
242
|
+
const char *strptr = StringValuePtr(obj);
|
243
|
+
t = mpfr_set_str(mpfra, strptr, 10, rndt);
|
244
|
+
}
|
245
|
+
else {
|
246
|
+
obj = rb_funcallv(obj, id_to_f, 0, NULL);
|
247
|
+
double d = NUM2DBL(obj);
|
248
|
+
t = mpfr_set_d(mpfra, d, rndt);
|
249
|
+
}
|
250
|
+
mpfr_subnormalize(mpfra, t, rndt);
|
251
|
+
double d = mpfr_get_d(mpfra, rndt);
|
252
|
+
return DBL2NUM(d);
|
253
|
+
}
|
254
|
+
|
255
|
+
|
256
|
+
static void crmf_rbfloat_to_mpfr53(VALUE x, mpfr_t rx)
|
257
|
+
{
|
258
|
+
if (RB_INTEGER_TYPE_P(x))
|
259
|
+
x = rb_funcallv(x, id_to_f, 0, NULL);
|
260
|
+
if (!RB_TYPE_P(x, RUBY_T_FLOAT))
|
261
|
+
rb_raise(rb_eTypeError, "expecting a Float, not a %s", rb_obj_classname(x));
|
262
|
+
double d = NUM2DBL(x);
|
263
|
+
int t = mpfr_set_d(rx, d, MPFR_RNDN);
|
264
|
+
if (t)
|
265
|
+
rb_raise(rb_eRuntimeError, "%" PRIsVALUE " could not be set to a mpfr_t without rounding", x);
|
266
|
+
}
|
267
|
+
|
268
|
+
|
269
|
+
/* Add _a_ and _b_, round according to _rnd_.
|
270
|
+
* @overload add(a, b, rnd = :nearest)
|
271
|
+
* @param a [Float]
|
272
|
+
* @param b [Float]
|
273
|
+
* @param rnd [Symbol] :nearest, :down, :up, :zero or :away
|
274
|
+
*/
|
275
|
+
static VALUE crmf_float_add(int argc, VALUE *argv, VALUE self)
|
276
|
+
{
|
277
|
+
VALUE a = Qnil, b = Qnil, rnd = Qnil;
|
278
|
+
mpfr_rnd_t rndt = MPFR_RNDN;
|
279
|
+
MPFR_DECL_INIT(mpfra, 53);
|
280
|
+
MPFR_DECL_INIT(mpfrb, 53);
|
281
|
+
rb_scan_args(argc, argv, "21", &a, &b, &rnd);
|
282
|
+
crmf_rbfloat_to_mpfr53(a, mpfra);
|
283
|
+
crmf_rbfloat_to_mpfr53(b, mpfrb);
|
284
|
+
if (rnd != Qnil)
|
285
|
+
rndt = crmf_sym_to_rnd(rnd);
|
286
|
+
int t = mpfr_add(mpfra, mpfra, mpfrb, rndt);
|
287
|
+
mpfr_subnormalize(mpfra, t, rndt);
|
288
|
+
double d = mpfr_get_d(mpfra, rndt);
|
289
|
+
return DBL2NUM(d);
|
290
|
+
}
|
291
|
+
|
292
|
+
|
293
|
+
/* Subtract _b_ from _a_, round according to _rnd_.
|
294
|
+
* @overload sub(a, b, rnd = :nearest)
|
295
|
+
* @param a [Float]
|
296
|
+
* @param b [Float]
|
297
|
+
* @param rnd [Symbol] :nearest, :down, :up, :zero or :away
|
298
|
+
*/
|
299
|
+
static VALUE crmf_float_sub(int argc, VALUE *argv, VALUE self)
|
300
|
+
{
|
301
|
+
VALUE a = Qnil, b = Qnil, rnd = Qnil;
|
302
|
+
mpfr_rnd_t rndt = MPFR_RNDN;
|
303
|
+
MPFR_DECL_INIT(mpfra, 53);
|
304
|
+
MPFR_DECL_INIT(mpfrb, 53);
|
305
|
+
rb_scan_args(argc, argv, "21", &a, &b, &rnd);
|
306
|
+
crmf_rbfloat_to_mpfr53(a, mpfra);
|
307
|
+
crmf_rbfloat_to_mpfr53(b, mpfrb);
|
308
|
+
if (rnd != Qnil)
|
309
|
+
rndt = crmf_sym_to_rnd(rnd);
|
310
|
+
int t = mpfr_sub(mpfra, mpfra, mpfrb, rndt);
|
311
|
+
mpfr_subnormalize(mpfra, t, rndt);
|
312
|
+
double d = mpfr_get_d(mpfra, rndt);
|
313
|
+
return DBL2NUM(d);
|
314
|
+
}
|
315
|
+
|
316
|
+
|
317
|
+
/* Multiply _a_ and _b_, rounding according to _rnd_.
|
318
|
+
* @overload mul(a, b, rnd = :nearest)
|
319
|
+
* @param a [Float]
|
320
|
+
* @param b [Float]
|
321
|
+
* @param rnd [Symbol] :nearest, :down, :up, :zero or :away
|
322
|
+
*/
|
323
|
+
static VALUE crmf_float_mul(int argc, VALUE *argv, VALUE self)
|
324
|
+
{
|
325
|
+
VALUE a = Qnil, b = Qnil, rnd = Qnil;
|
326
|
+
mpfr_rnd_t rndt = MPFR_RNDN;
|
327
|
+
MPFR_DECL_INIT(mpfra, 53);
|
328
|
+
MPFR_DECL_INIT(mpfrb, 53);
|
329
|
+
rb_scan_args(argc, argv, "21", &a, &b, &rnd);
|
330
|
+
crmf_rbfloat_to_mpfr53(a, mpfra);
|
331
|
+
crmf_rbfloat_to_mpfr53(b, mpfrb);
|
332
|
+
if (rnd != Qnil)
|
333
|
+
rndt = crmf_sym_to_rnd(rnd);
|
334
|
+
int t = mpfr_mul(mpfra, mpfra, mpfrb, rndt);
|
335
|
+
mpfr_subnormalize(mpfra, t, rndt);
|
336
|
+
double d = mpfr_get_d(mpfra, rndt);
|
337
|
+
return DBL2NUM(d);
|
338
|
+
}
|
339
|
+
|
340
|
+
|
341
|
+
/* Divide _a_ by _b_, rounding according to _rnd_.
|
342
|
+
* @overload div(a, b, rnd = :nearest)
|
343
|
+
* @param a [Float]
|
344
|
+
* @param b [Float]
|
345
|
+
* @param rnd [Symbol] :nearest, :down, :up, :zero or :away
|
346
|
+
*/
|
347
|
+
static VALUE crmf_float_div(int argc, VALUE *argv, VALUE self)
|
348
|
+
{
|
349
|
+
VALUE a = Qnil, b = Qnil, rnd = Qnil;
|
350
|
+
mpfr_rnd_t rndt = MPFR_RNDN;
|
351
|
+
MPFR_DECL_INIT(mpfra, 53);
|
352
|
+
MPFR_DECL_INIT(mpfrb, 53);
|
353
|
+
rb_scan_args(argc, argv, "21", &a, &b, &rnd);
|
354
|
+
crmf_rbfloat_to_mpfr53(a, mpfra);
|
355
|
+
crmf_rbfloat_to_mpfr53(b, mpfrb);
|
356
|
+
if (rnd != Qnil)
|
357
|
+
rndt = crmf_sym_to_rnd(rnd);
|
358
|
+
int t = mpfr_div(mpfra, mpfra, mpfrb, rndt);
|
359
|
+
mpfr_subnormalize(mpfra, t, rndt);
|
360
|
+
double d = mpfr_get_d(mpfra, rndt);
|
361
|
+
return DBL2NUM(d);
|
362
|
+
}
|
363
|
+
|
364
|
+
|
365
|
+
/* Return the square root of _a_ rounded in the direction _rnd_.
|
366
|
+
* Returns −0 if _a_ is −0, to be consistent with the IEEE 754 standard.
|
367
|
+
* Returns NaN if op is negative.
|
368
|
+
* @overload sqrt(a, rnd = :nearest)
|
369
|
+
* @param a [Float]
|
370
|
+
* @param rnd [Symbol] :nearest, :down, :up, :zero or :away
|
371
|
+
*/
|
372
|
+
static VALUE crmf_float_sqrt(int argc, VALUE *argv, VALUE self)
|
373
|
+
{
|
374
|
+
VALUE a = Qnil, rnd = Qnil;
|
375
|
+
mpfr_rnd_t rndt = MPFR_RNDN;
|
376
|
+
rb_scan_args(argc, argv, "11", &a, &rnd);
|
377
|
+
MPFR_DECL_INIT(mpfra, 53);
|
378
|
+
crmf_rbfloat_to_mpfr53(a, mpfra);
|
379
|
+
if (rnd != Qnil)
|
380
|
+
rndt = crmf_sym_to_rnd(rnd);
|
381
|
+
int t = mpfr_sqrt(mpfra, mpfra, rndt);
|
382
|
+
mpfr_subnormalize(mpfra, t, rndt);
|
383
|
+
double d = mpfr_get_d(mpfra, rndt);
|
384
|
+
return DBL2NUM(d);
|
385
|
+
}
|
386
|
+
|
387
|
+
|
388
|
+
/* Return the cubic root of _a_ rounded in the direction _rnd_.
|
389
|
+
* @overload cbrt(a, rnd = :nearest)
|
390
|
+
* @param a [Float]
|
391
|
+
* @param rnd [Symbol] :nearest, :down, :up, :zero or :away
|
392
|
+
*/
|
393
|
+
static VALUE crmf_float_cbrt(int argc, VALUE *argv, VALUE self)
|
394
|
+
{
|
395
|
+
VALUE a = Qnil, rnd = Qnil;
|
396
|
+
mpfr_rnd_t rndt = MPFR_RNDN;
|
397
|
+
rb_scan_args(argc, argv, "11", &a, &rnd);
|
398
|
+
MPFR_DECL_INIT(mpfra, 53);
|
399
|
+
crmf_rbfloat_to_mpfr53(a, mpfra);
|
400
|
+
if (rnd != Qnil)
|
401
|
+
rndt = crmf_sym_to_rnd(rnd);
|
402
|
+
int t = mpfr_cbrt(mpfra, mpfra, rndt);
|
403
|
+
mpfr_subnormalize(mpfra, t, rndt);
|
404
|
+
double d = mpfr_get_d(mpfra, rndt);
|
405
|
+
return DBL2NUM(d);
|
406
|
+
}
|
407
|
+
|
408
|
+
|
409
|
+
/* Returns the _n_ th root of _a_ rounded in the direction _rnd_.
|
410
|
+
* For _n_ = 0, returns NaN.
|
411
|
+
* For _n_ odd (resp. even) and _a_ negative (including −Inf), returns a negative number (resp. NaN).
|
412
|
+
* If _a_ is zero, returns zero with the sign obtained by the usual limit rules,
|
413
|
+
* i.e., the same sign as _a_ if _n_ is odd, and negative if _n_ is even.
|
414
|
+
*
|
415
|
+
* This functions agree with the `rootn` function of the IEEE 754-2008 standard and
|
416
|
+
* the P754/D2.41 draft of the next standard (Section 9.2).
|
417
|
+
* Note that it is here restricted to _n_ >= 0.
|
418
|
+
* Functions allowing a negative _n_ may be implemented in the future.
|
419
|
+
* @overload rootn(a, n, rnd = :nearest)
|
420
|
+
* @param a [Float]
|
421
|
+
* @param n [Integer] n >= 0
|
422
|
+
* @param rnd [Symbol] :nearest, :down, :up, :zero or :away
|
423
|
+
*/
|
424
|
+
static VALUE crmf_float_rootn(int argc, VALUE *argv, VALUE self)
|
425
|
+
{
|
426
|
+
VALUE a = Qnil, n = Qnil, rnd = Qnil;
|
427
|
+
mpfr_rnd_t rndt = MPFR_RNDN;
|
428
|
+
rb_scan_args(argc, argv, "21", &a, &n, &rnd);
|
429
|
+
MPFR_DECL_INIT(mpfra, 53);
|
430
|
+
crmf_rbfloat_to_mpfr53(a, mpfra);
|
431
|
+
if (!rb_integer_type_p(n))
|
432
|
+
rb_raise(rb_eTypeError, "expecting an integer as second argument, not a %s", rb_obj_classname(n));
|
433
|
+
if (rb_funcall(n, id_syminf, 1, INT2NUM(0)) == Qtrue)
|
434
|
+
rb_raise(rb_eRangeError, "n must be >= 0, not %" PRIsVALUE, n);
|
435
|
+
unsigned long int nn = NUM2ULL(n);
|
436
|
+
if (rnd != Qnil)
|
437
|
+
rndt = crmf_sym_to_rnd(rnd);
|
438
|
+
int t = mpfr_rootn_ui(mpfra, mpfra, nn, rndt);
|
439
|
+
mpfr_subnormalize(mpfra, t, rndt);
|
440
|
+
double d = mpfr_get_d(mpfra, rndt);
|
441
|
+
return DBL2NUM(d);
|
442
|
+
}
|
443
|
+
|
444
|
+
|
445
|
+
/* Returns the positive difference of _a_ and _b_ rounded in the direction _rnd_.
|
446
|
+
* That is _a_ - _b_ if _a_ > _b_, +0 if _a_ <= _b_, and NaN if _a_ or _b_ is NaN.
|
447
|
+
* @overload dim(a, b, rnd = :nearest)
|
448
|
+
* @param a [Float]
|
449
|
+
* @param b [Float]
|
450
|
+
* @param rnd [Symbol] :nearest, :down, :up, :zero or :away
|
451
|
+
*/
|
452
|
+
static VALUE crmf_float_dim(int argc, VALUE *argv, VALUE self)
|
453
|
+
{
|
454
|
+
VALUE a = Qnil, b = Qnil, rnd = Qnil;
|
455
|
+
mpfr_rnd_t rndt = MPFR_RNDN;
|
456
|
+
rb_scan_args(argc, argv, "21", &a, &b, &rnd);
|
457
|
+
MPFR_DECL_INIT(mpfra, 53);
|
458
|
+
MPFR_DECL_INIT(mpfrb, 53);
|
459
|
+
crmf_rbfloat_to_mpfr53(a, mpfra);
|
460
|
+
crmf_rbfloat_to_mpfr53(b, mpfrb);
|
461
|
+
if (rnd != Qnil)
|
462
|
+
rndt = crmf_sym_to_rnd(rnd);
|
463
|
+
int t = mpfr_dim(mpfra, mpfra, mpfrb, rndt);
|
464
|
+
mpfr_subnormalize(mpfra, t, rndt);
|
465
|
+
double d = mpfr_get_d(mpfra, rndt);
|
466
|
+
return DBL2NUM(d);
|
467
|
+
}
|
468
|
+
|
469
|
+
|
470
|
+
/* Returns (_a_ times _b_) + _c_ rounded in the direction _rnd_.
|
471
|
+
* Concerning special values (signed zeros, infinities, NaN), these functions behave like a multiplication
|
472
|
+
* followed by a separate addition or subtraction. That is, the fused operation matters only for rounding.
|
473
|
+
* @overload fma(a, b, c, rnd = :nearest)
|
474
|
+
* @param a [Float]
|
475
|
+
* @param b [Float]
|
476
|
+
* @param c [Float]
|
477
|
+
* @param rnd [Symbol] :nearest, :down, :up, :zero or :away
|
478
|
+
*/
|
479
|
+
static VALUE crmf_float_fma(int argc, VALUE *argv, VALUE self)
|
480
|
+
{
|
481
|
+
VALUE a = Qnil, b = Qnil, c = Qnil, rnd = Qnil;
|
482
|
+
mpfr_rnd_t rndt = MPFR_RNDN;
|
483
|
+
rb_scan_args(argc, argv, "31", &a, &b, &c, &rnd);
|
484
|
+
MPFR_DECL_INIT(mpfra, 53);
|
485
|
+
MPFR_DECL_INIT(mpfrb, 53);
|
486
|
+
MPFR_DECL_INIT(mpfrc, 53);
|
487
|
+
crmf_rbfloat_to_mpfr53(a, mpfra);
|
488
|
+
crmf_rbfloat_to_mpfr53(b, mpfrb);
|
489
|
+
crmf_rbfloat_to_mpfr53(c, mpfrc);
|
490
|
+
if (rnd != Qnil)
|
491
|
+
rndt = crmf_sym_to_rnd(rnd);
|
492
|
+
int t = mpfr_fma(mpfra, mpfra, mpfrb, mpfrc, rndt);
|
493
|
+
mpfr_subnormalize(mpfra, t, rndt);
|
494
|
+
double d = mpfr_get_d(mpfra, rndt);
|
495
|
+
return DBL2NUM(d);
|
496
|
+
}
|
497
|
+
|
498
|
+
|
499
|
+
/* Returns (_a_ times _b_) - _c_ rounded in the direction _rnd_.
|
500
|
+
* Concerning special values (signed zeros, infinities, NaN), these functions behave like a multiplication
|
501
|
+
* followed by a separate addition or subtraction. That is, the fused operation matters only for rounding.
|
502
|
+
* @overload fms(a, b, c, rnd = :nearest)
|
503
|
+
* @param a [Float]
|
504
|
+
* @param b [Float]
|
505
|
+
* @param c [Float]
|
506
|
+
* @param rnd [Symbol] :nearest, :down, :up, :zero or :away
|
507
|
+
*/
|
508
|
+
static VALUE crmf_float_fms(int argc, VALUE *argv, VALUE self)
|
509
|
+
{
|
510
|
+
VALUE a = Qnil, b = Qnil, c = Qnil, rnd = Qnil;
|
511
|
+
mpfr_rnd_t rndt = MPFR_RNDN;
|
512
|
+
rb_scan_args(argc, argv, "31", &a, &b, &c, &rnd);
|
513
|
+
MPFR_DECL_INIT(mpfra, 53);
|
514
|
+
MPFR_DECL_INIT(mpfrb, 53);
|
515
|
+
MPFR_DECL_INIT(mpfrc, 53);
|
516
|
+
crmf_rbfloat_to_mpfr53(a, mpfra);
|
517
|
+
crmf_rbfloat_to_mpfr53(b, mpfrb);
|
518
|
+
crmf_rbfloat_to_mpfr53(c, mpfrc);
|
519
|
+
if (rnd != Qnil)
|
520
|
+
rndt = crmf_sym_to_rnd(rnd);
|
521
|
+
int t = mpfr_fms(mpfra, mpfra, mpfrb, mpfrc, rndt);
|
522
|
+
mpfr_subnormalize(mpfra, t, rndt);
|
523
|
+
double d = mpfr_get_d(mpfra, rndt);
|
524
|
+
return DBL2NUM(d);
|
525
|
+
}
|
526
|
+
|
527
|
+
|
528
|
+
/* Returns (_a_ times _b_) + (_c_ times _d_) rounded in the direction _rnd_.
|
529
|
+
* In case the computation of _a_ times _b_ overflows or underflows (or that of _c_ times _d_),
|
530
|
+
* the result is computed as if the two intermediate products were computed with rounding toward zero.
|
531
|
+
* @overload fmma(a, b, c, d, rnd = :nearest)
|
532
|
+
* @param a [Float]
|
533
|
+
* @param b [Float]
|
534
|
+
* @param c [Float]
|
535
|
+
* @param d [Float]
|
536
|
+
* @param rnd [Symbol] :nearest, :down, :up, :zero or :away
|
537
|
+
*/
|
538
|
+
static VALUE crmf_float_fmma(int argc, VALUE *argv, VALUE self)
|
539
|
+
{
|
540
|
+
VALUE a = Qnil, b = Qnil, c = Qnil, d = Qnil, rnd = Qnil;
|
541
|
+
mpfr_rnd_t rndt = MPFR_RNDN;
|
542
|
+
rb_scan_args(argc, argv, "41", &a, &b, &c, &d, &rnd);
|
543
|
+
MPFR_DECL_INIT(mpfra, 53);
|
544
|
+
MPFR_DECL_INIT(mpfrb, 53);
|
545
|
+
MPFR_DECL_INIT(mpfrc, 53);
|
546
|
+
MPFR_DECL_INIT(mpfrd, 53);
|
547
|
+
crmf_rbfloat_to_mpfr53(a, mpfra);
|
548
|
+
crmf_rbfloat_to_mpfr53(b, mpfrb);
|
549
|
+
crmf_rbfloat_to_mpfr53(c, mpfrc);
|
550
|
+
crmf_rbfloat_to_mpfr53(d, mpfrd);
|
551
|
+
if (rnd != Qnil)
|
552
|
+
rndt = crmf_sym_to_rnd(rnd);
|
553
|
+
int t = mpfr_fmma(mpfra, mpfra, mpfrb, mpfrc, mpfrd, rndt);
|
554
|
+
mpfr_subnormalize(mpfra, t, rndt);
|
555
|
+
double r = mpfr_get_d(mpfra, rndt);
|
556
|
+
return DBL2NUM(r);
|
557
|
+
}
|
558
|
+
|
559
|
+
|
560
|
+
/* Returns (_a_ times _b_) - (_c_ times _d_) rounded in the direction _rnd_.
|
561
|
+
* In case the computation of _a_ times _b_ overflows or underflows (or that of _c_ times _d_),
|
562
|
+
* the result is computed as if the two intermediate products were computed with rounding toward zero.
|
563
|
+
* @overload fmms(a, b, c, d, rnd = :nearest)
|
564
|
+
* @param a [Float]
|
565
|
+
* @param b [Float]
|
566
|
+
* @param c [Float]
|
567
|
+
* @param d [Float]
|
568
|
+
* @param rnd [Symbol] :nearest, :down, :up, :zero or :away
|
569
|
+
*/
|
570
|
+
static VALUE crmf_float_fmms(int argc, VALUE *argv, VALUE self)
|
571
|
+
{
|
572
|
+
VALUE a = Qnil, b = Qnil, c = Qnil, d = Qnil, rnd = Qnil;
|
573
|
+
mpfr_rnd_t rndt = MPFR_RNDN;
|
574
|
+
rb_scan_args(argc, argv, "41", &a, &b, &c, &d, &rnd);
|
575
|
+
MPFR_DECL_INIT(mpfra, 53);
|
576
|
+
MPFR_DECL_INIT(mpfrb, 53);
|
577
|
+
MPFR_DECL_INIT(mpfrc, 53);
|
578
|
+
MPFR_DECL_INIT(mpfrd, 53);
|
579
|
+
crmf_rbfloat_to_mpfr53(a, mpfra);
|
580
|
+
crmf_rbfloat_to_mpfr53(b, mpfrb);
|
581
|
+
crmf_rbfloat_to_mpfr53(c, mpfrc);
|
582
|
+
crmf_rbfloat_to_mpfr53(d, mpfrd);
|
583
|
+
if (rnd != Qnil)
|
584
|
+
rndt = crmf_sym_to_rnd(rnd);
|
585
|
+
int t = mpfr_fmms(mpfra, mpfra, mpfrb, mpfrc, mpfrd, rndt);
|
586
|
+
mpfr_subnormalize(mpfra, t, rndt);
|
587
|
+
double r = mpfr_get_d(mpfra, rndt);
|
588
|
+
return DBL2NUM(r);
|
589
|
+
}
|
590
|
+
|
591
|
+
|
592
|
+
/* Returns the Euclidean norm of _x_ and _y_, rounded in the direction _rnd_.
|
593
|
+
* That is, the square root of the sum of the squares of _x_ and _y_.
|
594
|
+
* Special values are handled as described in the ISO C99 (Section F.9.4.3) and IEEE 754-2008 (Section 9.2.1)
|
595
|
+
* standards: If _x_ or _y_ is an infinity, then +Inf is returned, even if the other number is NaN.
|
596
|
+
* @overload hypot(a, b, rnd = :nearest)
|
597
|
+
* @param a [Float]
|
598
|
+
* @param b [Float]
|
599
|
+
* @param rnd [Symbol] :nearest, :down, :up, :zero or :away
|
600
|
+
*/
|
601
|
+
static VALUE crmf_float_hypot(int argc, VALUE *argv, VALUE self)
|
602
|
+
{
|
603
|
+
VALUE a = Qnil, b = Qnil, rnd = Qnil;
|
604
|
+
mpfr_rnd_t rndt = MPFR_RNDN;
|
605
|
+
rb_scan_args(argc, argv, "21", &a, &b, &rnd);
|
606
|
+
MPFR_DECL_INIT(mpfra, 53);
|
607
|
+
MPFR_DECL_INIT(mpfrb, 53);
|
608
|
+
crmf_rbfloat_to_mpfr53(a, mpfra);
|
609
|
+
crmf_rbfloat_to_mpfr53(b, mpfrb);
|
610
|
+
if (rnd != Qnil)
|
611
|
+
rndt = crmf_sym_to_rnd(rnd);
|
612
|
+
int t = mpfr_hypot(mpfra, mpfra, mpfrb, rndt);
|
613
|
+
mpfr_subnormalize(mpfra, t, rndt);
|
614
|
+
double d = mpfr_get_d(mpfra, rndt);
|
615
|
+
return DBL2NUM(d);
|
616
|
+
}
|
617
|
+
|
618
|
+
|
619
|
+
/* Returns the natural logarithm of _x_, rounded in the direction _rnd_.
|
620
|
+
* Returns +0 if _x_ is 1 (in all rounding modes), for consistency with the ISO C99 and IEEE 754-2008 standards.
|
621
|
+
* Returns -Inf if _x_ is ±0 (i.e., the sign of the zero has no influence on the result).
|
622
|
+
* @overload log(x, rnd = :nearest)
|
623
|
+
* @param x [Float]
|
624
|
+
* @param rnd [Symbol] :nearest, :down, :up, :zero or :away
|
625
|
+
*/
|
626
|
+
static VALUE crmf_float_log(int argc, VALUE *argv, VALUE self)
|
627
|
+
{
|
628
|
+
VALUE x = Qnil, rnd = Qnil;
|
629
|
+
mpfr_rnd_t rndt = MPFR_RNDN;
|
630
|
+
rb_scan_args(argc, argv, "11", &x, &rnd);
|
631
|
+
if (rnd != Qnil)
|
632
|
+
rndt = crmf_sym_to_rnd(rnd);
|
633
|
+
MPFR_DECL_INIT(mpfrx, 53);
|
634
|
+
crmf_rbfloat_to_mpfr53(x, mpfrx);
|
635
|
+
int t = mpfr_log(mpfrx, mpfrx, rndt);
|
636
|
+
mpfr_subnormalize(mpfrx, t, rndt);
|
637
|
+
double d = mpfr_get_d(mpfrx, rndt);
|
638
|
+
return DBL2NUM(d);
|
639
|
+
}
|
640
|
+
|
641
|
+
|
642
|
+
/* Returns the logarithm base 2 of _x_, rounded in the direction _rnd_.
|
643
|
+
* Returns +0 if _x_ is 1 (in all rounding modes), for consistency with the ISO C99 and IEEE 754-2008 standards.
|
644
|
+
* Returns -Inf if _x_ is ±0 (i.e., the sign of the zero has no influence on the result).
|
645
|
+
* @overload log2(x, rnd = :nearest)
|
646
|
+
* @param x [Float]
|
647
|
+
* @param rnd [Symbol] :nearest, :down, :up, :zero or :away
|
648
|
+
*/
|
649
|
+
static VALUE crmf_float_log2(int argc, VALUE *argv, VALUE self)
|
650
|
+
{
|
651
|
+
VALUE x = Qnil, rnd = Qnil;
|
652
|
+
mpfr_rnd_t rndt = MPFR_RNDN;
|
653
|
+
rb_scan_args(argc, argv, "11", &x, &rnd);
|
654
|
+
if (rnd != Qnil)
|
655
|
+
rndt = crmf_sym_to_rnd(rnd);
|
656
|
+
MPFR_DECL_INIT(mpfrx, 53);
|
657
|
+
crmf_rbfloat_to_mpfr53(x, mpfrx);
|
658
|
+
int t = mpfr_log2(mpfrx, mpfrx, rndt);
|
659
|
+
mpfr_subnormalize(mpfrx, t, rndt);
|
660
|
+
double d = mpfr_get_d(mpfrx, rndt);
|
661
|
+
return DBL2NUM(d);
|
662
|
+
}
|
663
|
+
|
664
|
+
|
665
|
+
/* Returns the logarithm base 10 of _x_, rounded in the direction _rnd_.
|
666
|
+
* Returns +0 if _x_ is 1 (in all rounding modes), for consistency with the ISO C99 and IEEE 754-2008 standards.
|
667
|
+
* Returns -Inf if _x_ is ±0 (i.e., the sign of the zero has no influence on the result).
|
668
|
+
* @overload log10(x, rnd = :nearest)
|
669
|
+
* @param x [Float]
|
670
|
+
* @param rnd [Symbol] :nearest, :down, :up, :zero or :away
|
671
|
+
*/
|
672
|
+
static VALUE crmf_float_log10(int argc, VALUE *argv, VALUE self)
|
673
|
+
{
|
674
|
+
VALUE x = Qnil, rnd = Qnil;
|
675
|
+
mpfr_rnd_t rndt = MPFR_RNDN;
|
676
|
+
rb_scan_args(argc, argv, "11", &x, &rnd);
|
677
|
+
if (rnd != Qnil)
|
678
|
+
rndt = crmf_sym_to_rnd(rnd);
|
679
|
+
MPFR_DECL_INIT(mpfrx, 53);
|
680
|
+
crmf_rbfloat_to_mpfr53(x, mpfrx);
|
681
|
+
int t = mpfr_log10(mpfrx, mpfrx, rndt);
|
682
|
+
mpfr_subnormalize(mpfrx, t, rndt);
|
683
|
+
double d = mpfr_get_d(mpfrx, rndt);
|
684
|
+
return DBL2NUM(d);
|
685
|
+
}
|
686
|
+
|
687
|
+
|
688
|
+
/* Returns the natural logarithm of 1 + _x_, rounded in the direction _rnd_.
|
689
|
+
* Returns +0 if _x_ is -1.
|
690
|
+
* @overload log1p(x, rnd = :nearest)
|
691
|
+
* @param x [Float]
|
692
|
+
* @param rnd [Symbol] :nearest, :down, :up, :zero or :away
|
693
|
+
*/
|
694
|
+
static VALUE crmf_float_log1p(int argc, VALUE *argv, VALUE self)
|
695
|
+
{
|
696
|
+
VALUE x = Qnil, rnd = Qnil;
|
697
|
+
mpfr_rnd_t rndt = MPFR_RNDN;
|
698
|
+
rb_scan_args(argc, argv, "11", &x, &rnd);
|
699
|
+
if (rnd != Qnil)
|
700
|
+
rndt = crmf_sym_to_rnd(rnd);
|
701
|
+
MPFR_DECL_INIT(mpfrx, 53);
|
702
|
+
crmf_rbfloat_to_mpfr53(x, mpfrx);
|
703
|
+
int t = mpfr_log1p(mpfrx, mpfrx, rndt);
|
704
|
+
mpfr_subnormalize(mpfrx, t, rndt);
|
705
|
+
double d = mpfr_get_d(mpfrx, rndt);
|
706
|
+
return DBL2NUM(d);
|
707
|
+
}
|
708
|
+
|
709
|
+
|
710
|
+
/* Returns the exponential of _x_, rounded in the direction _rnd_.
|
711
|
+
* @overload exp(x, rnd = :nearest)
|
712
|
+
* @param x [Float]
|
713
|
+
* @param rnd [Symbol] :nearest, :down, :up, :zero or :away
|
714
|
+
*/
|
715
|
+
static VALUE crmf_float_exp(int argc, VALUE *argv, VALUE self)
|
716
|
+
{
|
717
|
+
VALUE x = Qnil, rnd = Qnil;
|
718
|
+
mpfr_rnd_t rndt = MPFR_RNDN;
|
719
|
+
rb_scan_args(argc, argv, "11", &x, &rnd);
|
720
|
+
if (rnd != Qnil)
|
721
|
+
rndt = crmf_sym_to_rnd(rnd);
|
722
|
+
MPFR_DECL_INIT(mpfrx, 53);
|
723
|
+
crmf_rbfloat_to_mpfr53(x, mpfrx);
|
724
|
+
int t = mpfr_exp(mpfrx, mpfrx, rndt);
|
725
|
+
mpfr_subnormalize(mpfrx, t, rndt);
|
726
|
+
double d = mpfr_get_d(mpfrx, rndt);
|
727
|
+
return DBL2NUM(d);
|
728
|
+
}
|
729
|
+
|
730
|
+
|
731
|
+
/* Returns the 2 power of _x_, rounded in the direction _rnd_.
|
732
|
+
* @overload exp2(x, rnd = :nearest)
|
733
|
+
* @param x [Float]
|
734
|
+
* @param rnd [Symbol] :nearest, :down, :up, :zero or :away
|
735
|
+
*/
|
736
|
+
static VALUE crmf_float_exp2(int argc, VALUE *argv, VALUE self)
|
737
|
+
{
|
738
|
+
VALUE x = Qnil, rnd = Qnil;
|
739
|
+
mpfr_rnd_t rndt = MPFR_RNDN;
|
740
|
+
rb_scan_args(argc, argv, "11", &x, &rnd);
|
741
|
+
if (rnd != Qnil)
|
742
|
+
rndt = crmf_sym_to_rnd(rnd);
|
743
|
+
MPFR_DECL_INIT(mpfrx, 53);
|
744
|
+
crmf_rbfloat_to_mpfr53(x, mpfrx);
|
745
|
+
int t = mpfr_exp2(mpfrx, mpfrx, rndt);
|
746
|
+
mpfr_subnormalize(mpfrx, t, rndt);
|
747
|
+
double d = mpfr_get_d(mpfrx, rndt);
|
748
|
+
return DBL2NUM(d);
|
749
|
+
}
|
750
|
+
|
751
|
+
|
752
|
+
/* Returns the 10 power of _x_, rounded in the direction _rnd_.
|
753
|
+
* @overload exp10(x, rnd = :nearest)
|
754
|
+
* @param x [Float]
|
755
|
+
* @param rnd [Symbol] :nearest, :down, :up, :zero or :away
|
756
|
+
*/
|
757
|
+
static VALUE crmf_float_exp10(int argc, VALUE *argv, VALUE self)
|
758
|
+
{
|
759
|
+
VALUE x = Qnil, rnd = Qnil;
|
760
|
+
mpfr_rnd_t rndt = MPFR_RNDN;
|
761
|
+
rb_scan_args(argc, argv, "11", &x, &rnd);
|
762
|
+
if (rnd != Qnil)
|
763
|
+
rndt = crmf_sym_to_rnd(rnd);
|
764
|
+
MPFR_DECL_INIT(mpfrx, 53);
|
765
|
+
crmf_rbfloat_to_mpfr53(x, mpfrx);
|
766
|
+
int t = mpfr_exp10(mpfrx, mpfrx, rndt);
|
767
|
+
mpfr_subnormalize(mpfrx, t, rndt);
|
768
|
+
double d = mpfr_get_d(mpfrx, rndt);
|
769
|
+
return DBL2NUM(d);
|
770
|
+
}
|
771
|
+
|
772
|
+
|
773
|
+
/* Returns the exp(_x_) - 1, rounded in the direction _rnd_.
|
774
|
+
* @overload expm1(x, rnd = :nearest)
|
775
|
+
* @param x [Float]
|
776
|
+
* @param rnd [Symbol] :nearest, :down, :up, :zero or :away
|
777
|
+
*/
|
778
|
+
static VALUE crmf_float_expm1(int argc, VALUE *argv, VALUE self)
|
779
|
+
{
|
780
|
+
VALUE x = Qnil, rnd = Qnil;
|
781
|
+
mpfr_rnd_t rndt = MPFR_RNDN;
|
782
|
+
rb_scan_args(argc, argv, "11", &x, &rnd);
|
783
|
+
if (rnd != Qnil)
|
784
|
+
rndt = crmf_sym_to_rnd(rnd);
|
785
|
+
MPFR_DECL_INIT(mpfrx, 53);
|
786
|
+
crmf_rbfloat_to_mpfr53(x, mpfrx);
|
787
|
+
int t = mpfr_expm1(mpfrx, mpfrx, rndt);
|
788
|
+
mpfr_subnormalize(mpfrx, t, rndt);
|
789
|
+
double d = mpfr_get_d(mpfrx, rndt);
|
790
|
+
return DBL2NUM(d);
|
791
|
+
}
|
792
|
+
|
793
|
+
|
794
|
+
/* Returns _x_ raised to _y_, rounded in the direction _rnd_.
|
795
|
+
*
|
796
|
+
* Special values are handled as described in the ISO C99 and IEEE 754-2008 standards for the pow function:
|
797
|
+
* - pow(±0, y) returns plus or minus infinity for y a negative odd integer.
|
798
|
+
* - pow(±0, y) returns plus infinity for y negative and not an odd integer.
|
799
|
+
* - pow(±0, y) returns plus or minus zero for y a positive odd integer.
|
800
|
+
* - pow(±0, y) returns plus zero for y positive and not an odd integer.
|
801
|
+
* - pow(-1, ±Inf) returns 1.
|
802
|
+
* - pow(+1, y) returns 1 for any y, even a NaN.
|
803
|
+
* - pow(x, ±0) returns 1 for any x, even a NaN.
|
804
|
+
* - pow(x, y) returns NaN for finite negative x and finite non-integer y.
|
805
|
+
* - pow(x, -Inf) returns plus infinity for 0 < abs(x) < 1, and plus zero for abs(x) > 1.
|
806
|
+
* - pow(x, +Inf) returns plus zero for 0 < abs(x) < 1, and plus infinity for abs(x) > 1.
|
807
|
+
* - pow(-Inf, y) returns minus zero for y a negative odd integer.
|
808
|
+
* - pow(-Inf, y) returns plus zero for y negative and not an odd integer.
|
809
|
+
* - pow(-Inf, y) returns minus infinity for y a positive odd integer.
|
810
|
+
* - pow(-Inf, y) returns plus infinity for y positive and not an odd integer.
|
811
|
+
* - pow(+Inf, y) returns plus zero for y negative, and plus infinity for y positive.
|
812
|
+
* @overload pow(x, y, rnd = :nearest)
|
813
|
+
* @param x [Float]
|
814
|
+
* @param y [Float]
|
815
|
+
* @param rnd [Symbol] :nearest, :down, :up, :zero or :away
|
816
|
+
*/
|
817
|
+
static VALUE crmf_float_pow(int argc, VALUE *argv, VALUE self)
|
818
|
+
{
|
819
|
+
VALUE x = Qnil, y = Qnil, rnd = Qnil;
|
820
|
+
mpfr_rnd_t rndt = MPFR_RNDN;
|
821
|
+
rb_scan_args(argc, argv, "21", &x, &y, &rnd);
|
822
|
+
if (rnd != Qnil)
|
823
|
+
rndt = crmf_sym_to_rnd(rnd);
|
824
|
+
MPFR_DECL_INIT(mpfrx, 53);
|
825
|
+
MPFR_DECL_INIT(mpfry, 53);
|
826
|
+
crmf_rbfloat_to_mpfr53(x, mpfrx);
|
827
|
+
crmf_rbfloat_to_mpfr53(y, mpfry);
|
828
|
+
int t = mpfr_pow(mpfrx, mpfrx, mpfry, rndt);
|
829
|
+
mpfr_subnormalize(mpfrx, t, rndt);
|
830
|
+
double d = mpfr_get_d(mpfrx, rndt);
|
831
|
+
return DBL2NUM(d);
|
832
|
+
}
|
833
|
+
|
834
|
+
|
835
|
+
/* Returns _x_ raised to the integer power _n_, rounded in the direction _rnd_.
|
836
|
+
*
|
837
|
+
* Special values are handled as described in the ISO C99 and IEEE 754-2008 standards for the pow function:
|
838
|
+
* - pow(±0, n) returns plus or minus infinity for _n_ a negative odd integer.
|
839
|
+
* - pow(±0, n) returns plus infinity for _n_ negative and not an odd integer.
|
840
|
+
* - pow(±0, n) returns plus or minus zero for _n_ a positive odd integer.
|
841
|
+
* - pow(±0, n) returns plus zero for _n_ positive and not an odd integer.
|
842
|
+
* - pow(+1, n) returns 1 for any _n_.
|
843
|
+
* - pow(x, 0) returns 1 for any _x_, even a NaN.
|
844
|
+
* - pow(-Inf, n) returns minus zero for _n_ negative and odd.
|
845
|
+
* - pow(-Inf, n) returns plus zero for _n_ negative and even.
|
846
|
+
* - pow(-Inf, n) returns minus infinity for _n_ positive and odd.
|
847
|
+
* - pow(-Inf, n) returns plus infinity for _n_ positive and even.
|
848
|
+
* - pow(+Inf, n) returns plus zero for _n_ negative, and plus infinity for _n_ positive.
|
849
|
+
* @overload pown(x, n, rnd = :nearest)
|
850
|
+
* @param x [Float] base
|
851
|
+
* @param n [Integer] exponent
|
852
|
+
* @param rnd [Symbol] :nearest, :down, :up, :zero or :away
|
853
|
+
*/
|
854
|
+
static VALUE crmf_float_pown(int argc, VALUE *argv, VALUE self)
|
855
|
+
{
|
856
|
+
VALUE x = Qnil, n = Qnil, rnd = Qnil;
|
857
|
+
mpfr_rnd_t rndt = MPFR_RNDN;
|
858
|
+
rb_scan_args(argc, argv, "21", &x, &n, &rnd);
|
859
|
+
if (rnd != Qnil)
|
860
|
+
rndt = crmf_sym_to_rnd(rnd);
|
861
|
+
MPFR_DECL_INIT(mpfrx, 53);
|
862
|
+
crmf_rbfloat_to_mpfr53(x, mpfrx);
|
863
|
+
if (!rb_integer_type_p(n))
|
864
|
+
rb_raise(rb_eTypeError, "expecting an integer as second argument, not a %s", rb_obj_classname(n));
|
865
|
+
long int nn = NUM2LL(n);
|
866
|
+
int t = mpfr_pow_si(mpfrx, mpfrx, nn, rndt);
|
867
|
+
mpfr_subnormalize(mpfrx, t, rndt);
|
868
|
+
double d = mpfr_get_d(mpfrx, rndt);
|
869
|
+
return DBL2NUM(d);
|
870
|
+
}
|
871
|
+
|
872
|
+
|
873
|
+
/* Returns the cosine of _x_, rounded in the direction _rnd_.
|
874
|
+
* @overload cos(x, rnd = :nearest)
|
875
|
+
* @param x [Float]
|
876
|
+
* @param rnd [Symbol] :nearest, :down, :up, :zero or :away
|
877
|
+
*/
|
878
|
+
static VALUE crmf_float_cos(int argc, VALUE *argv, VALUE self)
|
879
|
+
{
|
880
|
+
VALUE x = Qnil, rnd = Qnil;
|
881
|
+
mpfr_rnd_t rndt = MPFR_RNDN;
|
882
|
+
rb_scan_args(argc, argv, "11", &x, &rnd);
|
883
|
+
if (rnd != Qnil)
|
884
|
+
rndt = crmf_sym_to_rnd(rnd);
|
885
|
+
MPFR_DECL_INIT(mpfrx, 53);
|
886
|
+
crmf_rbfloat_to_mpfr53(x, mpfrx);
|
887
|
+
int t = mpfr_cos(mpfrx, mpfrx, rndt);
|
888
|
+
mpfr_subnormalize(mpfrx, t, rndt);
|
889
|
+
double d = mpfr_get_d(mpfrx, rndt);
|
890
|
+
return DBL2NUM(d);
|
891
|
+
}
|
892
|
+
|
893
|
+
|
894
|
+
/* Returns the sine of _x_, rounded in the direction _rnd_.
|
895
|
+
* @overload sin(x, rnd = :nearest)
|
896
|
+
* @param x [Float]
|
897
|
+
* @param rnd [Symbol] :nearest, :down, :up, :zero or :away
|
898
|
+
*/
|
899
|
+
static VALUE crmf_float_sin(int argc, VALUE *argv, VALUE self)
|
900
|
+
{
|
901
|
+
VALUE x = Qnil, rnd = Qnil;
|
902
|
+
mpfr_rnd_t rndt = MPFR_RNDN;
|
903
|
+
rb_scan_args(argc, argv, "11", &x, &rnd);
|
904
|
+
if (rnd != Qnil)
|
905
|
+
rndt = crmf_sym_to_rnd(rnd);
|
906
|
+
MPFR_DECL_INIT(mpfrx, 53);
|
907
|
+
crmf_rbfloat_to_mpfr53(x, mpfrx);
|
908
|
+
int t = mpfr_sin(mpfrx, mpfrx, rndt);
|
909
|
+
mpfr_subnormalize(mpfrx, t, rndt);
|
910
|
+
double d = mpfr_get_d(mpfrx, rndt);
|
911
|
+
return DBL2NUM(d);
|
912
|
+
}
|
913
|
+
|
914
|
+
|
915
|
+
/* Returns the tangent of _x_, rounded in the direction _rnd_.
|
916
|
+
* @overload tan(x, rnd = :nearest)
|
917
|
+
* @param x [Float]
|
918
|
+
* @param rnd [Symbol] :nearest, :down, :up, :zero or :away
|
919
|
+
*/
|
920
|
+
static VALUE crmf_float_tan(int argc, VALUE *argv, VALUE self)
|
921
|
+
{
|
922
|
+
VALUE x = Qnil, rnd = Qnil;
|
923
|
+
mpfr_rnd_t rndt = MPFR_RNDN;
|
924
|
+
rb_scan_args(argc, argv, "11", &x, &rnd);
|
925
|
+
if (rnd != Qnil)
|
926
|
+
rndt = crmf_sym_to_rnd(rnd);
|
927
|
+
MPFR_DECL_INIT(mpfrx, 53);
|
928
|
+
crmf_rbfloat_to_mpfr53(x, mpfrx);
|
929
|
+
int t = mpfr_tan(mpfrx, mpfrx, rndt);
|
930
|
+
mpfr_subnormalize(mpfrx, t, rndt);
|
931
|
+
double d = mpfr_get_d(mpfrx, rndt);
|
932
|
+
return DBL2NUM(d);
|
933
|
+
}
|
934
|
+
|
935
|
+
|
936
|
+
/* Returns the arc-cosine of _x_, rounded in the direction _rnd_.
|
937
|
+
*
|
938
|
+
* Note that since `Float.acos(-1.0)` returns the floating-point number
|
939
|
+
* closest to _pi_ according to the given rounding mode,
|
940
|
+
* this number might not be in the output range 0 <= _acos(x)_ < _pi_ of the arc-cosine function;
|
941
|
+
* still, the result lies in the image of the output range by the rounding function.
|
942
|
+
* @overload acos(x, rnd = :nearest)
|
943
|
+
* @param x [Float]
|
944
|
+
* @param rnd [Symbol] :nearest, :down, :up, :zero or :away
|
945
|
+
*/
|
946
|
+
static VALUE crmf_float_acos(int argc, VALUE *argv, VALUE self)
|
947
|
+
{
|
948
|
+
VALUE x = Qnil, rnd = Qnil;
|
949
|
+
mpfr_rnd_t rndt = MPFR_RNDN;
|
950
|
+
rb_scan_args(argc, argv, "11", &x, &rnd);
|
951
|
+
if (rnd != Qnil)
|
952
|
+
rndt = crmf_sym_to_rnd(rnd);
|
953
|
+
MPFR_DECL_INIT(mpfrx, 53);
|
954
|
+
crmf_rbfloat_to_mpfr53(x, mpfrx);
|
955
|
+
int t = mpfr_acos(mpfrx, mpfrx, rndt);
|
956
|
+
mpfr_subnormalize(mpfrx, t, rndt);
|
957
|
+
double d = mpfr_get_d(mpfrx, rndt);
|
958
|
+
return DBL2NUM(d);
|
959
|
+
}
|
960
|
+
|
961
|
+
|
962
|
+
/* Returns the arc-sine of _x_, rounded in the direction _rnd_.
|
963
|
+
*
|
964
|
+
* Note that since `Float.asin(1)` returns the floating-point number
|
965
|
+
* closest to _pi_/2 according to the given rounding mode,
|
966
|
+
* this number might not be in the output range -_pi_/2 <= _asin(x)_ < _pi_/2 of the arc-sine function;
|
967
|
+
* still, the result lies in the image of the output range by the rounding function.
|
968
|
+
* The same holds for asin(-1).
|
969
|
+
* @overload asin(x, rnd = :nearest)
|
970
|
+
* @param x [Float]
|
971
|
+
* @param rnd [Symbol] :nearest, :down, :up, :zero or :away
|
972
|
+
*/
|
973
|
+
static VALUE crmf_float_asin(int argc, VALUE *argv, VALUE self)
|
974
|
+
{
|
975
|
+
VALUE x = Qnil, rnd = Qnil;
|
976
|
+
mpfr_rnd_t rndt = MPFR_RNDN;
|
977
|
+
rb_scan_args(argc, argv, "11", &x, &rnd);
|
978
|
+
if (rnd != Qnil)
|
979
|
+
rndt = crmf_sym_to_rnd(rnd);
|
980
|
+
MPFR_DECL_INIT(mpfrx, 53);
|
981
|
+
crmf_rbfloat_to_mpfr53(x, mpfrx);
|
982
|
+
int t = mpfr_asin(mpfrx, mpfrx, rndt);
|
983
|
+
mpfr_subnormalize(mpfrx, t, rndt);
|
984
|
+
double d = mpfr_get_d(mpfrx, rndt);
|
985
|
+
return DBL2NUM(d);
|
986
|
+
}
|
987
|
+
|
988
|
+
|
989
|
+
/* Returns the arc-tangent of _x_, rounded in the direction _rnd_.
|
990
|
+
*
|
991
|
+
* Note that since `Float.atan(Float::INFINITY)` returns the floating-point number
|
992
|
+
* closest to _pi_/2 according to the given rounding mode,
|
993
|
+
* this number might not be in the output range -_pi_/2 <= _atan(x)_ < _pi_/2 of the arc-tangent function;
|
994
|
+
* still, the result lies in the image of the output range by the rounding function.
|
995
|
+
* The same holds for atan(-Inf).
|
996
|
+
* @overload atan(x, rnd = :nearest)
|
997
|
+
* @param x [Float]
|
998
|
+
* @param rnd [Symbol] :nearest, :down, :up, :zero or :away
|
999
|
+
*/
|
1000
|
+
static VALUE crmf_float_atan(int argc, VALUE *argv, VALUE self)
|
1001
|
+
{
|
1002
|
+
VALUE x = Qnil, rnd = Qnil;
|
1003
|
+
mpfr_rnd_t rndt = MPFR_RNDN;
|
1004
|
+
rb_scan_args(argc, argv, "11", &x, &rnd);
|
1005
|
+
if (rnd != Qnil)
|
1006
|
+
rndt = crmf_sym_to_rnd(rnd);
|
1007
|
+
MPFR_DECL_INIT(mpfrx, 53);
|
1008
|
+
crmf_rbfloat_to_mpfr53(x, mpfrx);
|
1009
|
+
int t = mpfr_atan(mpfrx, mpfrx, rndt);
|
1010
|
+
mpfr_subnormalize(mpfrx, t, rndt);
|
1011
|
+
double d = mpfr_get_d(mpfrx, rndt);
|
1012
|
+
return DBL2NUM(d);
|
1013
|
+
}
|
1014
|
+
|
1015
|
+
|
1016
|
+
/* Returns the arc-tangent2 of _y_ and _x_, rounded in the direction _rnd_.
|
1017
|
+
*
|
1018
|
+
* - if _x_ > 0, atan2(_y_, _x_) = atan(_y_/_x_);
|
1019
|
+
* - if _x_ < 0, atan2(_y_, _x_) = sign(_y_)*(_Pi_ - atan(abs(_y_/_x_))), thus a number from -Pi to Pi.
|
1020
|
+
*
|
1021
|
+
* As for {atan}, in case the exact mathematical result is +Pi or -Pi,
|
1022
|
+
* its rounded result might be outside the function output range.
|
1023
|
+
*
|
1024
|
+
* `Float.atan2(y, 0)` does not raise any floating-point exception.
|
1025
|
+
* Special values are handled as described in the ISO C99 and IEEE 754-2008 standards for the atan2 function:
|
1026
|
+
* - atan2(+0, -0) returns +Pi.
|
1027
|
+
* - atan2(-0, -0) returns -Pi.
|
1028
|
+
* - atan2(+0, +0) returns +0.
|
1029
|
+
* - atan2(-0, +0) returns -0.
|
1030
|
+
* - atan2(+0, x) returns +Pi for x < 0.
|
1031
|
+
* - atan2(-0, x) returns -Pi for x < 0.
|
1032
|
+
* - atan2(+0, x) returns +0 for x > 0.
|
1033
|
+
* - atan2(-0, x) returns -0 for x > 0.
|
1034
|
+
* - atan2(y, 0) returns -Pi/2 for y < 0.
|
1035
|
+
* - atan2(y, 0) returns +Pi/2 for y > 0.
|
1036
|
+
* - atan2(+Inf, -Inf) returns +3*Pi/4.
|
1037
|
+
* - atan2(-Inf, -Inf) returns -3*Pi/4.
|
1038
|
+
* - atan2(+Inf, +Inf) returns +Pi/4.
|
1039
|
+
* - atan2(-Inf, +Inf) returns -Pi/4.
|
1040
|
+
* - atan2(+Inf, x) returns +Pi/2 for finite x.
|
1041
|
+
* - atan2(-Inf, x) returns -Pi/2 for finite x.
|
1042
|
+
* - atan2(y, -Inf) returns +Pi for finite y > 0.
|
1043
|
+
* - atan2(y, -Inf) returns -Pi for finite y < 0.
|
1044
|
+
* - atan2(y, +Inf) returns +0 for finite y > 0.
|
1045
|
+
* - atan2(y, +Inf) returns -0 for finite y < 0.
|
1046
|
+
*
|
1047
|
+
* @overload atan2(y, x, rnd = :nearest)
|
1048
|
+
* @param y [Float]
|
1049
|
+
* @param x [Float]
|
1050
|
+
* @param rnd [Symbol] :nearest, :down, :up, :zero or :away
|
1051
|
+
*/
|
1052
|
+
static VALUE crmf_float_atan2(int argc, VALUE *argv, VALUE self)
|
1053
|
+
{
|
1054
|
+
VALUE y = Qnil, x = Qnil, rnd = Qnil;
|
1055
|
+
mpfr_rnd_t rndt = MPFR_RNDN;
|
1056
|
+
rb_scan_args(argc, argv, "21", &y, &x, &rnd);
|
1057
|
+
if (rnd != Qnil)
|
1058
|
+
rndt = crmf_sym_to_rnd(rnd);
|
1059
|
+
MPFR_DECL_INIT(mpfry, 53);
|
1060
|
+
crmf_rbfloat_to_mpfr53(y, mpfry);
|
1061
|
+
MPFR_DECL_INIT(mpfrx, 53);
|
1062
|
+
crmf_rbfloat_to_mpfr53(x, mpfrx);
|
1063
|
+
int t = mpfr_atan2(mpfrx, mpfry, mpfrx, rndt);
|
1064
|
+
mpfr_subnormalize(mpfrx, t, rndt);
|
1065
|
+
double d = mpfr_get_d(mpfrx, rndt);
|
1066
|
+
return DBL2NUM(d);
|
1067
|
+
}
|
1068
|
+
|
1069
|
+
|
1070
|
+
/* Returns the hyperbolic cosine of _x_, rounded in the direction _rnd_.
|
1071
|
+
* @overload cosh(x, rnd = :nearest)
|
1072
|
+
* @param x [Float]
|
1073
|
+
* @param rnd [Symbol] :nearest, :down, :up, :zero or :away
|
1074
|
+
*/
|
1075
|
+
static VALUE crmf_float_cosh(int argc, VALUE *argv, VALUE self)
|
1076
|
+
{
|
1077
|
+
VALUE x = Qnil, rnd = Qnil;
|
1078
|
+
mpfr_rnd_t rndt = MPFR_RNDN;
|
1079
|
+
rb_scan_args(argc, argv, "11", &x, &rnd);
|
1080
|
+
if (rnd != Qnil)
|
1081
|
+
rndt = crmf_sym_to_rnd(rnd);
|
1082
|
+
MPFR_DECL_INIT(mpfrx, 53);
|
1083
|
+
crmf_rbfloat_to_mpfr53(x, mpfrx);
|
1084
|
+
int t = mpfr_cosh(mpfrx, mpfrx, rndt);
|
1085
|
+
mpfr_subnormalize(mpfrx, t, rndt);
|
1086
|
+
double d = mpfr_get_d(mpfrx, rndt);
|
1087
|
+
return DBL2NUM(d);
|
1088
|
+
}
|
1089
|
+
|
1090
|
+
|
1091
|
+
/* Returns the hyperbolic sine of _x_, rounded in the direction _rnd_.
|
1092
|
+
* @overload sinh(x, rnd = :nearest)
|
1093
|
+
* @param x [Float]
|
1094
|
+
* @param rnd [Symbol] :nearest, :down, :up, :zero or :away
|
1095
|
+
*/
|
1096
|
+
static VALUE crmf_float_sinh(int argc, VALUE *argv, VALUE self)
|
1097
|
+
{
|
1098
|
+
VALUE x = Qnil, rnd = Qnil;
|
1099
|
+
mpfr_rnd_t rndt = MPFR_RNDN;
|
1100
|
+
rb_scan_args(argc, argv, "11", &x, &rnd);
|
1101
|
+
if (rnd != Qnil)
|
1102
|
+
rndt = crmf_sym_to_rnd(rnd);
|
1103
|
+
MPFR_DECL_INIT(mpfrx, 53);
|
1104
|
+
crmf_rbfloat_to_mpfr53(x, mpfrx);
|
1105
|
+
int t = mpfr_sinh(mpfrx, mpfrx, rndt);
|
1106
|
+
mpfr_subnormalize(mpfrx, t, rndt);
|
1107
|
+
double d = mpfr_get_d(mpfrx, rndt);
|
1108
|
+
return DBL2NUM(d);
|
1109
|
+
}
|
1110
|
+
|
1111
|
+
|
1112
|
+
/* Returns the hyperbolic tangent of _x_, rounded in the direction _rnd_.
|
1113
|
+
* @overload tanh(x, rnd = :nearest)
|
1114
|
+
* @param x [Float]
|
1115
|
+
* @param rnd [Symbol] :nearest, :down, :up, :zero or :away
|
1116
|
+
*/
|
1117
|
+
static VALUE crmf_float_tanh(int argc, VALUE *argv, VALUE self)
|
1118
|
+
{
|
1119
|
+
VALUE x = Qnil, rnd = Qnil;
|
1120
|
+
mpfr_rnd_t rndt = MPFR_RNDN;
|
1121
|
+
rb_scan_args(argc, argv, "11", &x, &rnd);
|
1122
|
+
if (rnd != Qnil)
|
1123
|
+
rndt = crmf_sym_to_rnd(rnd);
|
1124
|
+
MPFR_DECL_INIT(mpfrx, 53);
|
1125
|
+
crmf_rbfloat_to_mpfr53(x, mpfrx);
|
1126
|
+
int t = mpfr_tanh(mpfrx, mpfrx, rndt);
|
1127
|
+
mpfr_subnormalize(mpfrx, t, rndt);
|
1128
|
+
double d = mpfr_get_d(mpfrx, rndt);
|
1129
|
+
return DBL2NUM(d);
|
1130
|
+
}
|
1131
|
+
|
1132
|
+
|
1133
|
+
/* Returns the inverse hyperbolic cosine of _x_, rounded in the direction _rnd_.
|
1134
|
+
* @overload acosh(x, rnd = :nearest)
|
1135
|
+
* @param x [Float]
|
1136
|
+
* @param rnd [Symbol] :nearest, :down, :up, :zero or :away
|
1137
|
+
*/
|
1138
|
+
static VALUE crmf_float_acosh(int argc, VALUE *argv, VALUE self)
|
1139
|
+
{
|
1140
|
+
VALUE x = Qnil, rnd = Qnil;
|
1141
|
+
mpfr_rnd_t rndt = MPFR_RNDN;
|
1142
|
+
rb_scan_args(argc, argv, "11", &x, &rnd);
|
1143
|
+
if (rnd != Qnil)
|
1144
|
+
rndt = crmf_sym_to_rnd(rnd);
|
1145
|
+
MPFR_DECL_INIT(mpfrx, 53);
|
1146
|
+
crmf_rbfloat_to_mpfr53(x, mpfrx);
|
1147
|
+
int t = mpfr_acosh(mpfrx, mpfrx, rndt);
|
1148
|
+
mpfr_subnormalize(mpfrx, t, rndt);
|
1149
|
+
double d = mpfr_get_d(mpfrx, rndt);
|
1150
|
+
return DBL2NUM(d);
|
1151
|
+
}
|
1152
|
+
|
1153
|
+
|
1154
|
+
/* Returns the inverse hyperbolic sine of _x_, rounded in the direction _rnd_.
|
1155
|
+
* @overload asinh(x, rnd = :nearest)
|
1156
|
+
* @param x [Float]
|
1157
|
+
* @param rnd [Symbol] :nearest, :down, :up, :zero or :away
|
1158
|
+
*/
|
1159
|
+
static VALUE crmf_float_asinh(int argc, VALUE *argv, VALUE self)
|
1160
|
+
{
|
1161
|
+
VALUE x = Qnil, rnd = Qnil;
|
1162
|
+
mpfr_rnd_t rndt = MPFR_RNDN;
|
1163
|
+
rb_scan_args(argc, argv, "11", &x, &rnd);
|
1164
|
+
if (rnd != Qnil)
|
1165
|
+
rndt = crmf_sym_to_rnd(rnd);
|
1166
|
+
MPFR_DECL_INIT(mpfrx, 53);
|
1167
|
+
crmf_rbfloat_to_mpfr53(x, mpfrx);
|
1168
|
+
int t = mpfr_asinh(mpfrx, mpfrx, rndt);
|
1169
|
+
mpfr_subnormalize(mpfrx, t, rndt);
|
1170
|
+
double d = mpfr_get_d(mpfrx, rndt);
|
1171
|
+
return DBL2NUM(d);
|
1172
|
+
}
|
1173
|
+
|
1174
|
+
|
1175
|
+
/* Returns the inverse hyperbolic tangent of _x_, rounded in the direction _rnd_.
|
1176
|
+
* @overload atanh(x, rnd = :nearest)
|
1177
|
+
* @param x [Float]
|
1178
|
+
* @param rnd [Symbol] :nearest, :down, :up, :zero or :away
|
1179
|
+
*/
|
1180
|
+
static VALUE crmf_float_atanh(int argc, VALUE *argv, VALUE self)
|
1181
|
+
{
|
1182
|
+
VALUE x = Qnil, rnd = Qnil;
|
1183
|
+
mpfr_rnd_t rndt = MPFR_RNDN;
|
1184
|
+
rb_scan_args(argc, argv, "11", &x, &rnd);
|
1185
|
+
if (rnd != Qnil)
|
1186
|
+
rndt = crmf_sym_to_rnd(rnd);
|
1187
|
+
MPFR_DECL_INIT(mpfrx, 53);
|
1188
|
+
crmf_rbfloat_to_mpfr53(x, mpfrx);
|
1189
|
+
int t = mpfr_atanh(mpfrx, mpfrx, rndt);
|
1190
|
+
mpfr_subnormalize(mpfrx, t, rndt);
|
1191
|
+
double d = mpfr_get_d(mpfrx, rndt);
|
1192
|
+
return DBL2NUM(d);
|
1193
|
+
}
|
1194
|
+
|
1195
|
+
|
1196
|
+
#define crmf_get_const_from_func(res, func, rnd) \
|
1197
|
+
do { \
|
1198
|
+
MPFR_DECL_INIT(mpfrc, 53); \
|
1199
|
+
int t; \
|
1200
|
+
t = func(mpfrc, rnd); \
|
1201
|
+
mpfr_subnormalize(mpfrc, t, rnd); \
|
1202
|
+
res = mpfr_get_d(mpfrc, rnd); \
|
1203
|
+
} while(0)
|
1204
|
+
|
1205
|
+
|
1206
|
+
|
1207
|
+
static VALUE crmf_exp_rn(VALUE self, VALUE x) {
|
1208
|
+
return DBL2NUM(exp_rn(NUM2DBL(x)));
|
1209
|
+
}
|
1210
|
+
|
1211
|
+
static VALUE crmf_exp_rd(VALUE self, VALUE x) {
|
1212
|
+
return DBL2NUM(exp_rd(NUM2DBL(x)));
|
1213
|
+
}
|
1214
|
+
|
1215
|
+
static VALUE crmf_exp_ru(VALUE self, VALUE x) {
|
1216
|
+
return DBL2NUM(exp_ru(NUM2DBL(x)));
|
1217
|
+
}
|
1218
|
+
|
1219
|
+
static VALUE crmf_exp_rz(VALUE self, VALUE x) {
|
1220
|
+
return DBL2NUM(exp_rz(NUM2DBL(x)));
|
1221
|
+
}
|
1222
|
+
|
1223
|
+
|
1224
|
+
static VALUE crmf_log_rn(VALUE self, VALUE x) {
|
1225
|
+
return DBL2NUM(log_rn(NUM2DBL(x)));
|
1226
|
+
}
|
1227
|
+
|
1228
|
+
static VALUE crmf_log_rd(VALUE self, VALUE x) {
|
1229
|
+
return DBL2NUM(log_rd(NUM2DBL(x)));
|
1230
|
+
}
|
1231
|
+
|
1232
|
+
static VALUE crmf_log_ru(VALUE self, VALUE x) {
|
1233
|
+
return DBL2NUM(log_ru(NUM2DBL(x)));
|
1234
|
+
}
|
1235
|
+
|
1236
|
+
static VALUE crmf_log_rz(VALUE self, VALUE x) {
|
1237
|
+
return DBL2NUM(log_rz(NUM2DBL(x)));
|
1238
|
+
}
|
1239
|
+
|
1240
|
+
|
1241
|
+
static VALUE crmf_log2_rn(VALUE self, VALUE x) {
|
1242
|
+
return DBL2NUM(log2_rn(NUM2DBL(x)));
|
1243
|
+
}
|
1244
|
+
|
1245
|
+
static VALUE crmf_log2_rd(VALUE self, VALUE x) {
|
1246
|
+
return DBL2NUM(log2_rd(NUM2DBL(x)));
|
1247
|
+
}
|
1248
|
+
|
1249
|
+
static VALUE crmf_log2_ru(VALUE self, VALUE x) {
|
1250
|
+
return DBL2NUM(log2_ru(NUM2DBL(x)));
|
1251
|
+
}
|
1252
|
+
|
1253
|
+
static VALUE crmf_log2_rz(VALUE self, VALUE x) {
|
1254
|
+
return DBL2NUM(log2_rz(NUM2DBL(x)));
|
1255
|
+
}
|
1256
|
+
|
1257
|
+
|
1258
|
+
static VALUE crmf_log10_rn(VALUE self, VALUE x) {
|
1259
|
+
return DBL2NUM(log10_rn(NUM2DBL(x)));
|
1260
|
+
}
|
1261
|
+
|
1262
|
+
static VALUE crmf_log10_rd(VALUE self, VALUE x) {
|
1263
|
+
return DBL2NUM(log10_rd(NUM2DBL(x)));
|
1264
|
+
}
|
1265
|
+
|
1266
|
+
static VALUE crmf_log10_ru(VALUE self, VALUE x) {
|
1267
|
+
return DBL2NUM(log10_ru(NUM2DBL(x)));
|
1268
|
+
}
|
1269
|
+
|
1270
|
+
static VALUE crmf_log10_rz(VALUE self, VALUE x) {
|
1271
|
+
return DBL2NUM(log10_rz(NUM2DBL(x)));
|
1272
|
+
}
|
1273
|
+
|
1274
|
+
|
1275
|
+
/* Returns exp(_x_) - 1, rounded to nearest */
|
1276
|
+
static VALUE crmf_expm1_rn(VALUE self, VALUE x) {
|
1277
|
+
return DBL2NUM(expm1_rn(NUM2DBL(x)));
|
1278
|
+
}
|
1279
|
+
|
1280
|
+
/* Returns exp(_x_) - 1, rounded down */
|
1281
|
+
static VALUE crmf_expm1_rd(VALUE self, VALUE x) {
|
1282
|
+
return DBL2NUM(expm1_rd(NUM2DBL(x)));
|
1283
|
+
}
|
1284
|
+
|
1285
|
+
/* Returns exp(_x_) - 1, rounded up */
|
1286
|
+
static VALUE crmf_expm1_ru(VALUE self, VALUE x) {
|
1287
|
+
return DBL2NUM(expm1_ru(NUM2DBL(x)));
|
1288
|
+
}
|
1289
|
+
|
1290
|
+
/* Returns exp(_x_) - 1, rounded toward zero */
|
1291
|
+
static VALUE crmf_expm1_rz(VALUE self, VALUE x) {
|
1292
|
+
return DBL2NUM(expm1_rz(NUM2DBL(x)));
|
1293
|
+
}
|
1294
|
+
|
1295
|
+
|
1296
|
+
/* Returns log(_x_ + 1), rounded to nearest */
|
1297
|
+
static VALUE crmf_log1p_rn(VALUE self, VALUE x) {
|
1298
|
+
return DBL2NUM(log1p_rn(NUM2DBL(x)));
|
1299
|
+
}
|
1300
|
+
|
1301
|
+
/* Returns log(_x_ + 1), rounded down */
|
1302
|
+
static VALUE crmf_log1p_rd(VALUE self, VALUE x) {
|
1303
|
+
return DBL2NUM(log1p_rd(NUM2DBL(x)));
|
1304
|
+
}
|
1305
|
+
|
1306
|
+
/* Returns log(_x_ + 1), rounded up */
|
1307
|
+
static VALUE crmf_log1p_ru(VALUE self, VALUE x) {
|
1308
|
+
return DBL2NUM(log1p_ru(NUM2DBL(x)));
|
1309
|
+
}
|
1310
|
+
|
1311
|
+
/* Returns log(_x_ + 1), rounded toward zero */
|
1312
|
+
static VALUE crmf_log1p_rz(VALUE self, VALUE x) {
|
1313
|
+
return DBL2NUM(log1p_rz(NUM2DBL(x)));
|
1314
|
+
}
|
1315
|
+
|
1316
|
+
|
1317
|
+
static VALUE crmf_cos_rn(VALUE self, VALUE x) {
|
1318
|
+
return DBL2NUM(cos_rn(NUM2DBL(x)));
|
1319
|
+
}
|
1320
|
+
|
1321
|
+
static VALUE crmf_cos_rd(VALUE self, VALUE x) {
|
1322
|
+
return DBL2NUM(cos_rd(NUM2DBL(x)));
|
1323
|
+
}
|
1324
|
+
|
1325
|
+
static VALUE crmf_cos_ru(VALUE self, VALUE x) {
|
1326
|
+
return DBL2NUM(cos_ru(NUM2DBL(x)));
|
1327
|
+
}
|
1328
|
+
|
1329
|
+
static VALUE crmf_cos_rz(VALUE self, VALUE x) {
|
1330
|
+
return DBL2NUM(cos_rz(NUM2DBL(x)));
|
1331
|
+
}
|
1332
|
+
|
1333
|
+
|
1334
|
+
static VALUE crmf_sin_rn(VALUE self, VALUE x) {
|
1335
|
+
return DBL2NUM(sin_rn(NUM2DBL(x)));
|
1336
|
+
}
|
1337
|
+
|
1338
|
+
static VALUE crmf_sin_rd(VALUE self, VALUE x) {
|
1339
|
+
return DBL2NUM(sin_rd(NUM2DBL(x)));
|
1340
|
+
}
|
1341
|
+
|
1342
|
+
static VALUE crmf_sin_ru(VALUE self, VALUE x) {
|
1343
|
+
return DBL2NUM(sin_ru(NUM2DBL(x)));
|
1344
|
+
}
|
1345
|
+
|
1346
|
+
static VALUE crmf_sin_rz(VALUE self, VALUE x) {
|
1347
|
+
return DBL2NUM(sin_rz(NUM2DBL(x)));
|
1348
|
+
}
|
1349
|
+
|
1350
|
+
|
1351
|
+
static VALUE crmf_tan_rn(VALUE self, VALUE x) {
|
1352
|
+
return DBL2NUM(tan_rn(NUM2DBL(x)));
|
1353
|
+
}
|
1354
|
+
|
1355
|
+
static VALUE crmf_tan_rd(VALUE self, VALUE x) {
|
1356
|
+
return DBL2NUM(tan_rd(NUM2DBL(x)));
|
1357
|
+
}
|
1358
|
+
|
1359
|
+
static VALUE crmf_tan_ru(VALUE self, VALUE x) {
|
1360
|
+
return DBL2NUM(tan_ru(NUM2DBL(x)));
|
1361
|
+
}
|
1362
|
+
|
1363
|
+
static VALUE crmf_tan_rz(VALUE self, VALUE x) {
|
1364
|
+
return DBL2NUM(tan_rz(NUM2DBL(x)));
|
1365
|
+
}
|
1366
|
+
|
1367
|
+
|
1368
|
+
static VALUE crmf_acos_rn(VALUE self, VALUE x) {
|
1369
|
+
return DBL2NUM(acos_rn(NUM2DBL(x)));
|
1370
|
+
}
|
1371
|
+
|
1372
|
+
static VALUE crmf_acos_rd(VALUE self, VALUE x) {
|
1373
|
+
return DBL2NUM(acos_rd(NUM2DBL(x)));
|
1374
|
+
}
|
1375
|
+
|
1376
|
+
static VALUE crmf_acos_ru(VALUE self, VALUE x) {
|
1377
|
+
return DBL2NUM(acos_ru(NUM2DBL(x)));
|
1378
|
+
}
|
1379
|
+
|
1380
|
+
static VALUE crmf_acos_rz(VALUE self, VALUE x) {
|
1381
|
+
return DBL2NUM(acos_rz(NUM2DBL(x)));
|
1382
|
+
}
|
1383
|
+
|
1384
|
+
|
1385
|
+
static VALUE crmf_asin_rn(VALUE self, VALUE x) {
|
1386
|
+
return DBL2NUM(asin_rn(NUM2DBL(x)));
|
1387
|
+
}
|
1388
|
+
|
1389
|
+
static VALUE crmf_asin_rd(VALUE self, VALUE x) {
|
1390
|
+
return DBL2NUM(asin_rd(NUM2DBL(x)));
|
1391
|
+
}
|
1392
|
+
|
1393
|
+
static VALUE crmf_asin_ru(VALUE self, VALUE x) {
|
1394
|
+
return DBL2NUM(asin_ru(NUM2DBL(x)));
|
1395
|
+
}
|
1396
|
+
|
1397
|
+
static VALUE crmf_asin_rz(VALUE self, VALUE x) {
|
1398
|
+
return DBL2NUM(asin_rz(NUM2DBL(x)));
|
1399
|
+
}
|
1400
|
+
|
1401
|
+
|
1402
|
+
static VALUE crmf_atan_rn(VALUE self, VALUE x) {
|
1403
|
+
return DBL2NUM(atan_rn(NUM2DBL(x)));
|
1404
|
+
}
|
1405
|
+
|
1406
|
+
static VALUE crmf_atan_rd(VALUE self, VALUE x) {
|
1407
|
+
return DBL2NUM(atan_rd(NUM2DBL(x)));
|
1408
|
+
}
|
1409
|
+
|
1410
|
+
static VALUE crmf_atan_ru(VALUE self, VALUE x) {
|
1411
|
+
return DBL2NUM(atan_ru(NUM2DBL(x)));
|
1412
|
+
}
|
1413
|
+
|
1414
|
+
static VALUE crmf_atan_rz(VALUE self, VALUE x) {
|
1415
|
+
return DBL2NUM(atan_rz(NUM2DBL(x)));
|
1416
|
+
}
|
1417
|
+
|
1418
|
+
|
1419
|
+
static VALUE crmf_cosh_rn(VALUE self, VALUE x) {
|
1420
|
+
return DBL2NUM(cosh_rn(NUM2DBL(x)));
|
1421
|
+
}
|
1422
|
+
|
1423
|
+
static VALUE crmf_cosh_rd(VALUE self, VALUE x) {
|
1424
|
+
return DBL2NUM(cosh_rd(NUM2DBL(x)));
|
1425
|
+
}
|
1426
|
+
|
1427
|
+
static VALUE crmf_cosh_ru(VALUE self, VALUE x) {
|
1428
|
+
return DBL2NUM(cosh_ru(NUM2DBL(x)));
|
1429
|
+
}
|
1430
|
+
|
1431
|
+
static VALUE crmf_cosh_rz(VALUE self, VALUE x) {
|
1432
|
+
return DBL2NUM(cosh_rz(NUM2DBL(x)));
|
1433
|
+
}
|
1434
|
+
|
1435
|
+
|
1436
|
+
static VALUE crmf_sinh_rn(VALUE self, VALUE x) {
|
1437
|
+
return DBL2NUM(sinh_rn(NUM2DBL(x)));
|
1438
|
+
}
|
1439
|
+
|
1440
|
+
static VALUE crmf_sinh_rd(VALUE self, VALUE x) {
|
1441
|
+
return DBL2NUM(sinh_rd(NUM2DBL(x)));
|
1442
|
+
}
|
1443
|
+
|
1444
|
+
static VALUE crmf_sinh_ru(VALUE self, VALUE x) {
|
1445
|
+
return DBL2NUM(sinh_ru(NUM2DBL(x)));
|
1446
|
+
}
|
1447
|
+
|
1448
|
+
static VALUE crmf_sinh_rz(VALUE self, VALUE x) {
|
1449
|
+
return DBL2NUM(sinh_rz(NUM2DBL(x)));
|
1450
|
+
}
|
1451
|
+
|
1452
|
+
|
1453
|
+
#define CRMF_MPFR_MONADIC(func, rnd) \
|
1454
|
+
MPFR_DECL_INIT(mpfrx, 53); \
|
1455
|
+
mpfr_set_d(mpfrx, NUM2DBL(x), MPFR_RNDN); \
|
1456
|
+
int t = mpfr_##func(mpfrx, mpfrx, rnd); \
|
1457
|
+
mpfr_subnormalize(mpfrx, t, rnd); \
|
1458
|
+
double d = mpfr_get_d(mpfrx, rnd); \
|
1459
|
+
return DBL2NUM(d);
|
1460
|
+
|
1461
|
+
|
1462
|
+
static VALUE crmf_exp2_rz(VALUE self, VALUE x) {CRMF_MPFR_MONADIC(exp2, MPFR_RNDZ)}
|
1463
|
+
static VALUE crmf_exp2_rd(VALUE self, VALUE x) {CRMF_MPFR_MONADIC(exp2, MPFR_RNDD)}
|
1464
|
+
static VALUE crmf_exp2_ru(VALUE self, VALUE x) {CRMF_MPFR_MONADIC(exp2, MPFR_RNDU)}
|
1465
|
+
static VALUE crmf_exp2_rn(VALUE self, VALUE x) {CRMF_MPFR_MONADIC(exp2, MPFR_RNDN)}
|
1466
|
+
|
1467
|
+
static VALUE crmf_exp10_rz(VALUE self, VALUE x) {CRMF_MPFR_MONADIC(exp10, MPFR_RNDZ)}
|
1468
|
+
static VALUE crmf_exp10_rd(VALUE self, VALUE x) {CRMF_MPFR_MONADIC(exp10, MPFR_RNDD)}
|
1469
|
+
static VALUE crmf_exp10_ru(VALUE self, VALUE x) {CRMF_MPFR_MONADIC(exp10, MPFR_RNDU)}
|
1470
|
+
static VALUE crmf_exp10_rn(VALUE self, VALUE x) {CRMF_MPFR_MONADIC(exp10, MPFR_RNDN)}
|
1471
|
+
|
1472
|
+
static VALUE crmf_tanh_rz(VALUE self, VALUE x) {CRMF_MPFR_MONADIC(tanh, MPFR_RNDZ)}
|
1473
|
+
static VALUE crmf_tanh_rd(VALUE self, VALUE x) {CRMF_MPFR_MONADIC(tanh, MPFR_RNDD)}
|
1474
|
+
static VALUE crmf_tanh_ru(VALUE self, VALUE x) {CRMF_MPFR_MONADIC(tanh, MPFR_RNDU)}
|
1475
|
+
static VALUE crmf_tanh_rn(VALUE self, VALUE x) {CRMF_MPFR_MONADIC(tanh, MPFR_RNDN)}
|
1476
|
+
|
1477
|
+
static VALUE crmf_acosh_rz(VALUE self, VALUE x) {CRMF_MPFR_MONADIC(acosh, MPFR_RNDZ)}
|
1478
|
+
static VALUE crmf_acosh_rd(VALUE self, VALUE x) {CRMF_MPFR_MONADIC(acosh, MPFR_RNDD)}
|
1479
|
+
static VALUE crmf_acosh_ru(VALUE self, VALUE x) {CRMF_MPFR_MONADIC(acosh, MPFR_RNDU)}
|
1480
|
+
static VALUE crmf_acosh_rn(VALUE self, VALUE x) {CRMF_MPFR_MONADIC(acosh, MPFR_RNDN)}
|
1481
|
+
|
1482
|
+
static VALUE crmf_asinh_rz(VALUE self, VALUE x) {CRMF_MPFR_MONADIC(asinh, MPFR_RNDZ)}
|
1483
|
+
static VALUE crmf_asinh_rd(VALUE self, VALUE x) {CRMF_MPFR_MONADIC(asinh, MPFR_RNDD)}
|
1484
|
+
static VALUE crmf_asinh_ru(VALUE self, VALUE x) {CRMF_MPFR_MONADIC(asinh, MPFR_RNDU)}
|
1485
|
+
static VALUE crmf_asinh_rn(VALUE self, VALUE x) {CRMF_MPFR_MONADIC(asinh, MPFR_RNDN)}
|
1486
|
+
|
1487
|
+
static VALUE crmf_atanh_rz(VALUE self, VALUE x) {CRMF_MPFR_MONADIC(atanh, MPFR_RNDZ)}
|
1488
|
+
static VALUE crmf_atanh_rd(VALUE self, VALUE x) {CRMF_MPFR_MONADIC(atanh, MPFR_RNDD)}
|
1489
|
+
static VALUE crmf_atanh_ru(VALUE self, VALUE x) {CRMF_MPFR_MONADIC(atanh, MPFR_RNDU)}
|
1490
|
+
static VALUE crmf_atanh_rn(VALUE self, VALUE x) {CRMF_MPFR_MONADIC(atanh, MPFR_RNDN)}
|
1491
|
+
|
1492
|
+
static VALUE crmf_sqrt_rz(VALUE self, VALUE x) {CRMF_MPFR_MONADIC(sqrt, MPFR_RNDZ)}
|
1493
|
+
static VALUE crmf_sqrt_rd(VALUE self, VALUE x) {CRMF_MPFR_MONADIC(sqrt, MPFR_RNDD)}
|
1494
|
+
static VALUE crmf_sqrt_ru(VALUE self, VALUE x) {CRMF_MPFR_MONADIC(sqrt, MPFR_RNDU)}
|
1495
|
+
static VALUE crmf_sqrt_rn(VALUE self, VALUE x) {CRMF_MPFR_MONADIC(sqrt, MPFR_RNDN)}
|
1496
|
+
|
1497
|
+
/* Cubic root, rounded toward zero. */
|
1498
|
+
static VALUE crmf_cbrt_rz(VALUE self, VALUE x) {CRMF_MPFR_MONADIC(cbrt, MPFR_RNDZ)}
|
1499
|
+
/* Cubic root, rounded down */
|
1500
|
+
static VALUE crmf_cbrt_rd(VALUE self, VALUE x) {CRMF_MPFR_MONADIC(cbrt, MPFR_RNDD)}
|
1501
|
+
/* Cubic root, rounded up */
|
1502
|
+
static VALUE crmf_cbrt_ru(VALUE self, VALUE x) {CRMF_MPFR_MONADIC(cbrt, MPFR_RNDU)}
|
1503
|
+
/* Cubic root, rounded toward nearest */
|
1504
|
+
static VALUE crmf_cbrt_rn(VALUE self, VALUE x) {CRMF_MPFR_MONADIC(cbrt, MPFR_RNDN)}
|
1505
|
+
|
1506
|
+
|
1507
|
+
#define CRMF_MPFR_DYADIC(x, y, func, rnd) \
|
1508
|
+
MPFR_DECL_INIT(mpfrx, 53); \
|
1509
|
+
MPFR_DECL_INIT(mpfry, 53); \
|
1510
|
+
mpfr_set_d(mpfrx, NUM2DBL(x), MPFR_RNDN); \
|
1511
|
+
mpfr_set_d(mpfry, NUM2DBL(y), MPFR_RNDN); \
|
1512
|
+
int t = mpfr_##func(mpfrx, mpfrx, mpfry, rnd); \
|
1513
|
+
mpfr_subnormalize(mpfrx, t, rnd); \
|
1514
|
+
double d = mpfr_get_d(mpfrx, rnd); \
|
1515
|
+
return DBL2NUM(d);
|
1516
|
+
|
1517
|
+
|
1518
|
+
static VALUE crmf_pow_rz(VALUE self, VALUE x, VALUE y) {CRMF_MPFR_DYADIC(x, y, pow, MPFR_RNDZ)}
|
1519
|
+
static VALUE crmf_pow_rd(VALUE self, VALUE x, VALUE y) {CRMF_MPFR_DYADIC(x, y, pow, MPFR_RNDD)}
|
1520
|
+
static VALUE crmf_pow_ru(VALUE self, VALUE x, VALUE y) {CRMF_MPFR_DYADIC(x, y, pow, MPFR_RNDU)}
|
1521
|
+
static VALUE crmf_pow_rn(VALUE self, VALUE x, VALUE y) {CRMF_MPFR_DYADIC(x, y, pow, MPFR_RNDN)}
|
1522
|
+
|
1523
|
+
static VALUE crmf_atan2_rz(VALUE self, VALUE x, VALUE y) {CRMF_MPFR_DYADIC(y, x, atan2, MPFR_RNDZ)}
|
1524
|
+
static VALUE crmf_atan2_rd(VALUE self, VALUE x, VALUE y) {CRMF_MPFR_DYADIC(y, x, atan2, MPFR_RNDD)}
|
1525
|
+
static VALUE crmf_atan2_ru(VALUE self, VALUE x, VALUE y) {CRMF_MPFR_DYADIC(y, x, atan2, MPFR_RNDU)}
|
1526
|
+
static VALUE crmf_atan2_rn(VALUE self, VALUE x, VALUE y) {CRMF_MPFR_DYADIC(y, x, atan2, MPFR_RNDN)}
|
1527
|
+
|
1528
|
+
static VALUE crmf_hypot_rz(VALUE self, VALUE x, VALUE y) {CRMF_MPFR_DYADIC(y, x, atan2, MPFR_RNDZ)}
|
1529
|
+
static VALUE crmf_hypot_rd(VALUE self, VALUE x, VALUE y) {CRMF_MPFR_DYADIC(y, x, atan2, MPFR_RNDD)}
|
1530
|
+
static VALUE crmf_hypot_ru(VALUE self, VALUE x, VALUE y) {CRMF_MPFR_DYADIC(y, x, atan2, MPFR_RNDU)}
|
1531
|
+
static VALUE crmf_hypot_rn(VALUE self, VALUE x, VALUE y) {CRMF_MPFR_DYADIC(y, x, atan2, MPFR_RNDN)}
|
1532
|
+
|
1533
|
+
|
1534
|
+
#define CRMF_MPFR_DYADIC_INTEGER(x, n, func, rnd) \
|
1535
|
+
MPFR_DECL_INIT(mpfrx, 53); \
|
1536
|
+
mpfr_set_d(mpfrx, NUM2DBL(x), MPFR_RNDN); \
|
1537
|
+
int t = mpfr_##func(mpfrx, mpfrx, n, rnd); \
|
1538
|
+
mpfr_subnormalize(mpfrx, t, rnd); \
|
1539
|
+
double d = mpfr_get_d(mpfrx, rnd); \
|
1540
|
+
return DBL2NUM(d);
|
1541
|
+
|
1542
|
+
|
1543
|
+
/* @param x [Float]
|
1544
|
+
* @param n [Integer] n ∈ ℤ
|
1545
|
+
*/
|
1546
|
+
static VALUE crmf_pown_rz(VALUE self, VALUE x, VALUE n) {CRMF_MPFR_DYADIC_INTEGER(x, NUM2LONG(n), pow_si, MPFR_RNDZ)}
|
1547
|
+
/* @param x [Float]
|
1548
|
+
* @param n [Integer] n ∈ ℤ
|
1549
|
+
*/
|
1550
|
+
static VALUE crmf_pown_rd(VALUE self, VALUE x, VALUE n) {CRMF_MPFR_DYADIC_INTEGER(x, NUM2LONG(n), pow_si, MPFR_RNDD)}
|
1551
|
+
/* @param x [Float]
|
1552
|
+
* @param n [Integer] n ∈ ℤ
|
1553
|
+
*/
|
1554
|
+
static VALUE crmf_pown_ru(VALUE self, VALUE x, VALUE n) {CRMF_MPFR_DYADIC_INTEGER(x, NUM2LONG(n), pow_si, MPFR_RNDU)}
|
1555
|
+
/* @param x [Float]
|
1556
|
+
* @param n [Integer] n ∈ ℤ
|
1557
|
+
*/
|
1558
|
+
static VALUE crmf_pown_rn(VALUE self, VALUE x, VALUE n) {CRMF_MPFR_DYADIC_INTEGER(x, NUM2LONG(n), pow_si, MPFR_RNDN)}
|
1559
|
+
|
1560
|
+
|
1561
|
+
/* @param x [Float]
|
1562
|
+
* @param n [Integer] n ∈ ℕ
|
1563
|
+
*/
|
1564
|
+
static VALUE crmf_rootn_rz(VALUE self, VALUE x, VALUE n) {CRMF_MPFR_DYADIC_INTEGER(x, NUM2ULONG(n), pow_si, MPFR_RNDZ)}
|
1565
|
+
/* @param x [Float]
|
1566
|
+
* @param n [Integer] n ∈ ℕ
|
1567
|
+
*/
|
1568
|
+
static VALUE crmf_rootn_rd(VALUE self, VALUE x, VALUE n) {CRMF_MPFR_DYADIC_INTEGER(x, NUM2ULONG(n), pow_si, MPFR_RNDD)}
|
1569
|
+
/* @param x [Float]
|
1570
|
+
* @param n [Integer] n ∈ ℕ
|
1571
|
+
*/
|
1572
|
+
static VALUE crmf_rootn_ru(VALUE self, VALUE x, VALUE n) {CRMF_MPFR_DYADIC_INTEGER(x, NUM2ULONG(n), pow_si, MPFR_RNDU)}
|
1573
|
+
/* @param x [Float]
|
1574
|
+
* @param n [Integer] n ∈ ℕ
|
1575
|
+
*/
|
1576
|
+
static VALUE crmf_rootn_rn(VALUE self, VALUE x, VALUE n) {CRMF_MPFR_DYADIC_INTEGER(x, NUM2ULONG(n), pow_si, MPFR_RNDN)}
|
1577
|
+
|
1578
|
+
|
1579
|
+
static VALUE crmf_add_rz(VALUE self, VALUE x, VALUE y)
|
1580
|
+
{
|
1581
|
+
double dx = NUM2DBL(x);
|
1582
|
+
double dy = NUM2DBL(y);
|
1583
|
+
fesetround(FE_TOWARDZERO);
|
1584
|
+
double dr = dx + dy;
|
1585
|
+
fesetround(FE_TONEAREST);
|
1586
|
+
return DBL2NUM(dr);
|
1587
|
+
}
|
1588
|
+
|
1589
|
+
static VALUE crmf_add_rd(VALUE self, VALUE x, VALUE y)
|
1590
|
+
{
|
1591
|
+
double dx = NUM2DBL(x);
|
1592
|
+
double dy = NUM2DBL(y);
|
1593
|
+
fesetround(FE_DOWNWARD);
|
1594
|
+
double dr = dx + dy;
|
1595
|
+
fesetround(FE_TONEAREST);
|
1596
|
+
return DBL2NUM(dr);
|
1597
|
+
}
|
1598
|
+
|
1599
|
+
static VALUE crmf_add_ru(VALUE self, VALUE x, VALUE y)
|
1600
|
+
{
|
1601
|
+
double dx = NUM2DBL(x);
|
1602
|
+
double dy = NUM2DBL(y);
|
1603
|
+
fesetround(FE_UPWARD);
|
1604
|
+
double dr = dx + dy;
|
1605
|
+
fesetround(FE_TONEAREST);
|
1606
|
+
return DBL2NUM(dr);
|
1607
|
+
}
|
1608
|
+
|
1609
|
+
static VALUE crmf_add_rn(VALUE self, VALUE x, VALUE y)
|
1610
|
+
{
|
1611
|
+
double dx = NUM2DBL(x);
|
1612
|
+
double dy = NUM2DBL(y);
|
1613
|
+
fesetround(FE_TONEAREST);
|
1614
|
+
double dr = dx + dy;
|
1615
|
+
return DBL2NUM(dr);
|
1616
|
+
}
|
1617
|
+
|
1618
|
+
|
1619
|
+
static VALUE crmf_sub_rz(VALUE self, VALUE x, VALUE y)
|
1620
|
+
{
|
1621
|
+
double dx = NUM2DBL(x);
|
1622
|
+
double dy = NUM2DBL(y);
|
1623
|
+
fesetround(FE_TOWARDZERO);
|
1624
|
+
double dr = dx - dy;
|
1625
|
+
fesetround(FE_TONEAREST);
|
1626
|
+
return DBL2NUM(dr);
|
1627
|
+
}
|
1628
|
+
|
1629
|
+
static VALUE crmf_sub_rd(VALUE self, VALUE x, VALUE y)
|
1630
|
+
{
|
1631
|
+
double dx = NUM2DBL(x);
|
1632
|
+
double dy = NUM2DBL(y);
|
1633
|
+
fesetround(FE_DOWNWARD);
|
1634
|
+
double dr = dx - dy;
|
1635
|
+
fesetround(FE_TONEAREST);
|
1636
|
+
return DBL2NUM(dr);
|
1637
|
+
}
|
1638
|
+
|
1639
|
+
static VALUE crmf_sub_ru(VALUE self, VALUE x, VALUE y)
|
1640
|
+
{
|
1641
|
+
double dx = NUM2DBL(x);
|
1642
|
+
double dy = NUM2DBL(y);
|
1643
|
+
fesetround(FE_UPWARD);
|
1644
|
+
double dr = dx - dy;
|
1645
|
+
fesetround(FE_TONEAREST);
|
1646
|
+
return DBL2NUM(dr);
|
1647
|
+
}
|
1648
|
+
|
1649
|
+
static VALUE crmf_sub_rn(VALUE self, VALUE x, VALUE y)
|
1650
|
+
{
|
1651
|
+
double dx = NUM2DBL(x);
|
1652
|
+
double dy = NUM2DBL(y);
|
1653
|
+
fesetround(FE_TONEAREST);
|
1654
|
+
double dr = dx - dy;
|
1655
|
+
return DBL2NUM(dr);
|
1656
|
+
}
|
1657
|
+
|
1658
|
+
|
1659
|
+
static VALUE crmf_mul_rz(VALUE self, VALUE x, VALUE y)
|
1660
|
+
{
|
1661
|
+
double dx = NUM2DBL(x);
|
1662
|
+
double dy = NUM2DBL(y);
|
1663
|
+
fesetround(FE_TOWARDZERO);
|
1664
|
+
double dr = dx * dy;
|
1665
|
+
fesetround(FE_TONEAREST);
|
1666
|
+
return DBL2NUM(dr);
|
1667
|
+
}
|
1668
|
+
|
1669
|
+
static VALUE crmf_mul_rd(VALUE self, VALUE x, VALUE y)
|
1670
|
+
{
|
1671
|
+
double dx = NUM2DBL(x);
|
1672
|
+
double dy = NUM2DBL(y);
|
1673
|
+
fesetround(FE_DOWNWARD);
|
1674
|
+
double dr = dx * dy;
|
1675
|
+
fesetround(FE_TONEAREST);
|
1676
|
+
return DBL2NUM(dr);
|
1677
|
+
}
|
1678
|
+
|
1679
|
+
static VALUE crmf_mul_ru(VALUE self, VALUE x, VALUE y)
|
1680
|
+
{
|
1681
|
+
double dx = NUM2DBL(x);
|
1682
|
+
double dy = NUM2DBL(y);
|
1683
|
+
fesetround(FE_UPWARD);
|
1684
|
+
double dr = dx * dy;
|
1685
|
+
fesetround(FE_TONEAREST);
|
1686
|
+
return DBL2NUM(dr);
|
1687
|
+
}
|
1688
|
+
|
1689
|
+
static VALUE crmf_mul_rn(VALUE self, VALUE x, VALUE y)
|
1690
|
+
{
|
1691
|
+
double dx = NUM2DBL(x);
|
1692
|
+
double dy = NUM2DBL(y);
|
1693
|
+
fesetround(FE_TONEAREST);
|
1694
|
+
double dr = dx * dy;
|
1695
|
+
return DBL2NUM(dr);
|
1696
|
+
}
|
1697
|
+
|
1698
|
+
|
1699
|
+
static VALUE crmf_div_rz(VALUE self, VALUE x, VALUE y)
|
1700
|
+
{
|
1701
|
+
double dx = NUM2DBL(x);
|
1702
|
+
double dy = NUM2DBL(y);
|
1703
|
+
fesetround(FE_TOWARDZERO);
|
1704
|
+
double dr = dx / dy;
|
1705
|
+
fesetround(FE_TONEAREST);
|
1706
|
+
return DBL2NUM(dr);
|
1707
|
+
}
|
1708
|
+
|
1709
|
+
static VALUE crmf_div_rd(VALUE self, VALUE x, VALUE y)
|
1710
|
+
{
|
1711
|
+
double dx = NUM2DBL(x);
|
1712
|
+
double dy = NUM2DBL(y);
|
1713
|
+
fesetround(FE_DOWNWARD);
|
1714
|
+
double dr = dx / dy;
|
1715
|
+
fesetround(FE_TONEAREST);
|
1716
|
+
return DBL2NUM(dr);
|
1717
|
+
}
|
1718
|
+
|
1719
|
+
static VALUE crmf_div_ru(VALUE self, VALUE x, VALUE y)
|
1720
|
+
{
|
1721
|
+
double dx = NUM2DBL(x);
|
1722
|
+
double dy = NUM2DBL(y);
|
1723
|
+
fesetround(FE_UPWARD);
|
1724
|
+
double dr = dx / dy;
|
1725
|
+
fesetround(FE_TONEAREST);
|
1726
|
+
return DBL2NUM(dr);
|
1727
|
+
}
|
1728
|
+
|
1729
|
+
static VALUE crmf_div_rn(VALUE self, VALUE x, VALUE y)
|
1730
|
+
{
|
1731
|
+
double dx = NUM2DBL(x);
|
1732
|
+
double dy = NUM2DBL(y);
|
1733
|
+
fesetround(FE_TONEAREST);
|
1734
|
+
double dr = dx / dy;
|
1735
|
+
return DBL2NUM(dr);
|
1736
|
+
}
|
1737
|
+
|
1738
|
+
|
1739
|
+
|
1740
|
+
CRMF_PUBLIC void Init_crmf()
|
1741
|
+
{
|
1742
|
+
id_to_f = rb_intern("to_f");
|
1743
|
+
id_to_s = rb_intern("to_s");
|
1744
|
+
id_nearest = rb_intern("nearest");
|
1745
|
+
id_down = rb_intern("down");
|
1746
|
+
id_up = rb_intern("up");
|
1747
|
+
id_zero = rb_intern("zero");
|
1748
|
+
id_away = rb_intern("away");
|
1749
|
+
id_syminf = rb_intern("<");
|
1750
|
+
id_sign = rb_intern("sign");
|
1751
|
+
id_sign_bit = rb_intern("sign_bit");
|
1752
|
+
id_exponent_bits = rb_intern("exponent_bits");
|
1753
|
+
id_fraction_bits = rb_intern("fraction_bits");
|
1754
|
+
id_exponent = rb_intern("exponent");
|
1755
|
+
id_significand = rb_intern("significand");
|
1756
|
+
id_isignificand = rb_intern("isignificand");
|
1757
|
+
id_flag = rb_intern("flag");
|
1758
|
+
id_infinity = rb_intern("infinity");
|
1759
|
+
id_nan = rb_intern("nan");
|
1760
|
+
id_subnormal = rb_intern("subnormal");
|
1761
|
+
id_zero = rb_intern("zero");
|
1762
|
+
|
1763
|
+
m_CRMF = rb_define_module("CRMF");
|
1764
|
+
|
1765
|
+
mpfr_set_emin(-1073);
|
1766
|
+
mpfr_set_emax(1024);
|
1767
|
+
|
1768
|
+
rb_define_module_function(rb_cFloat, "add", crmf_float_add, -1);
|
1769
|
+
rb_define_module_function(rb_cFloat, "sub", crmf_float_sub, -1);
|
1770
|
+
rb_define_module_function(rb_cFloat, "mul", crmf_float_mul, -1);
|
1771
|
+
rb_define_module_function(rb_cFloat, "div", crmf_float_div, -1);
|
1772
|
+
rb_define_module_function(rb_cFloat, "sqrt", crmf_float_sqrt, -1);
|
1773
|
+
rb_define_module_function(rb_cFloat, "cbrt", crmf_float_cbrt, -1);
|
1774
|
+
rb_define_module_function(rb_cFloat, "rootn", crmf_float_rootn, -1);
|
1775
|
+
rb_define_module_function(rb_cFloat, "dim", crmf_float_dim, -1);
|
1776
|
+
rb_define_module_function(rb_cFloat, "fma", crmf_float_fma, -1);
|
1777
|
+
rb_define_module_function(rb_cFloat, "fms", crmf_float_fms, -1);
|
1778
|
+
rb_define_module_function(rb_cFloat, "fmma", crmf_float_fmma, -1);
|
1779
|
+
rb_define_module_function(rb_cFloat, "fmms", crmf_float_fmms, -1);
|
1780
|
+
rb_define_module_function(rb_cFloat, "hypot", crmf_float_hypot, -1);
|
1781
|
+
rb_define_module_function(rb_cFloat, "log", crmf_float_log, -1);
|
1782
|
+
rb_define_module_function(rb_cFloat, "log2", crmf_float_log2, -1);
|
1783
|
+
rb_define_module_function(rb_cFloat, "log10", crmf_float_log10, -1);
|
1784
|
+
rb_define_module_function(rb_cFloat, "log1p", crmf_float_log1p, -1);
|
1785
|
+
rb_define_module_function(rb_cFloat, "exp", crmf_float_exp, -1);
|
1786
|
+
rb_define_module_function(rb_cFloat, "exp2", crmf_float_exp2, -1);
|
1787
|
+
rb_define_module_function(rb_cFloat, "exp10", crmf_float_exp10, -1);
|
1788
|
+
rb_define_module_function(rb_cFloat, "expm1", crmf_float_expm1, -1);
|
1789
|
+
rb_define_module_function(rb_cFloat, "pow", crmf_float_pow, -1);
|
1790
|
+
rb_define_module_function(rb_cFloat, "pown", crmf_float_pown, -1);
|
1791
|
+
rb_define_module_function(rb_cFloat, "cos", crmf_float_cos, -1);
|
1792
|
+
rb_define_module_function(rb_cFloat, "sin", crmf_float_sin, -1);
|
1793
|
+
rb_define_module_function(rb_cFloat, "tan", crmf_float_tan, -1);
|
1794
|
+
rb_define_module_function(rb_cFloat, "acos", crmf_float_acos, -1);
|
1795
|
+
rb_define_module_function(rb_cFloat, "asin", crmf_float_asin, -1);
|
1796
|
+
rb_define_module_function(rb_cFloat, "atan", crmf_float_atan, -1);
|
1797
|
+
rb_define_module_function(rb_cFloat, "atan2", crmf_float_atan2, -1);
|
1798
|
+
rb_define_module_function(rb_cFloat, "cosh", crmf_float_cosh, -1);
|
1799
|
+
rb_define_module_function(rb_cFloat, "sinh", crmf_float_sinh, -1);
|
1800
|
+
rb_define_module_function(rb_cFloat, "tanh", crmf_float_tanh, -1);
|
1801
|
+
rb_define_module_function(rb_cFloat, "acosh", crmf_float_acosh, -1);
|
1802
|
+
rb_define_module_function(rb_cFloat, "asinh", crmf_float_asinh, -1);
|
1803
|
+
rb_define_module_function(rb_cFloat, "atanh", crmf_float_atanh, -1);
|
1804
|
+
|
1805
|
+
rb_define_module_function(m_CRMF, "to_float", crmf_object_to_float, -1);
|
1806
|
+
rb_define_module_function(rb_cFloat, "build_up", crmf_float_build_up, 3);
|
1807
|
+
|
1808
|
+
rb_define_method(rb_cFloat, "break_down", crmf_float_break_down, 0);
|
1809
|
+
rb_define_method(rb_cFloat, "subnormal?", crmf_float_is_subnormal, 0);
|
1810
|
+
|
1811
|
+
double d;
|
1812
|
+
|
1813
|
+
crmf_get_const_from_func(d, mpfr_const_log2, MPFR_RNDD);
|
1814
|
+
// @return [Float] ↓log(2)↓
|
1815
|
+
rb_define_const(m_CRMF, "LOG2_DOWN", DBL2NUM(d));
|
1816
|
+
|
1817
|
+
crmf_get_const_from_func(d, mpfr_const_log2, MPFR_RNDU);
|
1818
|
+
// @return [Float] ↑log(2)↑
|
1819
|
+
rb_define_const(m_CRMF, "LOG2_UP", DBL2NUM(d));
|
1820
|
+
|
1821
|
+
crmf_get_const_from_func(d, mpfr_const_pi, MPFR_RNDD);
|
1822
|
+
// @return [Float] ↓𝛑↓
|
1823
|
+
rb_define_const(m_CRMF, "PI_DOWN", DBL2NUM(d));
|
1824
|
+
|
1825
|
+
crmf_get_const_from_func(d, mpfr_const_pi, MPFR_RNDU);
|
1826
|
+
// @return [Float] ↑𝛑↑
|
1827
|
+
rb_define_const(m_CRMF, "PI_UP", DBL2NUM(d));
|
1828
|
+
|
1829
|
+
crmf_get_const_from_func(d, mpfr_const_euler, MPFR_RNDD);
|
1830
|
+
// @return [Float] ↓euler↓
|
1831
|
+
rb_define_const(m_CRMF, "EULER_DOWN", DBL2NUM(d));
|
1832
|
+
|
1833
|
+
crmf_get_const_from_func(d, mpfr_const_euler, MPFR_RNDU);
|
1834
|
+
// @return [Float] ↑euler↑
|
1835
|
+
rb_define_const(m_CRMF, "EULER_UP", DBL2NUM(d));
|
1836
|
+
|
1837
|
+
|
1838
|
+
rb_define_module_function(m_CRMF, "exp_rz", crmf_exp_rz, 1);
|
1839
|
+
rb_define_module_function(m_CRMF, "exp_rd", crmf_exp_rd, 1);
|
1840
|
+
rb_define_module_function(m_CRMF, "exp_ru", crmf_exp_ru, 1);
|
1841
|
+
rb_define_module_function(m_CRMF, "exp_rn", crmf_exp_rn, 1);
|
1842
|
+
rb_define_module_function(m_CRMF, "exp2_rz", crmf_exp2_rz, 1);
|
1843
|
+
rb_define_module_function(m_CRMF, "exp2_rd", crmf_exp2_rd, 1);
|
1844
|
+
rb_define_module_function(m_CRMF, "exp2_ru", crmf_exp2_ru, 1);
|
1845
|
+
rb_define_module_function(m_CRMF, "exp2_rn", crmf_exp2_rn, 1);
|
1846
|
+
rb_define_module_function(m_CRMF, "exp10_rz", crmf_exp10_rz, 1);
|
1847
|
+
rb_define_module_function(m_CRMF, "exp10_rd", crmf_exp10_rd, 1);
|
1848
|
+
rb_define_module_function(m_CRMF, "exp10_ru", crmf_exp10_ru, 1);
|
1849
|
+
rb_define_module_function(m_CRMF, "exp10_rn", crmf_exp10_rn, 1);
|
1850
|
+
rb_define_module_function(m_CRMF, "log_rz", crmf_log_rz, 1);
|
1851
|
+
rb_define_module_function(m_CRMF, "log_rd", crmf_log_rd, 1);
|
1852
|
+
rb_define_module_function(m_CRMF, "log_ru", crmf_log_ru, 1);
|
1853
|
+
rb_define_module_function(m_CRMF, "log_rn", crmf_log_rn, 1);
|
1854
|
+
rb_define_module_function(m_CRMF, "log2_rz", crmf_log2_rz, 1);
|
1855
|
+
rb_define_module_function(m_CRMF, "log2_rd", crmf_log2_rd, 1);
|
1856
|
+
rb_define_module_function(m_CRMF, "log2_ru", crmf_log2_ru, 1);
|
1857
|
+
rb_define_module_function(m_CRMF, "log2_rn", crmf_log2_rn, 1);
|
1858
|
+
rb_define_module_function(m_CRMF, "log10_rz", crmf_log10_rz, 1);
|
1859
|
+
rb_define_module_function(m_CRMF, "log10_rd", crmf_log10_rd, 1);
|
1860
|
+
rb_define_module_function(m_CRMF, "log10_ru", crmf_log10_ru, 1);
|
1861
|
+
rb_define_module_function(m_CRMF, "log10_rn", crmf_log10_rn, 1);
|
1862
|
+
rb_define_module_function(m_CRMF, "expm1_rz", crmf_expm1_rz, 1);
|
1863
|
+
rb_define_module_function(m_CRMF, "expm1_rd", crmf_expm1_rd, 1);
|
1864
|
+
rb_define_module_function(m_CRMF, "expm1_ru", crmf_expm1_ru, 1);
|
1865
|
+
rb_define_module_function(m_CRMF, "expm1_rn", crmf_expm1_rn, 1);
|
1866
|
+
rb_define_module_function(m_CRMF, "log1p_rz", crmf_log1p_rz, 1);
|
1867
|
+
rb_define_module_function(m_CRMF, "log1p_rd", crmf_log1p_rd, 1);
|
1868
|
+
rb_define_module_function(m_CRMF, "log1p_ru", crmf_log1p_ru, 1);
|
1869
|
+
rb_define_module_function(m_CRMF, "log1p_rn", crmf_log1p_rn, 1);
|
1870
|
+
rb_define_module_function(m_CRMF, "cos_rz", crmf_cos_rz, 1);
|
1871
|
+
rb_define_module_function(m_CRMF, "cos_rd", crmf_cos_rd, 1);
|
1872
|
+
rb_define_module_function(m_CRMF, "cos_ru", crmf_cos_ru, 1);
|
1873
|
+
rb_define_module_function(m_CRMF, "cos_rn", crmf_cos_rn, 1);
|
1874
|
+
rb_define_module_function(m_CRMF, "sin_rz", crmf_sin_rz, 1);
|
1875
|
+
rb_define_module_function(m_CRMF, "sin_rd", crmf_sin_rd, 1);
|
1876
|
+
rb_define_module_function(m_CRMF, "sin_ru", crmf_sin_ru, 1);
|
1877
|
+
rb_define_module_function(m_CRMF, "sin_rn", crmf_sin_rn, 1);
|
1878
|
+
rb_define_module_function(m_CRMF, "tan_rz", crmf_tan_rz, 1);
|
1879
|
+
rb_define_module_function(m_CRMF, "tan_rd", crmf_tan_rd, 1);
|
1880
|
+
rb_define_module_function(m_CRMF, "tan_ru", crmf_tan_ru, 1);
|
1881
|
+
rb_define_module_function(m_CRMF, "tan_rn", crmf_tan_rn, 1);
|
1882
|
+
rb_define_module_function(m_CRMF, "acos_rz", crmf_acos_rz, 1);
|
1883
|
+
rb_define_module_function(m_CRMF, "acos_rd", crmf_acos_rd, 1);
|
1884
|
+
rb_define_module_function(m_CRMF, "acos_ru", crmf_acos_ru, 1);
|
1885
|
+
rb_define_module_function(m_CRMF, "acos_rn", crmf_acos_rn, 1);
|
1886
|
+
rb_define_module_function(m_CRMF, "asin_rz", crmf_asin_rz, 1);
|
1887
|
+
rb_define_module_function(m_CRMF, "asin_rd", crmf_asin_rd, 1);
|
1888
|
+
rb_define_module_function(m_CRMF, "asin_ru", crmf_asin_ru, 1);
|
1889
|
+
rb_define_module_function(m_CRMF, "asin_rn", crmf_asin_rn, 1);
|
1890
|
+
rb_define_module_function(m_CRMF, "atan_rz", crmf_atan_rz, 1);
|
1891
|
+
rb_define_module_function(m_CRMF, "atan_rd", crmf_atan_rd, 1);
|
1892
|
+
rb_define_module_function(m_CRMF, "atan_ru", crmf_atan_ru, 1);
|
1893
|
+
rb_define_module_function(m_CRMF, "atan_rn", crmf_atan_rn, 1);
|
1894
|
+
rb_define_module_function(m_CRMF, "cosh_rz", crmf_cosh_rz, 1);
|
1895
|
+
rb_define_module_function(m_CRMF, "cosh_rd", crmf_cosh_rd, 1);
|
1896
|
+
rb_define_module_function(m_CRMF, "cosh_ru", crmf_cosh_ru, 1);
|
1897
|
+
rb_define_module_function(m_CRMF, "cosh_rn", crmf_cosh_rn, 1);
|
1898
|
+
rb_define_module_function(m_CRMF, "sinh_rz", crmf_sinh_rz, 1);
|
1899
|
+
rb_define_module_function(m_CRMF, "sinh_rd", crmf_sinh_rd, 1);
|
1900
|
+
rb_define_module_function(m_CRMF, "sinh_ru", crmf_sinh_ru, 1);
|
1901
|
+
rb_define_module_function(m_CRMF, "sinh_rn", crmf_sinh_rn, 1);
|
1902
|
+
rb_define_module_function(m_CRMF, "tanh_rz", crmf_tanh_rz, 1);
|
1903
|
+
rb_define_module_function(m_CRMF, "tanh_rd", crmf_tanh_rd, 1);
|
1904
|
+
rb_define_module_function(m_CRMF, "tanh_ru", crmf_tanh_ru, 1);
|
1905
|
+
rb_define_module_function(m_CRMF, "tanh_rn", crmf_tanh_rn, 1);
|
1906
|
+
rb_define_module_function(m_CRMF, "acosh_rz", crmf_acosh_rz, 1);
|
1907
|
+
rb_define_module_function(m_CRMF, "acosh_rd", crmf_acosh_rd, 1);
|
1908
|
+
rb_define_module_function(m_CRMF, "acosh_ru", crmf_acosh_ru, 1);
|
1909
|
+
rb_define_module_function(m_CRMF, "acosh_rn", crmf_acosh_rn, 1);
|
1910
|
+
rb_define_module_function(m_CRMF, "asinh_rz", crmf_asinh_rz, 1);
|
1911
|
+
rb_define_module_function(m_CRMF, "asinh_rd", crmf_asinh_rd, 1);
|
1912
|
+
rb_define_module_function(m_CRMF, "asinh_ru", crmf_asinh_ru, 1);
|
1913
|
+
rb_define_module_function(m_CRMF, "asinh_rn", crmf_asinh_rn, 1);
|
1914
|
+
rb_define_module_function(m_CRMF, "atanh_rz", crmf_atanh_rz, 1);
|
1915
|
+
rb_define_module_function(m_CRMF, "atanh_rd", crmf_atanh_rd, 1);
|
1916
|
+
rb_define_module_function(m_CRMF, "atanh_ru", crmf_atanh_ru, 1);
|
1917
|
+
rb_define_module_function(m_CRMF, "atanh_rn", crmf_atanh_rn, 1);
|
1918
|
+
rb_define_module_function(m_CRMF, "sqrt_rz", crmf_sqrt_rz, 1);
|
1919
|
+
rb_define_module_function(m_CRMF, "sqrt_rd", crmf_sqrt_rd, 1);
|
1920
|
+
rb_define_module_function(m_CRMF, "sqrt_ru", crmf_sqrt_ru, 1);
|
1921
|
+
rb_define_module_function(m_CRMF, "sqrt_rn", crmf_sqrt_rn, 1);
|
1922
|
+
rb_define_module_function(m_CRMF, "cbrt_rz", crmf_cbrt_rz, 1);
|
1923
|
+
rb_define_module_function(m_CRMF, "cbrt_rd", crmf_cbrt_rd, 1);
|
1924
|
+
rb_define_module_function(m_CRMF, "cbrt_ru", crmf_cbrt_ru, 1);
|
1925
|
+
rb_define_module_function(m_CRMF, "cbrt_rn", crmf_cbrt_rn, 1);
|
1926
|
+
rb_define_module_function(m_CRMF, "pow_rz", crmf_pow_rz, 2);
|
1927
|
+
rb_define_module_function(m_CRMF, "pow_rd", crmf_pow_rd, 2);
|
1928
|
+
rb_define_module_function(m_CRMF, "pow_ru", crmf_pow_ru, 2);
|
1929
|
+
rb_define_module_function(m_CRMF, "pow_rn", crmf_pow_rn, 2);
|
1930
|
+
rb_define_module_function(m_CRMF, "atan2_rz", crmf_atan2_rz, 2);
|
1931
|
+
rb_define_module_function(m_CRMF, "atan2_rd", crmf_atan2_rd, 2);
|
1932
|
+
rb_define_module_function(m_CRMF, "atan2_ru", crmf_atan2_ru, 2);
|
1933
|
+
rb_define_module_function(m_CRMF, "atan2_rn", crmf_atan2_rn, 2);
|
1934
|
+
rb_define_module_function(m_CRMF, "hypot_rz", crmf_hypot_rz, 2);
|
1935
|
+
rb_define_module_function(m_CRMF, "hypot_rd", crmf_hypot_rd, 2);
|
1936
|
+
rb_define_module_function(m_CRMF, "hypot_ru", crmf_hypot_ru, 2);
|
1937
|
+
rb_define_module_function(m_CRMF, "hypot_rn", crmf_hypot_rn, 2);
|
1938
|
+
rb_define_module_function(m_CRMF, "pown_rz", crmf_pown_rz, 2);
|
1939
|
+
rb_define_module_function(m_CRMF, "pown_rd", crmf_pown_rd, 2);
|
1940
|
+
rb_define_module_function(m_CRMF, "pown_ru", crmf_pown_ru, 2);
|
1941
|
+
rb_define_module_function(m_CRMF, "pown_rn", crmf_pown_rn, 2);
|
1942
|
+
rb_define_module_function(m_CRMF, "rootn_rz", crmf_rootn_rz, 2);
|
1943
|
+
rb_define_module_function(m_CRMF, "rootn_rd", crmf_rootn_rd, 2);
|
1944
|
+
rb_define_module_function(m_CRMF, "rootn_ru", crmf_rootn_ru, 2);
|
1945
|
+
rb_define_module_function(m_CRMF, "rootn_rn", crmf_rootn_rn, 2);
|
1946
|
+
rb_define_module_function(m_CRMF, "add_rz", crmf_add_rz, 2);
|
1947
|
+
rb_define_module_function(m_CRMF, "add_rd", crmf_add_rd, 2);
|
1948
|
+
rb_define_module_function(m_CRMF, "add_ru", crmf_add_ru, 2);
|
1949
|
+
rb_define_module_function(m_CRMF, "add_rn", crmf_add_rn, 2);
|
1950
|
+
rb_define_module_function(m_CRMF, "sub_rz", crmf_sub_rz, 2);
|
1951
|
+
rb_define_module_function(m_CRMF, "sub_rd", crmf_sub_rd, 2);
|
1952
|
+
rb_define_module_function(m_CRMF, "sub_ru", crmf_sub_ru, 2);
|
1953
|
+
rb_define_module_function(m_CRMF, "sub_rn", crmf_sub_rn, 2);
|
1954
|
+
rb_define_module_function(m_CRMF, "mul_rz", crmf_mul_rz, 2);
|
1955
|
+
rb_define_module_function(m_CRMF, "mul_rd", crmf_mul_rd, 2);
|
1956
|
+
rb_define_module_function(m_CRMF, "mul_ru", crmf_mul_ru, 2);
|
1957
|
+
rb_define_module_function(m_CRMF, "mul_rn", crmf_mul_rn, 2);
|
1958
|
+
rb_define_module_function(m_CRMF, "div_rz", crmf_div_rz, 2);
|
1959
|
+
rb_define_module_function(m_CRMF, "div_rd", crmf_div_rd, 2);
|
1960
|
+
rb_define_module_function(m_CRMF, "div_ru", crmf_div_ru, 2);
|
1961
|
+
rb_define_module_function(m_CRMF, "div_rn", crmf_div_rn, 2);
|
1962
|
+
|
1963
|
+
crlibm_init();
|
1964
|
+
}
|
1965
|
+
|
1966
|
+
|