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.
@@ -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
+