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,2657 @@
1
+ /*******************************************************************************
2
+ numerable.c -- Numerable for quadmath arithmetic
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
+
12
+ #define OPE_ADD 1
13
+ #define OPE_SUB 2
14
+ #define OPE_MUL 3
15
+ #define OPE_DIV 4
16
+ #define OPE_MOD 5
17
+ #define OPE_POW 6
18
+ #define OPE_CMP 7
19
+ #define OPE_COERCE 8
20
+
21
+ #define FMT_EMPTY 0
22
+ #define FMT_DRCTV 1
23
+ #define FMT_WIDTH 2
24
+ #define FMT_WIDTH_SCALAR 3
25
+ #define FMT_POINT 4
26
+ #define FMT_PREC 5
27
+ #define FMT_PREC_SCALAR 6
28
+ #define FMT_SET_FT 7
29
+
30
+ #define FLAG_SHARP 0x1
31
+ #define FLAG_ZERO 0x2
32
+ #define FLAG_SPACE 0x4
33
+ #define FLAG_PLUS 0x8
34
+ #define FLAG_MINUS 0x10
35
+
36
+ #define FT_FLT 0
37
+ #define FT_DBL 1
38
+ #define FT_LDBL 2
39
+ #define FT_QUAD 3
40
+
41
+ #define BUF_SIZ 128
42
+
43
+ __complex128
44
+ cmodq(__complex128 z, __complex128 w)
45
+ {
46
+ return 0+0i; // 未定義
47
+ }
48
+
49
+ static inline VALUE
50
+ numeric_to_f128_inline(VALUE self, int exception)
51
+ {
52
+
53
+ if (!rb_respond_to(self, rb_intern("to_f128")))
54
+ {
55
+ if (!exception)
56
+ return Qnil;
57
+ else
58
+ rb_raise(rb_eNoMethodError,
59
+ "can't convert %"PRIsVALUE" into %s",
60
+ rb_String(self), rb_class2name(rb_cFloat128));
61
+ }
62
+ else
63
+ return rb_funcall(self, rb_intern("to_f128"), 0);
64
+ }
65
+
66
+ /*
67
+ * call-seq:
68
+ * to_f128 -> Float128
69
+ *
70
+ * A hook for subclasses that require the system to convert to Float128 type.
71
+ * Internally it calls a method. In reality it is undefined.
72
+ */
73
+ static VALUE
74
+ numeric_to_f128(VALUE self)
75
+ {
76
+ return numeric_to_f128_inline(self, true);
77
+ }
78
+
79
+ static inline VALUE
80
+ numeric_to_c128_inline(VALUE self, int exception)
81
+ {
82
+ if (!rb_respond_to(self, rb_intern("to_c128")))
83
+ {
84
+ if (!exception)
85
+ return Qnil;
86
+ else
87
+ rb_raise(rb_eNoMethodError,
88
+ "can't convert %"PRIsVALUE" into %s",
89
+ rb_String(self), rb_class2name(rb_cComplex128));
90
+ }
91
+ else
92
+ return rb_funcall(self, rb_intern("to_c128"), 0);
93
+ }
94
+
95
+ /*
96
+ * call-seq:
97
+ * to_c128 -> Complex128
98
+ *
99
+ * A hook for subclasses that require the system to convert to Float128 type.
100
+ * Internally it calls a method. In reality it is undefined.
101
+ */
102
+ static VALUE
103
+ numeric_to_c128(VALUE self)
104
+ {
105
+ return numeric_to_c128_inline(self, true);
106
+ }
107
+
108
+ static VALUE
109
+ string_to_f128_inline(VALUE self, int exception)
110
+ {
111
+ char *sp = NULL;
112
+ __float128 x = strtoflt128(StringValuePtr(self), &sp);
113
+
114
+ if (strlen(sp) != 0)
115
+ {
116
+ if (exception == true)
117
+ rb_raise(rb_eArgError,
118
+ "invalid value for Float128(): %"PRIsVALUE"", self);
119
+ else
120
+ return Qnil;
121
+ }
122
+
123
+ return rb_float128_cf128(x);
124
+ }
125
+
126
+ /*
127
+ * call-seq:
128
+ * to_f128 -> Float128
129
+ *
130
+ * Creates a Float128 type from a String. Implemented as a library function.
131
+ *
132
+ * '1.3'.to_f128 # => 1.3
133
+ * 1.3.to_f128 # => 1.3000000000000000444089209850062
134
+ * Float128('true') #=> ArgumentError
135
+ */
136
+ static VALUE
137
+ string_to_f128(VALUE self)
138
+ {
139
+ VALUE val = string_to_f128_inline(self, false);
140
+
141
+ if (NIL_P(val))
142
+ val = rb_float128_cf128(0);
143
+
144
+ return val;
145
+ }
146
+
147
+ static VALUE
148
+ string_to_c128_inline(VALUE self, int exception)
149
+ {
150
+ char *sp = NULL;
151
+ __float128 x = strtoflt128(StringValuePtr(self), &sp);
152
+ __complex128 z = 0+0i;
153
+
154
+ if (strlen(sp) == 0)
155
+ __real__ z = x;
156
+ else
157
+ {
158
+ const char c = sp[0];
159
+ switch (c) {
160
+ case 'i':
161
+ if (strlen(sp) == 1)
162
+ {
163
+ __imag__ z = x;
164
+ goto retval;
165
+ }
166
+ break;
167
+ case '+': case '-':
168
+ __real__ z = x;
169
+ __imag__ z = strtoflt128(sp, &sp);
170
+ if (strlen(sp) == 1 && sp[0] == 'i')
171
+ goto retval;
172
+ break;
173
+ }
174
+ if (exception == true)
175
+ rb_raise(rb_eArgError,
176
+ "invalid value for Complex128(): %"PRIsVALUE"", self);
177
+ else
178
+ return Qnil;
179
+ }
180
+ retval:
181
+ return rb_complex128_cc128(z);
182
+ }
183
+
184
+ /*
185
+ * call-seq:
186
+ * to_c128 -> Complex128
187
+ *
188
+ * Creates a Complex128 type from a String. Implemented as a library function.
189
+ *
190
+ * Complex128('-12i') #=> (0.0-12.0i)
191
+ * Complex128('-1+12i') #=> (-1.0+12.0i)
192
+ * Complex128('1.0e2+1e1i') #=> (100.0+10.0i)
193
+ */
194
+ static VALUE
195
+ string_to_c128(VALUE self)
196
+ {
197
+ VALUE val = string_to_c128_inline(self, false);
198
+
199
+ if (NIL_P(val))
200
+ val = rb_complex128_cc128(0+0i);
201
+
202
+ return val;
203
+ }
204
+
205
+ static inline __float128
206
+ integer_to_cf128(VALUE self)
207
+ {
208
+ __float128 x = 0.0Q;
209
+ switch (TYPE(self)) {
210
+ case T_FIXNUM:
211
+ x = (__float128)FIX2LONG(self);
212
+ break;
213
+ case T_BIGNUM:
214
+ VALUE inum = rb_big2str(self, 10);
215
+ x = strtoflt128(StringValuePtr(inum), NULL);
216
+ default:
217
+ break;
218
+ }
219
+ return x;
220
+ }
221
+
222
+ /*
223
+ * call-seq:
224
+ * to_f128 -> Float128
225
+ *
226
+ * Converts from Integer to Float128 type.
227
+ * Internally, the conversion is performed in a way that minimizes loss of precision.
228
+ *
229
+ * 1.to_f128 # => 1.0
230
+ * (-1024**1024).to_f128 # => -3.52497141210838265713481483980028e+3082
231
+ */
232
+ static VALUE
233
+ integer_to_f128(VALUE self)
234
+ {
235
+ __float128 x = integer_to_cf128(self);
236
+
237
+ return rb_float128_cf128(x);
238
+ }
239
+
240
+ /*
241
+ * call-seq:
242
+ * to_c128 -> Complex128
243
+ *
244
+ * Convert from Integer to Complex128 type.
245
+ * It has the same implementation as to_f128, but first converts to Float128 type and then performs type casting at the C level.
246
+ *
247
+ * -1.to_c128 # => (-1.0+0.0i)
248
+
249
+ */
250
+ static VALUE
251
+ integer_to_c128(VALUE self)
252
+ {
253
+ __complex128 z = (__complex128)integer_to_cf128(self);
254
+ return rb_complex128_cc128(z);
255
+ }
256
+
257
+
258
+
259
+ static inline __float128
260
+ rational_to_cf128(VALUE self)
261
+ {
262
+ VALUE numer = rb_rational_num(self),
263
+ denom = rb_rational_den(self);
264
+
265
+ return integer_to_cf128(numer) / integer_to_cf128(denom);
266
+ }
267
+
268
+ /*
269
+ * call-seq:
270
+ * to_f128 -> Float128
271
+ *
272
+ * Convert from Rational to Float128 type.
273
+ * Accurate type conversion can be expected because the conversion involves extracting the numerator and denominator separately and then dividing them.
274
+ * When Rational is generated from double precision, some values​may be missing information.
275
+ *
276
+ * (-1/3r).to_f128 # => -0.333333333333333333333333333333333
277
+ * Rational(2.1).to_f128 # => 2.1000000000000000888178419700125
278
+ */
279
+ static VALUE
280
+ rational_to_f128(VALUE self)
281
+ {
282
+ __float128 x = rational_to_cf128(self);
283
+
284
+ return rb_float128_cf128(x);
285
+ }
286
+
287
+ /*
288
+ * call-seq:
289
+ * to_c128 -> Complex128
290
+ *
291
+ * Convert from Rational to Complex128 type.
292
+ * It has the same implementation as to_f128, but it is first converted to Float128 and then typecast at the C level.
293
+ *
294
+ * Rational(-1, 2).to_c128 # => (-0.5+0.0i)
295
+ */
296
+ static VALUE
297
+ rational_to_c128(VALUE self)
298
+ {
299
+ __complex128 z = (__complex128)rational_to_cf128(self);
300
+ return rb_complex128_cc128(z);
301
+ }
302
+
303
+
304
+ /*
305
+ * call-seq:
306
+ * to_f128 -> Float128
307
+ *
308
+ * Converts Float to Float128 type. Type casting is performed at the C level.
309
+ * Note that this is a conversion from double to quad precision, so information may be lost.
310
+ *
311
+ * Float::INFINITY.to_f128 == Float::INFINITY # => true
312
+ * -Float('1').to_f128 == Float128('-1.0') # => true
313
+ * -Float('1.1').to_f128 == Float128('-1.1') # => false
314
+ *
315
+ */
316
+ static VALUE
317
+ float_to_f128(VALUE self)
318
+ {
319
+ double x = NUM2DBL(self);
320
+
321
+ return rb_float128_cf128((__float128)x);
322
+ }
323
+
324
+ /*
325
+ * call-seq:
326
+ * to_c128 -> Complex128
327
+ *
328
+ * Converts Float to Complex128 type. Type casting is performed at the C level.
329
+ * Note that this is a conversion from double to quad precision, so information may be lost.
330
+ *
331
+ * Float::INFINITY.to_c128 # => (Infinity+0.0i)
332
+ * c128 = 1.5.to_c128 # => (1.5+0.0i)
333
+ * c128.class # => Complex128
334
+ */
335
+ static VALUE
336
+ float_to_c128(VALUE self)
337
+ {
338
+ double x = NUM2DBL(self);
339
+ return rb_complex128_cc128((__complex128)x);
340
+ }
341
+
342
+
343
+
344
+ static inline __float128
345
+ elem_to_cf128(VALUE self)
346
+ {
347
+ __float128 x;
348
+ switch (TYPE(self)) {
349
+ case T_FIXNUM:
350
+ case T_BIGNUM:
351
+ x = integer_to_cf128(self);
352
+ break;
353
+ case T_RATIONAL:
354
+ x = rational_to_cf128(self);
355
+ break;
356
+ case T_FLOAT:
357
+ x = (__float128)NUM2DBL(self);
358
+ break;
359
+ default:
360
+ if (CLASS_OF(self) != rb_cFloat128)
361
+ self = rb_funcall(self, rb_intern("to_f128"), 0);
362
+
363
+ x = rb_float128_value(self);
364
+
365
+ break;
366
+ }
367
+ return x;
368
+ }
369
+
370
+
371
+ static inline VALUE
372
+ nucomp_to_f128_inline(VALUE self, int exception)
373
+ {
374
+ VALUE real = rb_complex_real(self),
375
+ imag = rb_complex_imag(self);
376
+
377
+ if (elem_to_cf128(imag) != 0)
378
+ {
379
+ if (!exception)
380
+ return Qnil;
381
+ else
382
+ rb_raise(rb_eRangeError,
383
+ "can't convert %"PRIsVALUE" into %s",
384
+ rb_String(self), rb_class2name(rb_cFloat128));
385
+ }
386
+ return rb_float128_cf128(elem_to_cf128(real));
387
+ }
388
+
389
+ static VALUE
390
+ nucomp_to_f128(VALUE self)
391
+ {
392
+ return nucomp_to_f128_inline(self, true);
393
+ }
394
+
395
+ static VALUE
396
+ nucomp_to_c128(VALUE self)
397
+ {
398
+ VALUE real = rb_complex_real(self),
399
+ imag = rb_complex_imag(self);
400
+ __complex128 z;
401
+ __real__ z = elem_to_cf128(real);
402
+ __imag__ z = elem_to_cf128(imag);
403
+
404
+ return rb_complex128_cc128(z);
405
+ }
406
+
407
+ static inline VALUE
408
+ complex128_to_f128_inline(VALUE self, int exception)
409
+ {
410
+ __complex128 z = rb_complex128_value(self);
411
+
412
+ if (cimagq(z) != 0)
413
+ {
414
+ if (!exception)
415
+ return Qnil;
416
+ else
417
+ rb_raise(rb_eRangeError,
418
+ "can't convert %"PRIsVALUE" into %s",
419
+ rb_String(self), rb_class2name(rb_cFloat128));
420
+ }
421
+ return rb_float128_cf128(crealq(z));
422
+ }
423
+
424
+ static inline VALUE
425
+ float128_to_c128_inline(VALUE self)
426
+ {
427
+ __float128 x = rb_float128_value(self);
428
+
429
+ return rb_complex128_cc128((__complex128)x);
430
+ }
431
+
432
+ /*
433
+ * call-seq:
434
+ * Float128(val) -> Float128
435
+ * Float128(val, exception: false) -> Float128 | nil
436
+ *
437
+ * Generates a Float128 from +val+. +val+ can be generated from +self+ or other numeric classes, String, etc.
438
+ * If the conversion is not possible, a RangeError is raised.
439
+ * Literals are converted to quadruple precision whenever possible. However, caution is required when converting from double precision, as there is a low chance that precision will be preserved.
440
+ * By setting the keyword argument exception to false, nil will be returned in the event of an exception.
441
+ *
442
+ * Float128(1) # => 1.0
443
+ * Float128(2.0) # => 2.0
444
+ * Float128(2.1) # => 2.1000000000000000888178419700125
445
+ * Float128('2.1') # => 2.1
446
+ * Float128(1.0/3.0) # => 0.333333333333333314829616256247391
447
+ * Float128(1/3r) # => 0.333333333333333333333333333333333
448
+ * Float128(1+0i) # => 1.0
449
+ * Float128(1i) # => RangeError
450
+ * Float128(1i, exception: false) # => nil
451
+ * Float128('1+1', exception: false) # => nil
452
+ */
453
+ static VALUE
454
+ f_Float128(int argc, VALUE *argv, VALUE self)
455
+ {
456
+ VALUE val, opts = Qnil;
457
+ argc = rb_scan_args(argc, argv, "11", &val, &opts);
458
+ int exception = opts_exception_p(opts);
459
+
460
+ switch (TYPE(val)) {
461
+ case T_FIXNUM:
462
+ case T_BIGNUM:
463
+ val = integer_to_f128(val);
464
+ break;
465
+ case T_RATIONAL:
466
+ val = rational_to_f128(val);
467
+ break;
468
+ case T_FLOAT:
469
+ val = float_to_f128(val);
470
+ break;
471
+ case T_COMPLEX:
472
+ val = nucomp_to_f128_inline(val, exception);
473
+ break;
474
+ case T_STRING:
475
+ val = string_to_f128_inline(val, exception);
476
+ break;
477
+ default:
478
+ if (CLASS_OF(val) == rb_cFloat128);
479
+ else if (CLASS_OF(val) == rb_cComplex128)
480
+ val = complex128_to_f128_inline(val, exception);
481
+ else
482
+ val = numeric_to_f128_inline(val, exception);
483
+ break;
484
+ }
485
+ return val;
486
+ }
487
+
488
+ /*
489
+ * call-seq:
490
+ * Complex128(val) -> Complex128
491
+ * Complex128(val, exception: false) -> Complex128 | nil
492
+ *
493
+ * Generates a Complex128 from +val+. +val+ can be generated from +self+ or other numeric classes, String, etc.
494
+ *
495
+ * Complex128(5) # => (5.0+0.0i)
496
+ * Complex128(5.0) # => (5.0+0.0i)
497
+ * Complex128(2/3r) # => (0.666666666666666666666666666666667+0.0i)
498
+ * Complex128(1+2i) # => (1.0+2.0i)
499
+ * Complex128(Float128('1.3')) # => (1.3+0.0i)
500
+ * Complex128(1.3) # => (1.3000000000000000444089209850062+0.0i)
501
+ * Complex128('1.3') # => (1.3+0.0i)
502
+ * Complex128('5i') #=> (0.0+5.0i)
503
+ * Complex128('2-12', exception: false) #=> nil
504
+ */
505
+ static VALUE
506
+ f_Complex128(int argc, VALUE *argv, VALUE self)
507
+ {
508
+ VALUE val, opts = Qnil;
509
+ argc = rb_scan_args(argc, argv, "11", &val, &opts);
510
+ int exception = opts_exception_p(opts);
511
+
512
+ switch (TYPE(val)) {
513
+ case T_FIXNUM:
514
+ case T_BIGNUM:
515
+ val = integer_to_c128(val);
516
+ break;
517
+ case T_RATIONAL:
518
+ val = rational_to_c128(val);
519
+ break;
520
+ case T_FLOAT:
521
+ val = float_to_c128(val);
522
+ break;
523
+ case T_COMPLEX:
524
+ val = nucomp_to_c128(val);
525
+ break;
526
+ case T_STRING:
527
+ val = string_to_c128_inline(val, exception);
528
+ break;
529
+ default:
530
+ if (CLASS_OF(val) == rb_cComplex128);
531
+ else if (CLASS_OF(val) == rb_cFloat128)
532
+ val = float128_to_c128_inline(val);
533
+ else
534
+ val = numeric_to_c128_inline(val, exception);
535
+ break;
536
+ }
537
+ return val;
538
+ }
539
+
540
+
541
+ /*
542
+ * call-seq:
543
+ * polar -> [Float128, Float128]
544
+ *
545
+ * Returns the absolute value and argument of +self+ as an array. It behaves the same as Float but has different precision.
546
+ *
547
+ * 1.0.polar # => [1.0, 0]
548
+ * Float128('2.0').polar # => [2.0, 0]
549
+ * -1.0.polar # => [1.0, 3.141592653589793]
550
+ * Float128('-1.0').polar # => [1.0, 3.1415926535897932384626433832795]
551
+ *
552
+ */
553
+ static VALUE
554
+ float128_polar(VALUE self)
555
+ {
556
+ __float128 f128 = GetF128(self);
557
+
558
+ if (signbitq(f128))
559
+ return rb_assoc_new(
560
+ rb_float128_cf128(fabsq(f128)),
561
+ rb_float128_cf128(M_PIq));
562
+ else
563
+ return rb_assoc_new(
564
+ rb_float128_cf128(fabsq(f128)),
565
+ INT2NUM(0));
566
+ }
567
+
568
+
569
+ /*
570
+ * call-seq:
571
+ * abs -> Float128
572
+ * magnitude -> Float128
573
+ *
574
+ * Returns the absolute value of +self+.
575
+ */
576
+ static VALUE
577
+ float128_abs(VALUE self)
578
+ {
579
+ __float128 f128 = GetF128(self);
580
+
581
+ return rb_float128_cf128(fabsq(f128));
582
+ }
583
+
584
+ /*
585
+ * call-seq:
586
+ * abs2 -> Float128
587
+ *
588
+ * Returns the absolute value squared of +self+.
589
+ */
590
+ static VALUE
591
+ float128_abs2(VALUE self)
592
+ {
593
+ __float128 f128 = GetF128(self);
594
+
595
+ return rb_float128_cf128(f128 * f128);
596
+ }
597
+
598
+
599
+ /*
600
+ * call-seq:
601
+ * arg -> 0 | QuadMath::PI
602
+ * angle -> 0 | QuadMath::PI
603
+ * phase -> 0 | QuadMath::PI
604
+ *
605
+ * Returns the argument of +self+ (0 if positive, PI if negative).
606
+ * It behaves the same as the Float type, but has different a class.
607
+ *
608
+ * Float128('1').arg # => 0
609
+ * Float128('-1').arg # => 3.1415926535897932384626433832795
610
+ * Float('-1').arg # => 3.141592653589793
611
+ */
612
+ static VALUE
613
+ float128_arg(VALUE self)
614
+ {
615
+ __float128 f128 = GetF128(self);
616
+
617
+ return signbitq(f128) ?
618
+ rb_float128_cf128(M_PIq) :
619
+ INT2NUM(0);
620
+ }
621
+
622
+
623
+ static inline __float128
624
+ f128_modulo(__float128 x, __float128 y)
625
+ {
626
+ switch ((signbitq(x) << 1) | signbitq(y)) {
627
+ case 0b00: case 0b11:
628
+ return fmodq(x, y);
629
+ default:
630
+ return x - y * floorq(x / y);
631
+ }
632
+ }
633
+
634
+ static inline __float128
635
+ get_real(VALUE num)
636
+ {
637
+ __float128 real;
638
+ VALUE nucomp;
639
+
640
+ switch (convertion_num_types(num)) {
641
+ case NUM_FIXNUM:
642
+ case NUM_BIGNUM:
643
+ real = integer_to_cf128(num);
644
+ break;
645
+ case NUM_RATIONAL:
646
+ real = rational_to_cf128(num);
647
+ break;
648
+ case NUM_FLOAT:
649
+ real = (__float128)NUM2DBL(num);
650
+ break;
651
+ case NUM_COMPLEX:
652
+ nucomp = nucomp_to_f128_inline(num, false);
653
+ if (NIL_P(nucomp)) goto not_a_real;
654
+ real = rb_float128_value(nucomp);
655
+ break;
656
+ case NUM_FLOAT128:
657
+ real = rb_float128_value(num);
658
+ break;
659
+ case NUM_COMPLEX128:
660
+ nucomp = complex128_to_f128_inline(num, false);
661
+ if (NIL_P(nucomp)) goto not_a_real;
662
+ real = rb_float128_value(nucomp);
663
+ break;
664
+ case NUM_OTHERTYPE:
665
+ default:
666
+ if (RTEST(rb_obj_is_kind_of(num, rb_cNumeric)))
667
+ {
668
+ VALUE val = numeric_to_f128_inline(num, false);
669
+ if (NIL_P(val)) goto not_a_real;
670
+ real = rb_float128_value(val);
671
+ }
672
+ else
673
+ goto not_a_real;
674
+ break;
675
+ }
676
+ return real;
677
+
678
+ not_a_real:
679
+ rb_raise(rb_eTypeError, "not a real");
680
+
681
+ }
682
+
683
+ static inline void
684
+ unknown_opecode(void)
685
+ {
686
+ rb_warn("unknown operator code (in %s)", __func__);
687
+ }
688
+
689
+ static VALUE
690
+ float128_ope_integer(VALUE self, VALUE other, int ope)
691
+ {
692
+ __float128 x = GetF128(self);
693
+ __float128 y = integer_to_cf128(other);
694
+
695
+ switch (ope) {
696
+ case OPE_ADD:
697
+ return rb_float128_cf128(x + y);
698
+ break;
699
+ case OPE_SUB:
700
+ return rb_float128_cf128(x - y);
701
+ break;
702
+ case OPE_MUL:
703
+ return rb_float128_cf128(x * y);
704
+ break;
705
+ case OPE_DIV:
706
+ return rb_float128_cf128(x / y);
707
+ break;
708
+ case OPE_MOD:
709
+ return rb_float128_cf128(f128_modulo(x, y));
710
+ break;
711
+ case OPE_POW:
712
+ return rb_float128_cf128(powq(x, y));
713
+ break;
714
+ case OPE_CMP:
715
+ if (isnanq(x))
716
+ return Qnil;
717
+ else if (x < y)
718
+ return INT2NUM(-1);
719
+ else if (x > y)
720
+ return INT2NUM(1);
721
+ else /* (x == y) */
722
+ return INT2NUM(0);
723
+ break;
724
+ case OPE_COERCE:
725
+ return rb_assoc_new(
726
+ rb_float128_cf128(y),
727
+ rb_float128_cf128(x));
728
+ break;
729
+ default:
730
+ unknown_opecode();
731
+ return rb_float128_cf128(0.q);
732
+ break;
733
+ }
734
+ }
735
+
736
+ static VALUE
737
+ float128_ope_rational(VALUE self, VALUE other, int ope)
738
+ {
739
+ __float128 x = GetF128(self);
740
+ __float128 y = rational_to_cf128(other);
741
+
742
+ switch (ope) {
743
+ case OPE_ADD:
744
+ return rb_float128_cf128(x + y);
745
+ break;
746
+ case OPE_SUB:
747
+ return rb_float128_cf128(x - y);
748
+ break;
749
+ case OPE_MUL:
750
+ return rb_float128_cf128(x * y);
751
+ break;
752
+ case OPE_DIV:
753
+ return rb_float128_cf128(x / y);
754
+ break;
755
+ case OPE_MOD:
756
+ return rb_float128_cf128(f128_modulo(x, y));
757
+ break;
758
+ case OPE_POW:
759
+ return rb_float128_cf128(powq(x, y));
760
+ break;
761
+ case OPE_CMP:
762
+ if (isnanq(x))
763
+ return Qnil;
764
+ else if (x < y)
765
+ return INT2NUM(-1);
766
+ else if (x > y)
767
+ return INT2NUM(1);
768
+ else /* (x == y) */
769
+ return INT2NUM(0);
770
+ break;
771
+ case OPE_COERCE:
772
+ return rb_assoc_new(
773
+ rb_float128_cf128(y),
774
+ rb_float128_cf128(x));
775
+ break;
776
+ default:
777
+ unknown_opecode();
778
+ return rb_float128_cf128(0.q);
779
+ break;
780
+ }
781
+ }
782
+
783
+ static VALUE
784
+ float128_ope_float(VALUE self, VALUE other, int ope)
785
+ {
786
+ __float128 x = GetF128(self);
787
+ __float128 y = (__float128)NUM2DBL(other);
788
+
789
+ switch (ope) {
790
+ case OPE_ADD:
791
+ return rb_float128_cf128(x + y);
792
+ break;
793
+ case OPE_SUB:
794
+ return rb_float128_cf128(x - y);
795
+ break;
796
+ case OPE_MUL:
797
+ return rb_float128_cf128(x * y);
798
+ break;
799
+ case OPE_DIV:
800
+ return rb_float128_cf128(x / y);
801
+ break;
802
+ case OPE_MOD:
803
+ return rb_float128_cf128(f128_modulo(x, y));
804
+ break;
805
+ case OPE_POW:
806
+ return rb_float128_cf128(powq(x, y));
807
+ break;
808
+ case OPE_CMP:
809
+ if (isnanq(x) || isnanq(y))
810
+ return Qnil;
811
+ else if (x < y)
812
+ return INT2NUM(-1);
813
+ else if (x > y)
814
+ return INT2NUM( 1);
815
+ else /* (x == y) */
816
+ return INT2NUM( 0);
817
+ break;
818
+ case OPE_COERCE:
819
+ return rb_assoc_new(
820
+ rb_float128_cf128(y),
821
+ rb_float128_cf128(x));
822
+ break;
823
+ default:
824
+ unknown_opecode();
825
+ return rb_float128_cf128(0.q);
826
+ break;
827
+ }
828
+ }
829
+
830
+ static VALUE
831
+ float128_ope_float128(VALUE self, VALUE other, int ope)
832
+ {
833
+ __float128 x = GetF128(self);
834
+ __float128 y = GetF128(other);
835
+
836
+ switch (ope) {
837
+ case OPE_ADD:
838
+ return rb_float128_cf128(x + y);
839
+ break;
840
+ case OPE_SUB:
841
+ return rb_float128_cf128(x - y);
842
+ break;
843
+ case OPE_MUL:
844
+ return rb_float128_cf128(x * y);
845
+ break;
846
+ case OPE_DIV:
847
+ return rb_float128_cf128(x / y);
848
+ break;
849
+ case OPE_MOD:
850
+ return rb_float128_cf128(f128_modulo(x, y));
851
+ break;
852
+ case OPE_POW:
853
+ return rb_float128_cf128(powq(x, y));
854
+ break;
855
+ case OPE_CMP:
856
+ if (isnanq(x) || isnanq(y))
857
+ return Qnil;
858
+ else if (x < y)
859
+ return INT2NUM(-1);
860
+ else if (x > y)
861
+ return INT2NUM( 1);
862
+ else /* (x == y) */
863
+ return INT2NUM( 0);
864
+ break;
865
+ case OPE_COERCE:
866
+ return rb_assoc_new(
867
+ rb_float128_cf128(y),
868
+ rb_float128_cf128(x));
869
+ break;
870
+ default:
871
+ unknown_opecode();
872
+ return rb_float128_cf128(0.q);
873
+ break;
874
+ }
875
+ }
876
+
877
+ VALUE
878
+ float128_nucomp_pow(VALUE x, VALUE y)
879
+ {
880
+ if (RTEST(rb_num_coerce_cmp(INT2FIX(0), rb_complex_imag(y), rb_intern("=="))))
881
+ {
882
+ __float128 x_real = GetF128(x);
883
+ __float128 y_real = get_real(rb_complex_real(y));
884
+ __float128 z_real = powq(x_real, y_real);
885
+ return rb_Complex(rb_float128_cf128(z_real), rb_complex_imag(y));
886
+ }
887
+ else
888
+ {
889
+ __float128 x_real = GetF128(x);
890
+ #if 0
891
+ __float128 y_real = get_real(rb_complex_real(y));
892
+ __float128 y_imag = get_real(rb_complex_imag(y));
893
+ __float128 z_real = powq(x_real, y_real) * cosq(y_imag * logq(x_real));
894
+ __float128 z_imag = powq(x_real, y_real) * sinq(y_imag * logq(x_real));
895
+ return rb_Complex(rb_float128_cf128(z_real), rb_float128_cf128(z_imag));
896
+ #else
897
+ __complex128 z;
898
+ __real__ z = get_real(rb_complex_real(y));
899
+ __imag__ z = get_real(rb_complex_imag(y));
900
+ z = cpowq(x_real, z);
901
+ return rb_Complex(
902
+ rb_float128_cf128(crealq(z)),
903
+ rb_float128_cf128(cimagq(z)));
904
+ #endif
905
+ }
906
+ }
907
+
908
+ static VALUE
909
+ float128_ope_nucomp(VALUE self, VALUE other, int ope)
910
+ {
911
+ VALUE x = rb_Complex1(self);
912
+ VALUE y = other;
913
+ switch (ope) {
914
+ case OPE_ADD:
915
+ return rb_complex_plus(x, y);
916
+ break;
917
+ case OPE_SUB:
918
+ return rb_complex_minus(x, y);
919
+ break;
920
+ case OPE_MUL:
921
+ return rb_complex_mul(x, y);
922
+ break;
923
+ case OPE_DIV:
924
+ return rb_complex_div(x, y);
925
+ break;
926
+ case OPE_MOD:
927
+ // undefined
928
+ return rb_num_coerce_bin(x, y, '%');
929
+ break;
930
+ case OPE_POW:
931
+ return float128_nucomp_pow(self, other);
932
+ break;
933
+ case OPE_CMP:
934
+ return rb_num_coerce_cmp(x, y, rb_intern("<=>"));
935
+ break;
936
+ case OPE_COERCE:
937
+ return rb_assoc_new(y, x);
938
+ break;
939
+ default:
940
+ unknown_opecode();
941
+ return rb_float128_cf128(0.q);
942
+ break;
943
+ }
944
+ }
945
+
946
+ static VALUE
947
+ float128_ope_complex128(VALUE self, VALUE other, int ope)
948
+ {
949
+ __float128 x = GetF128(self);
950
+ __complex128 y = rb_complex128_value(other);
951
+
952
+ switch (ope) {
953
+ case OPE_ADD:
954
+ return rb_complex128_cc128(x + y);
955
+ break;
956
+ case OPE_SUB:
957
+ return rb_complex128_cc128(x - y);
958
+ break;
959
+ case OPE_MUL:
960
+ return rb_complex128_cc128(x * y);
961
+ break;
962
+ case OPE_DIV:
963
+ return rb_complex128_cc128(x / y);
964
+ break;
965
+ case OPE_MOD:
966
+ return rb_complex128_cc128(cmodq(x, y));
967
+ break;
968
+ case OPE_POW:
969
+ return rb_complex128_cc128(cpowq(x, y));
970
+ break;
971
+ case OPE_CMP:
972
+ if (isnanq(x) || isnanq(crealq(y)) || (cimagq(y) != 0))
973
+ return Qnil;
974
+ else
975
+ {
976
+ __float128 y_real = crealq(y);
977
+ if (x < y_real)
978
+ return INT2NUM(-1);
979
+ else if (x > y_real)
980
+ return INT2NUM( 1);
981
+ else /* (x == y_real) */
982
+ return INT2NUM( 0);
983
+ }
984
+ break;
985
+ case OPE_COERCE:
986
+ return rb_assoc_new(
987
+ rb_complex128_cc128(y),
988
+ rb_complex128_cc128((__complex128)x));
989
+ break;
990
+ default:
991
+ unknown_opecode();
992
+ return rb_float128_cf128(0.q);
993
+ break;
994
+ }
995
+ }
996
+
997
+ /*
998
+ * call-seq:
999
+ * Float128 + Numeric -> Float128 | Complex128 | Complex
1000
+ *
1001
+ * Adds the right operands.
1002
+ * If the right operand is a real number, it is converted to Float128, and if it is a complex number, it is converted to the Complex class and then operated on.
1003
+ */
1004
+ static VALUE
1005
+ float128_add(VALUE self, VALUE other)
1006
+ {
1007
+ switch (convertion_num_types(other)) {
1008
+ case NUM_FIXNUM:
1009
+ case NUM_BIGNUM:
1010
+ return float128_ope_integer(self, other, OPE_ADD);
1011
+ break;
1012
+ case NUM_RATIONAL:
1013
+ return float128_ope_rational(self, other, OPE_ADD);
1014
+ break;
1015
+ case NUM_FLOAT:
1016
+ return float128_ope_float(self, other, OPE_ADD);
1017
+ break;
1018
+ case NUM_COMPLEX:
1019
+ return float128_ope_nucomp(self, other, OPE_ADD);
1020
+ break;
1021
+ case NUM_FLOAT128:
1022
+ return float128_ope_float128(self, other, OPE_ADD);
1023
+ break;
1024
+ case NUM_COMPLEX128:
1025
+ case NUM_OTHERTYPE:
1026
+ default:
1027
+ return rb_num_coerce_bin(self, other, '+');
1028
+ break;
1029
+ }
1030
+ }
1031
+
1032
+ /*
1033
+ * call-seq:
1034
+ * Float128 - Numeric -> Float128 | Complex128 | Complex
1035
+ *
1036
+ * Subtracts the right operand.
1037
+ * If the right operand is a real number, it is converted to Float128, and if it is a complex number, it is converted to the Complex class and then operated on.
1038
+ */
1039
+ static VALUE
1040
+ float128_sub(VALUE self, VALUE other)
1041
+ {
1042
+ switch (convertion_num_types(other)) {
1043
+ case NUM_FIXNUM:
1044
+ case NUM_BIGNUM:
1045
+ return float128_ope_integer(self, other, OPE_SUB);
1046
+ break;
1047
+ case NUM_RATIONAL:
1048
+ return float128_ope_rational(self, other, OPE_SUB);
1049
+ break;
1050
+ case NUM_FLOAT:
1051
+ return float128_ope_float(self, other, OPE_SUB);
1052
+ break;
1053
+ case NUM_COMPLEX:
1054
+ return float128_ope_nucomp(self, other, OPE_SUB);
1055
+ break;
1056
+ case NUM_FLOAT128:
1057
+ return float128_ope_float128(self, other, OPE_SUB);
1058
+ break;
1059
+ case NUM_COMPLEX128:
1060
+ case NUM_OTHERTYPE:
1061
+ default:
1062
+ return rb_num_coerce_bin(self, other, '-');
1063
+ break;
1064
+ }
1065
+ }
1066
+
1067
+ /*
1068
+ * call-seq:
1069
+ * Float128 * Numeric -> Float128 | Complex128 | Complex
1070
+ *
1071
+ * Multiplies with the right operand.
1072
+ * If the right operand is a real number, it is converted to Float128, and if it is a complex number, it is converted to the Complex class and then operated on.
1073
+ */
1074
+ static VALUE
1075
+ float128_mul(VALUE self, VALUE other)
1076
+ {
1077
+ switch (convertion_num_types(other)) {
1078
+ case NUM_FIXNUM:
1079
+ case NUM_BIGNUM:
1080
+ return float128_ope_integer(self, other, OPE_MUL);
1081
+ break;
1082
+ case NUM_RATIONAL:
1083
+ return float128_ope_rational(self, other, OPE_MUL);
1084
+ break;
1085
+ case NUM_FLOAT:
1086
+ return float128_ope_float(self, other, OPE_MUL);
1087
+ break;
1088
+ case NUM_COMPLEX:
1089
+ return float128_ope_nucomp(self, other, OPE_MUL);
1090
+ break;
1091
+ case NUM_FLOAT128:
1092
+ return float128_ope_float128(self, other, OPE_MUL);
1093
+ break;
1094
+ case NUM_COMPLEX128:
1095
+ case NUM_OTHERTYPE:
1096
+ default:
1097
+ return rb_num_coerce_bin(self, other, '*');
1098
+ break;
1099
+ }
1100
+ }
1101
+
1102
+ /*
1103
+ * call-seq:
1104
+ * Float128 / Numeric -> Float128 | Complex128 | Complex
1105
+ *
1106
+ * Takes the quotient of the right operand.
1107
+ * If the right operand is a real number, it is converted to Float128, and if it is a complex number, it is converted to the Complex class and then operated on.
1108
+ */
1109
+ static VALUE
1110
+ float128_div(VALUE self, VALUE other)
1111
+ {
1112
+ switch (convertion_num_types(other)) {
1113
+ case NUM_FIXNUM:
1114
+ case NUM_BIGNUM:
1115
+ return float128_ope_integer(self, other, OPE_DIV);
1116
+ break;
1117
+ case NUM_RATIONAL:
1118
+ return float128_ope_rational(self, other, OPE_DIV);
1119
+ break;
1120
+ case NUM_FLOAT:
1121
+ return float128_ope_float(self, other, OPE_DIV);
1122
+ break;
1123
+ case NUM_COMPLEX:
1124
+ return float128_ope_nucomp(self, other, OPE_DIV);
1125
+ break;
1126
+ case NUM_FLOAT128:
1127
+ return float128_ope_float128(self, other, OPE_DIV);
1128
+ break;
1129
+ case NUM_COMPLEX128:
1130
+ case NUM_OTHERTYPE:
1131
+ default:
1132
+ return rb_num_coerce_bin(self, other, '/');
1133
+ break;
1134
+ }
1135
+ }
1136
+
1137
+ /*
1138
+ * call-seq:
1139
+ * Float128 % Numeric -> Float128
1140
+ *
1141
+ * Performs modulo calculation with the right operand.
1142
+ * If the operands have the same sign, divide towards zero; if they do not, divide towards negative.
1143
+ */
1144
+ static VALUE
1145
+ float128_mod(VALUE self, VALUE other)
1146
+ {
1147
+ switch (convertion_num_types(other)) {
1148
+ case NUM_FIXNUM:
1149
+ case NUM_BIGNUM:
1150
+ return float128_ope_integer(self, other, OPE_MOD);
1151
+ break;
1152
+ case NUM_RATIONAL:
1153
+ return float128_ope_rational(self, other, OPE_MOD);
1154
+ break;
1155
+ case NUM_FLOAT:
1156
+ return float128_ope_float(self, other, OPE_MOD);
1157
+ break;
1158
+ case NUM_COMPLEX:
1159
+ return float128_ope_nucomp(self, other, OPE_MOD);
1160
+ break;
1161
+ case NUM_FLOAT128:
1162
+ return float128_ope_float128(self, other, OPE_MOD);
1163
+ break;
1164
+ case NUM_COMPLEX128:
1165
+ case NUM_OTHERTYPE:
1166
+ default:
1167
+ return rb_num_coerce_bin(self, other, '%');
1168
+ break;
1169
+ }
1170
+ }
1171
+
1172
+ /*
1173
+ * call-seq:
1174
+ * Float128 ** Numeric -> Float128 | Complex128 | Complex
1175
+ *
1176
+ * Exponentiates the right operand.
1177
+ * If the right operand is a real number, it is converted to Float128, and if it is a complex number, it is converted to the Complex class and then operated on. */
1178
+ static VALUE
1179
+ float128_pow(VALUE self, VALUE other)
1180
+ {
1181
+ switch (convertion_num_types(other)) {
1182
+ case NUM_FIXNUM:
1183
+ case NUM_BIGNUM:
1184
+ return float128_ope_integer(self, other, OPE_POW);
1185
+ break;
1186
+ case NUM_RATIONAL:
1187
+ return float128_ope_rational(self, other, OPE_POW);
1188
+ break;
1189
+ case NUM_FLOAT:
1190
+ return float128_ope_float(self, other, OPE_POW);
1191
+ break;
1192
+ case NUM_COMPLEX:
1193
+ return float128_ope_nucomp(self, other, OPE_POW);
1194
+ break;
1195
+ case NUM_FLOAT128:
1196
+ return float128_ope_float128(self, other, OPE_POW);
1197
+ break;
1198
+ case NUM_COMPLEX128:
1199
+ case NUM_OTHERTYPE:
1200
+ default:
1201
+ return rb_num_coerce_bin(self, other, rb_intern("**"));
1202
+ break;
1203
+ }
1204
+ }
1205
+
1206
+ /*
1207
+ * call-seq:
1208
+ * Float128 <=> Numeric -> -1 | 0 | 1 | nil
1209
+ *
1210
+ * Compares the operands.
1211
+ * Returns -1 if +other+ is greater than +self+, 0 if they are the same, 1 if they are less than +self+, or nil if the comparison is not possible.
1212
+ */
1213
+ static VALUE
1214
+ float128_cmp(VALUE self, VALUE other)
1215
+ {
1216
+ switch (convertion_num_types(other)) {
1217
+ case NUM_FIXNUM:
1218
+ case NUM_BIGNUM:
1219
+ return float128_ope_integer(self, other, OPE_CMP);
1220
+ break;
1221
+ case NUM_RATIONAL:
1222
+ return float128_ope_rational(self, other, OPE_CMP);
1223
+ break;
1224
+ case NUM_FLOAT:
1225
+ return float128_ope_float(self, other, OPE_CMP);
1226
+ break;
1227
+ case NUM_COMPLEX:
1228
+ return float128_ope_nucomp(self, other, OPE_CMP);
1229
+ break;
1230
+ case NUM_FLOAT128:
1231
+ return float128_ope_float128(self, other, OPE_CMP);
1232
+ break;
1233
+ case NUM_COMPLEX128:
1234
+ return float128_ope_complex128(self, other, OPE_CMP);
1235
+ break;
1236
+ case NUM_OTHERTYPE:
1237
+ default:
1238
+ return rb_num_coerce_cmp(self, other, rb_intern("<=>"));
1239
+ break;
1240
+ }
1241
+ }
1242
+
1243
+ /*
1244
+ * call-seq:
1245
+ * coerce(other) -> [other, self]
1246
+ *
1247
+ * It sets +other+ equal to +self+, converts it to an array of pairs [other, self], and returns it.
1248
+ *
1249
+ * 1.0.coerce(Float128::MAX).all?(Float) # => true
1250
+ * 1.0.to_f128.coerce(Float::MAX).all?(Float128) # => true
1251
+ */
1252
+ static VALUE
1253
+ float128_coerce(int argc, VALUE *argv, VALUE self)
1254
+ {
1255
+ VALUE other;
1256
+ rb_scan_args(argc, argv, "10", &other);
1257
+ switch (convertion_num_types(other)) {
1258
+ case NUM_FIXNUM:
1259
+ case NUM_BIGNUM:
1260
+ return float128_ope_integer(self, other, OPE_COERCE);
1261
+ break;
1262
+ case NUM_RATIONAL:
1263
+ return float128_ope_rational(self, other, OPE_COERCE);
1264
+ break;
1265
+ case NUM_FLOAT:
1266
+ return float128_ope_float(self, other, OPE_COERCE);
1267
+ break;
1268
+ case NUM_COMPLEX:
1269
+ return float128_ope_nucomp(self, other, OPE_COERCE);
1270
+ break;
1271
+ case NUM_FLOAT128:
1272
+ return float128_ope_float128(self, other, OPE_COERCE);
1273
+ break;
1274
+ case NUM_COMPLEX128:
1275
+ return float128_ope_complex128(self, other, OPE_COERCE);
1276
+ break;
1277
+ case NUM_OTHERTYPE:
1278
+ default:
1279
+ return rb_call_super(argc, argv);
1280
+ break;
1281
+ }
1282
+ }
1283
+
1284
+ static VALUE
1285
+ float128_fused_multiply_add(VALUE xhs, VALUE yhs, VALUE zhs)
1286
+ {
1287
+ __float128 x = get_real(xhs),
1288
+ y = get_real(yhs),
1289
+ z = get_real(zhs);
1290
+
1291
+ return rb_float128_cf128(fmaq(x, y, z));
1292
+ }
1293
+
1294
+ /*
1295
+ * call-seq:
1296
+ * Float128.fma(x, y, z) -> Float128
1297
+ *
1298
+ * Uses fused multiply-add algorithm to efficiently compute x*y+z.
1299
+ * It often produces more accurate results than mathematical calculations.
1300
+ * The arguments are considered to be quadruple-precision floating point numbers.
1301
+ * If this is not possible, an implicit type conversion will be attempted, and if conversion is not possible, a TypeError will be raised.
1302
+ *
1303
+ * Float128.fma(1/3r, 2/3r, 3/3r) # => 1.2222222222222222222222222222222
1304
+ * # 精度の違い
1305
+ * Float128.fma(1.1, 1.2, 1.3) # => 2.6200000000000001021405182655144
1306
+ * Float128.fma('1.1'.to_f128, '1.2'.to_f128, '1.3'.to_f128) # => 2.62
1307
+ */
1308
+ static VALUE
1309
+ float128_s_fma(int argc, VALUE *argv, VALUE self)
1310
+ {
1311
+ VALUE xhs, yhs, zhs;
1312
+ rb_scan_args(argc, argv, "30", &xhs, &yhs, &zhs);
1313
+
1314
+ return float128_fused_multiply_add(xhs, yhs, zhs);
1315
+ }
1316
+
1317
+ static VALUE
1318
+ float128_sincos(VALUE xhs)
1319
+ {
1320
+ __float128 x = get_real(xhs), sin, cos;
1321
+ sincosq(x, &sin, &cos);
1322
+ return rb_assoc_new( rb_float128_cf128(sin), rb_float128_cf128(cos) );
1323
+ }
1324
+
1325
+ /*
1326
+ * call-seq:
1327
+ * Float128.sincos(x) -> [Float128, Float128]
1328
+ *
1329
+ * Returns an array of sines and cosines of x.
1330
+ * The arguments are considered to be quadruple-precision floating point numbers.
1331
+ * If this is not possible, an implicit type conversion will be attempted, and if conversion is not possible, a TypeError will be raised.
1332
+ *
1333
+ * Float128.sincos(2) # => [0.909297426825681695396019865911745, -0.416146836547142386997568229500762]
1334
+ */
1335
+ static VALUE
1336
+ float128_s_sincos(int argc, VALUE *argv, VALUE self)
1337
+ {
1338
+ VALUE xhs;
1339
+ rb_scan_args(argc, argv, "10", &xhs);
1340
+
1341
+ return float128_sincos(xhs);
1342
+ }
1343
+
1344
+ static VALUE
1345
+ float128_fmin(VALUE lhs, VALUE rhs)
1346
+ {
1347
+ __float128 l = get_real(lhs), r = get_real(rhs);
1348
+ return rb_float128_cf128(fminq(l, r));
1349
+ }
1350
+
1351
+ /*
1352
+ * call-seq:
1353
+ * Float128.fmin(l, r) -> Float128
1354
+ *
1355
+ * 引数+l+と+r+を比べて小さいほうを返す.
1356
+ * The arguments are considered to be quadruple-precision floating point numbers.
1357
+ * If this is not possible, an implicit type conversion will be attempted, and if conversion is not possible, a TypeError will be raised.
1358
+ *
1359
+ * Float128.fmin(1.23r, 4.56r) # => 1.23
1360
+ * # 二倍精度と四倍精度の同値を比較
1361
+ * Float128.fmin(1.1r, 1.1r) # => 1.1
1362
+ * Float128.fmin(-1.1r, -1.1) # => -1.1000000000000000888178419700125
1363
+ */
1364
+ static VALUE
1365
+ float128_s_fmin(int argc, VALUE *argv, VALUE self)
1366
+ {
1367
+ VALUE lhs, rhs;
1368
+ rb_scan_args(argc, argv, "20", &lhs, &rhs);
1369
+
1370
+ return float128_fmin(lhs, rhs);
1371
+ }
1372
+
1373
+ static VALUE
1374
+ float128_fmax(VALUE lhs, VALUE rhs)
1375
+ {
1376
+ __float128 l = get_real(lhs), r = get_real(rhs);
1377
+ return rb_float128_cf128(fmaxq(l, r));
1378
+ }
1379
+
1380
+ /*
1381
+ * call-seq:
1382
+ * Float128.fmax(l, r) -> Float128
1383
+ *
1384
+ * 引数+l+と+r+を比べて大きいほうを返す.
1385
+ * The arguments are considered to be quadruple-precision floating point numbers.
1386
+ * If this is not possible, an implicit type conversion will be attempted, and if conversion is not possible, a TypeError will be raised.
1387
+ *
1388
+ * Float128.fmax(1.23r, 4.56r) # => 4.56
1389
+ * # 二倍精度と四倍精度の同値を比較
1390
+ * Float128.fmax(1.1r, 1.1r) # => 1.1000000000000000888178419700125
1391
+ * Float128.fmax(-1.1r, -1.1) # => -1.1
1392
+ */
1393
+ static VALUE
1394
+ float128_s_fmax(int argc, VALUE *argv, VALUE self)
1395
+ {
1396
+ VALUE lhs, rhs;
1397
+ rb_scan_args(argc, argv, "20", &lhs, &rhs);
1398
+
1399
+ return float128_fmax(lhs, rhs);
1400
+ }
1401
+
1402
+ /*
1403
+ * call-seq:
1404
+ * Float128.ldexp(x, exp) -> Float128
1405
+ *
1406
+ * xに2のexp乗をかけた値を返す(Load Exponent).Mathモジュールにも同名関数があるが,返却値は四倍精度である.
1407
+ * frexpで分解した指数と仮数をもとの数値に戻すのに使う.
1408
+ *
1409
+ * fra, exp = '2.2'.to_f128.frexp # => [0.55, 2]
1410
+ * Float128.ldexp(fra, exp) # => 2.2
1411
+ */
1412
+ static VALUE
1413
+ float128_s_ldexp(VALUE obj, VALUE x, VALUE exp)
1414
+ {
1415
+ __float128 v_x = get_real(x);
1416
+ int v_exp = NUM2INT(exp);
1417
+
1418
+ return rb_float128_cf128(ldexpq(v_x, v_exp));
1419
+ }
1420
+
1421
+ /*
1422
+ * call-seq:
1423
+ * Float128.scalb(x, n) -> Float128
1424
+ * Float128.scalbn(x, n) -> Float128
1425
+ *
1426
+ * xにFloat::RADIXのn乗をかけた値を返す.返却値は四倍精度である.
1427
+ * メソッド名はC/C++の策定のときのオリジナルだが,(もちろん)newの意味を持つnが付け加えられたaliasもある.
1428
+ * 内部的にはnがlong型パージョンなscalblnq()を使用する.
1429
+ *
1430
+ * # 3.0 * Float::RADIX ** 4
1431
+ * Float128.scalb(3, 4) # => 48.0
1432
+ */
1433
+ static VALUE
1434
+ float128_s_scalb(VALUE obj, VALUE x, VALUE exp)
1435
+ {
1436
+ __float128 v_x = get_real(x);
1437
+ long v_exp = NUM2LONG(exp);
1438
+
1439
+ return rb_float128_cf128(scalblnq(v_x, v_exp));
1440
+ }
1441
+
1442
+
1443
+ /*
1444
+ * call-seq:
1445
+ * polar -> [Float128, Float128]
1446
+ *
1447
+ * +self+の絶対値と偏角を配列にして返す.成分はいずれもFloat128である.
1448
+ *
1449
+ * Complex128.polar(1, 2).polar # => [1, 2]
1450
+ */
1451
+ static VALUE
1452
+ complex128_polar(VALUE self)
1453
+ {
1454
+ __complex128 c128 = GetC128(self);
1455
+
1456
+ return rb_assoc_new(
1457
+ rb_float128_cf128(cabsq(c128)),
1458
+ rb_float128_cf128(cargq(c128)));
1459
+ }
1460
+
1461
+ /*
1462
+ * call-seq:
1463
+ * abs -> Float128
1464
+ * magnitude -> Float128
1465
+ *
1466
+ * +self+の絶対値を返す.
1467
+ */
1468
+ static VALUE
1469
+ complex128_abs(VALUE self)
1470
+ {
1471
+ __complex128 c128 = GetC128(self);
1472
+
1473
+ return rb_float128_cf128(cabsq(c128));
1474
+ }
1475
+
1476
+ /*
1477
+ * call-seq:
1478
+ * abs2 -> Float128
1479
+ *
1480
+ * +self+の絶対値の二乗を返す.
1481
+ */
1482
+ static VALUE
1483
+ complex128_abs2(VALUE self)
1484
+ {
1485
+ __complex128 c128 = GetC128(self);
1486
+ __float128 abs_val = cabsq(c128);
1487
+
1488
+ return rb_float128_cf128(abs_val * abs_val);
1489
+ }
1490
+
1491
+ /*
1492
+ * call-seq:
1493
+ * arg -> Float128
1494
+ * angle -> Float128
1495
+ * phase -> Float128
1496
+ *
1497
+ * +self+の偏角を[-π,π]の範囲で返す.
1498
+ */
1499
+ static VALUE
1500
+ complex128_arg(VALUE self)
1501
+ {
1502
+ __complex128 c128 = GetC128(self);
1503
+
1504
+ return rb_float128_cf128(cargq(c128));
1505
+ }
1506
+
1507
+ /*
1508
+ * call-seq:
1509
+ * conj -> Complex128
1510
+ *
1511
+ * +self+の共役複素数を返す.
1512
+ */
1513
+ static VALUE
1514
+ complex128_conj(VALUE self)
1515
+ {
1516
+ __complex128 c128 = GetC128(self);
1517
+
1518
+ return rb_complex128_cc128(conjq(c128));
1519
+ }
1520
+
1521
+ static VALUE
1522
+ complex128_ope_integer(VALUE self, VALUE other, int ope)
1523
+ {
1524
+ __complex128 z = GetC128(self);
1525
+ __float128 w = integer_to_cf128(other);
1526
+
1527
+ switch (ope) {
1528
+ case OPE_ADD:
1529
+ return rb_complex128_cc128(z + w);
1530
+ break;
1531
+ case OPE_SUB:
1532
+ return rb_complex128_cc128(z - w);
1533
+ break;
1534
+ case OPE_MUL:
1535
+ return rb_complex128_cc128(z * w);
1536
+ break;
1537
+ case OPE_DIV:
1538
+ return rb_complex128_cc128(z / w);
1539
+ break;
1540
+ case OPE_MOD:
1541
+ return rb_complex128_cc128(cmodq(z, w));
1542
+ break;
1543
+ case OPE_POW:
1544
+ return rb_complex128_cc128(cpowq(z, w));
1545
+ break;
1546
+ case OPE_CMP:
1547
+ __float128 z_real = crealq(z);
1548
+ if (isnanq(z_real) || cimagq(z) != 0)
1549
+ return Qnil;
1550
+ else if (z_real < w)
1551
+ return INT2NUM(-1);
1552
+ else if (z_real > w)
1553
+ return INT2NUM(1);
1554
+ else /* (z_real == w) */
1555
+ return INT2NUM(0);
1556
+ break;
1557
+ case OPE_COERCE:
1558
+ return rb_assoc_new(
1559
+ rb_complex128_cc128(w),
1560
+ rb_complex128_cc128(z));
1561
+ break;
1562
+ default:
1563
+ unknown_opecode();
1564
+ return rb_complex128_cc128(0+0i);
1565
+ break;
1566
+ }
1567
+ }
1568
+
1569
+ static VALUE
1570
+ complex128_ope_rational(VALUE self, VALUE other, int ope)
1571
+ {
1572
+ __complex128 z = GetC128(self);
1573
+ __float128 w = rational_to_cf128(other);
1574
+
1575
+ switch (ope) {
1576
+ case OPE_ADD:
1577
+ return rb_complex128_cc128(z + w);
1578
+ break;
1579
+ case OPE_SUB:
1580
+ return rb_complex128_cc128(z - w);
1581
+ break;
1582
+ case OPE_MUL:
1583
+ return rb_complex128_cc128(z * w);
1584
+ break;
1585
+ case OPE_DIV:
1586
+ return rb_complex128_cc128(z / w);
1587
+ break;
1588
+ case OPE_MOD:
1589
+ return rb_complex128_cc128(cmodq(z, w));
1590
+ break;
1591
+ case OPE_POW:
1592
+ return rb_complex128_cc128(cpowq(z, w));
1593
+ break;
1594
+ case OPE_CMP:
1595
+ __float128 z_real = crealq(z);
1596
+ if (isnanq(z_real) || cimagq(z) != 0)
1597
+ return Qnil;
1598
+ else if (z_real < w)
1599
+ return INT2NUM(-1);
1600
+ else if (z_real > w)
1601
+ return INT2NUM(1);
1602
+ else /* (z_real == w) */
1603
+ return INT2NUM(0);
1604
+ break;
1605
+ case OPE_COERCE:
1606
+ return rb_assoc_new(
1607
+ rb_complex128_cc128(w),
1608
+ rb_complex128_cc128(z));
1609
+ break;
1610
+ default:
1611
+ unknown_opecode();
1612
+ return rb_complex128_cc128(0+0i);
1613
+ break;
1614
+ }
1615
+ }
1616
+
1617
+ static VALUE
1618
+ complex128_ope_float(VALUE self, VALUE other, int ope)
1619
+ {
1620
+ __complex128 z = GetC128(self);
1621
+ __float128 w = (__float128)NUM2DBL(other);
1622
+
1623
+ switch (ope) {
1624
+ case OPE_ADD:
1625
+ return rb_complex128_cc128(z + w);
1626
+ break;
1627
+ case OPE_SUB:
1628
+ return rb_complex128_cc128(z - w);
1629
+ break;
1630
+ case OPE_MUL:
1631
+ return rb_complex128_cc128(z * w);
1632
+ break;
1633
+ case OPE_DIV:
1634
+ return rb_complex128_cc128(z / w);
1635
+ break;
1636
+ case OPE_MOD:
1637
+ return rb_complex128_cc128(cmodq(z, w));
1638
+ break;
1639
+ case OPE_POW:
1640
+ return rb_complex128_cc128(cpowq(z, w));
1641
+ break;
1642
+ case OPE_CMP:
1643
+ __float128 z_real = crealq(z);
1644
+ if (isnanq(z_real) || isnanq(w) || cimagq(z) != 0)
1645
+ return Qnil;
1646
+ else if (z_real < w)
1647
+ return INT2NUM(-1);
1648
+ else if (z_real > w)
1649
+ return INT2NUM(1);
1650
+ else /* (z_real == w) */
1651
+ return INT2NUM(0);
1652
+ break;
1653
+ case OPE_COERCE:
1654
+ return rb_assoc_new(
1655
+ rb_complex128_cc128(w),
1656
+ rb_complex128_cc128(z));
1657
+ break;
1658
+ default:
1659
+ unknown_opecode();
1660
+ return rb_complex128_cc128(0+0i);
1661
+ break;
1662
+ }
1663
+ }
1664
+
1665
+ static VALUE
1666
+ complex128_ope_float128(VALUE self, VALUE other, int ope)
1667
+ {
1668
+ __complex128 z = GetC128(self);
1669
+ __float128 w = GetF128(other);
1670
+
1671
+ switch (ope) {
1672
+ case OPE_ADD:
1673
+ return rb_complex128_cc128(z + w);
1674
+ break;
1675
+ case OPE_SUB:
1676
+ return rb_complex128_cc128(z - w);
1677
+ break;
1678
+ case OPE_MUL:
1679
+ return rb_complex128_cc128(z * w);
1680
+ break;
1681
+ case OPE_DIV:
1682
+ return rb_complex128_cc128(z / w);
1683
+ break;
1684
+ case OPE_MOD:
1685
+ return rb_complex128_cc128(cmodq(z, w));
1686
+ break;
1687
+ case OPE_POW:
1688
+ return rb_complex128_cc128(cpowq(z, w));
1689
+ break;
1690
+ case OPE_CMP:
1691
+ __float128 z_real = crealq(z);
1692
+ if (isnanq(z_real) || isnanq(w) || cimagq(z) != 0)
1693
+ return Qnil;
1694
+ else if (z_real < w)
1695
+ return INT2NUM(-1);
1696
+ else if (z_real > w)
1697
+ return INT2NUM(1);
1698
+ else /* (z_real == w) */
1699
+ return INT2NUM(0);
1700
+ break;
1701
+ case OPE_COERCE:
1702
+ return rb_assoc_new(
1703
+ rb_complex128_cc128(w),
1704
+ rb_complex128_cc128(z));
1705
+ break;
1706
+ default:
1707
+ unknown_opecode();
1708
+ return rb_complex128_cc128(0+0i);
1709
+ break;
1710
+ }
1711
+ }
1712
+
1713
+ VALUE
1714
+ complex128_nucomp_mod(VALUE z, VALUE w)
1715
+ {
1716
+ return rb_Complex1(INT2FIX(0)); // 未定義
1717
+ }
1718
+
1719
+ VALUE
1720
+ complex128_nucomp_pow(VALUE z, VALUE w)
1721
+ {
1722
+ __complex128 z_value = GetC128(z);
1723
+ __complex128 w_value;
1724
+ __real__ w_value = get_real(rb_complex_real(w));
1725
+ __imag__ w_value = get_real(rb_complex_imag(w));
1726
+ __complex128 c = cpowq(z_value, w_value);
1727
+ return rb_Complex(
1728
+ rb_float128_cf128(crealq(c)),
1729
+ rb_float128_cf128(cimagq(c)));
1730
+ }
1731
+
1732
+ static VALUE
1733
+ complex128_ope_nucomp(VALUE self, VALUE other, int ope)
1734
+ {
1735
+ __complex128 c128 = GetC128(self);
1736
+ VALUE x = rb_Complex(
1737
+ rb_float128_cf128(crealq(c128)),
1738
+ rb_float128_cf128(cimagq(c128)));
1739
+ VALUE y = other;
1740
+ switch (ope) {
1741
+ case OPE_ADD:
1742
+ return rb_complex_plus(x, y);
1743
+ break;
1744
+ case OPE_SUB:
1745
+ return rb_complex_minus(x, y);
1746
+ break;
1747
+ case OPE_MUL:
1748
+ return rb_complex_mul(x, y);
1749
+ break;
1750
+ case OPE_DIV:
1751
+ return rb_complex_div(x, y);
1752
+ break;
1753
+ case OPE_MOD:
1754
+ return complex128_nucomp_mod(self, other);
1755
+ break;
1756
+ case OPE_POW:
1757
+ return complex128_nucomp_pow(self, other);
1758
+ break;
1759
+ case OPE_CMP:
1760
+ return rb_num_coerce_cmp(x, y, rb_intern("<=>"));
1761
+ break;
1762
+ case OPE_COERCE:
1763
+ return rb_assoc_new(y, x);
1764
+ break;
1765
+ default:
1766
+ unknown_opecode();
1767
+ return rb_complex128_cc128(0+0i);
1768
+ break;
1769
+ }
1770
+ }
1771
+
1772
+ static VALUE
1773
+ complex128_ope_complex128(VALUE self, VALUE other, int ope)
1774
+ {
1775
+ __complex128 z = GetC128(self);
1776
+ __complex128 w = GetC128(other);
1777
+
1778
+ switch (ope) {
1779
+ case OPE_ADD:
1780
+ return rb_complex128_cc128(z + w);
1781
+ break;
1782
+ case OPE_SUB:
1783
+ return rb_complex128_cc128(z - w);
1784
+ break;
1785
+ case OPE_MUL:
1786
+ return rb_complex128_cc128(z * w);
1787
+ break;
1788
+ case OPE_DIV:
1789
+ return rb_complex128_cc128(z / w);
1790
+ break;
1791
+ case OPE_MOD:
1792
+ return rb_complex128_cc128(cmodq(z, w));
1793
+ break;
1794
+ case OPE_POW:
1795
+ return rb_complex128_cc128(cpowq(z, w));
1796
+ break;
1797
+ case OPE_CMP:
1798
+ __float128 z_real = crealq(z), z_imag = cimagq(z);
1799
+ __float128 w_real = crealq(z), w_imag = cimagq(z);
1800
+ if (isnanq(z_real) || isnanq(z_imag) ||
1801
+ isnanq(w_real) || isnanq(w_imag) ||
1802
+ z_imag != 0 || w_imag != 0)
1803
+ return Qnil;
1804
+ else
1805
+ {
1806
+ if (z_real < w_real)
1807
+ return INT2NUM(-1);
1808
+ else if (z_real > w_real)
1809
+ return INT2NUM( 1);
1810
+ else /* (z_real == w_real) */
1811
+ return INT2NUM( 0);
1812
+ }
1813
+ break;
1814
+ case OPE_COERCE:
1815
+ return rb_assoc_new(other, self);
1816
+ break;
1817
+ default:
1818
+ unknown_opecode();
1819
+ return rb_complex128_cc128(0+0i);
1820
+ break;
1821
+ }
1822
+ }
1823
+
1824
+
1825
+
1826
+ /*
1827
+ * call-seq:
1828
+ * Complex128 + Numeric -> Complex128 | Complex
1829
+ *
1830
+ * 右オペランドを加算する.
1831
+ * 右オペランドがComplexクラスであればComplexクラスを,そのほかはComplex128クラスを返却値にそれぞれ演算する.
1832
+ */
1833
+ static VALUE
1834
+ complex128_add(VALUE self, VALUE other)
1835
+ {
1836
+ switch (convertion_num_types(other)) {
1837
+ case NUM_FIXNUM:
1838
+ case NUM_BIGNUM:
1839
+ return complex128_ope_integer(self, other, OPE_ADD);
1840
+ break;
1841
+ case NUM_RATIONAL:
1842
+ return complex128_ope_rational(self, other, OPE_ADD);
1843
+ break;
1844
+ case NUM_FLOAT:
1845
+ return complex128_ope_float(self, other, OPE_ADD);
1846
+ break;
1847
+ case NUM_COMPLEX:
1848
+ return complex128_ope_nucomp(self, other, OPE_ADD);
1849
+ break;
1850
+ case NUM_FLOAT128:
1851
+ return complex128_ope_float128(self, other, OPE_ADD);
1852
+ break;
1853
+ case NUM_COMPLEX128:
1854
+ return complex128_ope_complex128(self, other, OPE_ADD);
1855
+ break;
1856
+ case NUM_OTHERTYPE:
1857
+ default:
1858
+ return rb_num_coerce_bin(self, other, '+');
1859
+ break;
1860
+ }
1861
+ }
1862
+
1863
+ /*
1864
+ * call-seq:
1865
+ * Complex128 - Numeric -> Complex128 | Complex
1866
+ *
1867
+ * 右オペランドを減算する.
1868
+ * 右オペランドがComplexクラスであればComplexクラスを,そのほかはComplex128クラスを返却値にそれぞれ演算する.
1869
+ */
1870
+ static VALUE
1871
+ complex128_sub(VALUE self, VALUE other)
1872
+ {
1873
+ switch (convertion_num_types(other)) {
1874
+ case NUM_FIXNUM:
1875
+ case NUM_BIGNUM:
1876
+ return complex128_ope_integer(self, other, OPE_SUB);
1877
+ break;
1878
+ case NUM_RATIONAL:
1879
+ return complex128_ope_rational(self, other, OPE_SUB);
1880
+ break;
1881
+ case NUM_FLOAT:
1882
+ return complex128_ope_float(self, other, OPE_SUB);
1883
+ break;
1884
+ case NUM_COMPLEX:
1885
+ return complex128_ope_nucomp(self, other, OPE_SUB);
1886
+ break;
1887
+ case NUM_FLOAT128:
1888
+ return complex128_ope_float128(self, other, OPE_SUB);
1889
+ break;
1890
+ case NUM_COMPLEX128:
1891
+ return complex128_ope_complex128(self, other, OPE_SUB);
1892
+ break;
1893
+ case NUM_OTHERTYPE:
1894
+ default:
1895
+ return rb_num_coerce_bin(self, other, '-');
1896
+ break;
1897
+ }
1898
+ }
1899
+
1900
+ /*
1901
+ * call-seq:
1902
+ * Complex128 * Numeric -> Complex128 | Complex
1903
+ *
1904
+ * 右オペランドとの積を取る.
1905
+ * 右オペランドがComplexクラスであればComplexクラスを,そのほかはComplex128クラスを返却値にそれぞれ演算する.
1906
+ */
1907
+ static VALUE
1908
+ complex128_mul(VALUE self, VALUE other)
1909
+ {
1910
+ switch (convertion_num_types(other)) {
1911
+ case NUM_FIXNUM:
1912
+ case NUM_BIGNUM:
1913
+ return complex128_ope_integer(self, other, OPE_MUL);
1914
+ break;
1915
+ case NUM_RATIONAL:
1916
+ return complex128_ope_rational(self, other, OPE_MUL);
1917
+ break;
1918
+ case NUM_FLOAT:
1919
+ return complex128_ope_float(self, other, OPE_MUL);
1920
+ break;
1921
+ case NUM_COMPLEX:
1922
+ return complex128_ope_nucomp(self, other, OPE_MUL);
1923
+ break;
1924
+ case NUM_FLOAT128:
1925
+ return complex128_ope_float128(self, other, OPE_MUL);
1926
+ break;
1927
+ case NUM_COMPLEX128:
1928
+ return complex128_ope_complex128(self, other, OPE_MUL);
1929
+ break;
1930
+ case NUM_OTHERTYPE:
1931
+ default:
1932
+ return rb_num_coerce_bin(self, other, '*');
1933
+ break;
1934
+ }
1935
+ }
1936
+
1937
+ /*
1938
+ * call-seq:
1939
+ * Complex128 / Numeric -> Complex128 | Complex
1940
+ *
1941
+ * 右オペランドとの商を取る.
1942
+ * 右オペランドがComplexクラスであればComplexクラスを,そのほかはComplex128クラスを返却値にそれぞれ演算する.
1943
+ */
1944
+ static VALUE
1945
+ complex128_div(VALUE self, VALUE other)
1946
+ {
1947
+ switch (convertion_num_types(other)) {
1948
+ case NUM_FIXNUM:
1949
+ case NUM_BIGNUM:
1950
+ return complex128_ope_integer(self, other, OPE_DIV);
1951
+ break;
1952
+ case NUM_RATIONAL:
1953
+ return complex128_ope_rational(self, other, OPE_DIV);
1954
+ break;
1955
+ case NUM_FLOAT:
1956
+ return complex128_ope_float(self, other, OPE_DIV);
1957
+ break;
1958
+ case NUM_COMPLEX:
1959
+ return complex128_ope_nucomp(self, other, OPE_DIV);
1960
+ break;
1961
+ case NUM_FLOAT128:
1962
+ return complex128_ope_float128(self, other, OPE_DIV);
1963
+ break;
1964
+ case NUM_COMPLEX128:
1965
+ return complex128_ope_complex128(self, other, OPE_DIV);
1966
+ break;
1967
+ case NUM_OTHERTYPE:
1968
+ default:
1969
+ return rb_num_coerce_bin(self, other, '/');
1970
+ break;
1971
+ }
1972
+ }
1973
+
1974
+ /*
1975
+ * call-seq:
1976
+ * Complex128 % Numeric -> Complex128 | Complex
1977
+ *
1978
+ * 右オペランドと剰余計算を行う.
1979
+ * このメソッドは実装定義である.
1980
+ */
1981
+ static VALUE
1982
+ complex128_mod(VALUE self, VALUE other)
1983
+ {
1984
+ switch (convertion_num_types(other)) {
1985
+ case NUM_FIXNUM:
1986
+ case NUM_BIGNUM:
1987
+ return complex128_ope_integer(self, other, OPE_MOD);
1988
+ break;
1989
+ case NUM_RATIONAL:
1990
+ return complex128_ope_rational(self, other, OPE_MOD);
1991
+ break;
1992
+ case NUM_FLOAT:
1993
+ return complex128_ope_float(self, other, OPE_MOD);
1994
+ break;
1995
+ case NUM_COMPLEX:
1996
+ return complex128_ope_nucomp(self, other, OPE_MOD);
1997
+ break;
1998
+ case NUM_FLOAT128:
1999
+ return complex128_ope_float128(self, other, OPE_MOD);
2000
+ break;
2001
+ case NUM_COMPLEX128:
2002
+ return complex128_ope_complex128(self, other, OPE_MOD);
2003
+ break;
2004
+ case NUM_OTHERTYPE:
2005
+ default:
2006
+ return rb_num_coerce_bin(self, other, '%');
2007
+ break;
2008
+ }
2009
+ }
2010
+
2011
+ /*
2012
+ * call-seq:
2013
+ * Complex128 ** Numeric -> Complex128 | Complex
2014
+ *
2015
+ * 右オペランドと累乗計算を行う.
2016
+ * 右オペランドがComplexクラスであればComplexクラスを,そのほかはComplex128クラスを返却値にそれぞれ演算する.
2017
+ */
2018
+ static VALUE
2019
+ complex128_pow(VALUE self, VALUE other)
2020
+ {
2021
+ switch (convertion_num_types(other)) {
2022
+ case NUM_FIXNUM:
2023
+ case NUM_BIGNUM:
2024
+ return complex128_ope_integer(self, other, OPE_POW);
2025
+ break;
2026
+ case NUM_RATIONAL:
2027
+ return complex128_ope_rational(self, other, OPE_POW);
2028
+ break;
2029
+ case NUM_FLOAT:
2030
+ return complex128_ope_float(self, other, OPE_POW);
2031
+ break;
2032
+ case NUM_COMPLEX:
2033
+ return complex128_ope_nucomp(self, other, OPE_POW);
2034
+ break;
2035
+ case NUM_FLOAT128:
2036
+ return complex128_ope_float128(self, other, OPE_POW);
2037
+ break;
2038
+ case NUM_COMPLEX128:
2039
+ return complex128_ope_complex128(self, other, OPE_POW);
2040
+ break;
2041
+ case NUM_OTHERTYPE:
2042
+ default:
2043
+ return rb_num_coerce_bin(self, other, rb_intern("**"));
2044
+ break;
2045
+ }
2046
+ }
2047
+
2048
+ /*
2049
+ * call-seq:
2050
+ * Complex128 <=> Numeric -> -1 | 0 | 1 | nil
2051
+ *
2052
+ * オペランド同士の比較を行う.
2053
+ */
2054
+ static VALUE
2055
+ complex128_cmp(VALUE self, VALUE other)
2056
+ {
2057
+ switch (convertion_num_types(other)) {
2058
+ case NUM_FIXNUM:
2059
+ case NUM_BIGNUM:
2060
+ return complex128_ope_integer(self, other, OPE_CMP);
2061
+ break;
2062
+ case NUM_RATIONAL:
2063
+ return complex128_ope_rational(self, other, OPE_CMP);
2064
+ break;
2065
+ case NUM_FLOAT:
2066
+ return complex128_ope_float(self, other, OPE_CMP);
2067
+ break;
2068
+ case NUM_COMPLEX:
2069
+ return complex128_ope_nucomp(self, other, OPE_CMP);
2070
+ break;
2071
+ case NUM_FLOAT128:
2072
+ return complex128_ope_float128(self, other, OPE_CMP);
2073
+ break;
2074
+ case NUM_COMPLEX128:
2075
+ return complex128_ope_complex128(self, other, OPE_CMP);
2076
+ break;
2077
+ case NUM_OTHERTYPE:
2078
+ default:
2079
+ return rb_num_coerce_cmp(self, other, rb_intern("<=>"));
2080
+ break;
2081
+ }
2082
+ }
2083
+
2084
+ /*
2085
+ * call-seq:
2086
+ * coerce(other) -> [other, self]
2087
+ *
2088
+ * +other+を+self+と等しくしたうえで[other, self]のペア配列にしてこれを返す.
2089
+ */
2090
+ static VALUE
2091
+ complex128_coerce(int argc, VALUE *argv, VALUE self)
2092
+ {
2093
+ VALUE other;
2094
+ rb_scan_args(argc, argv, "10", &other);
2095
+ switch (convertion_num_types(other)) {
2096
+ case NUM_FIXNUM:
2097
+ case NUM_BIGNUM:
2098
+ return complex128_ope_integer(self, other, OPE_COERCE);
2099
+ break;
2100
+ case NUM_RATIONAL:
2101
+ return complex128_ope_rational(self, other, OPE_COERCE);
2102
+ break;
2103
+ case NUM_FLOAT:
2104
+ return complex128_ope_float(self, other, OPE_COERCE);
2105
+ break;
2106
+ case NUM_COMPLEX:
2107
+ return complex128_ope_nucomp(self, other, OPE_COERCE);
2108
+ break;
2109
+ case NUM_FLOAT128:
2110
+ return complex128_ope_float128(self, other, OPE_COERCE);
2111
+ break;
2112
+ case NUM_COMPLEX128:
2113
+ return complex128_ope_complex128(self, other, OPE_COERCE);
2114
+ break;
2115
+ case NUM_OTHERTYPE:
2116
+ default:
2117
+ return rb_call_super(argc, argv);
2118
+ break;
2119
+ }
2120
+ }
2121
+
2122
+ static VALUE
2123
+ complex128_polarize(VALUE rho, VALUE theta)
2124
+ {
2125
+ __float128 abs = get_real(rho),
2126
+ arg = get_real(theta);
2127
+ __complex128 expi = cexpiq(arg);
2128
+ return rb_complex128_cc128(abs * expi);
2129
+ }
2130
+
2131
+ /*
2132
+ * call-seq:
2133
+ * Complex128.polar(rho, theta = 0) -> Complex128
2134
+ *
2135
+ * 極座標(絶対値と偏角)からComplex128を生成する.偏角はラジアンを与える.
2136
+ * 絶対値のみ与えた場合,偏角の値は0である.
2137
+ * 引数は四倍精度の浮動小数点を考慮する.
2138
+ * 考慮できない場合,暗黙の型変換を試みるが,できない場合はTypeErrorを引き起こす.
2139
+ * リテラルは浮動小数点のとき内部的には二倍->四倍と型変換する.そのため精度が落ちる場合がある.
2140
+ *
2141
+ * # 整数リテラルでの生成
2142
+ * Complex128.polar(3) # => (3.0+0.0i)
2143
+ * # 浮動小数点リテラルでの生成.ある程度は精度落ちしない
2144
+ * Complex.polar(3, 2.0) # => (-1.2484405096414273+2.727892280477045i)
2145
+ * Complex128.polar(3, 2.0) # => (-1.2484405096414271609927046885022+2.7278922804770450861880595977352i)
2146
+ * # 精度比較.ある環境の場合
2147
+ * Complex128.polar(3, Math::PI) # => (-2.9999999999999999999999999999999+3.67394039744205953167819779682499e-16i)
2148
+ * Complex128.polar(3, QuadMath::PI) # => (-3.0+2.60154303903713430743911320781301e-34i)
2149
+ */
2150
+ static VALUE
2151
+ complex128_s_polar(int argc, VALUE *argv, VALUE self)
2152
+ {
2153
+ VALUE rho, theta;
2154
+ if (argc == 1)
2155
+ {
2156
+ theta = INT2FIX(0);
2157
+ rb_scan_args(argc, argv, "10", &rho);
2158
+ }
2159
+ else
2160
+ {
2161
+ rb_scan_args(argc, argv, "11", &rho, &theta);
2162
+ }
2163
+ return complex128_polarize(rho, theta);
2164
+ }
2165
+
2166
+ static VALUE
2167
+ complex128_rectangularize(VALUE r, VALUE i)
2168
+ {
2169
+ __float128 real = get_real(r),
2170
+ imag = get_real(i);
2171
+ __complex128 z;
2172
+ __real__ z = real;
2173
+ __imag__ z = imag;
2174
+ return rb_complex128_cc128(z);
2175
+ }
2176
+
2177
+ /*
2178
+ * call-seq:
2179
+ * Complex128.rect(real, imag = 0) -> Complex128
2180
+ * Complex128.rectangular(real, imag = 0) -> Complex128
2181
+ *
2182
+ * 直交座標からComplex128を生成する.
2183
+ * 引数は四倍精度の浮動小数点を考慮する.
2184
+ * 考慮できない場合,暗黙の型変換を試みるが,できない場合はTypeErrorを引き起こす.
2185
+ *
2186
+ * Complex128.rect(3) # => (3.0+0.0i)
2187
+ *
2188
+ * Complex128.rect(3, QuadMath::PI) # => (3.0+3.1415926535897932384626433832795i)
2189
+ * # 二倍精度のπで生成.情報が足りないため途中から精度落ちする
2190
+ * Complex128.rect(3, Math::PI) # => (3.0+3.1415926535897931159979634685441i)
2191
+ */
2192
+ static VALUE
2193
+ complex128_s_rect(int argc, VALUE *argv, VALUE self)
2194
+ {
2195
+ VALUE r, i;
2196
+ if (argc == 1)
2197
+ {
2198
+ i = INT2FIX(0);
2199
+ rb_scan_args(argc, argv, "10", &r);
2200
+ }
2201
+ else
2202
+ {
2203
+ rb_scan_args(argc, argv, "11", &r, &i);
2204
+ }
2205
+ return complex128_rectangularize(r, i);
2206
+ }
2207
+
2208
+
2209
+ /*
2210
+ * call-seq:
2211
+ * strtoflt128(str) -> Float128
2212
+ * strtoflt128(str, sp: "") -> Float128
2213
+ *
2214
+ * This is a front end for the library function strtoflt128(). It takes a String as the first argument +str+ and converts it to Float128 type.
2215
+ * If the keyword argument +sp+ is given, the second argument +sp+ of strtoflt128() will be received as the out buffer.
2216
+ *
2217
+ * strtoflt128('inf') # => Infinity
2218
+ * strtoflt128('-1') # => -1.0
2219
+ * strtoflt128('0xdeadbeef') # => 3735928559.0
2220
+ * sp = '' # => ""
2221
+ * strtoflt128('0+1i', sp: sp) # => 0.0
2222
+ * sp # => "+1i"
2223
+ */
2224
+ static VALUE
2225
+ f_strtoflt128(int argc, VALUE *argv, VALUE self)
2226
+ {
2227
+ static ID kwds[1];
2228
+ VALUE str, opts, sp;
2229
+ __float128 x;
2230
+
2231
+ if (!kwds[0]) kwds[0] = rb_intern_const("sp");
2232
+
2233
+ rb_scan_args(argc, argv, "10:", &str, &opts);
2234
+
2235
+ if (argc != 1)
2236
+ {
2237
+ char *next_pointer;
2238
+
2239
+ rb_get_kwargs(opts, kwds, 0, 1, &sp);
2240
+
2241
+ StringValue(sp);
2242
+ rb_str_resize(sp, 0);
2243
+
2244
+ x = strtoflt128(StringValuePtr(str), &next_pointer);
2245
+
2246
+ rb_str_cat_cstr(sp, next_pointer);
2247
+ }
2248
+ else
2249
+ x = strtoflt128(StringValuePtr(str), NULL);
2250
+
2251
+ return rb_float128_cf128(x);
2252
+ }
2253
+
2254
+ static int
2255
+ xsnprintf(char *buf, size_t sz, char *format, int width, int prec, __float128 x)
2256
+ {
2257
+ int n;
2258
+ if (width == 0 && prec == 0)
2259
+ n = quadmath_snprintf(buf, sz, format, x);
2260
+ else if (width != 0 && prec == 0)
2261
+ n = quadmath_snprintf(buf, sz, format, width, x);
2262
+ else if (width == 0 && prec != 0)
2263
+ n = quadmath_snprintf(buf, sz, format, prec, x);
2264
+ else /* if (width != 0 && prec != 0) */
2265
+ n = quadmath_snprintf(buf, sz, format, width, prec, x);
2266
+ return n;
2267
+ }
2268
+
2269
+ /*
2270
+ * call-seq:
2271
+ * quadmath_sprintf(format, *arg) -> String
2272
+ *
2273
+ * A front end that provides access to the quadmath_snprintf() library function.
2274
+ * Notice that the method name and argument count are slightly different from the library's.
2275
+ *
2276
+ * The format depends on the library functions.
2277
+ * The arguments of library functions are variable length and are determined by the compiler. Therefore, this front end handles this in the parser.
2278
+ * The parser is strict about formatting errors.
2279
+ *
2280
+ * The string is stored in an internal buffer and provided to the user level.
2281
+ * If the function throws an error because the internal buffer is insufficient, it will automatically allocate memory and pass it.
2282
+ *
2283
+ * quadmath_sprintf("%Qf", 2) # => "2.000000"
2284
+ * quadmath_sprintf("%Qf", 7/10r) # => "0.700000"
2285
+ * quadmath_sprintf("%.*Qf", Float128::DIG, 1/3r) # => "0.333333333333333333333333333333333"
2286
+ * quadmath_sprintf("%.*Qf", Float128::DIG, 1.0/3.0) # => "0.333333333333333314829616256247391"
2287
+ * quadmath_sprintf("%.*Qf", Float128::DIG, 1.to_f128 / 3) # => "0.333333333333333333333333333333333"
2288
+ * width = 46; prec = 20;
2289
+ * quadmath_sprintf("%+-#*.*Qe", width, prec, QuadMath.sqrt(2)) # => "+1.41421356237309504880e+00 "
2290
+ */
2291
+ static VALUE
2292
+ f_quadmath_sprintf(int argc, VALUE *argv, VALUE self)
2293
+ {
2294
+ VALUE vformat, arg, apptd, retval;
2295
+ char *format;
2296
+ int fmt_stat = FMT_EMPTY, flags = 0, width = 0, prec = 0, float_type = FT_FLT;
2297
+ long arg_offset = 0;
2298
+ char notation = 'f';
2299
+
2300
+ rb_scan_args(argc, argv, "1*", &vformat, &arg);
2301
+
2302
+ format = StringValuePtr(vformat);
2303
+ retval = rb_str_new(0,0);
2304
+
2305
+ for (long i = 0; i < RSTRING_LEN(vformat); i++)
2306
+ {
2307
+ const char c = format[i];
2308
+
2309
+ if (fmt_stat == FMT_EMPTY && c != '%')
2310
+ continue;
2311
+
2312
+ switch (c) {
2313
+ case '%':
2314
+ if (fmt_stat == FMT_EMPTY)
2315
+ fmt_stat = FMT_DRCTV;
2316
+ else
2317
+ goto fmt_error;
2318
+ break;
2319
+ case '#':
2320
+ if (fmt_stat == FMT_DRCTV)
2321
+ flags |= FLAG_SHARP;
2322
+ else
2323
+ goto fmt_error;
2324
+ break;
2325
+ case ' ':
2326
+ if (fmt_stat == FMT_DRCTV)
2327
+ flags |= FLAG_SPACE;
2328
+ else
2329
+ goto fmt_error;
2330
+ break;
2331
+ case '+':
2332
+ if (fmt_stat == FMT_DRCTV)
2333
+ flags |= FLAG_PLUS;
2334
+ else
2335
+ goto fmt_error;
2336
+ break;
2337
+ case '-':
2338
+ if (fmt_stat == FMT_DRCTV)
2339
+ flags |= FLAG_MINUS;
2340
+ else
2341
+ goto fmt_error;
2342
+ break;
2343
+ case '0': case '1': case '2': case '3': case '4':
2344
+ case '5': case '6': case '7': case '8': case '9':
2345
+ if (fmt_stat == FMT_DRCTV)
2346
+ {
2347
+ if (c == '0')
2348
+ flags |= FLAG_ZERO;
2349
+ else
2350
+ fmt_stat = FMT_WIDTH;
2351
+ }
2352
+ else if (fmt_stat == FMT_POINT)
2353
+ {
2354
+ fmt_stat = FMT_PREC;
2355
+ }
2356
+
2357
+ if (fmt_stat == FMT_WIDTH)
2358
+ {
2359
+ width = width * 10 + (c - '0');
2360
+ if (width < 0)
2361
+ goto biggest_width_error;
2362
+ }
2363
+ else if (fmt_stat == FMT_PREC)
2364
+ {
2365
+ prec = prec * 10 + (c - '0');
2366
+ if (prec < 0)
2367
+ goto biggest_prec_error;
2368
+ }
2369
+ else
2370
+ goto fmt_error;
2371
+
2372
+ break;
2373
+ case '*':
2374
+ if (fmt_stat == FMT_DRCTV)
2375
+ fmt_stat = FMT_WIDTH_SCALAR;
2376
+ else if (fmt_stat == FMT_POINT)
2377
+ fmt_stat = FMT_PREC_SCALAR;
2378
+ else
2379
+ goto fmt_error;
2380
+
2381
+ if (RARRAY_LEN(arg) <= arg_offset)
2382
+ goto too_few_arguments;
2383
+ else
2384
+ {
2385
+ VALUE item = rb_ary_entry(arg, arg_offset);
2386
+ long n;
2387
+
2388
+ if (!RB_TYPE_P(item, T_FIXNUM) ||
2389
+ !RB_TYPE_P(item, T_BIGNUM))
2390
+ item = rb_Integer(item);
2391
+
2392
+ n = NUM2LONG(item);
2393
+
2394
+ if (fmt_stat == FMT_WIDTH_SCALAR)
2395
+ {
2396
+ if (n < 0) goto biggest_width_error;
2397
+ width = (int)n;
2398
+ }
2399
+ else /* if (fmt_stat == FMT_PREC_SCALAR) */
2400
+ {
2401
+ if (n < 0) goto biggest_prec_error;
2402
+ prec = (int)n;
2403
+ }
2404
+
2405
+ arg_offset++;
2406
+ }
2407
+ break;
2408
+ case '.':
2409
+ switch (fmt_stat) {
2410
+ case FMT_DRCTV:
2411
+ case FMT_WIDTH:
2412
+ case FMT_WIDTH_SCALAR:
2413
+ fmt_stat = FMT_POINT;
2414
+ break;
2415
+ default:
2416
+ goto fmt_error;
2417
+ }
2418
+ break;
2419
+ case 'l':
2420
+ if (fmt_stat == FMT_POINT || fmt_stat == FMT_SET_FT)
2421
+ goto fmt_error;
2422
+
2423
+ float_type = FT_DBL;
2424
+ fmt_stat = FMT_SET_FT;
2425
+
2426
+ break;
2427
+ case 'L':
2428
+ if (fmt_stat == FMT_POINT || fmt_stat == FMT_SET_FT)
2429
+ goto fmt_error;
2430
+
2431
+ float_type = FT_LDBL;
2432
+ fmt_stat = FMT_SET_FT;
2433
+ break;
2434
+ case 'Q':
2435
+ if (fmt_stat == FMT_POINT || fmt_stat == FMT_SET_FT)
2436
+ goto fmt_error;
2437
+
2438
+ float_type = FT_QUAD;
2439
+ fmt_stat = FMT_SET_FT;
2440
+ break;
2441
+ case 'a': case 'A':
2442
+ case 'e': case 'E':
2443
+ case 'f': case 'F':
2444
+ case 'g': case 'G':
2445
+ if (fmt_stat == FMT_POINT) goto fmt_error;
2446
+
2447
+ if (float_type == FT_QUAD)
2448
+ {
2449
+ if (RARRAY_LEN(arg) <= arg_offset)
2450
+ goto too_few_arguments;
2451
+ else
2452
+ {
2453
+ __float128 x = get_real(rb_ary_entry(arg, arg_offset));
2454
+ int n;
2455
+ char buf[BUF_SIZ];
2456
+ apptd = rb_usascii_str_new_cstr("%");
2457
+ notation = isupper(c) ? c + 0x20 : c;
2458
+ if (flags & FLAG_PLUS) rb_str_concat(apptd, CHR2FIX('+'));
2459
+ if (flags & FLAG_MINUS) rb_str_concat(apptd, CHR2FIX('-'));
2460
+ if (flags & FLAG_SHARP) rb_str_concat(apptd, CHR2FIX('#'));
2461
+ if (flags & FLAG_ZERO) rb_str_concat(apptd, CHR2FIX('0'));
2462
+ if (flags & FLAG_SPACE) rb_str_concat(apptd, CHR2FIX(' '));
2463
+ if (width != 0) rb_str_concat(apptd, CHR2FIX('*'));
2464
+ if (prec != 0) { rb_str_concat(apptd, CHR2FIX('.'));
2465
+ rb_str_concat(apptd, CHR2FIX('*')); }
2466
+ rb_str_concat(apptd, CHR2FIX('Q'));
2467
+ rb_str_concat(apptd, CHR2FIX(notation));
2468
+
2469
+ n = xsnprintf(buf, BUF_SIZ, StringValuePtr(apptd), width, prec, x);
2470
+
2471
+ if ((size_t)n < sizeof(buf))
2472
+ rb_str_cat_cstr(retval, buf);
2473
+ else
2474
+ {
2475
+ n = xsnprintf(NULL, 0, StringValuePtr(apptd), width, prec, x);
2476
+ if (n > -1)
2477
+ {
2478
+ char *str = ruby_xmalloc(n + 1);
2479
+ if (str)
2480
+ {
2481
+ xsnprintf(str, n + 1, StringValuePtr(apptd), width, prec, x);
2482
+ rb_str_cat_cstr(retval, str);
2483
+ }
2484
+ ruby_xfree(str);
2485
+ }
2486
+ }
2487
+ }
2488
+ }
2489
+ goto return_value;
2490
+ break;
2491
+ default:
2492
+ goto fmt_error;
2493
+ break;
2494
+ }
2495
+ }
2496
+ return_value:
2497
+ return retval;
2498
+ fmt_error:
2499
+ rb_raise(rb_eArgError, "format error");
2500
+ biggest_width_error:
2501
+ rb_raise(rb_eArgError, "biggest (or negative) width size");
2502
+ biggest_prec_error:
2503
+ rb_raise(rb_eArgError, "biggest (or negative) precision size");
2504
+ too_few_arguments:
2505
+ rb_raise(rb_eArgError, "too few arguments");
2506
+ }
2507
+
2508
+ static VALUE
2509
+ float128_rationalable(VALUE self)
2510
+ {
2511
+ VALUE string;
2512
+ __float128 x = rb_float128_value(self);
2513
+
2514
+ switch (fpclassify(x)) {
2515
+ case FP_NAN:
2516
+
2517
+ rb_raise(rb_eFloatDomainError, "NaN");
2518
+ break;
2519
+ case FP_INFINITE:
2520
+ if (signbitq(x))
2521
+ rb_raise(rb_eFloatDomainError, "-Infinity");
2522
+ else
2523
+ rb_raise(rb_eFloatDomainError, "Infinity");
2524
+ break;
2525
+ case FP_ZERO:
2526
+ self = rb_Rational1(INT2FIX(0));
2527
+ break;
2528
+ case FP_NORMAL:
2529
+ case FP_SUBNORMAL:
2530
+ default:
2531
+ string = float128_to_s(0, 0, self);
2532
+ self = rb_Rational1(string);
2533
+ break;
2534
+ }
2535
+ return self;
2536
+ }
2537
+
2538
+ /*
2539
+ * call-seq:
2540
+ * to_r -> Rational
2541
+ *
2542
+ * Convert to Rational.
2543
+ */
2544
+ static VALUE
2545
+ float128_to_r(VALUE self)
2546
+ {
2547
+ return float128_rationalable(self);
2548
+ }
2549
+
2550
+ /*
2551
+ * call-seq:
2552
+ * to_r -> Rational
2553
+ *
2554
+ * Convert to Rational.
2555
+ */
2556
+ static VALUE
2557
+ complex128_to_r(VALUE self)
2558
+ {
2559
+ __complex128 z = rb_complex128_value(self);;
2560
+
2561
+ if (fpclassify(cimagq(z)) != FP_ZERO)
2562
+ rb_raise(rb_eTypeError,
2563
+ "can't convert %"PRIsVALUE" into Rational", self);
2564
+
2565
+ return float128_rationalable(rb_float128_cf128(crealq(z)));
2566
+ }
2567
+
2568
+
2569
+
2570
+ void
2571
+ InitVM_Numerable(void)
2572
+ {
2573
+ /* Numerical Type Conversions */
2574
+ rb_define_method(rb_cString, "to_f128", string_to_f128, 0);
2575
+ rb_define_method(rb_cString, "to_c128", string_to_c128, 0);
2576
+
2577
+ rb_define_method(rb_cNumeric, "to_f128", numeric_to_f128, 0);
2578
+ rb_define_method(rb_cNumeric, "to_c128", numeric_to_c128, 0);
2579
+
2580
+ rb_undef_method(rb_cNumeric, "to_f128");
2581
+ rb_undef_method(rb_cNumeric, "to_c128");
2582
+
2583
+ rb_define_method(rb_cInteger, "to_f128", integer_to_f128, 0);
2584
+ rb_define_method(rb_cInteger, "to_c128", integer_to_c128, 0);
2585
+
2586
+ rb_define_method(rb_cRational, "to_f128", rational_to_f128, 0);
2587
+ rb_define_method(rb_cRational, "to_c128", rational_to_c128, 0);
2588
+
2589
+ rb_define_method(rb_cFloat, "to_f128", float_to_f128, 0);
2590
+ rb_define_method(rb_cFloat, "to_c128", float_to_c128, 0);
2591
+
2592
+ rb_define_method(rb_cComplex, "to_f128", nucomp_to_f128, 0);
2593
+ rb_define_method(rb_cComplex, "to_c128", nucomp_to_c128, 0);
2594
+
2595
+ /* Global function */
2596
+ rb_define_global_function("Float128", f_Float128, -1);
2597
+ rb_define_global_function("Complex128", f_Complex128, -1);
2598
+ rb_define_global_function("strtoflt128", f_strtoflt128, -1);
2599
+ rb_define_global_function("quadmath_sprintf", f_quadmath_sprintf, -1);
2600
+
2601
+ /* Singleton Methods */
2602
+ rb_define_singleton_method(rb_cFloat128, "fma", float128_s_fma, -1);
2603
+ rb_define_singleton_method(rb_cFloat128, "sincos", float128_s_sincos, -1);
2604
+ rb_define_singleton_method(rb_cFloat128, "fmin", float128_s_fmin, -1);
2605
+ rb_define_singleton_method(rb_cFloat128, "fmax", float128_s_fmax, -1);
2606
+ rb_define_singleton_method(rb_cFloat128, "ldexp", float128_s_ldexp, 2);
2607
+ rb_define_singleton_method(rb_cFloat128, "scalb", float128_s_scalb, 2);
2608
+ rb_define_singleton_method(rb_cFloat128, "scalbn", float128_s_scalb, 2);
2609
+ rb_define_singleton_method(rb_cComplex128, "polar", complex128_s_polar, -1);
2610
+ rb_define_singleton_method(rb_cComplex128, "rect", complex128_s_rect, -1);
2611
+ rb_define_singleton_method(rb_cComplex128, "rectangular", complex128_s_rect, -1);
2612
+
2613
+ /* Operators & Evals */
2614
+ rb_define_method(rb_cFloat128, "polar", float128_polar, 0);
2615
+ rb_define_method(rb_cFloat128, "abs", float128_abs, 0);
2616
+ rb_define_alias(rb_cFloat128, "magnitude", "abs");
2617
+ rb_define_method(rb_cFloat128, "abs2", float128_abs2, 0);
2618
+ rb_define_method(rb_cFloat128, "arg", float128_arg, 0);
2619
+ rb_define_alias(rb_cFloat128, "angle", "arg");
2620
+ rb_define_alias(rb_cFloat128, "phase", "arg");
2621
+
2622
+ rb_define_method(rb_cFloat128, "+", float128_add, 1);
2623
+ rb_define_method(rb_cFloat128, "-", float128_sub, 1);
2624
+ rb_define_method(rb_cFloat128, "*", float128_mul, 1);
2625
+ rb_define_method(rb_cFloat128, "/", float128_div, 1);
2626
+ rb_define_method(rb_cFloat128, "%", float128_mod, 1);
2627
+ rb_define_method(rb_cFloat128, "modulo", float128_mod, 1);
2628
+ rb_define_method(rb_cFloat128, "**", float128_pow, 1);
2629
+ rb_define_method(rb_cFloat128, "<=>", float128_cmp, 1);
2630
+ rb_define_method(rb_cFloat128, "coerce", float128_coerce, -1);
2631
+
2632
+ rb_define_method(rb_cComplex128, "polar", complex128_polar, 0);
2633
+ rb_define_method(rb_cComplex128, "abs", complex128_abs, 0);
2634
+ rb_define_alias(rb_cComplex128, "magnitude", "abs");
2635
+ rb_define_method(rb_cComplex128, "abs2", complex128_abs2, 0);
2636
+ rb_define_method(rb_cComplex128, "arg", complex128_arg, 0);
2637
+ rb_define_alias(rb_cComplex128, "angle", "arg");
2638
+ rb_define_alias(rb_cComplex128, "phase", "arg");
2639
+ rb_define_method(rb_cComplex128, "conj", complex128_conj, 0);
2640
+
2641
+ rb_define_method(rb_cComplex128, "+", complex128_add, 1);
2642
+ rb_define_method(rb_cComplex128, "-", complex128_sub, 1);
2643
+ rb_define_method(rb_cComplex128, "*", complex128_mul, 1);
2644
+ rb_define_method(rb_cComplex128, "/", complex128_div, 1);
2645
+ rb_define_method(rb_cComplex128, "%", complex128_mod, 1);
2646
+ rb_define_method(rb_cComplex128, "modulo", complex128_mod, 1);
2647
+ rb_define_method(rb_cComplex128, "**", complex128_pow, 1);
2648
+ rb_define_method(rb_cComplex128, "<=>", complex128_cmp, 1);
2649
+ rb_define_method(rb_cComplex128, "coerce", complex128_coerce, -1);
2650
+
2651
+ rb_undef_method(rb_cComplex128, "%");
2652
+ rb_undef_method(rb_cComplex128, "modulo");
2653
+
2654
+ /* Rational */
2655
+ rb_define_method(rb_cFloat128, "to_r", float128_to_r, 0);
2656
+ rb_define_method(rb_cComplex128, "to_r", complex128_to_r, 0);
2657
+ }