quadmath 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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +11 -0
- data/CODE_OF_CONDUCT.md +132 -0
- data/LICENSE.txt +21 -0
- data/README.md +160 -0
- data/Rakefile +14 -0
- data/ext/quadmath/complex128.c +494 -0
- data/ext/quadmath/extconf.rb +15 -0
- data/ext/quadmath/float128.c +638 -0
- data/ext/quadmath/internal/rb_quadmath.h +77 -0
- data/ext/quadmath/main.c +31 -0
- data/ext/quadmath/missing/cerfcq.c +158 -0
- data/ext/quadmath/missing/cerfq.c +35 -0
- data/ext/quadmath/missing/cl2norm2q.c +43 -0
- data/ext/quadmath/missing/clgammaq.c +61 -0
- data/ext/quadmath/missing/ctgammaq.c +56 -0
- data/ext/quadmath/missing/ool_quad2str.c +738 -0
- data/ext/quadmath/missing/opts_exception_p.c +20 -0
- data/ext/quadmath/numerable.c +2657 -0
- data/ext/quadmath/quadmath.c +2768 -0
- data/ext/quadmath/rb_quadmath.h +75 -0
- data/lib/quadmath/quadmath.so +0 -0
- data/lib/quadmath/version.rb +5 -0
- data/lib/quadmath.rb +8 -0
- data/pkg/quadmath-0.1.0.gem +0 -0
- data/sig/ruby/quadmath.rbs +6 -0
- metadata +70 -0
|
@@ -0,0 +1,638 @@
|
|
|
1
|
+
/*******************************************************************************
|
|
2
|
+
float128.c -- Float128 Class
|
|
3
|
+
|
|
4
|
+
Author: Hironobu Inatsuka
|
|
5
|
+
*******************************************************************************/
|
|
6
|
+
#include <ruby.h>
|
|
7
|
+
#include <quadmath.h>
|
|
8
|
+
#include "rb_quadmath.h"
|
|
9
|
+
#include "internal/rb_quadmath.h"
|
|
10
|
+
|
|
11
|
+
char ool_quad2str(__float128 x, char format, int *exp, int *sign, char **buf);
|
|
12
|
+
|
|
13
|
+
struct F128 { __float128 value; } ;
|
|
14
|
+
|
|
15
|
+
static void
|
|
16
|
+
free_float128(void *v)
|
|
17
|
+
{
|
|
18
|
+
if (v != NULL)
|
|
19
|
+
{
|
|
20
|
+
xfree(v);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
static size_t
|
|
25
|
+
memsize_float128(const void *_)
|
|
26
|
+
{
|
|
27
|
+
return sizeof(struct F128);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
static const rb_data_type_t float128_data_type = {
|
|
31
|
+
"float128",
|
|
32
|
+
{0, free_float128, memsize_float128,},
|
|
33
|
+
0, 0,
|
|
34
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
static VALUE
|
|
38
|
+
float128_allocate(const __float128 x)
|
|
39
|
+
{
|
|
40
|
+
struct F128 *ptr = ruby_xcalloc(1, sizeof(struct F128));
|
|
41
|
+
VALUE obj;
|
|
42
|
+
ptr->value = x;
|
|
43
|
+
obj = TypedData_Wrap_Struct(rb_cFloat128, &float128_data_type, ptr);
|
|
44
|
+
RB_OBJ_FREEZE(obj);
|
|
45
|
+
return obj;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
__float128
|
|
49
|
+
GetF128(VALUE self)
|
|
50
|
+
{
|
|
51
|
+
struct F128 *f128;
|
|
52
|
+
|
|
53
|
+
TypedData_Get_Struct(self, struct F128, &float128_data_type, f128);
|
|
54
|
+
|
|
55
|
+
return f128->value;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
/*
|
|
60
|
+
* call-seq:
|
|
61
|
+
* hash -> Integer
|
|
62
|
+
*
|
|
63
|
+
* +self+のHash値を返す.
|
|
64
|
+
*
|
|
65
|
+
*/
|
|
66
|
+
static VALUE
|
|
67
|
+
float128_hash(VALUE self)
|
|
68
|
+
{
|
|
69
|
+
struct F128 *f128;
|
|
70
|
+
st_index_t hash;
|
|
71
|
+
|
|
72
|
+
TypedData_Get_Struct(self, struct F128, &float128_data_type, f128);
|
|
73
|
+
|
|
74
|
+
hash = rb_memhash(f128, sizeof(struct F128));
|
|
75
|
+
|
|
76
|
+
return ST2FIX(hash);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/*
|
|
80
|
+
* call-seq:
|
|
81
|
+
* eql?(other) -> bool
|
|
82
|
+
*
|
|
83
|
+
* +self+と+other+が等しければ真を返す.
|
|
84
|
+
*/
|
|
85
|
+
static VALUE
|
|
86
|
+
float128_eql_p(VALUE self, VALUE other)
|
|
87
|
+
{
|
|
88
|
+
__float128 left_f128, right_f128;
|
|
89
|
+
|
|
90
|
+
if (CLASS_OF(other) != rb_cFloat128)
|
|
91
|
+
return Qfalse;
|
|
92
|
+
|
|
93
|
+
left_f128 = GetF128(self);
|
|
94
|
+
right_f128 = GetF128(other);
|
|
95
|
+
|
|
96
|
+
return left_f128 == right_f128 ? Qtrue : Qfalse;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/*
|
|
100
|
+
* call-seq:
|
|
101
|
+
* finite? -> bool
|
|
102
|
+
*
|
|
103
|
+
* +self+が有限ならtrueを,そうでないならfalseを返す.
|
|
104
|
+
*
|
|
105
|
+
* Float128::INFINITY.finite? # => false
|
|
106
|
+
*/
|
|
107
|
+
static VALUE
|
|
108
|
+
float128_finite_p(VALUE self)
|
|
109
|
+
{
|
|
110
|
+
__float128 f128 = GetF128(self);
|
|
111
|
+
|
|
112
|
+
return (finite(f128)) ? Qtrue : Qfalse;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
/*
|
|
118
|
+
* call-seq:
|
|
119
|
+
* infinite? -> 1 | -1 | nil
|
|
120
|
+
*
|
|
121
|
+
* +self+が無限大の場合,負であれば-1を,正であれば1を,そうでないならnilを返す.
|
|
122
|
+
*
|
|
123
|
+
* Float128::INFINITY.infinite? # => 1
|
|
124
|
+
* (-Float128::INFINITY).infinite? # => -1
|
|
125
|
+
*/
|
|
126
|
+
static VALUE
|
|
127
|
+
float128_infinite_p(VALUE self)
|
|
128
|
+
{
|
|
129
|
+
__float128 f128 = GetF128(self);
|
|
130
|
+
int sign = isinfq(f128);
|
|
131
|
+
|
|
132
|
+
if (sign)
|
|
133
|
+
return INT2NUM(sign);
|
|
134
|
+
else
|
|
135
|
+
return Qnil;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
/*
|
|
140
|
+
* call-seq:
|
|
141
|
+
* nan? -> bool
|
|
142
|
+
*
|
|
143
|
+
* +self+がNaN(Not a Number)ならtrueを,そうでないならfalseを返す.
|
|
144
|
+
*
|
|
145
|
+
* Float128::NAN.nan? # => true
|
|
146
|
+
*/
|
|
147
|
+
static VALUE
|
|
148
|
+
float128_nan_p(VALUE self)
|
|
149
|
+
{
|
|
150
|
+
__float128 f128 = GetF128(self);
|
|
151
|
+
|
|
152
|
+
return isnanq(f128) ? Qtrue : Qfalse;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
/*
|
|
157
|
+
* call-seq:
|
|
158
|
+
* inspect -> String
|
|
159
|
+
*
|
|
160
|
+
* +self+を見やすくする.#to_sと働きは同じだが,引数を持たずジェネリック表記するのが異なる.
|
|
161
|
+
*
|
|
162
|
+
* Float128('10.0') #=> "10.0"
|
|
163
|
+
* Float128('1e34') #=> "1.0e+34"
|
|
164
|
+
* Float128('0.1') #=> "0.1"
|
|
165
|
+
* Float128('0.0000001') #=> "1.0e-7"
|
|
166
|
+
*/
|
|
167
|
+
static VALUE
|
|
168
|
+
float128_inspect(VALUE self)
|
|
169
|
+
{
|
|
170
|
+
char* str;
|
|
171
|
+
int exp, sign;
|
|
172
|
+
__float128 f128 = GetF128(self);
|
|
173
|
+
|
|
174
|
+
switch (ool_quad2str(f128, 'g', &exp, &sign, &str)) {
|
|
175
|
+
case '0':
|
|
176
|
+
rb_raise(rb_eRuntimeError, "error occured in ool_quad2str()");
|
|
177
|
+
break;
|
|
178
|
+
case '1':
|
|
179
|
+
if (sign == -1)
|
|
180
|
+
return rb_sprintf("-%s", str);
|
|
181
|
+
else
|
|
182
|
+
return rb_sprintf("%s", str);
|
|
183
|
+
break;
|
|
184
|
+
case 'e':
|
|
185
|
+
if (sign == -1)
|
|
186
|
+
return rb_sprintf("-%se%+d", str, exp);
|
|
187
|
+
else
|
|
188
|
+
return rb_sprintf("%se%+d", str, exp);
|
|
189
|
+
break;
|
|
190
|
+
case 'f':
|
|
191
|
+
if (sign == -1)
|
|
192
|
+
return rb_sprintf("-%s", str);
|
|
193
|
+
else
|
|
194
|
+
return rb_sprintf("%s", str);
|
|
195
|
+
break;
|
|
196
|
+
default:
|
|
197
|
+
rb_raise(rb_eRuntimeError, "format error");
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
return rb_str_new(0,0);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/*
|
|
204
|
+
* call-seq:
|
|
205
|
+
* to_s(base = nil) -> String
|
|
206
|
+
*
|
|
207
|
+
* +self+を文字列へ変換する.基数+base+ (2, 10, 16) を設定すると進数が変わる.
|
|
208
|
+
*
|
|
209
|
+
* Float128('10.0').to_s #=> "10.0"
|
|
210
|
+
* Float128('1e3').to_s(10) #=> "1.0e+3"
|
|
211
|
+
* Float128('0.1').to_s(2) #=> "0.1e+0"
|
|
212
|
+
* Float128('0.001').to_s(10) #=> "1.0e-3"
|
|
213
|
+
* Float128::MAX.to_s(16) #=> "0x1.ffffffffffffffffffffffffffffp+16383"
|
|
214
|
+
* Float128::INFINITY.to_s(2) #=> "Infinity" # 非数・無限は基数に関係なく文字列変換する
|
|
215
|
+
*
|
|
216
|
+
* +base+が範囲外であるとRangeErrorが発生する.
|
|
217
|
+
*/
|
|
218
|
+
VALUE
|
|
219
|
+
float128_to_s(int argc, VALUE *argv, VALUE self)
|
|
220
|
+
{
|
|
221
|
+
char *str;
|
|
222
|
+
VALUE base;
|
|
223
|
+
__float128 f128;
|
|
224
|
+
int exp, sign;
|
|
225
|
+
|
|
226
|
+
rb_scan_args(argc, argv, "01", &base);
|
|
227
|
+
|
|
228
|
+
if (NIL_P(base))
|
|
229
|
+
return float128_inspect(self);
|
|
230
|
+
|
|
231
|
+
to_s_retry:
|
|
232
|
+
switch(TYPE(base)) {
|
|
233
|
+
case T_FIXNUM:
|
|
234
|
+
long base_number = FIX2LONG(base);
|
|
235
|
+
f128 = GetF128(self);
|
|
236
|
+
switch (base_number) {
|
|
237
|
+
case 2:
|
|
238
|
+
if (isinfq(f128) || isnanq(f128))
|
|
239
|
+
goto to_s_none_finite;
|
|
240
|
+
if ('0' == ool_quad2str(f128, 'b', &exp, &sign, &str))
|
|
241
|
+
goto to_s_invalid_format;
|
|
242
|
+
if (sign == -1)
|
|
243
|
+
return rb_sprintf("-%se%+d", str, exp);
|
|
244
|
+
else
|
|
245
|
+
return rb_sprintf("%se%+d", str, exp);
|
|
246
|
+
break;
|
|
247
|
+
case 10:
|
|
248
|
+
if (isinfq(f128) || isnanq(f128))
|
|
249
|
+
goto to_s_none_finite;
|
|
250
|
+
if ('0' == ool_quad2str(f128, 'e', &exp, &sign, &str))
|
|
251
|
+
goto to_s_invalid_format;
|
|
252
|
+
if (sign == -1)
|
|
253
|
+
return rb_sprintf("-%se%+d", str, exp);
|
|
254
|
+
else
|
|
255
|
+
return rb_sprintf("%se%+d", str, exp);
|
|
256
|
+
break;
|
|
257
|
+
case 16:
|
|
258
|
+
if (isinfq(f128) || isnanq(f128))
|
|
259
|
+
goto to_s_none_finite;
|
|
260
|
+
if ('0' == ool_quad2str(f128, 'a', &exp, &sign, &str))
|
|
261
|
+
goto to_s_invalid_format;
|
|
262
|
+
if (sign == -1)
|
|
263
|
+
return rb_sprintf("-%sp%+d", str, exp);
|
|
264
|
+
else
|
|
265
|
+
return rb_sprintf("%sp%+d", str, exp);
|
|
266
|
+
break;
|
|
267
|
+
default:
|
|
268
|
+
break;
|
|
269
|
+
}
|
|
270
|
+
// break; /* going through to switch to BIGNUM */
|
|
271
|
+
case T_BIGNUM:
|
|
272
|
+
rb_raise(rb_eRangeError,
|
|
273
|
+
"unavailable radix: %"PRIsVALUE" (operational: 2,10,16)",
|
|
274
|
+
rb_String(base));
|
|
275
|
+
break;
|
|
276
|
+
default:
|
|
277
|
+
base = rb_Integer(base);
|
|
278
|
+
goto to_s_retry;
|
|
279
|
+
break;
|
|
280
|
+
}
|
|
281
|
+
to_s_none_finite:
|
|
282
|
+
if ('0' == ool_quad2str(f128, 'f', &exp, &sign, &str))
|
|
283
|
+
goto to_s_invalid_format;
|
|
284
|
+
if (sign == -1)
|
|
285
|
+
return rb_sprintf("-%s", str);
|
|
286
|
+
else
|
|
287
|
+
return rb_sprintf("%s", str);
|
|
288
|
+
to_s_invalid_format:
|
|
289
|
+
rb_raise(rb_eRuntimeError, "invalid format in ool_quad2str()");
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/*
|
|
293
|
+
* call-seq:
|
|
294
|
+
* to_i -> Integer
|
|
295
|
+
*
|
|
296
|
+
* +self+を整数にして返す.
|
|
297
|
+
* 非数や無限を変換しようとするとFloatDomainErrorが発生する.
|
|
298
|
+
*/
|
|
299
|
+
static VALUE
|
|
300
|
+
float128_to_i(VALUE self)
|
|
301
|
+
{
|
|
302
|
+
__float128 f128 = GetF128(self);
|
|
303
|
+
|
|
304
|
+
if (isinfq(f128) || isnanq(f128))
|
|
305
|
+
{
|
|
306
|
+
rb_raise(rb_eFloatDomainError, "%"PRIsVALUE"", rb_String(self));
|
|
307
|
+
}
|
|
308
|
+
else if (FIXABLE(f128))
|
|
309
|
+
{
|
|
310
|
+
return LONG2FIX((long)f128);
|
|
311
|
+
}
|
|
312
|
+
else
|
|
313
|
+
{
|
|
314
|
+
char* str;
|
|
315
|
+
int exp, sign;
|
|
316
|
+
|
|
317
|
+
ool_quad2str(f128, 'f', &exp, &sign, &str);
|
|
318
|
+
|
|
319
|
+
for (volatile int i = 0; i < (int)strlen(str); i++)
|
|
320
|
+
if (str[i] == '.') { str[i] = 0; break; }
|
|
321
|
+
|
|
322
|
+
if (sign == -1)
|
|
323
|
+
return rb_str_to_inum(rb_sprintf("-%s", str), 10, 1);
|
|
324
|
+
else /* if sign == 1 */
|
|
325
|
+
return rb_str_to_inum(rb_sprintf("%s", str), 10, 1);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/*
|
|
330
|
+
* call-seq:
|
|
331
|
+
* to_f -> Float
|
|
332
|
+
*
|
|
333
|
+
* +self+をFloat型にして返す.
|
|
334
|
+
* 内部的には__float128型をdouble型へキャストしている.
|
|
335
|
+
*/
|
|
336
|
+
static VALUE
|
|
337
|
+
float128_to_f(VALUE self)
|
|
338
|
+
{
|
|
339
|
+
__float128 f128 = GetF128(self);
|
|
340
|
+
|
|
341
|
+
return DBL2NUM((double)f128);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/*
|
|
345
|
+
* call-seq:
|
|
346
|
+
* to_f128 -> Float128
|
|
347
|
+
*
|
|
348
|
+
* 常に+self+を返す.
|
|
349
|
+
*/
|
|
350
|
+
static VALUE
|
|
351
|
+
float128_to_f128(VALUE self)
|
|
352
|
+
{
|
|
353
|
+
return self;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/*
|
|
357
|
+
* call-seq:
|
|
358
|
+
* to_c128 -> Complex128
|
|
359
|
+
*
|
|
360
|
+
* +self+をComplex128型にして返す.
|
|
361
|
+
* 内部的には__float128型を__complex128型へキャストしている.
|
|
362
|
+
*/
|
|
363
|
+
static VALUE
|
|
364
|
+
float128_to_c128(VALUE self)
|
|
365
|
+
{
|
|
366
|
+
__float128 f128 = GetF128(self);
|
|
367
|
+
|
|
368
|
+
return rb_complex128_cc128((__complex128)f128);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
#if 0
|
|
373
|
+
static VALUE
|
|
374
|
+
float128_initialize_copy(VALUE self, VALUE other)
|
|
375
|
+
{
|
|
376
|
+
struct F128 *pv = rb_check_typeddata(self, &float128_data_type);
|
|
377
|
+
struct F128 *x = rb_check_typeddata(other, &float128_data_type);
|
|
378
|
+
|
|
379
|
+
if (self != other)
|
|
380
|
+
{
|
|
381
|
+
pv->value = x->value;
|
|
382
|
+
}
|
|
383
|
+
return self;
|
|
384
|
+
}
|
|
385
|
+
#endif
|
|
386
|
+
|
|
387
|
+
/*
|
|
388
|
+
* call-seq:
|
|
389
|
+
* modf -> [Float128, Float128]
|
|
390
|
+
*
|
|
391
|
+
* +self+を整数部と小数部に分解し,ペアの配列で返す.
|
|
392
|
+
* これはC言語のmodf()を直接使えるようにしたものである.
|
|
393
|
+
*
|
|
394
|
+
* '12.345'.to_f128.modf # => [12.0, 0.345]
|
|
395
|
+
|
|
396
|
+
*/
|
|
397
|
+
static VALUE
|
|
398
|
+
float128_modf(VALUE self)
|
|
399
|
+
{
|
|
400
|
+
__float128 f128 = GetF128(self), intpart, frapart;
|
|
401
|
+
frapart = modfq(f128, &intpart);
|
|
402
|
+
return rb_assoc_new(
|
|
403
|
+
rb_float128_cf128(intpart),
|
|
404
|
+
rb_float128_cf128(frapart));
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/*
|
|
408
|
+
* call-seq:
|
|
409
|
+
* frexp -> [Float128, Integer]
|
|
410
|
+
*
|
|
411
|
+
* +self+を2を基底とした指数と仮数に分解し,[仮数, 指数]のペア配列で返す.
|
|
412
|
+
* 有限でない場合,どのような値が返るかは機種依存である.
|
|
413
|
+
*
|
|
414
|
+
* 8.to_f128.frexp # => [0.5, 4]
|
|
415
|
+
*/
|
|
416
|
+
static VALUE
|
|
417
|
+
float128_frexp(VALUE self)
|
|
418
|
+
{
|
|
419
|
+
__float128 f128 = GetF128(self), frapart;
|
|
420
|
+
int exppart;
|
|
421
|
+
frapart = frexpq(f128, &exppart);
|
|
422
|
+
return rb_assoc_new(
|
|
423
|
+
rb_float128_cf128(frapart),
|
|
424
|
+
INT2FIX(exppart));
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/*
|
|
428
|
+
* call-seq:
|
|
429
|
+
* scalb(n) -> Float128
|
|
430
|
+
* scalbn(n) -> Float128
|
|
431
|
+
*
|
|
432
|
+
* +self+にFloat::RADIXのn乗をかけた値にする.
|
|
433
|
+
* 特異メソッドにも同等のメソッドがあるが,こちらはレシーバをオペランドの代わりにしたものである.
|
|
434
|
+
*
|
|
435
|
+
* Float::RADIX # => 2
|
|
436
|
+
* x = 3.to_f128
|
|
437
|
+
* x.scalb(4) # => 48.0
|
|
438
|
+
*/
|
|
439
|
+
static VALUE
|
|
440
|
+
float128_scalb(VALUE self, VALUE n)
|
|
441
|
+
{
|
|
442
|
+
__float128 f128 = GetF128(self);
|
|
443
|
+
long v_exp = NUM2LONG(n);
|
|
444
|
+
|
|
445
|
+
return rb_float128_cf128(scalbln(f128, v_exp));
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
/*
|
|
449
|
+
* call-seq:
|
|
450
|
+
* floor -> Integer
|
|
451
|
+
*
|
|
452
|
+
* Returns floor function of +self+.
|
|
453
|
+
*
|
|
454
|
+
* Float128('1.1').floor # => 1
|
|
455
|
+
* Float128('2.5').floor # => 2
|
|
456
|
+
*/
|
|
457
|
+
static VALUE
|
|
458
|
+
float128_floor(VALUE self)
|
|
459
|
+
{
|
|
460
|
+
__float128 x = GetF128(self);
|
|
461
|
+
self = rb_float128_cf128(floorq(x));
|
|
462
|
+
return float128_to_i(self);
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
/*
|
|
466
|
+
* call-seq:
|
|
467
|
+
* ceil -> Integer
|
|
468
|
+
*
|
|
469
|
+
* Returns ceiling function of +self+.
|
|
470
|
+
*
|
|
471
|
+
* Float128('1.1').ceil # => 2
|
|
472
|
+
* Float128('2.5').ceil # => 3
|
|
473
|
+
*/
|
|
474
|
+
static VALUE
|
|
475
|
+
float128_ceil(VALUE self)
|
|
476
|
+
{
|
|
477
|
+
__float128 x = GetF128(self);
|
|
478
|
+
self = rb_float128_cf128(ceilq(x));
|
|
479
|
+
return float128_to_i(self);
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/*
|
|
483
|
+
* call-seq:
|
|
484
|
+
* round -> Integer
|
|
485
|
+
*
|
|
486
|
+
* Returns rounding-off of +self+.
|
|
487
|
+
*
|
|
488
|
+
* Float128('1.1').round # => 1
|
|
489
|
+
* Float128('2.5').round # => 3
|
|
490
|
+
*/
|
|
491
|
+
static VALUE
|
|
492
|
+
float128_round(VALUE self)
|
|
493
|
+
{
|
|
494
|
+
__float128 x = GetF128(self);
|
|
495
|
+
self = rb_float128_cf128(roundq(x));
|
|
496
|
+
return float128_to_i(self);
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
/*
|
|
500
|
+
* call-seq:
|
|
501
|
+
* truncate -> Integer
|
|
502
|
+
*
|
|
503
|
+
* Returns truncate of +self+.
|
|
504
|
+
*
|
|
505
|
+
* Float128('1.1').truncate # => 1
|
|
506
|
+
* Float128('2.5').truncate # => 2
|
|
507
|
+
*/
|
|
508
|
+
static VALUE
|
|
509
|
+
float128_truncate(VALUE self)
|
|
510
|
+
{
|
|
511
|
+
__float128 x = GetF128(self);
|
|
512
|
+
self = rb_float128_cf128(truncq(x));
|
|
513
|
+
return float128_to_i(self);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
|
|
517
|
+
static VALUE
|
|
518
|
+
float128_nextafter(VALUE f128, __float128 value)
|
|
519
|
+
{
|
|
520
|
+
__float128 x, y;
|
|
521
|
+
x = GetF128(f128);
|
|
522
|
+
y = nextafterq(x, value);
|
|
523
|
+
return rb_float128_cf128(y);
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
/*
|
|
527
|
+
* call-seq:
|
|
528
|
+
* next_float -> Float128
|
|
529
|
+
*
|
|
530
|
+
* Returns the next-larger representable \Float128.
|
|
531
|
+
*
|
|
532
|
+
* f128 = Float128('0') # => 0.0
|
|
533
|
+
* f128.next_float # => 0x0.0000000000000000000000000001p-16382
|
|
534
|
+
*
|
|
535
|
+
* f128 = Float128('1') # => 0x1p-1
|
|
536
|
+
* f128.next_float # => 0x1.0000000000000000000000000001p-1
|
|
537
|
+
*
|
|
538
|
+
* Float128('0.01').next_float # => 0.010000000000000000000000000000000002
|
|
539
|
+
* Float128('1').next_float # => 1.0000000000000000000000000000000002
|
|
540
|
+
* Float128('100').next_float # => 100.00000000000000000000000000000001
|
|
541
|
+
*/
|
|
542
|
+
static VALUE
|
|
543
|
+
float128_next_float(VALUE self)
|
|
544
|
+
{
|
|
545
|
+
return float128_nextafter(self, HUGE_VALQ);
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
/*
|
|
549
|
+
* call-seq:
|
|
550
|
+
* prev_float -> Float128
|
|
551
|
+
*
|
|
552
|
+
* Returns the next-smaller representable \Float128.
|
|
553
|
+
*
|
|
554
|
+
* f128 = Float128('0') # => 0.0
|
|
555
|
+
* f128.prev_float # => -0x0.0000000000000000000000000001p-16382
|
|
556
|
+
*
|
|
557
|
+
* f128 = Float128('1') # => 0x1p-1
|
|
558
|
+
* f128.prev_float # => 0x1.ffffffffffffffffffffffffffffp-2
|
|
559
|
+
*
|
|
560
|
+
* Float128('1').prev_float # => 0.999999999999999999999999999999999
|
|
561
|
+
* Float128('100').prev_float # => 99.9999999999999999999999999999999
|
|
562
|
+
*/
|
|
563
|
+
static VALUE
|
|
564
|
+
float128_prev_float(VALUE self)
|
|
565
|
+
{
|
|
566
|
+
return float128_nextafter(self, -HUGE_VALQ);
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
void
|
|
570
|
+
InitVM_Float128(void)
|
|
571
|
+
{
|
|
572
|
+
/* Class methods */
|
|
573
|
+
rb_undef_alloc_func(rb_cFloat128);
|
|
574
|
+
rb_undef_method(CLASS_OF(rb_cFloat128), "new");
|
|
575
|
+
|
|
576
|
+
/* Object methods */
|
|
577
|
+
rb_define_method(rb_cFloat128, "hash", float128_hash, 0);
|
|
578
|
+
rb_define_method(rb_cFloat128, "eql?", float128_eql_p, 1);
|
|
579
|
+
|
|
580
|
+
/* The unique Methods */
|
|
581
|
+
rb_define_method(rb_cFloat128, "infinite?", float128_infinite_p, 0);
|
|
582
|
+
rb_define_method(rb_cFloat128, "finite?", float128_finite_p, 0);
|
|
583
|
+
rb_define_method(rb_cFloat128, "nan?", float128_nan_p, 0);
|
|
584
|
+
|
|
585
|
+
/* Type convertion methods */
|
|
586
|
+
rb_define_method(rb_cFloat128, "inspect", float128_inspect, 0);
|
|
587
|
+
rb_define_method(rb_cFloat128, "to_s", float128_to_s, -1);
|
|
588
|
+
|
|
589
|
+
rb_define_method(rb_cFloat128, "to_f", float128_to_f, 0);
|
|
590
|
+
rb_define_method(rb_cFloat128, "to_f128", float128_to_f128, 0);
|
|
591
|
+
|
|
592
|
+
rb_define_method(rb_cFloat128, "to_i", float128_to_i, 0);
|
|
593
|
+
|
|
594
|
+
rb_define_method(rb_cFloat128, "to_c128", float128_to_c128, 0);
|
|
595
|
+
|
|
596
|
+
/* Utilities */
|
|
597
|
+
rb_define_method(rb_cFloat128, "modf", float128_modf, 0);
|
|
598
|
+
rb_define_method(rb_cFloat128, "frexp", float128_frexp, 0);
|
|
599
|
+
rb_define_method(rb_cFloat128, "scalb", float128_scalb, 1);
|
|
600
|
+
rb_define_alias(rb_cFloat128, "scalbn", "scalb");
|
|
601
|
+
rb_define_method(rb_cFloat128, "floor", float128_floor, 0);
|
|
602
|
+
rb_define_method(rb_cFloat128, "ceil", float128_ceil, 0);
|
|
603
|
+
rb_define_method(rb_cFloat128, "round", float128_round, 0);
|
|
604
|
+
rb_define_method(rb_cFloat128, "truncate", float128_truncate, 0);
|
|
605
|
+
rb_define_method(rb_cFloat128, "next_float", float128_next_float, 0);
|
|
606
|
+
rb_define_method(rb_cFloat128, "prev_float", float128_prev_float, 0);
|
|
607
|
+
|
|
608
|
+
/* Constants */
|
|
609
|
+
rb_define_const(rb_cFloat128, "NAN", rb_float128_cf128(nanq(NULL)));
|
|
610
|
+
rb_define_const(rb_cFloat128, "INFINITY", rb_float128_cf128(HUGE_VALQ));
|
|
611
|
+
|
|
612
|
+
rb_define_const(rb_cFloat128, "MAX", rb_float128_cf128(FLT128_MAX));
|
|
613
|
+
rb_define_const(rb_cFloat128, "MIN", rb_float128_cf128(FLT128_MIN));
|
|
614
|
+
rb_define_const(rb_cFloat128, "EPSILON", rb_float128_cf128(FLT128_EPSILON));
|
|
615
|
+
rb_define_const(rb_cFloat128, "DENORM_MIN", rb_float128_cf128(FLT128_DENORM_MIN));
|
|
616
|
+
rb_define_const(rb_cFloat128, "MANT_DIG", INT2NUM(FLT128_MANT_DIG));
|
|
617
|
+
rb_define_const(rb_cFloat128, "MIN_EXP", INT2NUM(FLT128_MIN_EXP));
|
|
618
|
+
rb_define_const(rb_cFloat128, "MAX_EXP", INT2NUM(FLT128_MAX_EXP));
|
|
619
|
+
rb_define_const(rb_cFloat128, "DIG", INT2NUM(FLT128_DIG));
|
|
620
|
+
rb_define_const(rb_cFloat128, "MIN_10_EXP", INT2NUM(FLT128_MIN_10_EXP));
|
|
621
|
+
rb_define_const(rb_cFloat128, "MAX_10_EXP", INT2NUM(FLT128_MAX_10_EXP));
|
|
622
|
+
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
VALUE
|
|
626
|
+
rb_float128_cf128(const __float128 x)
|
|
627
|
+
{
|
|
628
|
+
VALUE obj = float128_allocate(x);
|
|
629
|
+
return obj;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
__float128
|
|
633
|
+
rb_float128_value(VALUE x)
|
|
634
|
+
{
|
|
635
|
+
struct F128 *f128 = rb_check_typeddata(x, &float128_data_type);
|
|
636
|
+
|
|
637
|
+
return f128->value;
|
|
638
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#ifndef RB_QUADMATH_INTERNAL_TYPES_H
|
|
2
|
+
#define RB_QUADMATH_INTERNAL_TYPES_H
|
|
3
|
+
|
|
4
|
+
#if defined(__cplusplus)
|
|
5
|
+
extern "C" {
|
|
6
|
+
#endif
|
|
7
|
+
|
|
8
|
+
__float128 GetF128(VALUE);
|
|
9
|
+
__complex128 GetC128(VALUE);
|
|
10
|
+
|
|
11
|
+
VALUE float128_nucomp_pow(VALUE x, VALUE y);
|
|
12
|
+
VALUE float128_to_s(int argc, VALUE *argv, VALUE self);
|
|
13
|
+
|
|
14
|
+
enum NUMERIC_SUBCLASSES {
|
|
15
|
+
NUM_FIXNUM,
|
|
16
|
+
NUM_BIGNUM,
|
|
17
|
+
NUM_RATIONAL,
|
|
18
|
+
NUM_FLOAT,
|
|
19
|
+
NUM_COMPLEX,
|
|
20
|
+
NUM_FLOAT128,
|
|
21
|
+
NUM_COMPLEX128,
|
|
22
|
+
NUM_OTHERTYPE
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
static inline enum NUMERIC_SUBCLASSES
|
|
26
|
+
convertion_num_types(VALUE obj)
|
|
27
|
+
{
|
|
28
|
+
switch (TYPE(obj)) {
|
|
29
|
+
case T_FIXNUM:
|
|
30
|
+
return NUM_FIXNUM;
|
|
31
|
+
break;
|
|
32
|
+
case T_BIGNUM:
|
|
33
|
+
return NUM_BIGNUM;
|
|
34
|
+
break;
|
|
35
|
+
case T_RATIONAL:
|
|
36
|
+
return NUM_RATIONAL;
|
|
37
|
+
break;
|
|
38
|
+
case T_FLOAT:
|
|
39
|
+
return NUM_FLOAT;
|
|
40
|
+
break;
|
|
41
|
+
case T_COMPLEX:
|
|
42
|
+
return NUM_COMPLEX;
|
|
43
|
+
break;
|
|
44
|
+
case T_NIL:
|
|
45
|
+
case T_TRUE:
|
|
46
|
+
case T_FALSE:
|
|
47
|
+
rb_raise(rb_eTypeError,
|
|
48
|
+
"can't convert %"PRIsVALUE" into %s|%s",
|
|
49
|
+
rb_String(obj), rb_class2name(rb_cFloat128),
|
|
50
|
+
rb_class2name(rb_cComplex128));
|
|
51
|
+
default:
|
|
52
|
+
if (CLASS_OF(obj) == rb_cFloat128)
|
|
53
|
+
return NUM_FLOAT128;
|
|
54
|
+
else if (CLASS_OF(obj) == rb_cComplex128)
|
|
55
|
+
return NUM_COMPLEX128;
|
|
56
|
+
else
|
|
57
|
+
{
|
|
58
|
+
VALUE num_subclasses = rb_class_subclasses(rb_cNumeric);
|
|
59
|
+
if (RTEST(rb_ary_includes(num_subclasses, CLASS_OF(obj))))
|
|
60
|
+
return NUM_OTHERTYPE;
|
|
61
|
+
else
|
|
62
|
+
rb_raise(rb_eTypeError,
|
|
63
|
+
"can't convert %"PRIsVALUE" into %s|%s",
|
|
64
|
+
CLASS_OF(obj), rb_class2name(rb_cFloat128),
|
|
65
|
+
rb_class2name(rb_cComplex128));
|
|
66
|
+
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
#if defined(__cplusplus)
|
|
72
|
+
}
|
|
73
|
+
#endif
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
#endif /* RB_QUADMATH_INTERNAL_TYPES_H */
|
|
77
|
+
|