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,2768 @@
1
+ /*******************************************************************************
2
+ quadmath.c -- module QuadMath
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
+ static inline bool
12
+ num_real_p(VALUE self)
13
+ {
14
+ if (!rb_respond_to(self, rb_intern("real?")))
15
+ rb_fatal("method `real?' is undefined");
16
+ else
17
+ return RTEST(rb_funcall(self, rb_intern("real?"), 0));
18
+ }
19
+
20
+ static inline __float128
21
+ fixnum_to_cf128(VALUE self)
22
+ {
23
+ long x = FIX2LONG(self);
24
+
25
+ return (__float128)x;
26
+ }
27
+
28
+ static inline __float128
29
+ bignum_to_cf128(VALUE self)
30
+ {
31
+ VALUE inum = rb_big2str(self, 10);
32
+ __float128 x = strtoflt128(StringValuePtr(inum), NULL);
33
+
34
+ return x;
35
+ }
36
+
37
+ static inline __float128
38
+ integer_to_cf128(VALUE self)
39
+ {
40
+ __float128 x = 0.0Q;
41
+ switch (TYPE(self)) {
42
+ case T_FIXNUM:
43
+ x = fixnum_to_cf128(self);
44
+ break;
45
+ case T_BIGNUM:
46
+ x = bignum_to_cf128(self);
47
+ break;
48
+ default:
49
+ break;
50
+ }
51
+ return x;
52
+ }
53
+
54
+ static inline __float128
55
+ rational_to_cf128(VALUE self)
56
+ {
57
+ VALUE numer = rb_rational_num(self),
58
+ denom = rb_rational_den(self);
59
+ __float128 x = integer_to_cf128(numer) / integer_to_cf128(denom);
60
+
61
+ return x;
62
+ }
63
+
64
+ static inline __float128
65
+ float_to_cf128(VALUE self)
66
+ {
67
+ double x = NUM2DBL(self);
68
+
69
+ return (__float128)x;
70
+ }
71
+
72
+
73
+
74
+ static inline __float128
75
+ primitive_real_to_cf128(VALUE self)
76
+ {
77
+ __float128 x;
78
+ switch (TYPE(self)) {
79
+ case T_FIXNUM:
80
+ x = fixnum_to_cf128(self);
81
+ break;
82
+ case T_BIGNUM:
83
+ x = bignum_to_cf128(self);
84
+ break;
85
+ case T_RATIONAL:
86
+ x = rational_to_cf128(self);
87
+ break;
88
+ case T_FLOAT:
89
+ x = float_to_cf128(self);
90
+ break;
91
+ default:
92
+ self = rb_funcall(self, rb_intern("to_f128"), 0);
93
+ x = GetF128(self);
94
+ break;
95
+ }
96
+ return x;
97
+ }
98
+
99
+ static inline __complex128
100
+ nucomp_to_cc128(VALUE self)
101
+ {
102
+ VALUE real = rb_complex_real(self);
103
+ VALUE imag = rb_complex_imag(self);
104
+ __complex128 z = 0+0i;
105
+
106
+ __real__ z = primitive_real_to_cf128(real);
107
+ __imag__ z = primitive_real_to_cf128(imag);
108
+
109
+ return z;
110
+ }
111
+
112
+ static inline VALUE
113
+ complex128_to_nucomp(VALUE self)
114
+ {
115
+ __complex128 z = GetC128(self);
116
+ return rb_Complex(
117
+ rb_float128_cf128(crealq(z)),
118
+ rb_float128_cf128(cimagq(z)));
119
+ }
120
+
121
+ static VALUE
122
+ quadmath_exp_realsolve(__float128 x)
123
+ {
124
+ return rb_float128_cf128(expq(x));
125
+ }
126
+
127
+ static VALUE
128
+ quadmath_exp_nucompsolve(__complex128 z)
129
+ {
130
+ return rb_complex128_cc128(cexpq(z));
131
+ }
132
+
133
+ /*
134
+ * call-seq:
135
+ * QuadMath.exp(x) -> Float128 | Complex | Complex128
136
+ *
137
+ * xの指数関数を返す.xが実数なら実数解,複素数なら複素数解として各々返却する.
138
+ *
139
+ * QuadMath.exp(1) # => 2.7182818284590452353602874713526
140
+ * QuadMath.exp(-2.1r) # => 0.122456428252981910218647376072626
141
+ * QuadMath.exp(1+0i) # => (2.7182818284590452353602874713526+0.0i)
142
+ * QuadMath.exp('-10.4'.to_f128) # => 0.0000304324830084036365062222042316828
143
+ * QuadMath.exp(Complex128.rect(1.1r, 1))
144
+ * # => (1.6231578299489788500278329108526+2.5279185426966278702444317537622i)
145
+ */
146
+ static VALUE
147
+ quadmath_exp(VALUE unused_obj, VALUE x)
148
+ {
149
+ switch (convertion_num_types(x)) {
150
+ case NUM_FIXNUM:
151
+ return quadmath_exp_realsolve(fixnum_to_cf128(x));
152
+ break;
153
+ case NUM_BIGNUM:
154
+ return quadmath_exp_realsolve(bignum_to_cf128(x));
155
+ break;
156
+ case NUM_RATIONAL:
157
+ return quadmath_exp_realsolve(rational_to_cf128(x));
158
+ break;
159
+ case NUM_FLOAT:
160
+ return quadmath_exp_realsolve(float_to_cf128(x));
161
+ break;
162
+ case NUM_COMPLEX:
163
+ VALUE nucomp = quadmath_exp_nucompsolve(nucomp_to_cc128(x));
164
+ return complex128_to_nucomp(nucomp);
165
+ break;
166
+ case NUM_FLOAT128:
167
+ return quadmath_exp_realsolve(GetF128(x));
168
+ break;
169
+ case NUM_COMPLEX128:
170
+ return quadmath_exp_nucompsolve(GetC128(x));
171
+ break;
172
+ case NUM_OTHERTYPE:
173
+ default:
174
+ if (num_real_p(x))
175
+ return quadmath_exp_realsolve(rb_float128_value(x));
176
+ else
177
+ return quadmath_exp_nucompsolve(rb_complex128_value(x));
178
+ break;
179
+ }
180
+ }
181
+
182
+ static inline VALUE
183
+ quadmath_exp2_realsolve(__float128 x)
184
+ {
185
+ return rb_float128_cf128(exp2q(x));
186
+ }
187
+
188
+ static inline VALUE
189
+ quadmath_exp2_nucompsolve(__complex128 z)
190
+ {
191
+ return rb_complex128_cc128(cpowq(2, z));
192
+ }
193
+
194
+ /*
195
+ * call-seq:
196
+ * QuadMath.exp2(x) -> Integer | Rational | Float128 | Complex | Complex128
197
+ *
198
+ * 2のx乗を返す.xが整数なら正では整数解,負では有理数解,実数なら実数解,複素数なら複素数解として各々返却する.
199
+ * これは一般に`2 ** x`と計算するのとさして変わらない.唯一の違いは実数の精度が二倍ではなく四倍であることである.
200
+ *
201
+ * QuadMath.exp2(-1) # => (1/2)
202
+ * QuadMath.exp2(5) # => 32
203
+ * QuadMath.exp2(11/7r) # => 2.9719885782738968495997065734291
204
+ * QuadMath.exp2(Complex128::I) # => (0.76923890136397212657832999366127+0.638961276313634801150032911464701i)
205
+ */
206
+ static VALUE
207
+ quadmath_exp2(VALUE unused_obj, VALUE x)
208
+ {
209
+ switch (convertion_num_types(x)) {
210
+ case NUM_FIXNUM:
211
+ case NUM_BIGNUM:
212
+ return rb_num_coerce_bin(INT2NUM(2), x, rb_intern("**"));
213
+ break;
214
+ case NUM_RATIONAL:
215
+ return quadmath_exp2_realsolve(rational_to_cf128(x));
216
+ break;
217
+ case NUM_FLOAT:
218
+ return quadmath_exp2_realsolve(float_to_cf128(x));
219
+ break;
220
+ case NUM_COMPLEX:
221
+ return float128_nucomp_pow(rb_float128_cf128(2), x);
222
+ break;
223
+ case NUM_FLOAT128:
224
+ return quadmath_exp2_realsolve(GetF128(x));
225
+ break;
226
+ case NUM_COMPLEX128:
227
+ return quadmath_exp2_nucompsolve(GetC128(x));
228
+ break;
229
+ case NUM_OTHERTYPE:
230
+ default:
231
+ if (num_real_p(x))
232
+ return quadmath_exp2_realsolve(GetF128(x));
233
+ else
234
+ return quadmath_exp2_nucompsolve(GetC128(x));
235
+ break;
236
+ }
237
+ }
238
+
239
+ static inline VALUE
240
+ quadmath_expm1_realsolve(__float128 x)
241
+ {
242
+ return rb_float128_cf128(expm1q(x));
243
+ }
244
+
245
+ static inline VALUE
246
+ quadmath_expm1_nucompsolve(__complex128 z)
247
+ {
248
+ if (cimagq(z) == 0)
249
+ {
250
+ __float128 real = crealq(z);
251
+ return rb_complex128_cc128((__complex128)expm1q(real));
252
+ }
253
+ else
254
+ {
255
+ __complex128 w = 2 * cexpq(z / 2) * csinhq(z / 2);
256
+ return rb_complex128_cc128(w);
257
+ }
258
+ }
259
+
260
+ /*
261
+ * call-seq:
262
+ * QuadMath.expm1(x) -> Float128 | Complex128
263
+ *
264
+ * xの指数関数より1を引いた値を返す.
265
+ * この関数はゼロに近傍な値を数式通りにexp(x)-1と計算するよりも高精度化する.
266
+ * xが実数なら実数解,複素数なら複素数解として各々返却する.
267
+ *
268
+ * QuadMath.expm1('-1e-33'.to_f128) # => -1.0e-33
269
+ * QuadMath.exp('-1e-33'.to_f128)-1 # => -9.62964972193617926527988971292464e-34
270
+ * QuadMath.expm1(Complex128::I) # => (-0.459697694131860282599063392557023+0.841470984807896506652502321630299i)
271
+ */
272
+ static VALUE
273
+ quadmath_expm1(VALUE unused_obj, VALUE x)
274
+ {
275
+ switch (convertion_num_types(x)) {
276
+ case NUM_FIXNUM:
277
+ return quadmath_expm1_realsolve(fixnum_to_cf128(x));
278
+ break;
279
+ case NUM_BIGNUM:
280
+ return quadmath_expm1_realsolve(bignum_to_cf128(x));
281
+ break;
282
+ case NUM_RATIONAL:
283
+ return quadmath_expm1_realsolve(rational_to_cf128(x));
284
+ break;
285
+ case NUM_FLOAT:
286
+ return quadmath_expm1_realsolve(float_to_cf128(x));
287
+ break;
288
+ case NUM_COMPLEX:
289
+ VALUE nucomp = quadmath_expm1_nucompsolve(nucomp_to_cc128(x));
290
+ return complex128_to_nucomp(nucomp);
291
+ break;
292
+ case NUM_FLOAT128:
293
+ return quadmath_expm1_realsolve(GetF128(x));
294
+ break;
295
+ case NUM_COMPLEX128:
296
+ return quadmath_expm1_nucompsolve(GetC128(x));
297
+ break;
298
+ case NUM_OTHERTYPE:
299
+ default:
300
+ if (num_real_p(x))
301
+ return quadmath_expm1_realsolve(GetF128(x));
302
+ else
303
+ return quadmath_expm1_nucompsolve(GetC128(x));
304
+ break;
305
+ }
306
+ }
307
+
308
+ static inline VALUE
309
+ quadmath_log_realsolve(__float128 x)
310
+ {
311
+ if (isnanq(x))
312
+ return rb_float128_cf128(x);
313
+ else if (!signbitq(x))
314
+ return rb_float128_cf128(logq(x));
315
+ else
316
+ {
317
+ __complex128 z;
318
+ __real__ z = logq(fabsq(x));
319
+ __imag__ z = M_PIq;
320
+ return rb_complex128_cc128(z);
321
+ }
322
+ }
323
+
324
+ static inline VALUE
325
+ quadmath_log_nucompsolve(__complex128 z)
326
+ {
327
+ return rb_complex128_cc128(clogq(z));
328
+ }
329
+
330
+ /*
331
+ * call-seq:
332
+ * QuadMath.log(x) -> Float128 | Complex128
333
+ *
334
+ * xの自然対数を返す.
335
+ * xが実数なら正ならば実数解,負なら複素数解,複素数なら複素数解として値を各々返す.
336
+ *
337
+ * QuadMath.log(2) # => 0.693147180559945309417232121458176
338
+ * QuadMath.log(-2) # => (0.693147180559945309417232121458176+3.1415926535897932384626433832795i)
339
+ * QuadMath.log(Complex128::I) # => (0.0+1.5707963267948966192313216916397i)
340
+ */
341
+ static VALUE
342
+ quadmath_log(VALUE unused_obj, VALUE x)
343
+ {
344
+ switch (convertion_num_types(x)) {
345
+ case NUM_FIXNUM:
346
+ return quadmath_log_realsolve(fixnum_to_cf128(x));
347
+ break;
348
+ case NUM_BIGNUM:
349
+ return quadmath_log_realsolve(bignum_to_cf128(x));
350
+ break;
351
+ case NUM_RATIONAL:
352
+ return quadmath_log_realsolve(rational_to_cf128(x));
353
+ break;
354
+ case NUM_FLOAT:
355
+ return quadmath_log_realsolve(float_to_cf128(x));
356
+ break;
357
+ case NUM_COMPLEX:
358
+ VALUE nucomp = quadmath_log_nucompsolve(nucomp_to_cc128(x));
359
+ return complex128_to_nucomp(nucomp);
360
+ break;
361
+ case NUM_FLOAT128:
362
+ return quadmath_log_realsolve(GetF128(x));
363
+ break;
364
+ case NUM_COMPLEX128:
365
+ return quadmath_log_nucompsolve(GetC128(x));
366
+ break;
367
+ case NUM_OTHERTYPE:
368
+ default:
369
+ if (num_real_p(x))
370
+ return quadmath_log_realsolve(GetF128(x));
371
+ else
372
+ return quadmath_log_nucompsolve(GetC128(x));
373
+ break;
374
+ }
375
+ }
376
+
377
+ static inline VALUE
378
+ quadmath_log2_realsolve(__float128 x)
379
+ {
380
+ if (isnanq(x))
381
+ return rb_float128_cf128(x);
382
+ else if (!signbitq(x))
383
+ return rb_float128_cf128(log2q(x));
384
+ else
385
+ {
386
+ __complex128 z;
387
+ __real__ z = log2q(fabsq(x));
388
+ __imag__ z = M_PIq / M_LN2q;
389
+ return rb_complex128_cc128(z);
390
+ }
391
+ }
392
+
393
+ static inline VALUE
394
+ quadmath_log2_nucompsolve(__complex128 z)
395
+ {
396
+ return rb_complex128_cc128(clogq(z) / M_LN2q);
397
+ }
398
+
399
+ /*
400
+ * call-seq:
401
+ * QuadMath.log2(x) -> Float128 | Complex128
402
+ *
403
+ * xの2を底とする対数を返す.(Binary Logarithm)
404
+ * xが実数なら正ならば実数解,負なら複素数解,複素数なら複素数解として値を各々返す.
405
+ *
406
+ * Array.new(5){|i|i} # => [0, 1, 2, 3, 4]
407
+ * ary = Array.new(5){|i| 2**i} # => [1, 2, 4, 8, 16]
408
+ * ary.map {|x| QuadMath.log2(x)} # => [0.0, 1.0, 2.0, 3.0, 4.0]
409
+ *
410
+ * Array.new(5){|i|~i} # => [-1, -2, -3, -4, -5]
411
+ * ary = Array.new(5){|i| 2 ** ~i} # => [(1/2), (1/4), (1/8), (1/16), (1/32)]
412
+ * ary.map{|x| QuadMath.log2(x)} # => [-1.0, -2.0, -3.0, -4.0, -5.0]
413
+ *
414
+ * QuadMath.log2(1+1i) # => (0.5+1.1330900354567984524069207364291i)
415
+ */
416
+ static VALUE
417
+ quadmath_log2(VALUE unused_obj, VALUE x)
418
+ {
419
+ switch (convertion_num_types(x)) {
420
+ case NUM_FIXNUM:
421
+ return quadmath_log2_realsolve(fixnum_to_cf128(x));
422
+ break;
423
+ case NUM_BIGNUM:
424
+ return quadmath_log2_realsolve(bignum_to_cf128(x));
425
+ break;
426
+ case NUM_RATIONAL:
427
+ return quadmath_log2_realsolve(rational_to_cf128(x));
428
+ break;
429
+ case NUM_FLOAT:
430
+ return quadmath_log2_realsolve(float_to_cf128(x));
431
+ break;
432
+ case NUM_COMPLEX:
433
+ VALUE nucomp = quadmath_log2_nucompsolve(nucomp_to_cc128(x));
434
+ return complex128_to_nucomp(nucomp);
435
+ break;
436
+ case NUM_FLOAT128:
437
+ return quadmath_log2_realsolve(GetF128(x));
438
+ break;
439
+ case NUM_COMPLEX128:
440
+ return quadmath_log2_nucompsolve(GetC128(x));
441
+ break;
442
+ case NUM_OTHERTYPE:
443
+ default:
444
+ if (num_real_p(x))
445
+ return quadmath_log2_realsolve(GetF128(x));
446
+ else
447
+ return quadmath_log2_nucompsolve(GetC128(x));
448
+ break;
449
+ }
450
+ }
451
+
452
+ static inline VALUE
453
+ quadmath_log10_realsolve(__float128 x)
454
+ {
455
+ if (isnanq(x))
456
+ return rb_float128_cf128(x);
457
+ else if (!signbitq(x))
458
+ return rb_float128_cf128(log10q(x));
459
+ else
460
+ {
461
+ __complex128 z;
462
+ __real__ z = log10q(fabsq(x));
463
+ __imag__ z = M_PIq / M_LN10q;
464
+ return rb_complex128_cc128(z);
465
+ }
466
+ }
467
+
468
+ static inline VALUE
469
+ quadmath_log10_nucompsolve(__complex128 z)
470
+ {
471
+ return rb_complex128_cc128(clog10q(z));
472
+ }
473
+
474
+ /*
475
+ * call-seq:
476
+ * QuadMath.log10(x) -> Float128 | Complex128
477
+ *
478
+ * xの常用対数を返す.
479
+ * xが実数なら正ならば実数解,負なら複素数解,複素数なら複素数解として値を各々返す.
480
+ *
481
+ * Array.new(5){|i|i} # => [0, 1, 2, 3, 4]
482
+ * ary = Array.new(5){|i| 10**i} # => [1, 10, 100, 1000, 10000]
483
+ * ary.map {|x| QuadMath.log10(x)} # => [0.0, 1.0, 2.0, 3.0, 4.0]
484
+ *
485
+ * Array.new(5){|i|~i} # => [-1, -2, -3, -4, -5]
486
+ * ary = Array.new(5){|i|10 ** ~i} # => [(1/10), (1/100), (1/1000), (1/10000), (1/100000)]
487
+ * ary.map{|x| QuadMath.log10(x)} # => [-1.0, -2.0, -3.0, -4.0, -5.0]
488
+ *
489
+ * QuadMath.log10(1+1i) # => (0.150514997831990597606869447362246+0.341094088460460336871445906357839i)
490
+
491
+ */
492
+ static VALUE
493
+ quadmath_log10(VALUE unused_obj, VALUE x)
494
+ {
495
+ switch (convertion_num_types(x)) {
496
+ case NUM_FIXNUM:
497
+ return quadmath_log10_realsolve(fixnum_to_cf128(x));
498
+ break;
499
+ case NUM_BIGNUM:
500
+ return quadmath_log10_realsolve(bignum_to_cf128(x));
501
+ break;
502
+ case NUM_RATIONAL:
503
+ return quadmath_log10_realsolve(rational_to_cf128(x));
504
+ break;
505
+ case NUM_FLOAT:
506
+ return quadmath_log10_realsolve(float_to_cf128(x));
507
+ break;
508
+ case NUM_COMPLEX:
509
+ VALUE nucomp = quadmath_log10_nucompsolve(nucomp_to_cc128(x));
510
+ return complex128_to_nucomp(nucomp);
511
+ break;
512
+ case NUM_FLOAT128:
513
+ return quadmath_log10_realsolve(GetF128(x));
514
+ break;
515
+ case NUM_COMPLEX128:
516
+ return quadmath_log10_nucompsolve(GetC128(x));
517
+ break;
518
+ case NUM_OTHERTYPE:
519
+ default:
520
+ if (num_real_p(x))
521
+ return quadmath_log10_realsolve(GetF128(x));
522
+ else
523
+ return quadmath_log10_nucompsolve(GetC128(x));
524
+ break;
525
+ }
526
+ }
527
+
528
+ static inline VALUE
529
+ log1p_realsolve_neg(__float128 x)
530
+ {
531
+ __complex128 z = 2 * catanhq(x / (2 + x));
532
+ if (cimagq(z) != M_PIq)
533
+ __imag__ z = M_PIq;
534
+ return rb_complex128_cc128(z);
535
+ }
536
+
537
+ static inline VALUE
538
+ quadmath_log1p_realsolve(__float128 x)
539
+ {
540
+ if (isnanq(x))
541
+ return nanq("");
542
+ if (x >= -1)
543
+ return rb_float128_cf128(log1pq(x));
544
+ else
545
+ return log1p_realsolve_neg(x);
546
+ }
547
+
548
+ static inline VALUE
549
+ quadmath_log1p_nucompsolve(__complex128 z)
550
+ {
551
+ if (cimagq(z) == 0)
552
+ {
553
+ __float128 real = crealq(z);
554
+ if (real >= -1)
555
+ return rb_complex128_cc128((__complex128)log1pq(real));
556
+ else
557
+ return log1p_realsolve_neg(real);
558
+ }
559
+ else
560
+ return rb_complex128_cc128(clogq(1+z));
561
+ }
562
+
563
+ /*
564
+ * call-seq:
565
+ * QuadMath.log1p(x) -> Float128 | Complex128
566
+ *
567
+ * xに1を加算した自然対数を返す.
568
+ * この関数はxがゼロに近傍な値のとき数式通りにlog(1+x)と計算するよりも高精度化する.
569
+ * xが実数なら実数解,複素数なら複素数解として各々返却する.
570
+ *
571
+ * x = '-1e-16'.to_f128 # => -1.0e-16
572
+ * QuadMath.log1p(x) # => -1.00000000000000005e-16
573
+ * QuadMath.log(1+x) # => -1.0000000000000000502830161122942e-16
574
+
575
+ */
576
+ static VALUE
577
+ quadmath_log1p(VALUE unused_obj, VALUE x)
578
+ {
579
+ switch (convertion_num_types(x)) {
580
+ case NUM_FIXNUM:
581
+ return quadmath_log1p_realsolve(fixnum_to_cf128(x));
582
+ break;
583
+ case NUM_BIGNUM:
584
+ return quadmath_log1p_realsolve(bignum_to_cf128(x));
585
+ break;
586
+ case NUM_RATIONAL:
587
+ return quadmath_log1p_realsolve(rational_to_cf128(x));
588
+ break;
589
+ case NUM_FLOAT:
590
+ return quadmath_log1p_realsolve(float_to_cf128(x));
591
+ break;
592
+ case NUM_COMPLEX:
593
+ VALUE nucomp = quadmath_log1p_nucompsolve(nucomp_to_cc128(x));
594
+ return complex128_to_nucomp(nucomp);
595
+ break;
596
+ case NUM_FLOAT128:
597
+ return quadmath_log1p_realsolve(GetF128(x));
598
+ break;
599
+ case NUM_COMPLEX128:
600
+ return quadmath_log1p_nucompsolve(GetC128(x));
601
+ break;
602
+ case NUM_OTHERTYPE:
603
+ default:
604
+ if (num_real_p(x))
605
+ return quadmath_log1p_realsolve(GetF128(x));
606
+ else
607
+ return quadmath_log1p_nucompsolve(GetC128(x));
608
+ break;
609
+ }
610
+
611
+ }
612
+
613
+ static inline VALUE
614
+ quadmath_sqrt_realsolve(__float128 x)
615
+ {
616
+ if (!signbitq(x))
617
+ return rb_float128_cf128(sqrtq(x));
618
+ else
619
+ {
620
+ __complex128 z;
621
+ __real__ z = 0.q;
622
+ __imag__ z = sqrtq(fabsq(x));
623
+ return rb_complex128_cc128(z);
624
+ }
625
+ }
626
+
627
+ static inline VALUE
628
+ quadmath_sqrt_nucompsolve(__complex128 z)
629
+ {
630
+ return rb_complex128_cc128(csqrtq(z));
631
+ }
632
+
633
+ /*
634
+ * call-seq:
635
+ * QuadMath.sqrt(x) -> Float128 | Complex128
636
+ *
637
+ * xの平方根を返す.
638
+ * xが実数であり正の場合は実数解,負の場合は虚数解,複素数の場合は複素数解として各々返却する.
639
+ *
640
+ * QuadMath.sqrt(4) # => 2.0
641
+ * QuadMath.sqrt(-1) == Complex128::I # => true
642
+ * QuadMath.sqrt(1+1i) # => (1.0986841134678099660398011952406+0.455089860562227341304357757822468i)
643
+ */
644
+ static VALUE
645
+ quadmath_sqrt(VALUE unused_obj, VALUE x)
646
+ {
647
+
648
+ switch (convertion_num_types(x)) {
649
+ case NUM_FIXNUM:
650
+ return quadmath_sqrt_realsolve(fixnum_to_cf128(x));
651
+ break;
652
+ case NUM_BIGNUM:
653
+ return quadmath_sqrt_realsolve(bignum_to_cf128(x));
654
+ break;
655
+ case NUM_RATIONAL:
656
+ return quadmath_sqrt_realsolve(rational_to_cf128(x));
657
+ break;
658
+ case NUM_FLOAT:
659
+ return quadmath_sqrt_realsolve(float_to_cf128(x));
660
+ break;
661
+ case NUM_COMPLEX:
662
+ VALUE nucomp = quadmath_sqrt_nucompsolve(nucomp_to_cc128(x));
663
+ return complex128_to_nucomp(nucomp);
664
+ break;
665
+ case NUM_FLOAT128:
666
+ return quadmath_sqrt_realsolve(GetF128(x));
667
+ break;
668
+ case NUM_COMPLEX128:
669
+ return quadmath_sqrt_nucompsolve(GetC128(x));
670
+ break;
671
+ case NUM_OTHERTYPE:
672
+ default:
673
+ if (num_real_p(x))
674
+ return quadmath_sqrt_realsolve(GetF128(x));
675
+ else
676
+ return quadmath_sqrt_nucompsolve(GetC128(x));
677
+ break;
678
+ }
679
+ }
680
+
681
+ static inline VALUE
682
+ quadmath_sqrt3_realsolve(__float128 x)
683
+ {
684
+ if (!signbitq(x))
685
+ return rb_float128_cf128(cbrtq(x));
686
+ else
687
+ return rb_complex128_cc128(cpowq((__complex128)x, 1.q/3.q));
688
+ }
689
+
690
+ static inline VALUE
691
+ quadmath_sqrt3_nucompsolve(__complex128 z)
692
+ {
693
+ return rb_complex128_cc128(cpowq(z, (__complex128)(1.q/3.q)));
694
+ }
695
+
696
+ /*
697
+ * call-seq:
698
+ * QuadMath.sqrt3(x) -> Float128 | Complex128
699
+ *
700
+ * xの立方根を返す.
701
+ * xが実数であり正の場合は実数解,負の場合は複素数解,複素数の場合は複素数解として各々返却する.
702
+ *
703
+ * QuadMath.sqrt3(3*3*3) # => 3.0
704
+ * QuadMath.sqrt3(-1) # => (0.5+0.866025403784438646763723170752936i)
705
+ * QuadMath.sqrt3(1+1i) # => (1.0842150814913511818796660082610+0.290514555507251444503813188624929i)
706
+ */
707
+ static VALUE
708
+ quadmath_sqrt3(VALUE unused_obj, VALUE x)
709
+ {
710
+ switch (convertion_num_types(x)) {
711
+ case NUM_FIXNUM:
712
+ return quadmath_sqrt3_realsolve(fixnum_to_cf128(x));
713
+ break;
714
+ case NUM_BIGNUM:
715
+ return quadmath_sqrt3_realsolve(bignum_to_cf128(x));
716
+ break;
717
+ case NUM_RATIONAL:
718
+ return quadmath_sqrt3_realsolve(rational_to_cf128(x));
719
+ break;
720
+ case NUM_FLOAT:
721
+ return quadmath_sqrt3_realsolve(float_to_cf128(x));
722
+ break;
723
+ case NUM_COMPLEX:
724
+ VALUE nucomp = quadmath_sqrt3_nucompsolve(nucomp_to_cc128(x));
725
+ return complex128_to_nucomp(nucomp);
726
+ break;
727
+ case NUM_FLOAT128:
728
+ return quadmath_sqrt3_realsolve(GetF128(x));
729
+ break;
730
+ case NUM_COMPLEX128:
731
+ return quadmath_sqrt3_nucompsolve(GetC128(x));
732
+ break;
733
+ case NUM_OTHERTYPE:
734
+ default:
735
+ if (num_real_p(x))
736
+ return quadmath_sqrt3_realsolve(GetF128(x));
737
+ else
738
+ return quadmath_sqrt3_nucompsolve(GetC128(x));
739
+ break;
740
+ }
741
+ }
742
+
743
+ static inline VALUE
744
+ quadmath_cbrt_realsolve(__float128 x)
745
+ {
746
+ return rb_float128_cf128(cbrtq(x));
747
+ }
748
+
749
+ static inline VALUE
750
+ quadmath_cbrt_nucompsolve(__complex128 z)
751
+ {
752
+ if (cimagq(z) != 0)
753
+ return Qnil;
754
+
755
+ return quadmath_cbrt_realsolve(crealq(z));
756
+ }
757
+
758
+ /*
759
+ * call-seq:
760
+ * QuadMath.cbrt(x) -> Float128 | nil
761
+ *
762
+ * xの実数としての三乗根を返す.
763
+ * 実計算の'x ** 1/3'における複素根はcbrt関数では扱われない.そのため虚数が現れるならnilとして扱われる.
764
+ *
765
+ * QuadMath.cbrt(3*3*3) # => 3.0
766
+ * QuadMath.cbrt(-1) # => -1.0
767
+ * QuadMath.cbrt(1+1i) # => nil
768
+ */
769
+ static VALUE
770
+ quadmath_cbrt(VALUE unused_obj, VALUE x)
771
+ {
772
+ switch (convertion_num_types(x)) {
773
+ case NUM_FIXNUM:
774
+ return quadmath_cbrt_realsolve(fixnum_to_cf128(x));
775
+ break;
776
+ case NUM_BIGNUM:
777
+ return quadmath_cbrt_realsolve(bignum_to_cf128(x));
778
+ break;
779
+ case NUM_RATIONAL:
780
+ return quadmath_cbrt_realsolve(rational_to_cf128(x));
781
+ break;
782
+ case NUM_FLOAT:
783
+ return quadmath_cbrt_realsolve(float_to_cf128(x));
784
+ break;
785
+ case NUM_COMPLEX:
786
+ return quadmath_cbrt_nucompsolve(nucomp_to_cc128(x));
787
+ break;
788
+ case NUM_FLOAT128:
789
+ return quadmath_cbrt_realsolve(GetF128(x));
790
+ break;
791
+ case NUM_COMPLEX128:
792
+ return quadmath_cbrt_nucompsolve(GetC128(x));
793
+ break;
794
+ case NUM_OTHERTYPE:
795
+ default:
796
+ if (num_real_p(x))
797
+ return quadmath_cbrt_realsolve(GetF128(x));
798
+ else
799
+ return quadmath_cbrt_nucompsolve(GetC128(x));
800
+ break;
801
+ }
802
+ }
803
+
804
+ static inline VALUE
805
+ quadmath_sin_realsolve(__float128 x)
806
+ {
807
+ return rb_float128_cf128(sinq(x));
808
+ }
809
+
810
+ static inline VALUE
811
+ quadmath_sin_nucompsolve(__complex128 z)
812
+ {
813
+ return rb_complex128_cc128(csinq(z));
814
+ }
815
+
816
+ /*
817
+ * call-seq:
818
+ * QuadMath.sin(x) -> Float128 | Complex128
819
+ *
820
+ * xの正弦を返す.
821
+ * xが実数なら実数解,複素数なら複素数解として各々返却する.
822
+ *
823
+ * QuadMath.sin(0.5r * QuadMath::PI) / 0.5r # => 2.0
824
+ * QuadMath.sin(1+1i) # => (1.2984575814159772948260423658078+0.634963914784736108255082202991509i)
825
+ */
826
+ static VALUE
827
+ quadmath_sin(VALUE unused_obj, VALUE x)
828
+ {
829
+ switch (convertion_num_types(x)) {
830
+ case NUM_FIXNUM:
831
+ return quadmath_sin_realsolve(fixnum_to_cf128(x));
832
+ break;
833
+ case NUM_BIGNUM:
834
+ return quadmath_sin_realsolve(bignum_to_cf128(x));
835
+ break;
836
+ case NUM_RATIONAL:
837
+ return quadmath_sin_realsolve(rational_to_cf128(x));
838
+ break;
839
+ case NUM_FLOAT:
840
+ return quadmath_sin_realsolve(float_to_cf128(x));
841
+ break;
842
+ case NUM_COMPLEX:
843
+ VALUE nucomp = quadmath_sin_nucompsolve(nucomp_to_cc128(x));
844
+ return complex128_to_nucomp(nucomp);
845
+ break;
846
+ case NUM_FLOAT128:
847
+ return quadmath_sin_realsolve(GetF128(x));
848
+ break;
849
+ case NUM_COMPLEX128:
850
+ return quadmath_sin_nucompsolve(GetC128(x));
851
+ break;
852
+ case NUM_OTHERTYPE:
853
+ default:
854
+ if (num_real_p(x))
855
+ return quadmath_sin_realsolve(GetF128(x));
856
+ else
857
+ return quadmath_sin_nucompsolve(GetC128(x));
858
+ break;
859
+ }
860
+ }
861
+
862
+ static inline VALUE
863
+ quadmath_cos_realsolve(__float128 x)
864
+ {
865
+ return rb_float128_cf128(cosq(x));
866
+ }
867
+
868
+ static inline VALUE
869
+ quadmath_cos_nucompsolve(__complex128 z)
870
+ {
871
+ return rb_complex128_cc128(ccosq(z));
872
+ }
873
+
874
+ /*
875
+ * call-seq:
876
+ * QuadMath.cos(x) -> Float128 | Complex128
877
+ *
878
+ * xの余弦を返す.
879
+ * xが実数なら実数解,複素数なら複素数解として各々返却する.
880
+ *
881
+ * QuadMath.cos(0.5r * QuadMath::PI) / 0.5r # => 8.67181013012378102479704402604335e-35
882
+ * QuadMath.cos(1+1i) # => (0.833730025131149048883885394335094-0.988897705762865096382129540892686i)
883
+ */
884
+ static VALUE
885
+ quadmath_cos(VALUE unused_obj, VALUE x)
886
+ {
887
+ switch (convertion_num_types(x)) {
888
+ case NUM_FIXNUM:
889
+ return quadmath_cos_realsolve(fixnum_to_cf128(x));
890
+ break;
891
+ case NUM_BIGNUM:
892
+ return quadmath_cos_realsolve(bignum_to_cf128(x));
893
+ break;
894
+ case NUM_RATIONAL:
895
+ return quadmath_cos_realsolve(rational_to_cf128(x));
896
+ break;
897
+ case NUM_FLOAT:
898
+ return quadmath_cos_realsolve(float_to_cf128(x));
899
+ break;
900
+ case NUM_COMPLEX:
901
+ VALUE nucomp = quadmath_cos_nucompsolve(nucomp_to_cc128(x));
902
+ return complex128_to_nucomp(nucomp);
903
+ break;
904
+ case NUM_FLOAT128:
905
+ return quadmath_cos_realsolve(GetF128(x));
906
+ break;
907
+ case NUM_COMPLEX128:
908
+ return quadmath_cos_nucompsolve(GetC128(x));
909
+ break;
910
+ case NUM_OTHERTYPE:
911
+ default:
912
+ if (num_real_p(x))
913
+ return quadmath_cos_realsolve(GetF128(x));
914
+ else
915
+ return quadmath_cos_nucompsolve(GetC128(x));
916
+ break;
917
+ }
918
+ }
919
+
920
+ static inline __float128
921
+ tan_realsolve(__float128 x)
922
+ {
923
+ __float128 y;
924
+ switch (fpclassify(x)) {
925
+ case FP_NAN:
926
+ case FP_INFINITE:
927
+ y = nanq("");
928
+ break;
929
+ case FP_ZERO:
930
+ y = 0.q;
931
+ break;
932
+ default:
933
+ y = fmodq(fabsq(x), M_PIq * 2);
934
+ if (y == M_PI_2q)
935
+ y = copysignq(HUGE_VALQ, x);
936
+ else if (y == M_PIq)
937
+ y = 0.q;
938
+ else
939
+ y = tanq(x);
940
+ break;
941
+ }
942
+
943
+ return y;
944
+ }
945
+
946
+ static inline VALUE
947
+ quadmath_tan_realsolve(__float128 x)
948
+ {
949
+ return rb_float128_cf128(tan_realsolve(x));
950
+ }
951
+
952
+ static inline VALUE
953
+ quadmath_tan_nucompsolve(__complex128 z)
954
+ {
955
+ if (cimagq(z) == 0)
956
+ __real__ z = tan_realsolve(crealq(z));
957
+ else
958
+ z = ctanq(z);
959
+ return rb_complex128_cc128(z);
960
+ }
961
+
962
+ /*
963
+ * call-seq:
964
+ * QuadMath.tan(x) -> Float128 | Complex128
965
+ *
966
+ * xの正接を返す.
967
+ * xが実数なら実数解,複素数なら複素数解として各々返却する.
968
+ * この関数はxは周期性$2\pi$として虚数の現れていない数なら極と解釈し,特殊値を返す.
969
+ * 特殊値の送出は$-2\pi \le x \le 2\pi$の範囲内では正確な答を期待できる.しかし,範囲外で正確かどうかは機種依存である.
970
+ *
971
+ * QuadMath.tan(QuadMath.atan(Float128::INFINITY)) # => Infinity
972
+ * QuadMath.tan(3/4r * QuadMath::PI) # => -1.0
973
+ * QuadMath.tan(1+1i) # => (0.271752585319511716528843722498589+1.0839233273386945434757520612119i)
974
+
975
+ */
976
+ static VALUE
977
+ quadmath_tan(VALUE unused_obj, VALUE x)
978
+ {
979
+ switch (convertion_num_types(x)) {
980
+ case NUM_FIXNUM:
981
+ return quadmath_tan_realsolve(fixnum_to_cf128(x));
982
+ break;
983
+ case NUM_BIGNUM:
984
+ return quadmath_tan_realsolve(bignum_to_cf128(x));
985
+ break;
986
+ case NUM_RATIONAL:
987
+ return quadmath_tan_realsolve(rational_to_cf128(x));
988
+ break;
989
+ case NUM_FLOAT:
990
+ return quadmath_tan_realsolve(float_to_cf128(x));
991
+ break;
992
+ case NUM_COMPLEX:
993
+ VALUE nucomp = quadmath_tan_nucompsolve(nucomp_to_cc128(x));
994
+ return complex128_to_nucomp(nucomp);
995
+ break;
996
+ case NUM_FLOAT128:
997
+ return quadmath_tan_realsolve(GetF128(x));
998
+ break;
999
+ case NUM_COMPLEX128:
1000
+ return quadmath_tan_nucompsolve(GetC128(x));
1001
+ break;
1002
+ case NUM_OTHERTYPE:
1003
+ default:
1004
+ if (num_real_p(x))
1005
+ return quadmath_tan_realsolve(GetF128(x));
1006
+ else
1007
+ return quadmath_tan_nucompsolve(GetC128(x));
1008
+ break;
1009
+ }
1010
+ }
1011
+
1012
+ static inline VALUE
1013
+ quadmath_asin_realsolve(__float128 x)
1014
+ {
1015
+ if (x >= -1 && x <= 1)
1016
+ return rb_float128_cf128(asinq(x));
1017
+ else
1018
+ return rb_complex128_cc128(casinq((__complex128)x));
1019
+ }
1020
+
1021
+ static inline VALUE
1022
+ quadmath_asin_nucompsolve(__complex128 z)
1023
+ {
1024
+ return rb_complex128_cc128(casinq(z));
1025
+ }
1026
+
1027
+ /*
1028
+ * call-seq:
1029
+ * QuadMath.asin(x) -> Float128 | Complex128
1030
+ *
1031
+ * xの逆正弦を返す.
1032
+ * xが(-1<=x<=1)の範囲なら実数解,ほかは複素数解として各々返却する.
1033
+ *
1034
+ * QuadMath.asin(-1/4r) # => -0.252680255142078653485657436993711
1035
+ * QuadMath.asin(5/4r) # => (1.5707963267948966192313216916397+0.693147180559945309417232121458176i)
1036
+ * QuadMath.asin(1+1i) # => (0.666239432492515255104004895977792+1.0612750619050356520330189162135i)
1037
+
1038
+ */
1039
+ static VALUE
1040
+ quadmath_asin(VALUE unused_obj, VALUE x)
1041
+ {
1042
+ switch (convertion_num_types(x)) {
1043
+ case NUM_FIXNUM:
1044
+ return quadmath_asin_realsolve(fixnum_to_cf128(x));
1045
+ break;
1046
+ case NUM_BIGNUM:
1047
+ return quadmath_asin_realsolve(bignum_to_cf128(x));
1048
+ break;
1049
+ case NUM_RATIONAL:
1050
+ return quadmath_asin_realsolve(rational_to_cf128(x));
1051
+ break;
1052
+ case NUM_FLOAT:
1053
+ return quadmath_asin_realsolve(float_to_cf128(x));
1054
+ break;
1055
+ case NUM_COMPLEX:
1056
+ VALUE nucomp = quadmath_asin_nucompsolve(nucomp_to_cc128(x));
1057
+ return complex128_to_nucomp(nucomp);
1058
+ break;
1059
+ case NUM_FLOAT128:
1060
+ return quadmath_asin_realsolve(GetF128(x));
1061
+ break;
1062
+ case NUM_COMPLEX128:
1063
+ return quadmath_asin_nucompsolve(GetC128(x));
1064
+ break;
1065
+ case NUM_OTHERTYPE:
1066
+ default:
1067
+ if (num_real_p(x))
1068
+ return quadmath_asin_realsolve(GetF128(x));
1069
+ else
1070
+ return quadmath_asin_nucompsolve(GetC128(x));
1071
+ break;
1072
+ }
1073
+ }
1074
+
1075
+ static inline VALUE
1076
+ quadmath_acos_realsolve(__float128 x)
1077
+ {
1078
+ if (x >= -1 && x <= 1)
1079
+ return rb_float128_cf128(acosq(x));
1080
+ else
1081
+ return rb_complex128_cc128(cacosq((__complex128)x));
1082
+ }
1083
+
1084
+ static inline VALUE
1085
+ quadmath_acos_nucompsolve(__complex128 z)
1086
+ {
1087
+ return rb_complex128_cc128(cacosq(z));
1088
+ }
1089
+
1090
+ /*
1091
+ * call-seq:
1092
+ * QuadMath.acos(x) -> Float128 | Complex128
1093
+ *
1094
+ * xの逆余弦を返す.
1095
+ * xが(-1<=x<=1)の範囲なら実数解,ほかは複素数解として各々返却する.
1096
+ *
1097
+ * QuadMath.acos(-1/4r) # => 1.8234765819369752727169791286334
1098
+ * QuadMath.acos(5/4r) # => (0.0-0.693147180559945309417232121458176i)
1099
+ * QuadMath.acos(1+1i) # => (0.904556894302381364127316795661958-1.0612750619050356520330189162135i)
1100
+ */
1101
+ static VALUE
1102
+ quadmath_acos(VALUE unused_obj, VALUE x)
1103
+ {
1104
+ switch (convertion_num_types(x)) {
1105
+ case NUM_FIXNUM:
1106
+ return quadmath_acos_realsolve(fixnum_to_cf128(x));
1107
+ break;
1108
+ case NUM_BIGNUM:
1109
+ return quadmath_acos_realsolve(bignum_to_cf128(x));
1110
+ break;
1111
+ case NUM_RATIONAL:
1112
+ return quadmath_acos_realsolve(rational_to_cf128(x));
1113
+ break;
1114
+ case NUM_FLOAT:
1115
+ return quadmath_acos_realsolve(float_to_cf128(x));
1116
+ break;
1117
+ case NUM_COMPLEX:
1118
+ VALUE nucomp = quadmath_acos_nucompsolve(nucomp_to_cc128(x));
1119
+ return complex128_to_nucomp(nucomp);
1120
+ break;
1121
+ case NUM_FLOAT128:
1122
+ return quadmath_acos_realsolve(GetF128(x));
1123
+ break;
1124
+ case NUM_COMPLEX128:
1125
+ return quadmath_acos_nucompsolve(GetC128(x));
1126
+ break;
1127
+ case NUM_OTHERTYPE:
1128
+ default:
1129
+ if (num_real_p(x))
1130
+ return quadmath_acos_realsolve(GetF128(x));
1131
+ else
1132
+ return quadmath_acos_nucompsolve(GetC128(x));
1133
+ break;
1134
+ }
1135
+ }
1136
+
1137
+ static inline VALUE
1138
+ quadmath_atan_realsolve(__float128 x)
1139
+ {
1140
+ return rb_float128_cf128(atanq(x));
1141
+ }
1142
+
1143
+ static inline VALUE
1144
+ quadmath_atan_nucompsolve(__complex128 z)
1145
+ {
1146
+ return rb_complex128_cc128(catanq(z));
1147
+ }
1148
+
1149
+ /*
1150
+ * call-seq:
1151
+ * QuadMath.atan(x) -> Float128 | Complex128
1152
+ *
1153
+ * xの逆正接を返す.
1154
+ * xが実数なら実数解,複素数なら複素数解として各々返却する.
1155
+ *
1156
+ * QuadMath.atan(-Float128::INFINITY) == (-QuadMath::PI/2) # => true
1157
+ * QuadMath.atan(+Float128::INFINITY) == (+QuadMath::PI/2) # => true
1158
+ * QuadMath.atan(1+1i) # => (1.0172219678978513677227889615504+0.402359478108525093650189833306547i)
1159
+ */
1160
+ static VALUE
1161
+ quadmath_atan(VALUE unused_obj, VALUE x)
1162
+ {
1163
+ switch (convertion_num_types(x)) {
1164
+ case NUM_FIXNUM:
1165
+ return quadmath_atan_realsolve(fixnum_to_cf128(x));
1166
+ break;
1167
+ case NUM_BIGNUM:
1168
+ return quadmath_atan_realsolve(bignum_to_cf128(x));
1169
+ break;
1170
+ case NUM_RATIONAL:
1171
+ return quadmath_atan_realsolve(rational_to_cf128(x));
1172
+ break;
1173
+ case NUM_FLOAT:
1174
+ return quadmath_atan_realsolve(float_to_cf128(x));
1175
+ break;
1176
+ case NUM_COMPLEX:
1177
+ VALUE nucomp = quadmath_atan_nucompsolve(nucomp_to_cc128(x));
1178
+ return complex128_to_nucomp(nucomp);
1179
+ break;
1180
+ case NUM_FLOAT128:
1181
+ return quadmath_atan_realsolve(GetF128(x));
1182
+ break;
1183
+ case NUM_COMPLEX128:
1184
+ return quadmath_atan_nucompsolve(GetC128(x));
1185
+ break;
1186
+ case NUM_OTHERTYPE:
1187
+ default:
1188
+ if (num_real_p(x))
1189
+ return quadmath_atan_realsolve(GetF128(x));
1190
+ else
1191
+ return quadmath_atan_nucompsolve(GetC128(x));
1192
+ break;
1193
+ }
1194
+ }
1195
+
1196
+
1197
+ static inline VALUE
1198
+ quadmath_quadrant_realsolve(__float128 x, __float128 y)
1199
+ {
1200
+ return rb_float128_cf128(atan2q(y, x));
1201
+ }
1202
+
1203
+ static inline __complex128
1204
+ catan2q(__complex128 w, __complex128 z)
1205
+ {
1206
+ if (cimagq(z) == 0 && cimagq(w) == 0)
1207
+ {
1208
+ return (__complex128)atan2q(crealq(w), crealq(z));
1209
+ }
1210
+ else
1211
+ {
1212
+ __complex128 c1 = 0-1i;
1213
+ __complex128 c2 = z + 0+1i * w;
1214
+ __complex128 c3 = csqrtq(z * z + w * w);
1215
+ return c1 * clogq(c2 / c3);
1216
+ }
1217
+ }
1218
+
1219
+ static inline VALUE
1220
+ quadmath_quadrant_nucompsolve(__complex128 z, __complex128 w)
1221
+ {
1222
+ return rb_complex128_cc128(catan2q(w, z));
1223
+ }
1224
+
1225
+ static VALUE
1226
+ quadrant_inline(VALUE xsh, VALUE ysh)
1227
+ {
1228
+ VALUE nucomp;
1229
+ static __float128 x, y;
1230
+ static __complex128 z, w;
1231
+ bool x_nucomp_p = false, y_nucomp_p = false, using_rb_complex = false;
1232
+
1233
+ switch (convertion_num_types(xsh)) {
1234
+ case NUM_FIXNUM:
1235
+ x = fixnum_to_cf128(xsh);
1236
+ break;
1237
+ case NUM_BIGNUM:
1238
+ x = bignum_to_cf128(xsh);
1239
+ break;
1240
+ case NUM_RATIONAL:
1241
+ x = rational_to_cf128(xsh);
1242
+ break;
1243
+ case NUM_FLOAT:
1244
+ x = float_to_cf128(xsh);
1245
+ break;
1246
+ case NUM_COMPLEX:
1247
+ z = nucomp_to_cc128(xsh);
1248
+ x_nucomp_p = true;
1249
+ using_rb_complex = true;
1250
+ break;
1251
+ case NUM_FLOAT128:
1252
+ x = GetF128(xsh);
1253
+ break;
1254
+ case NUM_COMPLEX128:
1255
+ z = GetC128(xsh);
1256
+ x_nucomp_p = true;
1257
+ break;
1258
+ case NUM_OTHERTYPE:
1259
+ default:
1260
+ if (num_real_p(xsh))
1261
+ x = GetF128(xsh);
1262
+ else
1263
+ {
1264
+ z = GetC128(xsh);
1265
+ x_nucomp_p = true;
1266
+ }
1267
+ break;
1268
+ }
1269
+
1270
+ switch (convertion_num_types(ysh)) {
1271
+ case NUM_FIXNUM:
1272
+ y = fixnum_to_cf128(ysh);
1273
+ break;
1274
+ case NUM_BIGNUM:
1275
+ y = bignum_to_cf128(ysh);
1276
+ break;
1277
+ case NUM_RATIONAL:
1278
+ y = rational_to_cf128(ysh);
1279
+ break;
1280
+ case NUM_FLOAT:
1281
+ y = float_to_cf128(ysh);
1282
+ break;
1283
+ case NUM_COMPLEX:
1284
+ w = nucomp_to_cc128(ysh);
1285
+ y_nucomp_p = true;
1286
+ using_rb_complex = true;
1287
+ break;
1288
+ case NUM_FLOAT128:
1289
+ y = GetF128(ysh);
1290
+ break;
1291
+ case NUM_COMPLEX128:
1292
+ w = GetC128(ysh);
1293
+ y_nucomp_p = true;
1294
+ break;
1295
+ case NUM_OTHERTYPE:
1296
+ default:
1297
+ if (num_real_p(ysh))
1298
+ y = GetF128(ysh);
1299
+ else
1300
+ {
1301
+ w = GetC128(ysh);
1302
+ y_nucomp_p = true;
1303
+ }
1304
+ break;
1305
+ }
1306
+
1307
+ if (x_nucomp_p && y_nucomp_p)
1308
+ nucomp = quadmath_quadrant_nucompsolve(z, w);
1309
+ else if (x_nucomp_p && !y_nucomp_p)
1310
+ nucomp = quadmath_quadrant_nucompsolve(z, y);
1311
+ else if (!x_nucomp_p && y_nucomp_p)
1312
+ nucomp = quadmath_quadrant_nucompsolve(x, w);
1313
+ else
1314
+ return quadmath_quadrant_realsolve(x, y);
1315
+ if (using_rb_complex)
1316
+ return complex128_to_nucomp(nucomp);
1317
+ else
1318
+ return nucomp;
1319
+ }
1320
+
1321
+ /*
1322
+ * call-seq:
1323
+ * QuadMath.atan2(y, x) -> Float128 | Complex128
1324
+ *
1325
+ * xとyが象限のどのあたりにあるかを考慮し,atan(y/x)の答を返す.
1326
+ * 2変数に虚数が現れているならば `-i log( (x+iy) sqrt(x^2 + y^2))`を計算する.
1327
+ *
1328
+ * x = 2; y = 1.2r
1329
+ * QuadMath.atan2(y, x) # => 0.5404195002705841554435783646086
1330
+ * x = -2.1r; y = 1.2r+1i
1331
+ * QuadMath.atan2(y, x) # => (2.5425012953584908680165071231190-0.356967696991407745539638230102346i)
1332
+ */
1333
+ static VALUE
1334
+ quadmath_atan2(VALUE unused_obj, VALUE y, VALUE x)
1335
+ {
1336
+ return quadrant_inline(x, y);
1337
+ }
1338
+
1339
+ /*
1340
+ * call-seq:
1341
+ * QuadMath.quadrant(x, y) -> Float128 | Complex128
1342
+ *
1343
+ * xとyが象限のどのあたりにあるかを考慮し,atan(y/x)の答を返す.
1344
+ * 2変数に虚数が現れているならば `-i log( (x+iy) sqrt(x^2 + y^2))`を計算する.
1345
+ * この関数はatan2のaliasであるものの,引数の順番を考慮している.
1346
+ *
1347
+ * x = 2; y = 1.2r
1348
+ * QuadMath.quadrant(x, y) # => 0.5404195002705841554435783646086
1349
+ * x = -2.1r; y = 1.2r+1i
1350
+ * QuadMath.quadrant(x, y) # => (2.5425012953584908680165071231190-0.356967696991407745539638230102346i)
1351
+ */
1352
+ static VALUE
1353
+ quadmath_quadrant(VALUE unused_obj, VALUE x, VALUE y)
1354
+ {
1355
+ return quadrant_inline(x, y);
1356
+ }
1357
+
1358
+ static inline VALUE
1359
+ quadmath_sinh_realsolve(__float128 x)
1360
+ {
1361
+ return rb_float128_cf128(sinhq(x));
1362
+ }
1363
+
1364
+ static inline VALUE
1365
+ quadmath_sinh_nucompsolve(__complex128 x)
1366
+ {
1367
+ return rb_complex128_cc128(csinhq(x));
1368
+ }
1369
+
1370
+ /*
1371
+ * call-seq:
1372
+ * QuadMath.sinh(x) -> Float128 | Complex128
1373
+ *
1374
+ * xの双曲線正弦を返す.
1375
+ * xが実数なら実数解,複素数なら複素数解として各々返却する.
1376
+ *
1377
+ * QuadMath.sinh(1.2r) # => 1.5094613554121726964428949112592
1378
+ * QuadMath.sinh(1+1i) # => (0.634963914784736108255082202991509+1.2984575814159772948260423658078i)
1379
+ */
1380
+ static VALUE
1381
+ quadmath_sinh(VALUE unused_obj, VALUE x)
1382
+ {
1383
+ switch (convertion_num_types(x)) {
1384
+ case NUM_FIXNUM:
1385
+ return quadmath_sinh_realsolve(fixnum_to_cf128(x));
1386
+ break;
1387
+ case NUM_BIGNUM:
1388
+ return quadmath_sinh_realsolve(bignum_to_cf128(x));
1389
+ break;
1390
+ case NUM_RATIONAL:
1391
+ return quadmath_sinh_realsolve(rational_to_cf128(x));
1392
+ break;
1393
+ case NUM_FLOAT:
1394
+ return quadmath_sinh_realsolve(float_to_cf128(x));
1395
+ break;
1396
+ case NUM_COMPLEX:
1397
+ VALUE nucomp = quadmath_sinh_nucompsolve(nucomp_to_cc128(x));
1398
+ return complex128_to_nucomp(nucomp);
1399
+ break;
1400
+ case NUM_FLOAT128:
1401
+ return quadmath_sinh_realsolve(GetF128(x));
1402
+ break;
1403
+ case NUM_COMPLEX128:
1404
+ return quadmath_sinh_nucompsolve(GetC128(x));
1405
+ break;
1406
+ case NUM_OTHERTYPE:
1407
+ default:
1408
+ if (num_real_p(x))
1409
+ return quadmath_sinh_realsolve(GetF128(x));
1410
+ else
1411
+ return quadmath_sinh_nucompsolve(GetC128(x));
1412
+ break;
1413
+ }
1414
+ }
1415
+
1416
+ static inline VALUE
1417
+ quadmath_cosh_realsolve(__float128 x)
1418
+ {
1419
+ return rb_float128_cf128(coshq(x));
1420
+ }
1421
+
1422
+ static inline VALUE
1423
+ quadmath_cosh_nucompsolve(__complex128 x)
1424
+ {
1425
+ return rb_complex128_cc128(ccoshq(x));
1426
+ }
1427
+
1428
+ /*
1429
+ * call-seq:
1430
+ * QuadMath.cosh(x) -> Float128 | Complex128
1431
+ *
1432
+ * xの双曲線余弦を返す.
1433
+ * xが実数なら実数解,複素数なら複素数解として各々返却する.
1434
+ *
1435
+ * QuadMath.cosh(1.2r) # => 1.8106555673243747930878725183424
1436
+ * QuadMath.cosh(1+1i) # => (0.833730025131149048883885394335094+0.988897705762865096382129540892686i)
1437
+ */
1438
+ static VALUE
1439
+ quadmath_cosh(VALUE unused_obj, VALUE x)
1440
+ {
1441
+ switch (convertion_num_types(x)) {
1442
+ case NUM_FIXNUM:
1443
+ return quadmath_cosh_realsolve(fixnum_to_cf128(x));
1444
+ break;
1445
+ case NUM_BIGNUM:
1446
+ return quadmath_cosh_realsolve(bignum_to_cf128(x));
1447
+ break;
1448
+ case NUM_RATIONAL:
1449
+ return quadmath_cosh_realsolve(rational_to_cf128(x));
1450
+ break;
1451
+ case NUM_FLOAT:
1452
+ return quadmath_cosh_realsolve(float_to_cf128(x));
1453
+ break;
1454
+ case NUM_COMPLEX:
1455
+ VALUE nucomp = quadmath_cosh_nucompsolve(nucomp_to_cc128(x));
1456
+ return complex128_to_nucomp(nucomp);
1457
+ break;
1458
+ case NUM_FLOAT128:
1459
+ return quadmath_cosh_realsolve(GetF128(x));
1460
+ break;
1461
+ case NUM_COMPLEX128:
1462
+ return quadmath_cosh_nucompsolve(GetC128(x));
1463
+ break;
1464
+ case NUM_OTHERTYPE:
1465
+ default:
1466
+ if (num_real_p(x))
1467
+ return quadmath_cosh_realsolve(GetF128(x));
1468
+ else
1469
+ return quadmath_cosh_nucompsolve(GetC128(x));
1470
+ break;
1471
+ }
1472
+ }
1473
+
1474
+ static inline VALUE
1475
+ quadmath_tanh_realsolve(__float128 x)
1476
+ {
1477
+ return rb_float128_cf128(tanhq(x));
1478
+ }
1479
+
1480
+ static inline VALUE
1481
+ quadmath_tanh_nucompsolve(__complex128 x)
1482
+ {
1483
+ return rb_complex128_cc128(ctanhq(x));
1484
+ }
1485
+
1486
+ /*
1487
+ * call-seq:
1488
+ * QuadMath.tanh(x) -> Float128 | Complex128
1489
+ *
1490
+ * xの双曲線正接を返す.
1491
+ * xが実数なら実数解,複素数なら複素数解として各々返却する.
1492
+ *
1493
+ * QuadMath.tanh(+Float128::INFINITY) == +1 # => true
1494
+ * QuadMath.tanh(-Float128::INFINITY) == -1 # => true
1495
+ * QuadMath.tanh(1+1i) # => (1.0839233273386945434757520612119+0.271752585319511716528843722498589i)
1496
+ */
1497
+ static VALUE
1498
+ quadmath_tanh(VALUE unused_obj, VALUE x)
1499
+ {
1500
+ switch (convertion_num_types(x)) {
1501
+ case NUM_FIXNUM:
1502
+ return quadmath_tanh_realsolve(fixnum_to_cf128(x));
1503
+ break;
1504
+ case NUM_BIGNUM:
1505
+ return quadmath_tanh_realsolve(bignum_to_cf128(x));
1506
+ break;
1507
+ case NUM_RATIONAL:
1508
+ return quadmath_tanh_realsolve(rational_to_cf128(x));
1509
+ break;
1510
+ case NUM_FLOAT:
1511
+ return quadmath_tanh_realsolve(float_to_cf128(x));
1512
+ break;
1513
+ case NUM_COMPLEX:
1514
+ VALUE nucomp = quadmath_tanh_nucompsolve(nucomp_to_cc128(x));
1515
+ return complex128_to_nucomp(nucomp);
1516
+ break;
1517
+ case NUM_FLOAT128:
1518
+ return quadmath_tanh_realsolve(GetF128(x));
1519
+ break;
1520
+ case NUM_COMPLEX128:
1521
+ return quadmath_tanh_nucompsolve(GetC128(x));
1522
+ break;
1523
+ case NUM_OTHERTYPE:
1524
+ default:
1525
+ if (num_real_p(x))
1526
+ return quadmath_tanh_realsolve(GetF128(x));
1527
+ else
1528
+ return quadmath_tanh_nucompsolve(GetC128(x));
1529
+ break;
1530
+ }
1531
+ }
1532
+
1533
+ static inline VALUE
1534
+ quadmath_asinh_realsolve(__float128 x)
1535
+ {
1536
+ return rb_float128_cf128(asinhq(x));
1537
+ }
1538
+
1539
+ static inline VALUE
1540
+ quadmath_asinh_nucompsolve(__complex128 x)
1541
+ {
1542
+ return rb_complex128_cc128(casinhq(x));
1543
+ }
1544
+
1545
+ /*
1546
+ * call-seq:
1547
+ * QuadMath.asinh(x) -> Float128 | Complex128
1548
+ *
1549
+ * xの逆双曲線正弦を返す.
1550
+ * xが実数なら実数解,複素数なら複素数解として各々返却する.
1551
+ *
1552
+ * QuadMath.asinh(1) # => 0.881373587019543025232609324979792
1553
+ * QuadMath.asinh(1+1i) # => (1.0612750619050356520330189162135+0.666239432492515255104004895977792i)
1554
+ */
1555
+ static VALUE
1556
+ quadmath_asinh(VALUE unused_obj, VALUE x)
1557
+ {
1558
+ switch (convertion_num_types(x)) {
1559
+ case NUM_FIXNUM:
1560
+ return quadmath_asinh_realsolve(fixnum_to_cf128(x));
1561
+ break;
1562
+ case NUM_BIGNUM:
1563
+ return quadmath_asinh_realsolve(bignum_to_cf128(x));
1564
+ break;
1565
+ case NUM_RATIONAL:
1566
+ return quadmath_asinh_realsolve(rational_to_cf128(x));
1567
+ break;
1568
+ case NUM_FLOAT:
1569
+ return quadmath_asinh_realsolve(float_to_cf128(x));
1570
+ break;
1571
+ case NUM_COMPLEX:
1572
+ VALUE nucomp = quadmath_asinh_nucompsolve(nucomp_to_cc128(x));
1573
+ return complex128_to_nucomp(nucomp);
1574
+ break;
1575
+ case NUM_FLOAT128:
1576
+ return quadmath_asinh_realsolve(GetF128(x));
1577
+ break;
1578
+ case NUM_COMPLEX128:
1579
+ return quadmath_asinh_nucompsolve(GetC128(x));
1580
+ break;
1581
+ case NUM_OTHERTYPE:
1582
+ default:
1583
+ if (num_real_p(x))
1584
+ return quadmath_asinh_realsolve(GetF128(x));
1585
+ else
1586
+ return quadmath_asinh_nucompsolve(GetC128(x));
1587
+ break;
1588
+ }
1589
+ }
1590
+
1591
+ static inline VALUE
1592
+ quadmath_acosh_realsolve(__float128 x)
1593
+ {
1594
+ if (isnan(x))
1595
+ return rb_float128_cf128(nanq(""));
1596
+ if (x >= 1)
1597
+ return rb_float128_cf128(acoshq(x));
1598
+ else
1599
+ return rb_complex128_cc128(cacoshq((__complex128)x));
1600
+ }
1601
+
1602
+ static inline VALUE
1603
+ quadmath_acosh_nucompsolve(__complex128 x)
1604
+ {
1605
+ return rb_complex128_cc128(cacoshq(x));
1606
+ }
1607
+
1608
+ /*
1609
+ * call-seq:
1610
+ * QuadMath.acosh(x) -> Float128 | Complex128
1611
+ *
1612
+ * xの逆双曲線余弦を返す.
1613
+ * xが実数なら定義域(1<=x<=∞)は実数解,それ以外は複素数解,複素数なら複素数解として各々返却する.
1614
+ *
1615
+ * puts "%s %s" % [" (x)", " cosh^-1(x)"]
1616
+ * 0.step(20, 5){|x|
1617
+ * x/=10.0;
1618
+ * y = QuadMath.acosh(x)
1619
+ * y_str = y.to_s
1620
+ * if !y.real.negative? then y_str = " #{y.to_s}"; end
1621
+ * puts "%s %s" % [quadmath_sprintf("% 1.1Qf", x), y_str]
1622
+ * }
1623
+ * # => (x) cosh^-1(x)
1624
+ * # => 0.0 0.0+1.5707963267948966192313216916397i
1625
+ * # => 0.5 0.0+1.0471975511965977461542144610931i
1626
+ * # => 1.0 0.0
1627
+ * # => 1.5 0.962423650119206894995517826848737
1628
+ * # => 2.0 1.3169578969248167086250463473079
1629
+ *
1630
+ * QuadMath.acosh(1+1i) # => (1.0612750619050356520330189162135+0.904556894302381364127316795661958i)
1631
+ */
1632
+ static VALUE
1633
+ quadmath_acosh(VALUE unused_obj, VALUE x)
1634
+ {
1635
+ switch (convertion_num_types(x)) {
1636
+ case NUM_FIXNUM:
1637
+ return quadmath_acosh_realsolve(fixnum_to_cf128(x));
1638
+ break;
1639
+ case NUM_BIGNUM:
1640
+ return quadmath_acosh_realsolve(bignum_to_cf128(x));
1641
+ break;
1642
+ case NUM_RATIONAL:
1643
+ return quadmath_acosh_realsolve(rational_to_cf128(x));
1644
+ break;
1645
+ case NUM_FLOAT:
1646
+ return quadmath_acosh_realsolve(float_to_cf128(x));
1647
+ break;
1648
+ case NUM_COMPLEX:
1649
+ VALUE nucomp = quadmath_acosh_nucompsolve(nucomp_to_cc128(x));
1650
+ return complex128_to_nucomp(nucomp);
1651
+ break;
1652
+ case NUM_FLOAT128:
1653
+ return quadmath_acosh_realsolve(GetF128(x));
1654
+ break;
1655
+ case NUM_COMPLEX128:
1656
+ return quadmath_acosh_nucompsolve(GetC128(x));
1657
+ break;
1658
+ case NUM_OTHERTYPE:
1659
+ default:
1660
+ if (num_real_p(x))
1661
+ return quadmath_acosh_realsolve(GetF128(x));
1662
+ else
1663
+ return quadmath_acosh_nucompsolve(GetC128(x));
1664
+ break;
1665
+ }
1666
+ }
1667
+
1668
+ static inline VALUE
1669
+ quadmath_atanh_realsolve(__float128 x)
1670
+ {
1671
+ if (isnan(x))
1672
+ return rb_float128_cf128(nanq(""));
1673
+ if (x >= -1 && x <= 1)
1674
+ return rb_float128_cf128(atanhq(x));
1675
+ else
1676
+ return rb_complex128_cc128(catanhq((__complex128)x));
1677
+ }
1678
+
1679
+ static inline VALUE
1680
+ quadmath_atanh_nucompsolve(__complex128 x)
1681
+ {
1682
+ return rb_complex128_cc128(catanhq(x));
1683
+ }
1684
+
1685
+ /*
1686
+ * call-seq:
1687
+ * QuadMath.atanh(x) -> Float128 | Complex128
1688
+ *
1689
+ * xの逆双曲線正接を返す.
1690
+ * xが実数なら定義域(-1<=x<=1)は実数解,それ以外は複素数解,複素数なら複素数解として各々返却する.
1691
+ *
1692
+ * puts "%s %s" % [" (x)", " tanh^-1(x)"]
1693
+ * -15.step(15, 5){|x|
1694
+ * x/=10.0;
1695
+ * y = QuadMath.atanh(x)
1696
+ * y_str = y.to_s
1697
+ * if !y.real.negative? then y_str = " #{y.to_s}"; end
1698
+ * puts "%s %s" % [quadmath_sprintf("% 1.1Qf", x), y_str]
1699
+ * }
1700
+ * # => (x) tanh^-1(x)
1701
+ * # => -1.5 -0.804718956217050187300379666613093+1.5707963267948966192313216916397i
1702
+ * # => -1.0 -Infinity
1703
+ * # => -0.5 -0.549306144334054845697622618461263
1704
+ * # => 0.0 0.0
1705
+ * # => 0.5 0.549306144334054845697622618461263
1706
+ * # => 1.0 Infinity
1707
+ * # => 1.5 0.804718956217050187300379666613093+1.5707963267948966192313216916397i
1708
+ * QuadMath.atanh(1+1i) # => (0.402359478108525093650189833306547+1.0172219678978513677227889615504i)
1709
+ */
1710
+ static VALUE
1711
+ quadmath_atanh(VALUE unused_obj, VALUE x)
1712
+ {
1713
+ switch (convertion_num_types(x)) {
1714
+ case NUM_FIXNUM:
1715
+ return quadmath_atanh_realsolve(fixnum_to_cf128(x));
1716
+ break;
1717
+ case NUM_BIGNUM:
1718
+ return quadmath_atanh_realsolve(bignum_to_cf128(x));
1719
+ break;
1720
+ case NUM_RATIONAL:
1721
+ return quadmath_atanh_realsolve(rational_to_cf128(x));
1722
+ break;
1723
+ case NUM_FLOAT:
1724
+ return quadmath_atanh_realsolve(float_to_cf128(x));
1725
+ break;
1726
+ case NUM_COMPLEX:
1727
+ VALUE nucomp = quadmath_atanh_nucompsolve(nucomp_to_cc128(x));
1728
+ return complex128_to_nucomp(nucomp);
1729
+ break;
1730
+ case NUM_FLOAT128:
1731
+ return quadmath_atanh_realsolve(GetF128(x));
1732
+ break;
1733
+ case NUM_COMPLEX128:
1734
+ return quadmath_atanh_nucompsolve(GetC128(x));
1735
+ break;
1736
+ case NUM_OTHERTYPE:
1737
+ default:
1738
+ if (num_real_p(x))
1739
+ return quadmath_atanh_realsolve(GetF128(x));
1740
+ else
1741
+ return quadmath_atanh_nucompsolve(GetC128(x));
1742
+ break;
1743
+ }
1744
+ }
1745
+
1746
+ #ifndef HAVE_CL2NORM2Q
1747
+ __float128 cl2norm2q(__complex128, __complex128);
1748
+
1749
+ # include "missing/cl2norm2q.c"
1750
+
1751
+ #endif
1752
+
1753
+ static inline VALUE
1754
+ quadmath_hypot_realsolve(__float128 x, __float128 y)
1755
+ {
1756
+ return rb_float128_cf128(hypotq(x, y));
1757
+ }
1758
+
1759
+ static inline VALUE
1760
+ quadmath_hypot_nucompsolve(__complex128 z, __complex128 w)
1761
+ {
1762
+ return rb_float128_cf128(cl2norm2q(z, w));
1763
+ }
1764
+
1765
+ static VALUE
1766
+ hypot_inline(VALUE xsh, VALUE ysh)
1767
+ {
1768
+ static __float128 x, y;
1769
+ static __complex128 z, w;
1770
+ bool x_nucomp_p = false, y_nucomp_p = false;
1771
+
1772
+ switch (convertion_num_types(xsh)) {
1773
+ case NUM_FIXNUM:
1774
+ x = fixnum_to_cf128(xsh);
1775
+ break;
1776
+ case NUM_BIGNUM:
1777
+ x = bignum_to_cf128(xsh);
1778
+ break;
1779
+ case NUM_RATIONAL:
1780
+ x = rational_to_cf128(xsh);
1781
+ break;
1782
+ case NUM_FLOAT:
1783
+ x = float_to_cf128(xsh);
1784
+ break;
1785
+ case NUM_COMPLEX:
1786
+ z = nucomp_to_cc128(xsh);
1787
+ x_nucomp_p = true;
1788
+ break;
1789
+ case NUM_FLOAT128:
1790
+ x = GetF128(xsh);
1791
+ break;
1792
+ case NUM_COMPLEX128:
1793
+ z = GetC128(xsh);
1794
+ x_nucomp_p = true;
1795
+ break;
1796
+ case NUM_OTHERTYPE:
1797
+ default:
1798
+ if (num_real_p(xsh))
1799
+ x = GetF128(xsh);
1800
+ else
1801
+ {
1802
+ z = GetC128(xsh);
1803
+ x_nucomp_p = true;
1804
+ }
1805
+ break;
1806
+ }
1807
+
1808
+ switch (convertion_num_types(ysh)) {
1809
+ case NUM_FIXNUM:
1810
+ y = fixnum_to_cf128(ysh);
1811
+ break;
1812
+ case NUM_BIGNUM:
1813
+ y = bignum_to_cf128(ysh);
1814
+ break;
1815
+ case NUM_RATIONAL:
1816
+ y = rational_to_cf128(ysh);
1817
+ break;
1818
+ case NUM_FLOAT:
1819
+ y = float_to_cf128(ysh);
1820
+ break;
1821
+ case NUM_COMPLEX:
1822
+ w = nucomp_to_cc128(ysh);
1823
+ y_nucomp_p = true;
1824
+ break;
1825
+ case NUM_FLOAT128:
1826
+ y = GetF128(ysh);
1827
+ break;
1828
+ case NUM_COMPLEX128:
1829
+ w = GetC128(ysh);
1830
+ y_nucomp_p = true;
1831
+ break;
1832
+ case NUM_OTHERTYPE:
1833
+ default:
1834
+ if (num_real_p(ysh))
1835
+ y = GetF128(ysh);
1836
+ else
1837
+ {
1838
+ w = GetC128(ysh);
1839
+ y_nucomp_p = true;
1840
+ }
1841
+ break;
1842
+ }
1843
+
1844
+ if (x_nucomp_p && y_nucomp_p)
1845
+ return quadmath_hypot_nucompsolve(z, w);
1846
+ else if (x_nucomp_p && !y_nucomp_p)
1847
+ return quadmath_hypot_nucompsolve(z, y);
1848
+ else if (!x_nucomp_p && y_nucomp_p)
1849
+ return quadmath_hypot_nucompsolve(x, w);
1850
+ else
1851
+ return quadmath_hypot_realsolve(x, y);
1852
+ }
1853
+
1854
+ /*
1855
+ * call-seq:
1856
+ * QuadMath.hypot(x, y) -> Float128
1857
+ *
1858
+ * xとyの直角三角形の斜辺の長さを実数で返す.
1859
+ * 2変数に複素数が含まれているならL2ノルムの答を返す.答は実数解・複素数解ともに常に正の実数である.
1860
+ *
1861
+ * QuadMath.hypot(3, 4) # => 5.0
1862
+ *
1863
+ * z = w = 2+1i;
1864
+ * 5.times do
1865
+ * ans = QuadMath.hypot(z, w)
1866
+ * print "hypot(%s, %s)^2 = %s^2 " % [z, w, ans]
1867
+ * puts "= %s" % [ans ** 2]
1868
+ * z += 1; w += 1;
1869
+ * end
1870
+ * # => hypot(2+1i, 2+1i)^2 = 3.1622776601683793319988935444327^2 = 10.0
1871
+ * # => hypot(3+1i, 3+1i)^2 = 4.4721359549995793928183473374625^2 = 20.0
1872
+ * # => hypot(4+1i, 4+1i)^2 = 5.8309518948453004708741528775455^2 = 34.0
1873
+ * # => hypot(5+1i, 5+1i)^2 = 7.2111025509279785862384425349409^2 = 52.0
1874
+ * # => hypot(6+1i, 6+1i)^2 = 8.6023252670426267717294735350497^2 = 74.0
1875
+ */
1876
+ static VALUE
1877
+ quadmath_hypot(VALUE unused_obj, VALUE x, VALUE y)
1878
+ {
1879
+ return hypot_inline(x, y);
1880
+ }
1881
+
1882
+
1883
+ #ifndef HAVE_CERFCQ
1884
+ extern __complex128 cerfcq(__complex128);
1885
+ # include "missing/cerfcq.c"
1886
+ #endif
1887
+
1888
+ #ifndef HAVE_CERFQ
1889
+ extern __complex128 cerfq(__complex128);
1890
+ # include "missing/cerfq.c"
1891
+ #endif
1892
+
1893
+
1894
+ static inline VALUE
1895
+ quadmath_erf_realsolve(__float128 x)
1896
+ {
1897
+ return rb_float128_cf128(erfq(x));
1898
+ }
1899
+
1900
+ static inline VALUE
1901
+ quadmath_erf_nucompsolve(__complex128 z)
1902
+ {
1903
+ if (cimagq(z) == 0)
1904
+ return rb_complex128_cc128((__complex128)erfq(crealq(z)));
1905
+ else
1906
+ return rb_complex128_cc128(cerfq(z));
1907
+ }
1908
+
1909
+ /*
1910
+ * call-seq:
1911
+ * QuadMath.erf(x) -> Float128 | Complex128
1912
+ *
1913
+ * xの誤差関数を返す.
1914
+ * xが実数なら実数解,複素数なら複素数解として各々返却する.
1915
+ *
1916
+ * QuadMath.erf(-2) # => -0.995322265018952734162069256367253
1917
+ * QuadMath.erf( 2) # => 0.995322265018952734162069256367253
1918
+ * QuadMath.erf(Complex128::I) # => (0.0+1.6504257587975428760253377295613i)
1919
+ * QuadMath.erf(1+1i) # => (1.3161512816979476448802710802436+0.190453469237834686284108861969162i)
1920
+ */
1921
+ static VALUE
1922
+ quadmath_erf(VALUE unused_obj, VALUE x)
1923
+ {
1924
+ switch (convertion_num_types(x)) {
1925
+ case NUM_FIXNUM:
1926
+ return quadmath_erf_realsolve(fixnum_to_cf128(x));
1927
+ break;
1928
+ case NUM_BIGNUM:
1929
+ return quadmath_erf_realsolve(bignum_to_cf128(x));
1930
+ break;
1931
+ case NUM_RATIONAL:
1932
+ return quadmath_erf_realsolve(rational_to_cf128(x));
1933
+ break;
1934
+ case NUM_FLOAT:
1935
+ return quadmath_erf_realsolve(float_to_cf128(x));
1936
+ break;
1937
+ case NUM_COMPLEX:
1938
+ VALUE nucomp = quadmath_erf_nucompsolve(nucomp_to_cc128(x));
1939
+ return complex128_to_nucomp(nucomp);
1940
+ break;
1941
+ case NUM_FLOAT128:
1942
+ return quadmath_erf_realsolve(GetF128(x));
1943
+ break;
1944
+ case NUM_COMPLEX128:
1945
+ return quadmath_erf_nucompsolve(GetC128(x));
1946
+ break;
1947
+ case NUM_OTHERTYPE:
1948
+ default:
1949
+ if (num_real_p(x))
1950
+ return quadmath_erf_realsolve(GetF128(x));
1951
+ else
1952
+ return quadmath_erf_nucompsolve(GetC128(x));
1953
+ break;
1954
+ }
1955
+ }
1956
+
1957
+ static inline VALUE
1958
+ quadmath_erfc_realsolve(__float128 x)
1959
+ {
1960
+ return rb_float128_cf128(erfcq(x));
1961
+ }
1962
+
1963
+ static inline VALUE
1964
+ quadmath_erfc_nucompsolve(__complex128 z)
1965
+ {
1966
+ if (cimagq(z) == 0)
1967
+ return rb_complex128_cc128((__complex128)erfcq(crealq(z)));
1968
+ else
1969
+ return rb_complex128_cc128(cerfcq(z));
1970
+ }
1971
+
1972
+ /*
1973
+ * call-seq:
1974
+ * QuadMath.erfc(x) -> Float128 | Complex128
1975
+ *
1976
+ * xの相補誤差関数を返す.
1977
+ * xが実数なら実数解,複素数なら複素数解として各々返却する.
1978
+ *
1979
+ * QuadMath.erfc(-2) # => 1.9953222650189527341620692563672
1980
+ * QuadMath.erfc( 2) # => 0.00467773498104726583793074363274707
1981
+ * QuadMath.erfc(Complex128::I) # => (1.0-1.6504257587975428760253377295613i)
1982
+ * QuadMath.erfc(1+1i) # => (-0.31615128169794764488027108024367-0.190453469237834686284108861969162i)
1983
+ */
1984
+ static VALUE
1985
+ quadmath_erfc(VALUE unused_obj, VALUE x)
1986
+ {
1987
+ switch (convertion_num_types(x)) {
1988
+ case NUM_FIXNUM:
1989
+ return quadmath_erfc_realsolve(fixnum_to_cf128(x));
1990
+ break;
1991
+ case NUM_BIGNUM:
1992
+ return quadmath_erfc_realsolve(bignum_to_cf128(x));
1993
+ break;
1994
+ case NUM_RATIONAL:
1995
+ return quadmath_erfc_realsolve(rational_to_cf128(x));
1996
+ break;
1997
+ case NUM_FLOAT:
1998
+ return quadmath_erfc_realsolve(float_to_cf128(x));
1999
+ break;
2000
+ case NUM_COMPLEX:
2001
+ VALUE nucomp = quadmath_erfc_nucompsolve(nucomp_to_cc128(x));
2002
+ return complex128_to_nucomp(nucomp);
2003
+ break;
2004
+ case NUM_FLOAT128:
2005
+ return quadmath_erfc_realsolve(GetF128(x));
2006
+ break;
2007
+ case NUM_COMPLEX128:
2008
+ return quadmath_erfc_nucompsolve(GetC128(x));
2009
+ break;
2010
+ case NUM_OTHERTYPE:
2011
+ default:
2012
+ if (num_real_p(x))
2013
+ return quadmath_erfc_realsolve(GetF128(x));
2014
+ else
2015
+ return quadmath_erfc_nucompsolve(GetC128(x));
2016
+ break;
2017
+ }
2018
+ }
2019
+
2020
+
2021
+
2022
+ #ifndef HAVE_CLGAMMAQ
2023
+ extern __complex128 clgammaq(__complex128);
2024
+ # include "missing/clgammaq.c"
2025
+ #endif
2026
+
2027
+ static inline __complex128
2028
+ lgamma_negarg(__float128 x)
2029
+ {
2030
+ __complex128 z;
2031
+ __real__ z = lgammaq(x);
2032
+ __imag__ z = floorq(x) * M_PIq;
2033
+ return z;
2034
+ }
2035
+
2036
+
2037
+ static inline VALUE
2038
+ quadmath_lgamma_realsolve(__float128 x)
2039
+ {
2040
+ if (isnan(x))
2041
+ return rb_float128_cf128(nanq(""));
2042
+ if (!signbitq(x))
2043
+ return rb_float128_cf128(lgammaq(x));
2044
+ else
2045
+ return rb_complex128_cc128(lgamma_negarg(x));
2046
+ }
2047
+
2048
+
2049
+
2050
+ static inline VALUE
2051
+ quadmath_lgamma_nucompsolve(__complex128 z)
2052
+ {
2053
+ if (cimagq(z) == 0)
2054
+ {
2055
+ __float128 real = crealq(z);
2056
+ if (isnanq(real))
2057
+ return rb_complex128_cc128((__complex128)real);
2058
+ else if (!signbitq(real))
2059
+ return rb_complex128_cc128((__complex128)lgammaq(real));
2060
+ else
2061
+ return rb_complex128_cc128(lgamma_negarg(real));
2062
+ }
2063
+ else
2064
+ return rb_complex128_cc128(clgammaq(z));
2065
+ }
2066
+
2067
+ /*
2068
+ * call-seq:
2069
+ * QuadMath.lgamma(x) -> Float128 | Complex128
2070
+ *
2071
+ * xの対数ガンマ関数を返す.
2072
+ * xが実数で正なら実数解,負なら複素数解,複素数なら複素数解を返す.
2073
+ *
2074
+ *
2075
+ */
2076
+ static VALUE
2077
+ quadmath_lgamma(VALUE unused_obj, VALUE x)
2078
+ {
2079
+ switch (convertion_num_types(x)) {
2080
+ case NUM_FIXNUM:
2081
+ return quadmath_lgamma_realsolve(fixnum_to_cf128(x));
2082
+ break;
2083
+ case NUM_BIGNUM:
2084
+ return quadmath_lgamma_realsolve(bignum_to_cf128(x));
2085
+ break;
2086
+ case NUM_RATIONAL:
2087
+ return quadmath_lgamma_realsolve(rational_to_cf128(x));
2088
+ break;
2089
+ case NUM_FLOAT:
2090
+ return quadmath_lgamma_realsolve(float_to_cf128(x));
2091
+ break;
2092
+ case NUM_COMPLEX:
2093
+ VALUE nucomp = quadmath_lgamma_nucompsolve(nucomp_to_cc128(x));
2094
+ // return complex128_to_nucomp(nucomp);
2095
+ return nucomp;
2096
+ break;
2097
+ case NUM_FLOAT128:
2098
+ return quadmath_lgamma_realsolve(GetF128(x));
2099
+ break;
2100
+ case NUM_COMPLEX128:
2101
+ return quadmath_lgamma_nucompsolve(GetC128(x));
2102
+ break;
2103
+ case NUM_OTHERTYPE:
2104
+ default:
2105
+ if (num_real_p(x))
2106
+ return quadmath_lgamma_realsolve(GetF128(x));
2107
+ else
2108
+ return quadmath_lgamma_nucompsolve(GetC128(x));
2109
+ break;
2110
+ }
2111
+ }
2112
+
2113
+ static inline VALUE
2114
+ quadmath_lgamma_r_realsolve(__float128 x)
2115
+ {
2116
+ int sign = 1;
2117
+ __float128 y = lgammaq(x);
2118
+
2119
+ if (x < 0 && fmodq(floorq(x), 2))
2120
+ sign = -1;
2121
+
2122
+ return rb_assoc_new(rb_float128_cf128(y), INT2FIX(sign));
2123
+ }
2124
+
2125
+ static inline VALUE
2126
+ quadmath_lgamma_r_nucompsolve(__complex128 z)
2127
+ {
2128
+ int sign = 1;
2129
+ if (cimagq(z) == 0)
2130
+ {
2131
+ __float128 real = crealq(z);
2132
+ if (real < 0 && fmodq(floorq(real), 2))
2133
+ sign = -1;
2134
+ return rb_assoc_new(
2135
+ rb_float128_cf128(lgammaq(real)),
2136
+ INT2FIX(sign)
2137
+ );
2138
+ }
2139
+ else
2140
+ return rb_assoc_new(Qnil, INT2FIX(0));
2141
+ }
2142
+
2143
+ /*
2144
+ * call-seq:
2145
+ * QuadMath.lgamma_r(x) -> [Float128, Integer] | [nil, 0]
2146
+ * QuadMath.signgam(x) -> [Float128, Integer] | [nil, 0]
2147
+ *
2148
+ * 伝統的なlgamma_r()関数をquadmathモジュールとして提供する.対数ガンマ関数の実数解とその符号値が配列で渡される.
2149
+ * 値を指数に戻す場合,周期性$2\pi$は数値計算に精度を保証できない.オイラー積分で対数から指数に戻す場合は,大概にこのような関数を使用するべきである.
2150
+ * 虚数の現れている数値を渡すと,計算不能と判断し,nilと0のペアを返す.
2151
+ *
2152
+ * x = -0.5r
2153
+ * lgamm, sign = QuadMath.lgamma_r(x)
2154
+ * # => [1.2655121234846453964889457971347, -1]
2155
+ * QuadMath.exp(lgamm) * sign
2156
+ * # => -3.5449077018110320545963349666822
2157
+ * QuadMath.gamma(x)
2158
+ * # => -3.5449077018110320545963349666822
2159
+ */
2160
+ static VALUE
2161
+ quadmath_lgamma_r(VALUE unused_obj, VALUE x)
2162
+ {
2163
+ switch (convertion_num_types(x)) {
2164
+ case NUM_FIXNUM:
2165
+ return quadmath_lgamma_r_realsolve(fixnum_to_cf128(x));
2166
+ break;
2167
+ case NUM_BIGNUM:
2168
+ return quadmath_lgamma_r_realsolve(bignum_to_cf128(x));
2169
+ break;
2170
+ case NUM_RATIONAL:
2171
+ return quadmath_lgamma_r_realsolve(rational_to_cf128(x));
2172
+ break;
2173
+ case NUM_FLOAT:
2174
+ return quadmath_lgamma_r_realsolve(float_to_cf128(x));
2175
+ break;
2176
+ case NUM_COMPLEX:
2177
+ VALUE nucomp = quadmath_lgamma_r_nucompsolve(nucomp_to_cc128(x));
2178
+ // return complex128_to_nucomp(nucomp);
2179
+ return nucomp;
2180
+ break;
2181
+ case NUM_FLOAT128:
2182
+ return quadmath_lgamma_r_realsolve(GetF128(x));
2183
+ break;
2184
+ case NUM_COMPLEX128:
2185
+ return quadmath_lgamma_r_nucompsolve(GetC128(x));
2186
+ break;
2187
+ case NUM_OTHERTYPE:
2188
+ default:
2189
+ if (num_real_p(x))
2190
+ return quadmath_lgamma_r_realsolve(GetF128(x));
2191
+ else
2192
+ return quadmath_lgamma_r_nucompsolve(GetC128(x));
2193
+ break;
2194
+ }
2195
+ }
2196
+
2197
+
2198
+ #ifndef HAVE_CTGAMMAQ
2199
+ extern __complex128 ctgammaq(__complex128);
2200
+ # include "missing/ctgammaq.c"
2201
+ #endif
2202
+
2203
+
2204
+ static inline VALUE
2205
+ quadmath_gamma_realsolve(__float128 x)
2206
+ {
2207
+ return rb_float128_cf128(tgammaq(x));
2208
+ }
2209
+
2210
+
2211
+
2212
+ static inline VALUE
2213
+ quadmath_gamma_nucompsolve(__complex128 z)
2214
+ {
2215
+ if (cimagq(z) == 0)
2216
+ return rb_complex128_cc128((__complex128)tgammaq(crealq(z)));
2217
+ else
2218
+ #if 0
2219
+ return rb_complex128_cc128(ctgammaq(z));
2220
+ #else
2221
+ rb_raise(rb_eTypeError, "not a real");
2222
+ #endif
2223
+ }
2224
+
2225
+ /*
2226
+ * call-seq:
2227
+ * QuadMath.gamma(x) -> Float128 | Complex128
2228
+ *
2229
+ * xのガンマ関数を返す.
2230
+ * xが実数なら実数解,素数なら複素数解として各々返却する.
2231
+ *
2232
+ *
2233
+ */
2234
+ static VALUE
2235
+ quadmath_gamma(VALUE unused_obj, VALUE x)
2236
+ {
2237
+ switch (convertion_num_types(x)) {
2238
+ case NUM_FIXNUM:
2239
+ return quadmath_gamma_realsolve(fixnum_to_cf128(x));
2240
+ break;
2241
+ case NUM_BIGNUM:
2242
+ return quadmath_gamma_realsolve(bignum_to_cf128(x));
2243
+ break;
2244
+ case NUM_RATIONAL:
2245
+ return quadmath_gamma_realsolve(rational_to_cf128(x));
2246
+ break;
2247
+ case NUM_FLOAT:
2248
+ return quadmath_gamma_realsolve(float_to_cf128(x));
2249
+ break;
2250
+ case NUM_COMPLEX:
2251
+ VALUE nucomp = quadmath_gamma_nucompsolve(nucomp_to_cc128(x));
2252
+ #if 0
2253
+ return complex128_to_nucomp(nucomp);
2254
+ #else
2255
+ return nucomp;
2256
+ #endif
2257
+ break;
2258
+ case NUM_FLOAT128:
2259
+ return quadmath_gamma_realsolve(GetF128(x));
2260
+ break;
2261
+ case NUM_COMPLEX128:
2262
+ return quadmath_gamma_nucompsolve(GetC128(x));
2263
+ break;
2264
+ case NUM_OTHERTYPE:
2265
+ default:
2266
+ if (num_real_p(x))
2267
+ return quadmath_gamma_realsolve(GetF128(x));
2268
+ else
2269
+ return quadmath_gamma_nucompsolve(GetC128(x));
2270
+ break;
2271
+ }
2272
+ }
2273
+
2274
+ static inline VALUE
2275
+ quadmath_j0_realsolve(__float128 x)
2276
+ {
2277
+ return rb_float128_cf128(j0q(x));
2278
+ }
2279
+
2280
+ static inline VALUE
2281
+ quadmath_j0_nucompsolve(__float128 z)
2282
+ {
2283
+ if (cimagq(z) == 0)
2284
+ return rb_complex128_cc128((__complex128)j0q(crealq(z)));
2285
+ else
2286
+ #if 0
2287
+ return rb_complex128_cc128(cj0q(z));
2288
+ #else
2289
+ rb_raise(rb_eTypeError, "not a real");
2290
+ #endif
2291
+ }
2292
+
2293
+ /*
2294
+ * call-seq:
2295
+ * QuadMath.j0(x) -> Float128
2296
+ *
2297
+ * Computes the Bessel function of the first kind, first order of +x+.
2298
+ *
2299
+ * QuadMath.j0(Float128('1.5')) # => 0.511827671735918128749051744283412
2300
+ * QuadMath.j0(-2) # => 0.223890779141235668051827454649949
2301
+ * QuadMath.j0(2/5r) # => 0.960398226659563450344165306607428
2302
+ *
2303
+ */
2304
+ static VALUE
2305
+ quadmath_j0(VALUE unused_obj, VALUE x)
2306
+ {
2307
+ switch (convertion_num_types(x)) {
2308
+ case NUM_FIXNUM:
2309
+ return quadmath_j0_realsolve(fixnum_to_cf128(x));
2310
+ break;
2311
+ case NUM_BIGNUM:
2312
+ return quadmath_j0_realsolve(bignum_to_cf128(x));
2313
+ break;
2314
+ case NUM_RATIONAL:
2315
+ return quadmath_j0_realsolve(rational_to_cf128(x));
2316
+ break;
2317
+ case NUM_FLOAT:
2318
+ return quadmath_j0_realsolve(float_to_cf128(x));
2319
+ break;
2320
+ case NUM_COMPLEX:
2321
+ VALUE nucomp = quadmath_j0_nucompsolve(nucomp_to_cc128(x));
2322
+ #if 0
2323
+ return complex128_to_nucomp(nucomp);
2324
+ #else
2325
+ return nucomp;
2326
+ #endif
2327
+ break;
2328
+ case NUM_FLOAT128:
2329
+ return quadmath_j0_realsolve(GetF128(x));
2330
+ break;
2331
+ case NUM_COMPLEX128:
2332
+ return quadmath_j0_nucompsolve(GetC128(x));
2333
+ break;
2334
+ case NUM_OTHERTYPE:
2335
+ default:
2336
+ if (num_real_p(x))
2337
+ return quadmath_j0_realsolve(GetF128(x));
2338
+ else
2339
+ return quadmath_j0_nucompsolve(GetC128(x));
2340
+ break;
2341
+ }
2342
+ }
2343
+
2344
+ static inline VALUE
2345
+ quadmath_j1_realsolve(__float128 x)
2346
+ {
2347
+ return rb_float128_cf128(j1q(x));
2348
+ }
2349
+
2350
+ static inline VALUE
2351
+ quadmath_j1_nucompsolve(__float128 z)
2352
+ {
2353
+ if (cimagq(z) == 0)
2354
+ return rb_complex128_cc128((__complex128)j1q(crealq(z)));
2355
+ else
2356
+ #if 0
2357
+ return rb_complex128_cc128(cj1q(z));
2358
+ #else
2359
+ rb_raise(rb_eTypeError, "not a real");
2360
+ #endif
2361
+ }
2362
+
2363
+ /*
2364
+ * call-seq:
2365
+ * QuadMath.j1(x) -> Float128
2366
+ *
2367
+ * Computes the Bessel function of the first kind, second order of +x+.
2368
+ *
2369
+ * QuadMath.j1(Float128('1.7')) # => 0.577765231529023219798092027156419
2370
+ * QuadMath.j1(3/7r) # => 0.209403397190135593919658594927937
2371
+ *
2372
+ */
2373
+ static VALUE
2374
+ quadmath_j1(VALUE unused_obj, VALUE x)
2375
+ {
2376
+ switch (convertion_num_types(x)) {
2377
+ case NUM_FIXNUM:
2378
+ return quadmath_j1_realsolve(fixnum_to_cf128(x));
2379
+ break;
2380
+ case NUM_BIGNUM:
2381
+ return quadmath_j1_realsolve(bignum_to_cf128(x));
2382
+ break;
2383
+ case NUM_RATIONAL:
2384
+ return quadmath_j1_realsolve(rational_to_cf128(x));
2385
+ break;
2386
+ case NUM_FLOAT:
2387
+ return quadmath_j1_realsolve(float_to_cf128(x));
2388
+ break;
2389
+ case NUM_COMPLEX:
2390
+ VALUE nucomp = quadmath_j1_nucompsolve(nucomp_to_cc128(x));
2391
+ #if 0
2392
+ return complex128_to_nucomp(nucomp);
2393
+ #else
2394
+ return nucomp;
2395
+ #endif
2396
+ break;
2397
+ case NUM_FLOAT128:
2398
+ return quadmath_j1_realsolve(GetF128(x));
2399
+ break;
2400
+ case NUM_COMPLEX128:
2401
+ return quadmath_j1_nucompsolve(GetC128(x));
2402
+ break;
2403
+ case NUM_OTHERTYPE:
2404
+ default:
2405
+ if (num_real_p(x))
2406
+ return quadmath_j1_realsolve(GetF128(x));
2407
+ else
2408
+ return quadmath_j1_nucompsolve(GetC128(x));
2409
+ break;
2410
+ }
2411
+ }
2412
+
2413
+ static inline int
2414
+ value_to_cint(VALUE x)
2415
+ {
2416
+ #if 0
2417
+ ID cover_p = rb_intern("cover?");
2418
+ VALUE range = rb_range_new(INT2FIX(INT_MIN), INT2FIX(INT_MAX), false);
2419
+ #endif
2420
+ if (!RB_INTEGER_TYPE_P(x))
2421
+ x = rb_Integer(x);
2422
+ #if 0
2423
+ if (!RTEST(rb_funcall(range, cover_p, 1, x)))
2424
+ rb_raise(rb_eRangeError, "integer order not in range");
2425
+ #endif
2426
+ return NUM2INT(x);
2427
+ }
2428
+
2429
+ static inline VALUE
2430
+ quadmath_jn_realsolve(int order, __float128 x)
2431
+ {
2432
+ return rb_float128_cf128(jnq(order, x));
2433
+ }
2434
+
2435
+ static inline VALUE
2436
+ quadmath_jn_nucompsolve(int order, __float128 z)
2437
+ {
2438
+ if (cimagq(z) == 0)
2439
+ return rb_complex128_cc128((__complex128)jnq(order, crealq(z)));
2440
+ else
2441
+ #if 0
2442
+ return rb_complex128_cc128(cjnq(order, z));
2443
+ #else
2444
+ rb_raise(rb_eTypeError, "not a real");
2445
+ #endif
2446
+ }
2447
+
2448
+ /*
2449
+ * call-seq:
2450
+ * QuadMath.jn(order, x) -> Float128
2451
+ *
2452
+ * Computes the Bessel function of the first kind, +order+ of +x+.
2453
+ *
2454
+ * QuadMath.jn(2, 1) # => 0.114903484931900480469646881335167
2455
+ * QuadMath.jn(3, Float128('2.7')) # => 0.254045291587227349961546499656304
2456
+ */
2457
+ static VALUE
2458
+ quadmath_jn(VALUE unused_obj, VALUE order, VALUE x)
2459
+ {
2460
+ int vorder = value_to_cint(order);
2461
+ switch (convertion_num_types(x)) {
2462
+ case NUM_FIXNUM:
2463
+ return quadmath_jn_realsolve(vorder, fixnum_to_cf128(x));
2464
+ break;
2465
+ case NUM_BIGNUM:
2466
+ return quadmath_jn_realsolve(vorder, bignum_to_cf128(x));
2467
+ break;
2468
+ case NUM_RATIONAL:
2469
+ return quadmath_jn_realsolve(vorder, rational_to_cf128(x));
2470
+ break;
2471
+ case NUM_FLOAT:
2472
+ return quadmath_jn_realsolve(vorder, float_to_cf128(x));
2473
+ break;
2474
+ case NUM_COMPLEX:
2475
+ VALUE nucomp = quadmath_jn_nucompsolve(vorder, nucomp_to_cc128(x));
2476
+ #if 0
2477
+ return complex128_to_nucomp(nucomp);
2478
+ #else
2479
+ return nucomp;
2480
+ #endif
2481
+ break;
2482
+ case NUM_FLOAT128:
2483
+ return quadmath_jn_realsolve(vorder, GetF128(x));
2484
+ break;
2485
+ case NUM_COMPLEX128:
2486
+ return quadmath_jn_nucompsolve(vorder, GetC128(x));
2487
+ break;
2488
+ case NUM_OTHERTYPE:
2489
+ default:
2490
+ if (num_real_p(x))
2491
+ return quadmath_jn_realsolve(vorder, GetF128(x));
2492
+ else
2493
+ return quadmath_jn_nucompsolve(vorder, GetC128(x));
2494
+ break;
2495
+ }
2496
+ }
2497
+
2498
+ static inline VALUE
2499
+ quadmath_y0_realsolve(__float128 x)
2500
+ {
2501
+ return rb_float128_cf128(y0q(x));
2502
+ }
2503
+
2504
+ static inline VALUE
2505
+ quadmath_y0_nucompsolve(__float128 z)
2506
+ {
2507
+ if (cimagq(z) == 0)
2508
+ return rb_complex128_cc128((__complex128)y0q(crealq(z)));
2509
+ else
2510
+ #if 0
2511
+ return rb_complex128_cc128(cy0q(z));
2512
+ #else
2513
+ rb_raise(rb_eTypeError, "not a real");
2514
+ #endif
2515
+ }
2516
+
2517
+ /*
2518
+ * call-seq:
2519
+ * QuadMath.y0(x) -> Float128
2520
+ *
2521
+ * Computes the Bessel function of the second kind, first order of +x+.
2522
+ *
2523
+ * QuadMath.y0(1) # => 0.0882569642156769579829267660235151
2524
+ * QuadMath.y0(Float128('1.3')) # => 0.286535357165570093402992512691284
2525
+ * QuadMath.y0(2) # => 0.510375672649745119596606592727158
2526
+ * QuadMath.y0(200) # => -0.054265775249817910693500115141763
2527
+ * QuadMath.y0(20000) # => -0.000922448896060731022547929946760507
2528
+ * QuadMath.y0(1/3r) # => -0.734373073454472607761165475056708
2529
+ */
2530
+ static VALUE
2531
+ quadmath_y0(VALUE unused_obj, VALUE x)
2532
+ {
2533
+ switch (convertion_num_types(x)) {
2534
+ case NUM_FIXNUM:
2535
+ return quadmath_y0_realsolve(fixnum_to_cf128(x));
2536
+ break;
2537
+ case NUM_BIGNUM:
2538
+ return quadmath_y0_realsolve(bignum_to_cf128(x));
2539
+ break;
2540
+ case NUM_RATIONAL:
2541
+ return quadmath_y0_realsolve(rational_to_cf128(x));
2542
+ break;
2543
+ case NUM_FLOAT:
2544
+ return quadmath_y0_realsolve(float_to_cf128(x));
2545
+ break;
2546
+ case NUM_COMPLEX:
2547
+ VALUE nucomp = quadmath_y0_nucompsolve(nucomp_to_cc128(x));
2548
+ #if 0
2549
+ return complex128_to_nucomp(nucomp);
2550
+ #else
2551
+ return nucomp;
2552
+ #endif
2553
+ break;
2554
+ case NUM_FLOAT128:
2555
+ return quadmath_y0_realsolve(GetF128(x));
2556
+ break;
2557
+ case NUM_COMPLEX128:
2558
+ return quadmath_y0_nucompsolve(GetC128(x));
2559
+ break;
2560
+ case NUM_OTHERTYPE:
2561
+ default:
2562
+ if (num_real_p(x))
2563
+ return quadmath_y0_realsolve(GetF128(x));
2564
+ else
2565
+ return quadmath_y0_nucompsolve(GetC128(x));
2566
+ break;
2567
+ }
2568
+ }
2569
+
2570
+ static inline VALUE
2571
+ quadmath_y1_realsolve(__float128 x)
2572
+ {
2573
+ return rb_float128_cf128(y1q(x));
2574
+ }
2575
+
2576
+ static inline VALUE
2577
+ quadmath_y1_nucompsolve(__float128 z)
2578
+ {
2579
+ if (cimagq(z) == 0)
2580
+ return rb_complex128_cc128((__complex128)y1q(crealq(z)));
2581
+ else
2582
+ #if 0
2583
+ return rb_complex128_cc128(cy1q(z));
2584
+ #else
2585
+ rb_raise(rb_eTypeError, "not a real");
2586
+ #endif
2587
+ }
2588
+
2589
+ /*
2590
+ * call-seq:
2591
+ * QuadMath.y1(x) -> Float128
2592
+ *
2593
+ * Computes the Bessel function of the second kind, second order of +x+.
2594
+ *
2595
+ * QuadMath.y1(1) # => -0.781212821300288716547150000047965
2596
+ * QuadMath.y1(Float128('1.3')) # => -0.548519729980776075246816253582645
2597
+ * QuadMath.y1(2) # => -0.107032431540937546888370772277477
2598
+ * QuadMath.y1(100) # => -0.0203723120027597933047039326664145
2599
+ * QuadMath.y1(1000) # => -0.0247843312923517789148623560971413
2600
+ * QuadMath.y1(1/3r) # => -2.0881657798883862661909621637453
2601
+ */
2602
+ static VALUE
2603
+ quadmath_y1(VALUE unused_obj, VALUE x)
2604
+ {
2605
+ switch (convertion_num_types(x)) {
2606
+ case NUM_FIXNUM:
2607
+ return quadmath_y1_realsolve(fixnum_to_cf128(x));
2608
+ break;
2609
+ case NUM_BIGNUM:
2610
+ return quadmath_y1_realsolve(bignum_to_cf128(x));
2611
+ break;
2612
+ case NUM_RATIONAL:
2613
+ return quadmath_y1_realsolve(rational_to_cf128(x));
2614
+ break;
2615
+ case NUM_FLOAT:
2616
+ return quadmath_y1_realsolve(float_to_cf128(x));
2617
+ break;
2618
+ case NUM_COMPLEX:
2619
+ VALUE nucomp = quadmath_y1_nucompsolve(nucomp_to_cc128(x));
2620
+ #if 0
2621
+ return complex128_to_nucomp(nucomp);
2622
+ #else
2623
+ return nucomp;
2624
+ #endif
2625
+ break;
2626
+ case NUM_FLOAT128:
2627
+ return quadmath_y1_realsolve(GetF128(x));
2628
+ break;
2629
+ case NUM_COMPLEX128:
2630
+ return quadmath_y1_nucompsolve(GetC128(x));
2631
+ break;
2632
+ case NUM_OTHERTYPE:
2633
+ default:
2634
+ if (num_real_p(x))
2635
+ return quadmath_y1_realsolve(GetF128(x));
2636
+ else
2637
+ return quadmath_y1_nucompsolve(GetC128(x));
2638
+ break;
2639
+ }
2640
+ }
2641
+
2642
+ static inline VALUE
2643
+ quadmath_yn_realsolve(int order, __float128 x)
2644
+ {
2645
+ return rb_float128_cf128(ynq(order, x));
2646
+ }
2647
+
2648
+ static inline VALUE
2649
+ quadmath_yn_nucompsolve(int order, __float128 z)
2650
+ {
2651
+ if (cimagq(z) == 0)
2652
+ return rb_complex128_cc128((__complex128)ynq(order, crealq(z)));
2653
+ else
2654
+ #if 0
2655
+ return rb_complex128_cc128(cynq(order, z));
2656
+ #else
2657
+ rb_raise(rb_eTypeError, "not a real");
2658
+ #endif
2659
+ }
2660
+
2661
+ /*
2662
+ * call-seq:
2663
+ * QuadMath.yn(order, x) -> Float128
2664
+ *
2665
+ * Computes the Bessel function of the second kind, +order+ of +x+.
2666
+ *
2667
+ * QuadMath.yn(3, 2/3r) # => -18.2021440952126114787933209537936
2668
+ * QuadMath.yn(5, Float128('1.6')) # => -27.4921544939634722522098623648692
2669
+ */
2670
+ static VALUE
2671
+ quadmath_yn(VALUE unused_obj, VALUE order, VALUE x)
2672
+ {
2673
+ int vorder = value_to_cint(order);
2674
+ switch (convertion_num_types(x)) {
2675
+ case NUM_FIXNUM:
2676
+ return quadmath_yn_realsolve(vorder, fixnum_to_cf128(x));
2677
+ break;
2678
+ case NUM_BIGNUM:
2679
+ return quadmath_yn_realsolve(vorder, bignum_to_cf128(x));
2680
+ break;
2681
+ case NUM_RATIONAL:
2682
+ return quadmath_yn_realsolve(vorder, rational_to_cf128(x));
2683
+ break;
2684
+ case NUM_FLOAT:
2685
+ return quadmath_yn_realsolve(vorder, float_to_cf128(x));
2686
+ break;
2687
+ case NUM_COMPLEX:
2688
+ VALUE nucomp = quadmath_yn_nucompsolve(vorder, nucomp_to_cc128(x));
2689
+ #if 0
2690
+ return complex128_to_nucomp(nucomp);
2691
+ #else
2692
+ return nucomp;
2693
+ #endif
2694
+ break;
2695
+ case NUM_FLOAT128:
2696
+ return quadmath_yn_realsolve(vorder, GetF128(x));
2697
+ break;
2698
+ case NUM_COMPLEX128:
2699
+ return quadmath_yn_nucompsolve(vorder, GetC128(x));
2700
+ break;
2701
+ case NUM_OTHERTYPE:
2702
+ default:
2703
+ if (num_real_p(x))
2704
+ return quadmath_yn_realsolve(vorder, GetF128(x));
2705
+ else
2706
+ return quadmath_yn_nucompsolve(vorder, GetC128(x));
2707
+ break;
2708
+ }
2709
+ }
2710
+
2711
+ void
2712
+ InitVM_QuadMath(void)
2713
+ {
2714
+ /* Math-Functions */
2715
+ rb_define_module_function(rb_mQuadMath, "exp", quadmath_exp, 1);
2716
+ rb_define_module_function(rb_mQuadMath, "exp2", quadmath_exp2, 1);
2717
+ rb_define_module_function(rb_mQuadMath, "expm1", quadmath_expm1, 1);
2718
+ rb_define_module_function(rb_mQuadMath, "log", quadmath_log, 1);
2719
+ rb_define_module_function(rb_mQuadMath, "log2", quadmath_log2, 1);
2720
+ rb_define_module_function(rb_mQuadMath, "log10", quadmath_log10, 1);
2721
+ rb_define_module_function(rb_mQuadMath, "log1p", quadmath_log1p, 1);
2722
+ rb_define_module_function(rb_mQuadMath, "sqrt", quadmath_sqrt, 1);
2723
+ rb_define_module_function(rb_mQuadMath, "sqrt3", quadmath_sqrt3, 1);
2724
+ rb_define_module_function(rb_mQuadMath, "cbrt", quadmath_cbrt, 1);
2725
+ rb_define_module_function(rb_mQuadMath, "sin", quadmath_sin, 1);
2726
+ rb_define_module_function(rb_mQuadMath, "cos", quadmath_cos, 1);
2727
+ rb_define_module_function(rb_mQuadMath, "tan", quadmath_tan, 1);
2728
+ rb_define_module_function(rb_mQuadMath, "asin", quadmath_asin, 1);
2729
+ rb_define_module_function(rb_mQuadMath, "acos", quadmath_acos, 1);
2730
+ rb_define_module_function(rb_mQuadMath, "atan", quadmath_atan, 1);
2731
+ rb_define_module_function(rb_mQuadMath, "atan2", quadmath_atan2, 2);
2732
+ rb_define_module_function(rb_mQuadMath, "quadrant", quadmath_quadrant, 2);
2733
+ rb_define_module_function(rb_mQuadMath, "sinh", quadmath_sinh, 1);
2734
+ rb_define_module_function(rb_mQuadMath, "cosh", quadmath_cosh, 1);
2735
+ rb_define_module_function(rb_mQuadMath, "tanh", quadmath_tanh, 1);
2736
+ rb_define_module_function(rb_mQuadMath, "asinh", quadmath_asinh, 1);
2737
+ rb_define_module_function(rb_mQuadMath, "acosh", quadmath_acosh, 1);
2738
+ rb_define_module_function(rb_mQuadMath, "atanh", quadmath_atanh, 1);
2739
+ rb_define_module_function(rb_mQuadMath, "hypot", quadmath_hypot, 2);
2740
+ rb_define_module_function(rb_mQuadMath, "erf", quadmath_erf, 1);
2741
+ rb_define_module_function(rb_mQuadMath, "erfc", quadmath_erfc, 1);
2742
+ rb_define_module_function(rb_mQuadMath, "lgamma", quadmath_lgamma, 1);
2743
+ rb_define_module_function(rb_mQuadMath, "lgamma_r", quadmath_lgamma_r, 1);
2744
+ rb_define_module_function(rb_mQuadMath, "signgam", quadmath_lgamma_r, 1);
2745
+ rb_define_module_function(rb_mQuadMath, "gamma", quadmath_gamma, 1);
2746
+ rb_define_module_function(rb_mQuadMath, "j0", quadmath_j0, 1);
2747
+ rb_define_module_function(rb_mQuadMath, "j1", quadmath_j1, 1);
2748
+ rb_define_module_function(rb_mQuadMath, "jn", quadmath_jn, 2);
2749
+ rb_define_module_function(rb_mQuadMath, "y0", quadmath_y0, 1);
2750
+ rb_define_module_function(rb_mQuadMath, "y1", quadmath_y1, 1);
2751
+ rb_define_module_function(rb_mQuadMath, "yn", quadmath_yn, 2);
2752
+
2753
+
2754
+ /* Math-Constants */
2755
+ rb_define_const(rb_mQuadMath, "E", rb_float128_cf128(M_Eq));
2756
+ rb_define_const(rb_mQuadMath, "LOG2E", rb_float128_cf128(M_LOG2Eq));
2757
+ rb_define_const(rb_mQuadMath, "LOG10E", rb_float128_cf128(M_LOG10Eq));
2758
+ rb_define_const(rb_mQuadMath, "LN2", rb_float128_cf128(M_LN2q));
2759
+ rb_define_const(rb_mQuadMath, "LN10", rb_float128_cf128(M_LN10q));
2760
+ rb_define_const(rb_mQuadMath, "PI", rb_float128_cf128(M_PIq));
2761
+ rb_define_const(rb_mQuadMath, "PI_2", rb_float128_cf128(M_PI_2q));
2762
+ rb_define_const(rb_mQuadMath, "PI_4", rb_float128_cf128(M_PI_4q));
2763
+ rb_define_const(rb_mQuadMath, "ONE_PI", rb_float128_cf128(M_1_PIq));
2764
+ rb_define_const(rb_mQuadMath, "TWO_PI", rb_float128_cf128(M_2_PIq));
2765
+ rb_define_const(rb_mQuadMath, "TWO_SQRTPI", rb_float128_cf128(M_2_SQRTPIq));
2766
+ rb_define_const(rb_mQuadMath, "SQRT2", rb_float128_cf128(M_SQRT2q));
2767
+ rb_define_const(rb_mQuadMath, "SQRT1_2", rb_float128_cf128(M_SQRT1_2q));
2768
+ }