Ruby 2.7.0p0(2019-12-25revision647ee6f091eafcce70ffb75ddf7e121e192ab217)

complex.c
Go to the documentation of this file.
1 /*
2 complex.c: Coded by Tadayoshi Funaba 2008-2012
3
4 This implementation is based on Keiju Ishitsuka's Complex library
5 which is written in ruby.
6 */
7
8 #include "ruby/config.h"
9 #if defined _MSC_VER
10 /* Microsoft Visual C does not define M_PI and others by default */
11 # define _USE_MATH_DEFINES 1
12 #endif
13 #include <math.h>
14 #include "internal.h"
15 #include "id.h"
16
17 #define NDEBUG
18 #include "ruby_assert.h"
19
20 #define ZERO INT2FIX(0)
21 #define ONE INT2FIX(1)
22 #define TWO INT2FIX(2)
23 #if USE_FLONUM
24 #define RFLOAT_0 DBL2NUM(0)
25 #else
26 static VALUE RFLOAT_0;
27 #endif
28 #if defined(HAVE_SIGNBIT) && defined(__GNUC__) && defined(__sun) && \
29 !defined(signbit)
30 extern int signbit(double);
31 #endif
32
33 VALUE rb_cComplex;
34
35 static ID id_abs, id_arg,
36 id_denominator, id_numerator,
37 id_real_p, id_i_real, id_i_imag,
38 id_finite_p, id_infinite_p, id_rationalize,
39 id_PI;
40 #define id_to_i idTo_i
41 #define id_to_r idTo_r
42 #define id_negate idUMinus
43 #define id_expt idPow
44 #define id_to_f idTo_f
45 #define id_quo idQuo
46 #define id_fdiv idFdiv
47
48 #define f_boolcast(x) ((x) ? Qtrue : Qfalse)
49
50 #define fun1(n) \
51 inline static VALUE \
52 f_##n(VALUE x)\
53 {\
54 return rb_funcall(x, id_##n, 0);\
55 }
56
57 #define fun2(n) \
58 inline static VALUE \
59 f_##n(VALUE x, VALUE y)\
60 {\
61 return rb_funcall(x, id_##n, 1, y);\
62 }
63
64 #define PRESERVE_SIGNEDZERO
65
66 inline static VALUE
67 f_add(VALUE x, VALUE y)
68 {
69 if (RB_INTEGER_TYPE_P(x) &&
70 LIKELY(rb_method_basic_definition_p(rb_cInteger, idPLUS))) {
71 if (FIXNUM_ZERO_P(x))
72 return y;
73 if (FIXNUM_ZERO_P(y))
74 return x;
75 return rb_int_plus(x, y);
76 }
77 else if (RB_FLOAT_TYPE_P(x) &&
78 LIKELY(rb_method_basic_definition_p(rb_cFloat, idPLUS))) {
79 if (FIXNUM_ZERO_P(y))
80 return x;
81 return rb_float_plus(x, y);
82 }
83 else if (RB_TYPE_P(x, T_RATIONAL) &&
84 LIKELY(rb_method_basic_definition_p(rb_cRational, idPLUS))) {
85 if (FIXNUM_ZERO_P(y))
86 return x;
87 return rb_rational_plus(x, y);
88 }
89
90 return rb_funcall(x, '+', 1, y);
91 }
92
93 inline static VALUE
94 f_div(VALUE x, VALUE y)
95 {
96 if (FIXNUM_P(y) && FIX2LONG(y) == 1)
97 return x;
98 return rb_funcall(x, '/', 1, y);
99 }
100
101 inline static int
102 f_gt_p(VALUE x, VALUE y)
103 {
104 if (RB_INTEGER_TYPE_P(x)) {
105 if (FIXNUM_P(x) && FIXNUM_P(y))
106 return (SIGNED_VALUE)x > (SIGNED_VALUE)y;
107 return RTEST(rb_int_gt(x, y));
108 }
109 else if (RB_FLOAT_TYPE_P(x))
110 return RTEST(rb_float_gt(x, y));
111 else if (RB_TYPE_P(x, T_RATIONAL)) {
112 int const cmp = rb_cmpint(rb_rational_cmp(x, y), x, y);
113 return cmp > 0;
114 }
115 return RTEST(rb_funcall(x, '>', 1, y));
116 }
117
118 inline static VALUE
119 f_mul(VALUE x, VALUE y)
120 {
121 if (RB_INTEGER_TYPE_P(x) &&
122 LIKELY(rb_method_basic_definition_p(rb_cInteger, idMULT))) {
123 if (FIXNUM_ZERO_P(y))
124 return ZERO;
125 if (FIXNUM_ZERO_P(x) && RB_INTEGER_TYPE_P(y))
126 return ZERO;
127 if (x == ONE) return y;
128 if (y == ONE) return x;
129 return rb_int_mul(x, y);
130 }
131 else if (RB_FLOAT_TYPE_P(x) &&
132 LIKELY(rb_method_basic_definition_p(rb_cFloat, idMULT))) {
133 if (y == ONE) return x;
134 return rb_float_mul(x, y);
135 }
136 else if (RB_TYPE_P(x, T_RATIONAL) &&
137 LIKELY(rb_method_basic_definition_p(rb_cRational, idMULT))) {
138 if (y == ONE) return x;
139 return rb_rational_mul(x, y);
140 }
141 else if (LIKELY(rb_method_basic_definition_p(CLASS_OF(x), idMULT))) {
142 if (y == ONE) return x;
143 }
144 return rb_funcall(x, '*', 1, y);
145 }
146
147 inline static VALUE
148 f_sub(VALUE x, VALUE y)
149 {
150 if (FIXNUM_ZERO_P(y) &&
151 LIKELY(rb_method_basic_definition_p(CLASS_OF(x), idMINUS))) {
152 return x;
153 }
154 return rb_funcall(x, '-', 1, y);
155 }
156
157 inline static VALUE
158 f_abs(VALUE x)
159 {
160 if (RB_INTEGER_TYPE_P(x)) {
161 return rb_int_abs(x);
162 }
163 else if (RB_FLOAT_TYPE_P(x)) {
164 return rb_float_abs(x);
165 }
166 else if (RB_TYPE_P(x, T_RATIONAL)) {
167 return rb_rational_abs(x);
168 }
169 else if (RB_TYPE_P(x, T_COMPLEX)) {
170 return rb_complex_abs(x);
171 }
172 return rb_funcall(x, id_abs, 0);
173 }
174
175 static VALUE numeric_arg(VALUE self);
176 static VALUE float_arg(VALUE self);
177
178 inline static VALUE
179 f_arg(VALUE x)
180 {
181 if (RB_INTEGER_TYPE_P(x)) {
182 return numeric_arg(x);
183 }
184 else if (RB_FLOAT_TYPE_P(x)) {
185 return float_arg(x);
186 }
187 else if (RB_TYPE_P(x, T_RATIONAL)) {
188 return numeric_arg(x);
189 }
190 else if (RB_TYPE_P(x, T_COMPLEX)) {
191 return rb_complex_arg(x);
192 }
193 return rb_funcall(x, id_arg, 0);
194 }
195
196 inline static VALUE
197 f_numerator(VALUE x)
198 {
199 if (RB_TYPE_P(x, T_RATIONAL)) {
200 return RRATIONAL(x)->num;
201 }
202 if (RB_FLOAT_TYPE_P(x)) {
203 return rb_float_numerator(x);
204 }
205 return x;
206 }
207
208 inline static VALUE
209 f_denominator(VALUE x)
210 {
211 if (RB_TYPE_P(x, T_RATIONAL)) {
212 return RRATIONAL(x)->den;
213 }
214 if (RB_FLOAT_TYPE_P(x)) {
215 return rb_float_denominator(x);
216 }
217 return INT2FIX(1);
218 }
219
220 inline static VALUE
221 f_negate(VALUE x)
222 {
223 if (RB_INTEGER_TYPE_P(x)) {
224 return rb_int_uminus(x);
225 }
226 else if (RB_FLOAT_TYPE_P(x)) {
227 return rb_float_uminus(x);
228 }
229 else if (RB_TYPE_P(x, T_RATIONAL)) {
230 return rb_rational_uminus(x);
231 }
232 else if (RB_TYPE_P(x, T_COMPLEX)) {
233 return rb_complex_uminus(x);
234 }
235 return rb_funcall(x, id_negate, 0);
236 }
237
238 static bool nucomp_real_p(VALUE self);
239
240 static inline bool
241 f_real_p(VALUE x)
242 {
243 if (RB_INTEGER_TYPE_P(x)) {
244 return true;
245 }
246 else if (RB_FLOAT_TYPE_P(x)) {
247 return true;
248 }
249 else if (RB_TYPE_P(x, T_RATIONAL)) {
250 return true;
251 }
252 else if (RB_TYPE_P(x, T_COMPLEX)) {
253 return nucomp_real_p(x);
254 }
255 return rb_funcall(x, id_real_p, 0);
256 }
257
258 inline static VALUE
259 f_to_i(VALUE x)
260 {
261 if (RB_TYPE_P(x, T_STRING))
262 return rb_str_to_inum(x, 10, 0);
263 return rb_funcall(x, id_to_i, 0);
264 }
265
266 inline static VALUE
267 f_to_f(VALUE x)
268 {
269 if (RB_TYPE_P(x, T_STRING))
270 return DBL2NUM(rb_str_to_dbl(x, 0));
271 return rb_funcall(x, id_to_f, 0);
272 }
273
274 fun1(to_r)
275
276 inline static int
277 f_eqeq_p(VALUE x, VALUE y)
278 {
279 if (FIXNUM_P(x) && FIXNUM_P(y))
280 return x == y;
281 else if (RB_FLOAT_TYPE_P(x) || RB_FLOAT_TYPE_P(y))
282 return NUM2DBL(x) == NUM2DBL(y);
283 return (int)rb_equal(x, y);
284 }
285
286 fun2(expt)
287 fun2(fdiv)
288
289 static VALUE
290 f_quo(VALUE x, VALUE y)
291 {
292 if (RB_INTEGER_TYPE_P(x))
293 return rb_numeric_quo(x, y);
294 if (RB_FLOAT_TYPE_P(x))
295 return rb_float_div(x, y);
296 if (RB_TYPE_P(x, T_RATIONAL))
297 return rb_numeric_quo(x, y);
298
299 return rb_funcallv(x, id_quo, 1, &y);
300 }
301
302 inline static int
303 f_negative_p(VALUE x)
304 {
305 if (RB_INTEGER_TYPE_P(x))
306 return INT_NEGATIVE_P(x);
307 else if (RB_FLOAT_TYPE_P(x))
308 return RFLOAT_VALUE(x) < 0.0;
309 else if (RB_TYPE_P(x, T_RATIONAL))
310 return INT_NEGATIVE_P(RRATIONAL(x)->num);
311 return rb_num_negative_p(x);
312 }
313
314 #define f_positive_p(x) (!f_negative_p(x))
315
316 inline static int
317 f_zero_p(VALUE x)
318 {
319 if (RB_FLOAT_TYPE_P(x)) {
320 return FLOAT_ZERO_P(x);
321 }
322 else if (RB_INTEGER_TYPE_P(x)) {
323 return FIXNUM_ZERO_P(x);
324 }
325 else if (RB_TYPE_P(x, T_RATIONAL)) {
326 const VALUE num = RRATIONAL(x)->num;
327 return FIXNUM_ZERO_P(num);
328 }
329 return (int)rb_equal(x, ZERO);
330 }
331
332 #define f_nonzero_p(x) (!f_zero_p(x))
333
334 VALUE rb_flo_is_finite_p(VALUE num);
335 inline static int
336 f_finite_p(VALUE x)
337 {
338 if (RB_INTEGER_TYPE_P(x)) {
339 return TRUE;
340 }
341 else if (RB_FLOAT_TYPE_P(x)) {
342 return (int)rb_flo_is_finite_p(x);
343 }
344 else if (RB_TYPE_P(x, T_RATIONAL)) {
345 return TRUE;
346 }
347 return RTEST(rb_funcallv(x, id_finite_p, 0, 0));
348 }
349
350 VALUE rb_flo_is_infinite_p(VALUE num);
351 inline static VALUE
352 f_infinite_p(VALUE x)
353 {
354 if (RB_INTEGER_TYPE_P(x)) {
355 return Qnil;
356 }
357 else if (RB_FLOAT_TYPE_P(x)) {
358 return rb_flo_is_infinite_p(x);
359 }
360 else if (RB_TYPE_P(x, T_RATIONAL)) {
361 return Qnil;
362 }
363 return rb_funcallv(x, id_infinite_p, 0, 0);
364 }
365
366 inline static int
367 f_kind_of_p(VALUE x, VALUE c)
368 {
369 return (int)rb_obj_is_kind_of(x, c);
370 }
371
372 inline static int
373 k_numeric_p(VALUE x)
374 {
375 return f_kind_of_p(x, rb_cNumeric);
376 }
377
378 #define k_exact_p(x) (!RB_FLOAT_TYPE_P(x))
379
380 #define k_exact_zero_p(x) (k_exact_p(x) && f_zero_p(x))
381
382 #define get_dat1(x) \
383 struct RComplex *dat = RCOMPLEX(x)
384
385 #define get_dat2(x,y) \
386 struct RComplex *adat = RCOMPLEX(x), *bdat = RCOMPLEX(y)
387
388 inline static VALUE
389 nucomp_s_new_internal(VALUE klass, VALUE real, VALUE imag)
390 {
391 NEWOBJ_OF(obj, struct RComplex, klass, T_COMPLEX | (RGENGC_WB_PROTECTED_COMPLEX ? FL_WB_PROTECTED : 0));
392
393 RCOMPLEX_SET_REAL(obj, real);
394 RCOMPLEX_SET_IMAG(obj, imag);
395 OBJ_FREEZE_RAW(obj);
396
397 return (VALUE)obj;
398 }
399
400 static VALUE
401 nucomp_s_alloc(VALUE klass)
402 {
403 return nucomp_s_new_internal(klass, ZERO, ZERO);
404 }
405
406 inline static VALUE
407 f_complex_new_bang1(VALUE klass, VALUE x)
408 {
409 assert(!RB_TYPE_P(x, T_COMPLEX));
410 return nucomp_s_new_internal(klass, x, ZERO);
411 }
412
413 inline static VALUE
414 f_complex_new_bang2(VALUE klass, VALUE x, VALUE y)
415 {
416 assert(!RB_TYPE_P(x, T_COMPLEX));
417 assert(!RB_TYPE_P(y, T_COMPLEX));
418 return nucomp_s_new_internal(klass, x, y);
419 }
420
421 #ifdef CANONICALIZATION_FOR_MATHN
422 static int canonicalization = 0;
423
424 RUBY_FUNC_EXPORTED void
425 nucomp_canonicalization(int f)
426 {
427 canonicalization = f;
428 }
429 #else
430 #define canonicalization 0
431 #endif
432
433 inline static void
434 nucomp_real_check(VALUE num)
435 {
436 if (!RB_INTEGER_TYPE_P(num) &&
437 !RB_FLOAT_TYPE_P(num) &&
438 !RB_TYPE_P(num, T_RATIONAL)) {
439 if (!k_numeric_p(num) || !f_real_p(num))
440 rb_raise(rb_eTypeError, "not a real");
441 }
442 }
443
444 inline static VALUE
445 nucomp_s_canonicalize_internal(VALUE klass, VALUE real, VALUE imag)
446 {
447 int complex_r, complex_i;
448 #ifdef CANONICALIZATION_FOR_MATHN
449 if (k_exact_zero_p(imag) && canonicalization)
450 return real;
451 #endif
452 complex_r = RB_TYPE_P(real, T_COMPLEX);
453 complex_i = RB_TYPE_P(imag, T_COMPLEX);
454 if (!complex_r && !complex_i) {
455 return nucomp_s_new_internal(klass, real, imag);
456 }
457 else if (!complex_r) {
458 get_dat1(imag);
459
460 return nucomp_s_new_internal(klass,
461 f_sub(real, dat->imag),
462 f_add(ZERO, dat->real));
463 }
464 else if (!complex_i) {
465 get_dat1(real);
466
467 return nucomp_s_new_internal(klass,
468 dat->real,
469 f_add(dat->imag, imag));
470 }
471 else {
472 get_dat2(real, imag);
473
474 return nucomp_s_new_internal(klass,
475 f_sub(adat->real, bdat->imag),
476 f_add(adat->imag, bdat->real));
477 }
478 }
479
480 /*
481 * call-seq:
482 * Complex.rect(real[, imag]) -> complex
483 * Complex.rectangular(real[, imag]) -> complex
484 *
485 * Returns a complex object which denotes the given rectangular form.
486 *
487 * Complex.rectangular(1, 2) #=> (1+2i)
488 */
489 static VALUE
490 nucomp_s_new(int argc, VALUE *argv, VALUE klass)
491 {
492 VALUE real, imag;
493
494 switch (rb_scan_args(argc, argv, "11", &real, &imag)) {
495 case 1:
496 nucomp_real_check(real);
497 imag = ZERO;
498 break;
499 default:
500 nucomp_real_check(real);
501 nucomp_real_check(imag);
502 break;
503 }
504
505 return nucomp_s_canonicalize_internal(klass, real, imag);
506 }
507
508 inline static VALUE
509 f_complex_new2(VALUE klass, VALUE x, VALUE y)
510 {
511 assert(!RB_TYPE_P(x, T_COMPLEX));
512 return nucomp_s_canonicalize_internal(klass, x, y);
513 }
514
515 static VALUE nucomp_convert(VALUE klass, VALUE a1, VALUE a2, int raise);
516 static VALUE nucomp_s_convert(int argc, VALUE *argv, VALUE klass);
517
518 /*
519 * call-seq:
520 * Complex(x[, y], exception: true) -> numeric or nil
521 *
522 * Returns x+i*y;
523 *
524 * Complex(1, 2) #=> (1+2i)
525 * Complex('1+2i') #=> (1+2i)
526 * Complex(nil) #=> TypeError
527 * Complex(1, nil) #=> TypeError
528 *
529 * Complex(1, nil, exception: false) #=> nil
530 * Complex('1+2', exception: false) #=> nil
531 *
532 * Syntax of string form:
533 *
534 * string form = extra spaces , complex , extra spaces ;
535 * complex = real part | [ sign ] , imaginary part
536 * | real part , sign , imaginary part
537 * | rational , "@" , rational ;
538 * real part = rational ;
539 * imaginary part = imaginary unit | unsigned rational , imaginary unit ;
540 * rational = [ sign ] , unsigned rational ;
541 * unsigned rational = numerator | numerator , "/" , denominator ;
542 * numerator = integer part | fractional part | integer part , fractional part ;
543 * denominator = digits ;
544 * integer part = digits ;
545 * fractional part = "." , digits , [ ( "e" | "E" ) , [ sign ] , digits ] ;
546 * imaginary unit = "i" | "I" | "j" | "J" ;
547 * sign = "-" | "+" ;
548 * digits = digit , { digit | "_" , digit };
549 * digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
550 * extra spaces = ? \s* ? ;
551 *
552 * See String#to_c.
553 */
554 static VALUE
555 nucomp_f_complex(int argc, VALUE *argv, VALUE klass)
556 {
557 VALUE a1, a2, opts = Qnil;
558 int raise = TRUE;
559
560 if (rb_scan_args(argc, argv, "11:", &a1, &a2, &opts) == 1) {
561 a2 = Qundef;
562 }
563 if (!NIL_P(opts)) {
564 raise = rb_opts_exception_p(opts, raise);
565 }
566 if (argc > 0 && CLASS_OF(a1) == rb_cComplex && a2 == Qundef) {
567 return a1;
568 }
569 return nucomp_convert(rb_cComplex, a1, a2, raise);
570 }
571
572 #define imp1(n) \
573 inline static VALUE \
574 m_##n##_bang(VALUE x)\
575 {\
576 return rb_math_##n(x);\
577 }
578
579 imp1(cos)
580 imp1(cosh)
581 imp1(exp)
582
583 static VALUE
584 m_log_bang(VALUE x)
585 {
586 return rb_math_log(1, &x);
587 }
588
589 imp1(sin)
590 imp1(sinh)
591
592 static VALUE
593 m_cos(VALUE x)
594 {
595 if (!RB_TYPE_P(x, T_COMPLEX))
596 return m_cos_bang(x);
597 {
598 get_dat1(x);
599 return f_complex_new2(rb_cComplex,
600 f_mul(m_cos_bang(dat->real),
601 m_cosh_bang(dat->imag)),
602 f_mul(f_negate(m_sin_bang(dat->real)),
603 m_sinh_bang(dat->imag)));
604 }
605 }
606
607 static VALUE
608 m_sin(VALUE x)
609 {
610 if (!RB_TYPE_P(x, T_COMPLEX))
611 return m_sin_bang(x);
612 {
613 get_dat1(x);
614 return f_complex_new2(rb_cComplex,
615 f_mul(m_sin_bang(dat->real),
616 m_cosh_bang(dat->imag)),
617 f_mul(m_cos_bang(dat->real),
618 m_sinh_bang(dat->imag)));
619 }
620 }
621
622 static VALUE
623 f_complex_polar(VALUE klass, VALUE x, VALUE y)
624 {
625 assert(!RB_TYPE_P(x, T_COMPLEX));
626 assert(!RB_TYPE_P(y, T_COMPLEX));
627 if (f_zero_p(x) || f_zero_p(y)) {
628 if (canonicalization) return x;
629 return nucomp_s_new_internal(klass, x, RFLOAT_0);
630 }
631 if (RB_FLOAT_TYPE_P(y)) {
632 const double arg = RFLOAT_VALUE(y);
633 if (arg == M_PI) {
634 x = f_negate(x);
635 if (canonicalization) return x;
636 y = RFLOAT_0;
637 }
638 else if (arg == M_PI_2) {
639 y = x;
640 x = RFLOAT_0;
641 }
642 else if (arg == M_PI_2+M_PI) {
643 y = f_negate(x);
644 x = RFLOAT_0;
645 }
646 else if (RB_FLOAT_TYPE_P(x)) {
647 const double abs = RFLOAT_VALUE(x);
648 const double real = abs * cos(arg), imag = abs * sin(arg);
649 x = DBL2NUM(real);
650 if (canonicalization && imag == 0.0) return x;
651 y = DBL2NUM(imag);
652 }
653 else {
654 y = f_mul(x, DBL2NUM(sin(arg)));
655 x = f_mul(x, DBL2NUM(cos(arg)));
656 if (canonicalization && f_zero_p(y)) return x;
657 }
658 return nucomp_s_new_internal(klass, x, y);
659 }
660 return nucomp_s_canonicalize_internal(klass,
661 f_mul(x, m_cos(y)),
662 f_mul(x, m_sin(y)));
663 }
664
665 /* returns a Complex or Float of ang*PI-rotated abs */
666 VALUE
667 rb_dbl_complex_new_polar_pi(double abs, double ang)
668 {
669 double fi;
670 const double fr = modf(ang, &fi);
671 int pos = fr == +0.5;
672
673 if (pos || fr == -0.5) {
674 if ((modf(fi / 2.0, &fi) != fr) ^ pos) abs = -abs;
675 return rb_complex_new(RFLOAT_0, DBL2NUM(abs));
676 }
677 else if (fr == 0.0) {
678 if (modf(fi / 2.0, &fi) != 0.0) abs = -abs;
679 return DBL2NUM(abs);
680 }
681 else {
682 ang *= M_PI;
683 return rb_complex_new(DBL2NUM(abs * cos(ang)), DBL2NUM(abs * sin(ang)));
684 }
685 }
686
687 /*
688 * call-seq:
689 * Complex.polar(abs[, arg]) -> complex
690 *
691 * Returns a complex object which denotes the given polar form.
692 *
693 * Complex.polar(3, 0) #=> (3.0+0.0i)
694 * Complex.polar(3, Math::PI/2) #=> (1.836909530733566e-16+3.0i)
695 * Complex.polar(3, Math::PI) #=> (-3.0+3.673819061467132e-16i)
696 * Complex.polar(3, -Math::PI/2) #=> (1.836909530733566e-16-3.0i)
697 */
698 static VALUE
699 nucomp_s_polar(int argc, VALUE *argv, VALUE klass)
700 {
701 VALUE abs, arg;
702
703 switch (rb_scan_args(argc, argv, "11", &abs, &arg)) {
704 case 1:
705 nucomp_real_check(abs);
706 if (canonicalization) return abs;
707 return nucomp_s_new_internal(klass, abs, ZERO);
708 default:
709 nucomp_real_check(abs);
710 nucomp_real_check(arg);
711 break;
712 }
713 return f_complex_polar(klass, abs, arg);
714 }
715
716 /*
717 * call-seq:
718 * cmp.real -> real
719 *
720 * Returns the real part.
721 *
722 * Complex(7).real #=> 7
723 * Complex(9, -4).real #=> 9
724 */
725 VALUE
726 rb_complex_real(VALUE self)
727 {
728 get_dat1(self);
729 return dat->real;
730 }
731
732 /*
733 * call-seq:
734 * cmp.imag -> real
735 * cmp.imaginary -> real
736 *
737 * Returns the imaginary part.
738 *
739 * Complex(7).imaginary #=> 0
740 * Complex(9, -4).imaginary #=> -4
741 */
742 VALUE
743 rb_complex_imag(VALUE self)
744 {
745 get_dat1(self);
746 return dat->imag;
747 }
748
749 /*
750 * call-seq:
751 * -cmp -> complex
752 *
753 * Returns negation of the value.
754 *
755 * -Complex(1, 2) #=> (-1-2i)
756 */
757 VALUE
758 rb_complex_uminus(VALUE self)
759 {
760 get_dat1(self);
761 return f_complex_new2(CLASS_OF(self),
762 f_negate(dat->real), f_negate(dat->imag));
763 }
764
765 /*
766 * call-seq:
767 * cmp + numeric -> complex
768 *
769 * Performs addition.
770 *
771 * Complex(2, 3) + Complex(2, 3) #=> (4+6i)
772 * Complex(900) + Complex(1) #=> (901+0i)
773 * Complex(-2, 9) + Complex(-9, 2) #=> (-11+11i)
774 * Complex(9, 8) + 4 #=> (13+8i)
775 * Complex(20, 9) + 9.8 #=> (29.8+9i)
776 */
777 VALUE
778 rb_complex_plus(VALUE self, VALUE other)
779 {
780 if (RB_TYPE_P(other, T_COMPLEX)) {
781 VALUE real, imag;
782
783 get_dat2(self, other);
784
785 real = f_add(adat->real, bdat->real);
786 imag = f_add(adat->imag, bdat->imag);
787
788 return f_complex_new2(CLASS_OF(self), real, imag);
789 }
790 if (k_numeric_p(other) && f_real_p(other)) {
791 get_dat1(self);
792
793 return f_complex_new2(CLASS_OF(self),
794 f_add(dat->real, other), dat->imag);
795 }
796 return rb_num_coerce_bin(self, other, '+');
797 }
798
799 /*
800 * call-seq:
801 * cmp - numeric -> complex
802 *
803 * Performs subtraction.
804 *
805 * Complex(2, 3) - Complex(2, 3) #=> (0+0i)
806 * Complex(900) - Complex(1) #=> (899+0i)
807 * Complex(-2, 9) - Complex(-9, 2) #=> (7+7i)
808 * Complex(9, 8) - 4 #=> (5+8i)
809 * Complex(20, 9) - 9.8 #=> (10.2+9i)
810 */
811 VALUE
812 rb_complex_minus(VALUE self, VALUE other)
813 {
814 if (RB_TYPE_P(other, T_COMPLEX)) {
815 VALUE real, imag;
816
817 get_dat2(self, other);
818
819 real = f_sub(adat->real, bdat->real);
820 imag = f_sub(adat->imag, bdat->imag);
821
822 return f_complex_new2(CLASS_OF(self), real, imag);
823 }
824 if (k_numeric_p(other) && f_real_p(other)) {
825 get_dat1(self);
826
827 return f_complex_new2(CLASS_OF(self),
828 f_sub(dat->real, other), dat->imag);
829 }
830 return rb_num_coerce_bin(self, other, '-');
831 }
832
833 static VALUE
834 safe_mul(VALUE a, VALUE b, int az, int bz)
835 {
836 double v;
837 if (!az && bz && RB_FLOAT_TYPE_P(a) && (v = RFLOAT_VALUE(a), !isnan(v))) {
838 a = signbit(v) ? DBL2NUM(-1.0) : DBL2NUM(1.0);
839 }
840 if (!bz && az && RB_FLOAT_TYPE_P(b) && (v = RFLOAT_VALUE(b), !isnan(v))) {
841 b = signbit(v) ? DBL2NUM(-1.0) : DBL2NUM(1.0);
842 }
843 return f_mul(a, b);
844 }
845
846 static void
847 comp_mul(VALUE areal, VALUE aimag, VALUE breal, VALUE bimag, VALUE *real, VALUE *imag)
848 {
849 int arzero = f_zero_p(areal);
850 int aizero = f_zero_p(aimag);
851 int brzero = f_zero_p(breal);
852 int bizero = f_zero_p(bimag);
853 *real = f_sub(safe_mul(areal, breal, arzero, brzero),
854 safe_mul(aimag, bimag, aizero, bizero));
855 *imag = f_add(safe_mul(areal, bimag, arzero, bizero),
856 safe_mul(aimag, breal, aizero, brzero));
857 }
858
859 /*
860 * call-seq:
861 * cmp * numeric -> complex
862 *
863 * Performs multiplication.
864 *
865 * Complex(2, 3) * Complex(2, 3) #=> (-5+12i)
866 * Complex(900) * Complex(1) #=> (900+0i)
867 * Complex(-2, 9) * Complex(-9, 2) #=> (0-85i)
868 * Complex(9, 8) * 4 #=> (36+32i)
869 * Complex(20, 9) * 9.8 #=> (196.0+88.2i)
870 */
871 VALUE
872 rb_complex_mul(VALUE self, VALUE other)
873 {
874 if (RB_TYPE_P(other, T_COMPLEX)) {
875 VALUE real, imag;
876 get_dat2(self, other);
877
878 comp_mul(adat->real, adat->imag, bdat->real, bdat->imag, &real, &imag);
879
880 return f_complex_new2(CLASS_OF(self), real, imag);
881 }
882 if (k_numeric_p(other) && f_real_p(other)) {
883 get_dat1(self);
884
885 return f_complex_new2(CLASS_OF(self),
886 f_mul(dat->real, other),
887 f_mul(dat->imag, other));
888 }
889 return rb_num_coerce_bin(self, other, '*');
890 }
891
892 inline static VALUE
893 f_divide(VALUE self, VALUE other,
894 VALUE (*func)(VALUE, VALUE), ID id)
895 {
896 if (RB_TYPE_P(other, T_COMPLEX)) {
897 VALUE r, n, x, y;
898 int flo;
899 get_dat2(self, other);
900
901 flo = (RB_FLOAT_TYPE_P(adat->real) || RB_FLOAT_TYPE_P(adat->imag) ||
902 RB_FLOAT_TYPE_P(bdat->real) || RB_FLOAT_TYPE_P(bdat->imag));
903
904 if (f_gt_p(f_abs(bdat->real), f_abs(bdat->imag))) {
905 r = (*func)(bdat->imag, bdat->real);
906 n = f_mul(bdat->real, f_add(ONE, f_mul(r, r)));
907 x = (*func)(f_add(adat->real, f_mul(adat->imag, r)), n);
908 y = (*func)(f_sub(adat->imag, f_mul(adat->real, r)), n);
909 }
910 else {
911 r = (*func)(bdat->real, bdat->imag);
912 n = f_mul(bdat->imag, f_add(ONE, f_mul(r, r)));
913 x = (*func)(f_add(f_mul(adat->real, r), adat->imag), n);
914 y = (*func)(f_sub(f_mul(adat->imag, r), adat->real), n);
915 }
916 if (!flo) {
917 x = rb_rational_canonicalize(x);
918 y = rb_rational_canonicalize(y);
919 }
920 return f_complex_new2(CLASS_OF(self), x, y);
921 }
922 if (k_numeric_p(other) && f_real_p(other)) {
923 VALUE x, y;
924 get_dat1(self);
925 x = rb_rational_canonicalize((*func)(dat->real, other));
926 y = rb_rational_canonicalize((*func)(dat->imag, other));
927 return f_complex_new2(CLASS_OF(self), x, y);
928 }
929 return rb_num_coerce_bin(self, other, id);
930 }
931
932 #define rb_raise_zerodiv() rb_raise(rb_eZeroDivError, "divided by 0")
933
934 /*
935 * call-seq:
936 * cmp / numeric -> complex
937 * cmp.quo(numeric) -> complex
938 *
939 * Performs division.
940 *
941 * Complex(2, 3) / Complex(2, 3) #=> ((1/1)+(0/1)*i)
942 * Complex(900) / Complex(1) #=> ((900/1)+(0/1)*i)
943 * Complex(-2, 9) / Complex(-9, 2) #=> ((36/85)-(77/85)*i)
944 * Complex(9, 8) / 4 #=> ((9/4)+(2/1)*i)
945 * Complex(20, 9) / 9.8 #=> (2.0408163265306123+0.9183673469387754i)
946 */
947 VALUE
948 rb_complex_div(VALUE self, VALUE other)
949 {
950 return f_divide(self, other, f_quo, id_quo);
951 }
952
953 #define nucomp_quo rb_complex_div
954
955 /*
956 * call-seq:
957 * cmp.fdiv(numeric) -> complex
958 *
959 * Performs division as each part is a float, never returns a float.
960 *
961 * Complex(11, 22).fdiv(3) #=> (3.6666666666666665+7.333333333333333i)
962 */
963 static VALUE
964 nucomp_fdiv(VALUE self, VALUE other)
965 {
966 return f_divide(self, other, f_fdiv, id_fdiv);
967 }
968
969 inline static VALUE
970 f_reciprocal(VALUE x)
971 {
972 return f_quo(ONE, x);
973 }
974
975 /*
976 * call-seq:
977 * cmp ** numeric -> complex
978 *
979 * Performs exponentiation.
980 *
981 * Complex('i') ** 2 #=> (-1+0i)
982 * Complex(-8) ** Rational(1, 3) #=> (1.0000000000000002+1.7320508075688772i)
983 */
984 VALUE
985 rb_complex_pow(VALUE self, VALUE other)
986 {
987 if (k_numeric_p(other) && k_exact_zero_p(other))
988 return f_complex_new_bang1(CLASS_OF(self), ONE);
989
990 if (RB_TYPE_P(other, T_RATIONAL) && RRATIONAL(other)->den == LONG2FIX(1))
991 other = RRATIONAL(other)->num; /* c14n */
992
993 if (RB_TYPE_P(other, T_COMPLEX)) {
994 get_dat1(other);
995
996 if (k_exact_zero_p(dat->imag))
997 other = dat->real; /* c14n */
998 }
999
1000 if (RB_TYPE_P(other, T_COMPLEX)) {
1001 VALUE r, theta, nr, ntheta;
1002
1003 get_dat1(other);
1004
1005 r = f_abs(self);
1006 theta = f_arg(self);
1007
1008 nr = m_exp_bang(f_sub(f_mul(dat->real, m_log_bang(r)),
1009 f_mul(dat->imag, theta)));
1010 ntheta = f_add(f_mul(theta, dat->real),
1011 f_mul(dat->imag, m_log_bang(r)));
1012 return f_complex_polar(CLASS_OF(self), nr, ntheta);
1013 }
1014 if (FIXNUM_P(other)) {
1015 long n = FIX2LONG(other);
1016 if (n == 0) {
1017 return nucomp_s_new_internal(CLASS_OF(self), ONE, ZERO);
1018 }
1019 if (n < 0) {
1020 self = f_reciprocal(self);
1021 other = rb_int_uminus(other);
1022 n = -n;
1023 }
1024 {
1025 get_dat1(self);
1026 VALUE xr = dat->real, xi = dat->imag, zr = xr, zi = xi;
1027
1028 if (f_zero_p(xi)) {
1029 zr = rb_num_pow(zr, other);
1030 }
1031 else if (f_zero_p(xr)) {
1032 zi = rb_num_pow(zi, other);
1033 if (n & 2) zi = f_negate(zi);
1034 if (!(n & 1)) {
1035 VALUE tmp = zr;
1036 zr = zi;
1037 zi = tmp;
1038 }
1039 }
1040 else {
1041 while (--n) {
1042 long q, r;
1043
1044 for (; q = n / 2, r = n % 2, r == 0; n = q) {
1045 VALUE tmp = f_sub(f_mul(xr, xr), f_mul(xi, xi));
1046 xi = f_mul(f_mul(TWO, xr), xi);
1047 xr = tmp;
1048 }
1049 comp_mul(zr, zi, xr, xi, &zr, &zi);
1050 }
1051 }
1052 return nucomp_s_new_internal(CLASS_OF(self), zr, zi);
1053 }
1054 }
1055 if (k_numeric_p(other) && f_real_p(other)) {
1056 VALUE r, theta;
1057
1058 if (RB_TYPE_P(other, T_BIGNUM))
1059 rb_warn("in a**b, b may be too big");
1060
1061 r = f_abs(self);
1062 theta = f_arg(self);
1063
1064 return f_complex_polar(CLASS_OF(self), f_expt(r, other),
1065 f_mul(theta, other));
1066 }
1067 return rb_num_coerce_bin(self, other, id_expt);
1068 }
1069
1070 /*
1071 * call-seq:
1072 * cmp == object -> true or false
1073 *
1074 * Returns true if cmp equals object numerically.
1075 *
1076 * Complex(2, 3) == Complex(2, 3) #=> true
1077 * Complex(5) == 5 #=> true
1078 * Complex(0) == 0.0 #=> true
1079 * Complex('1/3') == 0.33 #=> false
1080 * Complex('1/2') == '1/2' #=> false
1081 */
1082 static VALUE
1083 nucomp_eqeq_p(VALUE self, VALUE other)
1084 {
1085 if (RB_TYPE_P(other, T_COMPLEX)) {
1086 get_dat2(self, other);
1087
1088 return f_boolcast(f_eqeq_p(adat->real, bdat->real) &&
1089 f_eqeq_p(adat->imag, bdat->imag));
1090 }
1091 if (k_numeric_p(other) && f_real_p(other)) {
1092 get_dat1(self);
1093
1094 return f_boolcast(f_eqeq_p(dat->real, other) && f_zero_p(dat->imag));
1095 }
1096 return f_boolcast(f_eqeq_p(other, self));
1097 }
1098
1099 static bool
1100 nucomp_real_p(VALUE self)
1101 {
1102 get_dat1(self);
1103 return(f_zero_p(dat->imag) ? true : false);
1104 }
1105
1106 /*
1107 * call-seq:
1108 * cmp <=> object -> 0, 1, -1, or nil
1109 *
1110 * If +cmp+'s imaginary part is zero, and +object+ is also a
1111 * real number (or a Complex number where the imaginary part is zero),
1112 * compare the real part of +cmp+ to object. Otherwise, return nil.
1113 *
1114 * Complex(2, 3) <=> Complex(2, 3) #=> nil
1115 * Complex(2, 3) <=> 1 #=> nil
1116 * Complex(2) <=> 1 #=> 1
1117 * Complex(2) <=> 2 #=> 0
1118 * Complex(2) <=> 3 #=> -1
1119 */
1120 static VALUE
1121 nucomp_cmp(VALUE self, VALUE other)
1122 {
1123 if (nucomp_real_p(self) && k_numeric_p(other)) {
1124 if (RB_TYPE_P(other, T_COMPLEX) && nucomp_real_p(other)) {
1125 get_dat2(self, other);
1126 return rb_funcall(adat->real, idCmp, 1, bdat->real);
1127 }
1128 else if (f_real_p(other)) {
1129 get_dat1(self);
1130 return rb_funcall(dat->real, idCmp, 1, other);
1131 }
1132 }
1133 return Qnil;
1134 }
1135
1136 /* :nodoc: */
1137 static VALUE
1138 nucomp_coerce(VALUE self, VALUE other)
1139 {
1140 if (RB_TYPE_P(other, T_COMPLEX))
1141 return rb_assoc_new(other, self);
1142 if (k_numeric_p(other) && f_real_p(other))
1143 return rb_assoc_new(f_complex_new_bang1(CLASS_OF(self), other), self);
1144
1145 rb_raise(rb_eTypeError, "%"PRIsVALUE" can't be coerced into %"PRIsVALUE,
1146 rb_obj_class(other), rb_obj_class(self));
1147 return Qnil;
1148 }
1149
1150 /*
1151 * call-seq:
1152 * cmp.abs -> real
1153 * cmp.magnitude -> real
1154 *
1155 * Returns the absolute part of its polar form.
1156 *
1157 * Complex(-1).abs #=> 1
1158 * Complex(3.0, -4.0).abs #=> 5.0
1159 */
1160 VALUE
1161 rb_complex_abs(VALUE self)
1162 {
1163 get_dat1(self);
1164
1165 if (f_zero_p(dat->real)) {
1166 VALUE a = f_abs(dat->imag);
1167 if (RB_FLOAT_TYPE_P(dat->real) && !RB_FLOAT_TYPE_P(dat->imag))
1168 a = f_to_f(a);
1169 return a;
1170 }
1171 if (f_zero_p(dat->imag)) {
1172 VALUE a = f_abs(dat->real);
1173 if (!RB_FLOAT_TYPE_P(dat->real) && RB_FLOAT_TYPE_P(dat->imag))
1174 a = f_to_f(a);
1175 return a;
1176 }
1177 return rb_math_hypot(dat->real, dat->imag);
1178 }
1179
1180 /*
1181 * call-seq:
1182 * cmp.abs2 -> real
1183 *
1184 * Returns square of the absolute value.
1185 *
1186 * Complex(-1).abs2 #=> 1
1187 * Complex(3.0, -4.0).abs2 #=> 25.0
1188 */
1189 static VALUE
1190 nucomp_abs2(VALUE self)
1191 {
1192 get_dat1(self);
1193 return f_add(f_mul(dat->real, dat->real),
1194 f_mul(dat->imag, dat->imag));
1195 }
1196
1197 /*
1198 * call-seq:
1199 * cmp.arg -> float
1200 * cmp.angle -> float
1201 * cmp.phase -> float
1202 *
1203 * Returns the angle part of its polar form.
1204 *
1205 * Complex.polar(3, Math::PI/2).arg #=> 1.5707963267948966
1206 */
1207 VALUE
1208 rb_complex_arg(VALUE self)
1209 {
1210 get_dat1(self);
1211 return rb_math_atan2(dat->imag, dat->real);
1212 }
1213
1214 /*
1215 * call-seq:
1216 * cmp.rect -> array
1217 * cmp.rectangular -> array
1218 *
1219 * Returns an array; [cmp.real, cmp.imag].
1220 *
1221 * Complex(1, 2).rectangular #=> [1, 2]
1222 */
1223 static VALUE
1224 nucomp_rect(VALUE self)
1225 {
1226 get_dat1(self);
1227 return rb_assoc_new(dat->real, dat->imag);
1228 }
1229
1230 /*
1231 * call-seq:
1232 * cmp.polar -> array
1233 *
1234 * Returns an array; [cmp.abs, cmp.arg].
1235 *
1236 * Complex(1, 2).polar #=> [2.23606797749979, 1.1071487177940904]
1237 */
1238 static VALUE
1239 nucomp_polar(VALUE self)
1240 {
1241 return rb_assoc_new(f_abs(self), f_arg(self));
1242 }
1243
1244 /*
1245 * call-seq:
1246 * cmp.conj -> complex
1247 * cmp.conjugate -> complex
1248 *
1249 * Returns the complex conjugate.
1250 *
1251 * Complex(1, 2).conjugate #=> (1-2i)
1252 */
1253 VALUE
1254 rb_complex_conjugate(VALUE self)
1255 {
1256 get_dat1(self);
1257 return f_complex_new2(CLASS_OF(self), dat->real, f_negate(dat->imag));
1258 }
1259
1260 /*
1261 * call-seq:
1262 * Complex(1).real? -> false
1263 * Complex(1, 2).real? -> false
1264 *
1265 * Returns false, even if the complex number has no imaginary part.
1266 */
1267 static VALUE
1268 nucomp_false(VALUE self)
1269 {
1270 return Qfalse;
1271 }
1272
1273 /*
1274 * call-seq:
1275 * cmp.denominator -> integer
1276 *
1277 * Returns the denominator (lcm of both denominator - real and imag).
1278 *
1279 * See numerator.
1280 */
1281 static VALUE
1282 nucomp_denominator(VALUE self)
1283 {
1284 get_dat1(self);
1285 return rb_lcm(f_denominator(dat->real), f_denominator(dat->imag));
1286 }
1287
1288 /*
1289 * call-seq:
1290 * cmp.numerator -> numeric
1291 *
1292 * Returns the numerator.
1293 *
1294 * 1 2 3+4i <- numerator
1295 * - + -i -> ----
1296 * 2 3 6 <- denominator
1297 *
1298 * c = Complex('1/2+2/3i') #=> ((1/2)+(2/3)*i)
1299 * n = c.numerator #=> (3+4i)
1300 * d = c.denominator #=> 6
1301 * n / d #=> ((1/2)+(2/3)*i)
1302 * Complex(Rational(n.real, d), Rational(n.imag, d))
1303 * #=> ((1/2)+(2/3)*i)
1304 * See denominator.
1305 */
1306 static VALUE
1307 nucomp_numerator(VALUE self)
1308 {
1309 VALUE cd;
1310
1311 get_dat1(self);
1312
1313 cd = nucomp_denominator(self);
1314 return f_complex_new2(CLASS_OF(self),
1315 f_mul(f_numerator(dat->real),
1316 f_div(cd, f_denominator(dat->real))),
1317 f_mul(f_numerator(dat->imag),
1318 f_div(cd, f_denominator(dat->imag))));
1319 }
1320
1321 /* :nodoc: */
1322 static VALUE
1323 nucomp_hash(VALUE self)
1324 {
1325 st_index_t v, h[2];
1326 VALUE n;
1327
1328 get_dat1(self);
1329 n = rb_hash(dat->real);
1330 h[0] = NUM2LONG(n);
1331 n = rb_hash(dat->imag);
1332 h[1] = NUM2LONG(n);
1333 v = rb_memhash(h, sizeof(h));
1334 return ST2FIX(v);
1335 }
1336
1337 /* :nodoc: */
1338 static VALUE
1339 nucomp_eql_p(VALUE self, VALUE other)
1340 {
1341 if (RB_TYPE_P(other, T_COMPLEX)) {
1342 get_dat2(self, other);
1343
1344 return f_boolcast((CLASS_OF(adat->real) == CLASS_OF(bdat->real)) &&
1345 (CLASS_OF(adat->imag) == CLASS_OF(bdat->imag)) &&
1346 f_eqeq_p(self, other));
1347
1348 }
1349 return Qfalse;
1350 }
1351
1352 inline static int
1353 f_signbit(VALUE x)
1354 {
1355 if (RB_FLOAT_TYPE_P(x)) {
1356 double f = RFLOAT_VALUE(x);
1357 return !isnan(f) && signbit(f);
1358 }
1359 return f_negative_p(x);
1360 }
1361
1362 inline static int
1363 f_tpositive_p(VALUE x)
1364 {
1365 return !f_signbit(x);
1366 }
1367
1368 static VALUE
1369 f_format(VALUE self, VALUE (*func)(VALUE))
1370 {
1371 VALUE s;
1372 int impos;
1373
1374 get_dat1(self);
1375
1376 impos = f_tpositive_p(dat->imag);
1377
1378 s = (*func)(dat->real);
1379 rb_str_cat2(s, !impos ? "-" : "+");
1380
1381 rb_str_concat(s, (*func)(f_abs(dat->imag)));
1382 if (!rb_isdigit(RSTRING_PTR(s)[RSTRING_LEN(s) - 1]))
1383 rb_str_cat2(s, "*");
1384 rb_str_cat2(s, "i");
1385
1386 return s;
1387 }
1388
1389 /*
1390 * call-seq:
1391 * cmp.to_s -> string
1392 *
1393 * Returns the value as a string.
1394 *
1395 * Complex(2).to_s #=> "2+0i"
1396 * Complex('-8/6').to_s #=> "-4/3+0i"
1397 * Complex('1/2i').to_s #=> "0+1/2i"
1398 * Complex(0, Float::INFINITY).to_s #=> "0+Infinity*i"
1399 * Complex(Float::NAN, Float::NAN).to_s #=> "NaN+NaN*i"
1400 */
1401 static VALUE
1402 nucomp_to_s(VALUE self)
1403 {
1404 return f_format(self, rb_String);
1405 }
1406
1407 /*
1408 * call-seq:
1409 * cmp.inspect -> string
1410 *
1411 * Returns the value as a string for inspection.
1412 *
1413 * Complex(2).inspect #=> "(2+0i)"
1414 * Complex('-8/6').inspect #=> "((-4/3)+0i)"
1415 * Complex('1/2i').inspect #=> "(0+(1/2)*i)"
1416 * Complex(0, Float::INFINITY).inspect #=> "(0+Infinity*i)"
1417 * Complex(Float::NAN, Float::NAN).inspect #=> "(NaN+NaN*i)"
1418 */
1419 static VALUE
1420 nucomp_inspect(VALUE self)
1421 {
1422 VALUE s;
1423
1424 s = rb_usascii_str_new2("(");
1425 rb_str_concat(s, f_format(self, rb_inspect));
1426 rb_str_cat2(s, ")");
1427
1428 return s;
1429 }
1430
1431 #define FINITE_TYPE_P(v) (RB_INTEGER_TYPE_P(v) || RB_TYPE_P(v, T_RATIONAL))
1432
1433 /*
1434 * call-seq:
1435 * cmp.finite? -> true or false
1436 *
1437 * Returns +true+ if +cmp+'s real and imaginary parts are both finite numbers,
1438 * otherwise returns +false+.
1439 */
1440 static VALUE
1441 rb_complex_finite_p(VALUE self)
1442 {
1443 get_dat1(self);
1444
1445 if (f_finite_p(dat->real) && f_finite_p(dat->imag)) {
1446 return Qtrue;
1447 }
1448 return Qfalse;
1449 }
1450
1451 /*
1452 * call-seq:
1453 * cmp.infinite? -> nil or 1
1454 *
1455 * Returns +1+ if +cmp+'s real or imaginary part is an infinite number,
1456 * otherwise returns +nil+.
1457 *
1458 * For example:
1459 *
1460 * (1+1i).infinite? #=> nil
1461 * (Float::INFINITY + 1i).infinite? #=> 1
1462 */
1463 static VALUE
1464 rb_complex_infinite_p(VALUE self)
1465 {
1466 get_dat1(self);
1467
1468 if (NIL_P(f_infinite_p(dat->real)) && NIL_P(f_infinite_p(dat->imag))) {
1469 return Qnil;
1470 }
1471 return ONE;
1472 }
1473
1474 /* :nodoc: */
1475 static VALUE
1476 nucomp_dumper(VALUE self)
1477 {
1478 return self;
1479 }
1480
1481 /* :nodoc: */
1482 static VALUE
1483 nucomp_loader(VALUE self, VALUE a)
1484 {
1485 get_dat1(self);
1486
1487 RCOMPLEX_SET_REAL(dat, rb_ivar_get(a, id_i_real));
1488 RCOMPLEX_SET_IMAG(dat, rb_ivar_get(a, id_i_imag));
1489 OBJ_FREEZE_RAW(self);
1490
1491 return self;
1492 }
1493
1494 /* :nodoc: */
1495 static VALUE
1496 nucomp_marshal_dump(VALUE self)
1497 {
1498 VALUE a;
1499 get_dat1(self);
1500
1501 a = rb_assoc_new(dat->real, dat->imag);
1502 rb_copy_generic_ivar(a, self);
1503 return a;
1504 }
1505
1506 /* :nodoc: */
1507 static VALUE
1508 nucomp_marshal_load(VALUE self, VALUE a)
1509 {
1510 Check_Type(a, T_ARRAY);
1511 if (RARRAY_LEN(a) != 2)
1512 rb_raise(rb_eArgError, "marshaled complex must have an array whose length is 2 but %ld", RARRAY_LEN(a));
1513 rb_ivar_set(self, id_i_real, RARRAY_AREF(a, 0));
1514 rb_ivar_set(self, id_i_imag, RARRAY_AREF(a, 1));
1515 return self;
1516 }
1517
1518 /* --- */
1519
1520 VALUE
1521 rb_complex_raw(VALUE x, VALUE y)
1522 {
1523 return nucomp_s_new_internal(rb_cComplex, x, y);
1524 }
1525
1526 VALUE
1527 rb_complex_new(VALUE x, VALUE y)
1528 {
1529 return nucomp_s_canonicalize_internal(rb_cComplex, x, y);
1530 }
1531
1532 VALUE
1533 rb_complex_new_polar(VALUE x, VALUE y)
1534 {
1535 return f_complex_polar(rb_cComplex, x, y);
1536 }
1537
1538 VALUE
1539 rb_complex_polar(VALUE x, VALUE y)
1540 {
1541 return rb_complex_new_polar(x, y);
1542 }
1543
1544 VALUE
1545 rb_Complex(VALUE x, VALUE y)
1546 {
1547 VALUE a[2];
1548 a[0] = x;
1549 a[1] = y;
1550 return nucomp_s_convert(2, a, rb_cComplex);
1551 }
1552
1560 VALUE
1561 rb_dbl_complex_new(double real, double imag)
1562 {
1563 return rb_complex_raw(DBL2NUM(real), DBL2NUM(imag));
1564 }
1565
1566 /*
1567 * call-seq:
1568 * cmp.to_i -> integer
1569 *
1570 * Returns the value as an integer if possible (the imaginary part
1571 * should be exactly zero).
1572 *
1573 * Complex(1, 0).to_i #=> 1
1574 * Complex(1, 0.0).to_i # RangeError
1575 * Complex(1, 2).to_i # RangeError
1576 */
1577 static VALUE
1578 nucomp_to_i(VALUE self)
1579 {
1580 get_dat1(self);
1581
1582 if (!k_exact_zero_p(dat->imag)) {
1583 rb_raise(rb_eRangeError, "can't convert %"PRIsVALUE" into Integer",
1584 self);
1585 }
1586 return f_to_i(dat->real);
1587 }
1588
1589 /*
1590 * call-seq:
1591 * cmp.to_f -> float
1592 *
1593 * Returns the value as a float if possible (the imaginary part should
1594 * be exactly zero).
1595 *
1596 * Complex(1, 0).to_f #=> 1.0
1597 * Complex(1, 0.0).to_f # RangeError
1598 * Complex(1, 2).to_f # RangeError
1599 */
1600 static VALUE
1601 nucomp_to_f(VALUE self)
1602 {
1603 get_dat1(self);
1604
1605 if (!k_exact_zero_p(dat->imag)) {
1606 rb_raise(rb_eRangeError, "can't convert %"PRIsVALUE" into Float",
1607 self);
1608 }
1609 return f_to_f(dat->real);
1610 }
1611
1612 /*
1613 * call-seq:
1614 * cmp.to_r -> rational
1615 *
1616 * Returns the value as a rational if possible (the imaginary part
1617 * should be exactly zero).
1618 *
1619 * Complex(1, 0).to_r #=> (1/1)
1620 * Complex(1, 0.0).to_r # RangeError
1621 * Complex(1, 2).to_r # RangeError
1622 *
1623 * See rationalize.
1624 */
1625 static VALUE
1626 nucomp_to_r(VALUE self)
1627 {
1628 get_dat1(self);
1629
1630 if (!k_exact_zero_p(dat->imag)) {
1631 rb_raise(rb_eRangeError, "can't convert %"PRIsVALUE" into Rational",
1632 self);
1633 }
1634 return f_to_r(dat->real);
1635 }
1636
1637 /*
1638 * call-seq:
1639 * cmp.rationalize([eps]) -> rational
1640 *
1641 * Returns the value as a rational if possible (the imaginary part
1642 * should be exactly zero).
1643 *
1644 * Complex(1.0/3, 0).rationalize #=> (1/3)
1645 * Complex(1, 0.0).rationalize # RangeError
1646 * Complex(1, 2).rationalize # RangeError
1647 *
1648 * See to_r.
1649 */
1650 static VALUE
1651 nucomp_rationalize(int argc, VALUE *argv, VALUE self)
1652 {
1653 get_dat1(self);
1654
1655 rb_check_arity(argc, 0, 1);
1656
1657 if (!k_exact_zero_p(dat->imag)) {
1658 rb_raise(rb_eRangeError, "can't convert %"PRIsVALUE" into Rational",
1659 self);
1660 }
1661 return rb_funcallv(dat->real, id_rationalize, argc, argv);
1662 }
1663
1664 /*
1665 * call-seq:
1666 * complex.to_c -> self
1667 *
1668 * Returns self.
1669 *
1670 * Complex(2).to_c #=> (2+0i)
1671 * Complex(-8, 6).to_c #=> (-8+6i)
1672 */
1673 static VALUE
1674 nucomp_to_c(VALUE self)
1675 {
1676 return self;
1677 }
1678
1679 /*
1680 * call-seq:
1681 * nil.to_c -> (0+0i)
1682 *
1683 * Returns zero as a complex.
1684 */
1685 static VALUE
1686 nilclass_to_c(VALUE self)
1687 {
1688 return rb_complex_new1(INT2FIX(0));
1689 }
1690
1691 /*
1692 * call-seq:
1693 * num.to_c -> complex
1694 *
1695 * Returns the value as a complex.
1696 */
1697 static VALUE
1698 numeric_to_c(VALUE self)
1699 {
1700 return rb_complex_new1(self);
1701 }
1702
1703 #include <ctype.h>
1704
1705 inline static int
1706 issign(int c)
1707 {
1708 return (c == '-' || c == '+');
1709 }
1710
1711 static int
1712 read_sign(const char **s,
1713 char **b)
1714 {
1715 int sign = '?';
1716
1717 if (issign(**s)) {
1718 sign = **b = **s;
1719 (*s)++;
1720 (*b)++;
1721 }
1722 return sign;
1723 }
1724
1725 inline static int
1726 isdecimal(int c)
1727 {
1728 return isdigit((unsigned char)c);
1729 }
1730
1731 static int
1732 read_digits(const char **s, int strict,
1733 char **b)
1734 {
1735 int us = 1;
1736
1737 if (!isdecimal(**s))
1738 return 0;
1739
1740 while (isdecimal(**s) || **s == '_') {
1741 if (**s == '_') {
1742 if (strict) {
1743 if (us)
1744 return 0;
1745 }
1746 us = 1;
1747 }
1748 else {
1749 **b = **s;
1750 (*b)++;
1751 us = 0;
1752 }
1753 (*s)++;
1754 }
1755 if (us)
1756 do {
1757 (*s)--;
1758 } while (**s == '_');
1759 return 1;
1760 }
1761
1762 inline static int
1763 islettere(int c)
1764 {
1765 return (c == 'e' || c == 'E');
1766 }
1767
1768 static int
1769 read_num(const char **s, int strict,
1770 char **b)
1771 {
1772 if (**s != '.') {
1773 if (!read_digits(s, strict, b))
1774 return 0;
1775 }
1776
1777 if (**s == '.') {
1778 **b = **s;
1779 (*s)++;
1780 (*b)++;
1781 if (!read_digits(s, strict, b)) {
1782 (*b)--;
1783 return 0;
1784 }
1785 }
1786
1787 if (islettere(**s)) {
1788 **b = **s;
1789 (*s)++;
1790 (*b)++;
1791 read_sign(s, b);
1792 if (!read_digits(s, strict, b)) {
1793 (*b)--;
1794 return 0;
1795 }
1796 }
1797 return 1;
1798 }
1799
1800 inline static int
1801 read_den(const char **s, int strict,
1802 char **b)
1803 {
1804 if (!read_digits(s, strict, b))
1805 return 0;
1806 return 1;
1807 }
1808
1809 static int
1810 read_rat_nos(const char **s, int strict,
1811 char **b)
1812 {
1813 if (!read_num(s, strict, b))
1814 return 0;
1815 if (**s == '/') {
1816 **b = **s;
1817 (*s)++;
1818 (*b)++;
1819 if (!read_den(s, strict, b)) {
1820 (*b)--;
1821 return 0;
1822 }
1823 }
1824 return 1;
1825 }
1826
1827 static int
1828 read_rat(const char **s, int strict,
1829 char **b)
1830 {
1831 read_sign(s, b);
1832 if (!read_rat_nos(s, strict, b))
1833 return 0;
1834 return 1;
1835 }
1836
1837 inline static int
1838 isimagunit(int c)
1839 {
1840 return (c == 'i' || c == 'I' ||
1841 c == 'j' || c == 'J');
1842 }
1843
1844 static VALUE
1845 str2num(char *s)
1846 {
1847 if (strchr(s, '/'))
1848 return rb_cstr_to_rat(s, 0);
1849 if (strpbrk(s, ".eE"))
1850 return DBL2NUM(rb_cstr_to_dbl(s, 0));
1851 return rb_cstr_to_inum(s, 10, 0);
1852 }
1853
1854 static int
1855 read_comp(const char **s, int strict,
1856 VALUE *ret, char **b)
1857 {
1858 char *bb;
1859 int sign;
1860 VALUE num, num2;
1861
1862 bb = *b;
1863
1864 sign = read_sign(s, b);
1865
1866 if (isimagunit(**s)) {
1867 (*s)++;
1868 num = INT2FIX((sign == '-') ? -1 : + 1);
1869 *ret = rb_complex_new2(ZERO, num);
1870 return 1; /* e.g. "i" */
1871 }
1872
1873 if (!read_rat_nos(s, strict, b)) {
1874 **b = '\0';
1875 num = str2num(bb);
1876 *ret = rb_complex_new2(num, ZERO);
1877 return 0; /* e.g. "-" */
1878 }
1879 **b = '\0';
1880 num = str2num(bb);
1881
1882 if (isimagunit(**s)) {
1883 (*s)++;
1884 *ret = rb_complex_new2(ZERO, num);
1885 return 1; /* e.g. "3i" */
1886 }
1887
1888 if (**s == '@') {
1889 int st;
1890
1891 (*s)++;
1892 bb = *b;
1893 st = read_rat(s, strict, b);
1894 **b = '\0';
1895 if (strlen(bb) < 1 ||
1896 !isdecimal(*(bb + strlen(bb) - 1))) {
1897 *ret = rb_complex_new2(num, ZERO);
1898 return 0; /* e.g. "1@-" */
1899 }
1900 num2 = str2num(bb);
1901 *ret = rb_complex_new_polar(num, num2);
1902 if (!st)
1903 return 0; /* e.g. "1@2." */
1904 else
1905 return 1; /* e.g. "1@2" */
1906 }
1907
1908 if (issign(**s)) {
1909 bb = *b;
1910 sign = read_sign(s, b);
1911 if (isimagunit(**s))
1912 num2 = INT2FIX((sign == '-') ? -1 : + 1);
1913 else {
1914 if (!read_rat_nos(s, strict, b)) {
1915 *ret = rb_complex_new2(num, ZERO);
1916 return 0; /* e.g. "1+xi" */
1917 }
1918 **b = '\0';
1919 num2 = str2num(bb);
1920 }
1921 if (!isimagunit(**s)) {
1922 *ret = rb_complex_new2(num, ZERO);
1923 return 0; /* e.g. "1+3x" */
1924 }
1925 (*s)++;
1926 *ret = rb_complex_new2(num, num2);
1927 return 1; /* e.g. "1+2i" */
1928 }
1929 /* !(@, - or +) */
1930 {
1931 *ret = rb_complex_new2(num, ZERO);
1932 return 1; /* e.g. "3" */
1933 }
1934 }
1935
1936 inline static void
1937 skip_ws(const char **s)
1938 {
1939 while (isspace((unsigned char)**s))
1940 (*s)++;
1941 }
1942
1943 static int
1944 parse_comp(const char *s, int strict, VALUE *num)
1945 {
1946 char *buf, *b;
1947 VALUE tmp;
1948 int ret = 1;
1949
1950 buf = ALLOCV_N(char, tmp, strlen(s) + 1);
1951 b = buf;
1952
1953 skip_ws(&s);
1954 if (!read_comp(&s, strict, num, &b)) {
1955 ret = 0;
1956 }
1957 else {
1958 skip_ws(&s);
1959
1960 if (strict)
1961 if (*s != '\0')
1962 ret = 0;
1963 }
1964 ALLOCV_END(tmp);
1965
1966 return ret;
1967 }
1968
1969 static VALUE
1970 string_to_c_strict(VALUE self, int raise)
1971 {
1972 char *s;
1973 VALUE num;
1974
1975 rb_must_asciicompat(self);
1976
1977 s = RSTRING_PTR(self);
1978
1979 if (!s || memchr(s, '\0', RSTRING_LEN(self))) {
1980 if (!raise) return Qnil;
1981 rb_raise(rb_eArgError, "string contains null byte");
1982 }
1983
1984 if (s && s[RSTRING_LEN(self)]) {
1985 rb_str_modify(self);
1986 s = RSTRING_PTR(self);
1987 s[RSTRING_LEN(self)] = '\0';
1988 }
1989
1990 if (!s)
1991 s = (char *)"";
1992
1993 if (!parse_comp(s, 1, &num)) {
1994 if (!raise) return Qnil;
1995 rb_raise(rb_eArgError, "invalid value for convert(): %+"PRIsVALUE,
1996 self);
1997 }
1998
1999 return num;
2000 }
2001
2002 /*
2003 * call-seq:
2004 * str.to_c -> complex
2005 *
2006 * Returns a complex which denotes the string form. The parser
2007 * ignores leading whitespaces and trailing garbage. Any digit
2008 * sequences can be separated by an underscore. Returns zero for null
2009 * or garbage string.
2010 *
2011 * '9'.to_c #=> (9+0i)
2012 * '2.5'.to_c #=> (2.5+0i)
2013 * '2.5/1'.to_c #=> ((5/2)+0i)
2014 * '-3/2'.to_c #=> ((-3/2)+0i)
2015 * '-i'.to_c #=> (0-1i)
2016 * '45i'.to_c #=> (0+45i)
2017 * '3-4i'.to_c #=> (3-4i)
2018 * '-4e2-4e-2i'.to_c #=> (-400.0-0.04i)
2019 * '-0.0-0.0i'.to_c #=> (-0.0-0.0i)
2020 * '1/2+3/4i'.to_c #=> ((1/2)+(3/4)*i)
2021 * 'ruby'.to_c #=> (0+0i)
2022 *
2023 * See Kernel.Complex.
2024 */
2025 static VALUE
2026 string_to_c(VALUE self)
2027 {
2028 char *s;
2029 VALUE num;
2030
2031 rb_must_asciicompat(self);
2032
2033 s = RSTRING_PTR(self);
2034
2035 if (s && s[RSTRING_LEN(self)]) {
2036 rb_str_modify(self);
2037 s = RSTRING_PTR(self);
2038 s[RSTRING_LEN(self)] = '\0';
2039 }
2040
2041 if (!s)
2042 s = (char *)"";
2043
2044 (void)parse_comp(s, 0, &num);
2045
2046 return num;
2047 }
2048
2049 static VALUE
2050 to_complex(VALUE val)
2051 {
2052 return rb_convert_type(val, T_COMPLEX, "Complex", "to_c");
2053 }
2054
2055 static VALUE
2056 nucomp_convert(VALUE klass, VALUE a1, VALUE a2, int raise)
2057 {
2058 if (NIL_P(a1) || NIL_P(a2)) {
2059 if (!raise) return Qnil;
2060 rb_raise(rb_eTypeError, "can't convert nil into Complex");
2061 }
2062
2063 if (RB_TYPE_P(a1, T_STRING)) {
2064 a1 = string_to_c_strict(a1, raise);
2065 if (NIL_P(a1)) return Qnil;
2066 }
2067
2068 if (RB_TYPE_P(a2, T_STRING)) {
2069 a2 = string_to_c_strict(a2, raise);
2070 if (NIL_P(a2)) return Qnil;
2071 }
2072
2073 if (RB_TYPE_P(a1, T_COMPLEX)) {
2074 {
2075 get_dat1(a1);
2076
2077 if (k_exact_zero_p(dat->imag))
2078 a1 = dat->real;
2079 }
2080 }
2081
2082 if (RB_TYPE_P(a2, T_COMPLEX)) {
2083 {
2084 get_dat1(a2);
2085
2086 if (k_exact_zero_p(dat->imag))
2087 a2 = dat->real;
2088 }
2089 }
2090
2091 if (RB_TYPE_P(a1, T_COMPLEX)) {
2092 if (a2 == Qundef || (k_exact_zero_p(a2)))
2093 return a1;
2094 }
2095
2096 if (a2 == Qundef) {
2097 if (k_numeric_p(a1) && !f_real_p(a1))
2098 return a1;
2099 /* should raise exception for consistency */
2100 if (!k_numeric_p(a1)) {
2101 if (!raise)
2102 return rb_protect(to_complex, a1, NULL);
2103 return to_complex(a1);
2104 }
2105 }
2106 else {
2107 if ((k_numeric_p(a1) && k_numeric_p(a2)) &&
2108 (!f_real_p(a1) || !f_real_p(a2)))
2109 return f_add(a1,
2110 f_mul(a2,
2111 f_complex_new_bang2(rb_cComplex, ZERO, ONE)));
2112 }
2113
2114 {
2115 int argc;
2116 VALUE argv2[2];
2117 argv2[0] = a1;
2118 if (a2 == Qundef) {
2119 argv2[1] = Qnil;
2120 argc = 1;
2121 }
2122 else {
2123 if (!raise && !RB_INTEGER_TYPE_P(a2) && !RB_FLOAT_TYPE_P(a2) && !RB_TYPE_P(a2, T_RATIONAL))
2124 return Qnil;
2125 argv2[1] = a2;
2126 argc = 2;
2127 }
2128 return nucomp_s_new(argc, argv2, klass);
2129 }
2130 }
2131
2132 static VALUE
2133 nucomp_s_convert(int argc, VALUE *argv, VALUE klass)
2134 {
2135 VALUE a1, a2;
2136
2137 if (rb_scan_args(argc, argv, "11", &a1, &a2) == 1) {
2138 a2 = Qundef;
2139 }
2140
2141 return nucomp_convert(klass, a1, a2, TRUE);
2142 }
2143
2144 /* --- */
2145
2146 /*
2147 * call-seq:
2148 * num.real -> self
2149 *
2150 * Returns self.
2151 */
2152 static VALUE
2153 numeric_real(VALUE self)
2154 {
2155 return self;
2156 }
2157
2158 /*
2159 * call-seq:
2160 * num.imag -> 0
2161 * num.imaginary -> 0
2162 *
2163 * Returns zero.
2164 */
2165 static VALUE
2166 numeric_imag(VALUE self)
2167 {
2168 return INT2FIX(0);
2169 }
2170
2171 /*
2172 * call-seq:
2173 * num.abs2 -> real
2174 *
2175 * Returns square of self.
2176 */
2177 static VALUE
2178 numeric_abs2(VALUE self)
2179 {
2180 return f_mul(self, self);
2181 }
2182
2183 /*
2184 * call-seq:
2185 * num.arg -> 0 or float
2186 * num.angle -> 0 or float
2187 * num.phase -> 0 or float
2188 *
2189 * Returns 0 if the value is positive, pi otherwise.
2190 */
2191 static VALUE
2192 numeric_arg(VALUE self)
2193 {
2194 if (f_positive_p(self))
2195 return INT2FIX(0);
2196 return DBL2NUM(M_PI);
2197 }
2198
2199 /*
2200 * call-seq:
2201 * num.rect -> array
2202 * num.rectangular -> array
2203 *
2204 * Returns an array; [num, 0].
2205 */
2206 static VALUE
2207 numeric_rect(VALUE self)
2208 {
2209 return rb_assoc_new(self, INT2FIX(0));
2210 }
2211
2212 static VALUE float_arg(VALUE self);
2213
2214 /*
2215 * call-seq:
2216 * num.polar -> array
2217 *
2218 * Returns an array; [num.abs, num.arg].
2219 */
2220 static VALUE
2221 numeric_polar(VALUE self)
2222 {
2223 VALUE abs, arg;
2224
2225 if (RB_INTEGER_TYPE_P(self)) {
2226 abs = rb_int_abs(self);
2227 arg = numeric_arg(self);
2228 }
2229 else if (RB_FLOAT_TYPE_P(self)) {
2230 abs = rb_float_abs(self);
2231 arg = float_arg(self);
2232 }
2233 else if (RB_TYPE_P(self, T_RATIONAL)) {
2234 abs = rb_rational_abs(self);
2235 arg = numeric_arg(self);
2236 }
2237 else {
2238 abs = f_abs(self);
2239 arg = f_arg(self);
2240 }
2241 return rb_assoc_new(abs, arg);
2242 }
2243
2244 /*
2245 * call-seq:
2246 * num.conj -> self
2247 * num.conjugate -> self
2248 *
2249 * Returns self.
2250 */
2251 static VALUE
2252 numeric_conj(VALUE self)
2253 {
2254 return self;
2255 }
2256
2257 /*
2258 * call-seq:
2259 * flo.arg -> 0 or float
2260 * flo.angle -> 0 or float
2261 * flo.phase -> 0 or float
2262 *
2263 * Returns 0 if the value is positive, pi otherwise.
2264 */
2265 static VALUE
2266 float_arg(VALUE self)
2267 {
2268 if (isnan(RFLOAT_VALUE(self)))
2269 return self;
2270 if (f_tpositive_p(self))
2271 return INT2FIX(0);
2272 return rb_const_get(rb_mMath, id_PI);
2273 }
2274
2275 /*
2276 * A complex number can be represented as a paired real number with
2277 * imaginary unit; a+bi. Where a is real part, b is imaginary part
2278 * and i is imaginary unit. Real a equals complex a+0i
2279 * mathematically.
2280 *
2281 * Complex object can be created as literal, and also by using
2282 * Kernel#Complex, Complex::rect, Complex::polar or to_c method.
2283 *
2284 * 2+1i #=> (2+1i)
2285 * Complex(1) #=> (1+0i)
2286 * Complex(2, 3) #=> (2+3i)
2287 * Complex.polar(2, 3) #=> (-1.9799849932008908+0.2822400161197344i)
2288 * 3.to_c #=> (3+0i)
2289 *
2290 * You can also create complex object from floating-point numbers or
2291 * strings.
2292 *
2293 * Complex(0.3) #=> (0.3+0i)
2294 * Complex('0.3-0.5i') #=> (0.3-0.5i)
2295 * Complex('2/3+3/4i') #=> ((2/3)+(3/4)*i)
2296 * Complex('1@2') #=> (-0.4161468365471424+0.9092974268256817i)
2297 *
2298 * 0.3.to_c #=> (0.3+0i)
2299 * '0.3-0.5i'.to_c #=> (0.3-0.5i)
2300 * '2/3+3/4i'.to_c #=> ((2/3)+(3/4)*i)
2301 * '1@2'.to_c #=> (-0.4161468365471424+0.9092974268256817i)
2302 *
2303 * A complex object is either an exact or an inexact number.
2304 *
2305 * Complex(1, 1) / 2 #=> ((1/2)+(1/2)*i)
2306 * Complex(1, 1) / 2.0 #=> (0.5+0.5i)
2307 */
2308 void
2309 Init_Complex(void)
2310 {
2311 VALUE compat;
2312 #undef rb_intern
2313 #define rb_intern(str) rb_intern_const(str)
2314
2315 id_abs = rb_intern("abs");
2316 id_arg = rb_intern("arg");
2317 id_denominator = rb_intern("denominator");
2318 id_numerator = rb_intern("numerator");
2319 id_real_p = rb_intern("real?");
2320 id_i_real = rb_intern("@real");
2321 id_i_imag = rb_intern("@image"); /* @image, not @imag */
2322 id_finite_p = rb_intern("finite?");
2323 id_infinite_p = rb_intern("infinite?");
2324 id_rationalize = rb_intern("rationalize");
2325 id_PI = rb_intern("PI");
2326
2327 rb_cComplex = rb_define_class("Complex", rb_cNumeric);
2328
2329 rb_define_alloc_func(rb_cComplex, nucomp_s_alloc);
2330 rb_undef_method(CLASS_OF(rb_cComplex), "allocate");
2331
2332 rb_undef_method(CLASS_OF(rb_cComplex), "new");
2333
2334 rb_define_singleton_method(rb_cComplex, "rectangular", nucomp_s_new, -1);
2335 rb_define_singleton_method(rb_cComplex, "rect", nucomp_s_new, -1);
2336 rb_define_singleton_method(rb_cComplex, "polar", nucomp_s_polar, -1);
2337
2338 rb_define_global_function("Complex", nucomp_f_complex, -1);
2339
2340 rb_undef_methods_from(rb_cComplex, rb_mComparable);
2341 rb_undef_method(rb_cComplex, "%");
2342 rb_undef_method(rb_cComplex, "div");
2343 rb_undef_method(rb_cComplex, "divmod");
2344 rb_undef_method(rb_cComplex, "floor");
2345 rb_undef_method(rb_cComplex, "ceil");
2346 rb_undef_method(rb_cComplex, "modulo");
2347 rb_undef_method(rb_cComplex, "remainder");
2348 rb_undef_method(rb_cComplex, "round");
2349 rb_undef_method(rb_cComplex, "step");
2350 rb_undef_method(rb_cComplex, "truncate");
2351 rb_undef_method(rb_cComplex, "i");
2352
2353 rb_define_method(rb_cComplex, "real", rb_complex_real, 0);
2354 rb_define_method(rb_cComplex, "imaginary", rb_complex_imag, 0);
2355 rb_define_method(rb_cComplex, "imag", rb_complex_imag, 0);
2356
2357 rb_define_method(rb_cComplex, "-@", rb_complex_uminus, 0);
2358 rb_define_method(rb_cComplex, "+", rb_complex_plus, 1);
2359 rb_define_method(rb_cComplex, "-", rb_complex_minus, 1);
2360 rb_define_method(rb_cComplex, "*", rb_complex_mul, 1);
2361 rb_define_method(rb_cComplex, "/", rb_complex_div, 1);
2362 rb_define_method(rb_cComplex, "quo", nucomp_quo, 1);
2363 rb_define_method(rb_cComplex, "fdiv", nucomp_fdiv, 1);
2364 rb_define_method(rb_cComplex, "**", rb_complex_pow, 1);
2365
2366 rb_define_method(rb_cComplex, "==", nucomp_eqeq_p, 1);
2367 rb_define_method(rb_cComplex, "<=>", nucomp_cmp, 1);
2368 rb_define_method(rb_cComplex, "coerce", nucomp_coerce, 1);
2369
2370 rb_define_method(rb_cComplex, "abs", rb_complex_abs, 0);
2371 rb_define_method(rb_cComplex, "magnitude", rb_complex_abs, 0);
2372 rb_define_method(rb_cComplex, "abs2", nucomp_abs2, 0);
2373 rb_define_method(rb_cComplex, "arg", rb_complex_arg, 0);
2374 rb_define_method(rb_cComplex, "angle", rb_complex_arg, 0);
2375 rb_define_method(rb_cComplex, "phase", rb_complex_arg, 0);
2376 rb_define_method(rb_cComplex, "rectangular", nucomp_rect, 0);
2377 rb_define_method(rb_cComplex, "rect", nucomp_rect, 0);
2378 rb_define_method(rb_cComplex, "polar", nucomp_polar, 0);
2379 rb_define_method(rb_cComplex, "conjugate", rb_complex_conjugate, 0);
2380 rb_define_method(rb_cComplex, "conj", rb_complex_conjugate, 0);
2381
2382 rb_define_method(rb_cComplex, "real?", nucomp_false, 0);
2383
2384 rb_define_method(rb_cComplex, "numerator", nucomp_numerator, 0);
2385 rb_define_method(rb_cComplex, "denominator", nucomp_denominator, 0);
2386
2387 rb_define_method(rb_cComplex, "hash", nucomp_hash, 0);
2388 rb_define_method(rb_cComplex, "eql?", nucomp_eql_p, 1);
2389
2390 rb_define_method(rb_cComplex, "to_s", nucomp_to_s, 0);
2391 rb_define_method(rb_cComplex, "inspect", nucomp_inspect, 0);
2392
2393 rb_undef_method(rb_cComplex, "positive?");
2394 rb_undef_method(rb_cComplex, "negative?");
2395
2396 rb_define_method(rb_cComplex, "finite?", rb_complex_finite_p, 0);
2397 rb_define_method(rb_cComplex, "infinite?", rb_complex_infinite_p, 0);
2398
2399 rb_define_private_method(rb_cComplex, "marshal_dump", nucomp_marshal_dump, 0);
2400 /* :nodoc: */
2401 compat = rb_define_class_under(rb_cComplex, "compatible", rb_cObject);
2402 rb_define_private_method(compat, "marshal_load", nucomp_marshal_load, 1);
2403 rb_marshal_define_compat(rb_cComplex, compat, nucomp_dumper, nucomp_loader);
2404
2405 /* --- */
2406
2407 rb_define_method(rb_cComplex, "to_i", nucomp_to_i, 0);
2408 rb_define_method(rb_cComplex, "to_f", nucomp_to_f, 0);
2409 rb_define_method(rb_cComplex, "to_r", nucomp_to_r, 0);
2410 rb_define_method(rb_cComplex, "rationalize", nucomp_rationalize, -1);
2411 rb_define_method(rb_cComplex, "to_c", nucomp_to_c, 0);
2412 rb_define_method(rb_cNilClass, "to_c", nilclass_to_c, 0);
2413 rb_define_method(rb_cNumeric, "to_c", numeric_to_c, 0);
2414
2415 rb_define_method(rb_cString, "to_c", string_to_c, 0);
2416
2417 rb_define_private_method(CLASS_OF(rb_cComplex), "convert", nucomp_s_convert, -1);
2418
2419 /* --- */
2420
2421 rb_define_method(rb_cNumeric, "real", numeric_real, 0);
2422 rb_define_method(rb_cNumeric, "imaginary", numeric_imag, 0);
2423 rb_define_method(rb_cNumeric, "imag", numeric_imag, 0);
2424 rb_define_method(rb_cNumeric, "abs2", numeric_abs2, 0);
2425 rb_define_method(rb_cNumeric, "arg", numeric_arg, 0);
2426 rb_define_method(rb_cNumeric, "angle", numeric_arg, 0);
2427 rb_define_method(rb_cNumeric, "phase", numeric_arg, 0);
2428 rb_define_method(rb_cNumeric, "rectangular", numeric_rect, 0);
2429 rb_define_method(rb_cNumeric, "rect", numeric_rect, 0);
2430 rb_define_method(rb_cNumeric, "polar", numeric_polar, 0);
2431 rb_define_method(rb_cNumeric, "conjugate", numeric_conj, 0);
2432 rb_define_method(rb_cNumeric, "conj", numeric_conj, 0);
2433
2434 rb_define_method(rb_cFloat, "arg", float_arg, 0);
2435 rb_define_method(rb_cFloat, "angle", float_arg, 0);
2436 rb_define_method(rb_cFloat, "phase", float_arg, 0);
2437
2438 /*
2439 * The imaginary unit.
2440 */
2441 rb_define_const(rb_cComplex, "I",
2442 f_complex_new_bang2(rb_cComplex, ZERO, ONE));
2443
2444 #if !USE_FLONUM
2445 rb_gc_register_mark_object(RFLOAT_0 = DBL2NUM(0.0));
2446 #endif
2447
2448 rb_provide("complex.so"); /* for backward compatibility */
2449 }
rb_rational_cmp
VALUE rb_rational_cmp(VALUE self, VALUE other)
Definition: rational.c:1097
rb_dbl_complex_new_polar_pi
VALUE rb_dbl_complex_new_polar_pi(double abs, double ang)
Definition: complex.c:667
INT_NEGATIVE_P
#define INT_NEGATIVE_P(x)
Definition: internal.h:1775
ID
unsigned long ID
Definition: ruby.h:103
rb_str_concat
VALUE rb_str_concat(VALUE, VALUE)
Definition: string.c:3065
rb_define_class
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:649
void
void
Definition: rb_mjit_min_header-2.7.0.h:13273
rb_method_basic_definition_p
#define rb_method_basic_definition_p(klass, mid)
Definition: rb_mjit_min_header-2.7.0.h:7900
f_to_i
#define f_to_i(x)
Definition: date_core.c:47
Check_Type
#define Check_Type(v, t)
Definition: ruby.h:595
TRUE
#define TRUE
Definition: nkf.h:175
abs
int abs(int)
rb_assoc_new
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:896
assert
#define assert(x)
Definition: dlmalloc.c:1176
rb_flo_is_finite_p
VALUE rb_flo_is_finite_p(VALUE num)
Definition: numeric.c:1770
id_fdiv
#define id_fdiv
Definition: complex.c:46
rb_opts_exception_p
int rb_opts_exception_p(VALUE opts, int default_value)
Definition: object.c:3125
rb_complex_pow
VALUE rb_complex_pow(VALUE self, VALUE other)
Definition: complex.c:985
rb_gc_register_mark_object
void rb_gc_register_mark_object(VALUE obj)
Definition: gc.c:7063
Init_Complex
void Init_Complex(void)
Definition: complex.c:2309
rb_complex_new_polar
VALUE rb_complex_new_polar(VALUE x, VALUE y)
Definition: complex.c:1533
rb_warn
void rb_warn(const char *fmt,...)
Definition: error.c:313
rb_complex_polar
VALUE rb_complex_polar(VALUE x, VALUE y)
Definition: complex.c:1539
rb_int_abs
VALUE rb_int_abs(VALUE num)
Definition: numeric.c:4855
rb_cNumeric
RUBY_EXTERN VALUE rb_cNumeric
Definition: ruby.h:2037
rb_scan_args
#define rb_scan_args(argc, argvp, fmt,...)
Definition: rb_mjit_min_header-2.7.0.h:6372
INT2FIX
#define INT2FIX(i)
Definition: ruby.h:263
strchr
char * strchr(char *, char)
rb_float_gt
VALUE rb_float_gt(VALUE x, VALUE y)
Definition: numeric.c:1503
id_denominator
#define id_denominator
Definition: rational.c:1974
nucomp_quo
#define nucomp_quo
Definition: complex.c:953
RSTRING_PTR
#define RSTRING_PTR(str)
Definition: ruby.h:1009
idMINUS
@ idMINUS
Definition: id.h:86
rb_marshal_define_compat
void rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE(*dumper)(VALUE), VALUE(*loader)(VALUE, VALUE))
Definition: marshal.c:133
NUM2LONG
#define NUM2LONG(x)
Definition: ruby.h:679
RFLOAT_0
#define RFLOAT_0
Definition: complex.c:24
rb_complex_div
VALUE rb_complex_div(VALUE self, VALUE other)
Definition: complex.c:948
rb_cstr_to_dbl
double rb_cstr_to_dbl(const char *, int)
Parses a string representation of a floating point number.
Definition: object.c:3319
rb_equal
VALUE rb_equal(VALUE, VALUE)
Same as Object#===, case equality.
Definition: object.c:124
f_reciprocal
#define f_reciprocal(x)
Definition: rational.c:1618
rb_rational_uminus
VALUE rb_rational_uminus(VALUE self)
Definition: rational.c:624
VALUE
unsigned long VALUE
Definition: ruby.h:102
rb_eArgError
VALUE rb_eArgError
Definition: error.c:923
id_quo
#define id_quo
Definition: complex.c:45
RB_TYPE_P
#define RB_TYPE_P(obj, type)
Definition: ruby.h:560
rb_rational_plus
VALUE rb_rational_plus(VALUE self, VALUE other)
Definition: rational.c:737
FIXNUM_ZERO_P
#define FIXNUM_ZERO_P(num)
Definition: internal.h:1773
rb_math_log
VALUE rb_math_log(int argc, const VALUE *argv)
Definition: math.c:459
M_PI
#define M_PI
Definition: missing.h:41
fun1
#define fun1(n)
Definition: complex.c:50
rb_num_negative_p
int rb_num_negative_p(VALUE)
Definition: numeric.c:313
rb_cFloat
RUBY_EXTERN VALUE rb_cFloat
Definition: ruby.h:2028
RGENGC_WB_PROTECTED_COMPLEX
#define RGENGC_WB_PROTECTED_COMPLEX
Definition: ruby.h:826
id.h
SIGNED_VALUE
#define SIGNED_VALUE
Definition: ruby.h:104
rb_define_global_function
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
Definition: class.c:1787
sin
double sin(double)
rb_inspect
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
Definition: object.c:551
RRATIONAL
#define RRATIONAL(obj)
Definition: internal.h:794
rb_str_cat2
#define rb_str_cat2
Definition: intern.h:912
Qundef
#define Qundef
Definition: ruby.h:470
rb_define_singleton_method
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1755
T_RATIONAL
#define T_RATIONAL
Definition: ruby.h:541
rb_str_modify
void rb_str_modify(VALUE)
Definition: string.c:2114
rb_complex_mul
VALUE rb_complex_mul(VALUE self, VALUE other)
Definition: complex.c:872
rb_str_to_dbl
double rb_str_to_dbl(VALUE, int)
Parses a string representation of a floating point number.
Definition: object.c:3371
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1551
rb_cstr_to_inum
VALUE rb_cstr_to_inum(const char *str, int base, int badcheck)
Definition: bignum.c:4012
Qfalse
#define Qfalse
Definition: ruby.h:467
rb_float_abs
VALUE rb_float_abs(VALUE flt)
Definition: numeric.c:1698
DBL2NUM
#define DBL2NUM(dbl)
Definition: ruby.h:967
rb_cRational
RUBY_EXTERN VALUE rb_cRational
Definition: ruby.h:2041
rb_numeric_quo
VALUE rb_numeric_quo(VALUE x, VALUE y)
Definition: rational.c:2014
rb_flo_is_infinite_p
VALUE rb_flo_is_infinite_p(VALUE num)
Definition: numeric.c:1750
rb_cInteger
RUBY_EXTERN VALUE rb_cInteger
Definition: ruby.h:2031
canonicalization
#define canonicalization
Definition: complex.c:430
NULL
#define NULL
Definition: _sdbm.c:101
T_COMPLEX
#define T_COMPLEX
Definition: ruby.h:542
rb_cmpint
#define rb_cmpint(cmp, a, b)
FL_WB_PROTECTED
#define FL_WB_PROTECTED
Definition: ruby.h:1279
PRIsVALUE
#define PRIsVALUE
Definition: ruby.h:166
FIX2LONG
#define FIX2LONG(x)
Definition: ruby.h:394
strlen
size_t strlen(const char *)
FLOAT_ZERO_P
#define FLOAT_ZERO_P(x)
Definition: internal.h:1777
rb_math_hypot
VALUE rb_math_hypot(VALUE, VALUE)
rb_int_uminus
VALUE rb_int_uminus(VALUE num)
Definition: numeric.c:3479
rb_undef_method
void rb_undef_method(VALUE klass, const char *name)
Definition: class.c:1575
rb_protect
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *pstate)
Protects a function call from potential global escapes from the function.
Definition: eval.c:1071
rb_check_arity
#define rb_check_arity
Definition: intern.h:347
RUBY_FUNC_EXPORTED
#define RUBY_FUNC_EXPORTED
Definition: defines.h:391
rb_memhash
st_index_t rb_memhash(const void *ptr, long len)
Definition: random.c:1440
rb_dbl_complex_new
VALUE rb_dbl_complex_new(double real, double imag)
Creates a Complex object.
Definition: complex.c:1561
v
int VALUE v
Definition: rb_mjit_min_header-2.7.0.h:12332
rb_funcallv
#define rb_funcallv(recv, mid, argc, argv)
Definition: rb_mjit_min_header-2.7.0.h:7899
rb_float_denominator
VALUE rb_float_denominator(VALUE x)
Definition: rational.c:2104
id_expt
#define id_expt
Definition: complex.c:43
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2669
rb_ivar_get
VALUE rb_ivar_get(VALUE, ID)
Definition: variable.c:1070
rb_eRangeError
VALUE rb_eRangeError
Definition: error.c:926
rb_str_to_inum
VALUE rb_str_to_inum(VALUE str, int base, int badcheck)
Definition: bignum.c:4268
f_positive_p
#define f_positive_p(x)
Definition: complex.c:314
obj
const VALUE VALUE obj
Definition: rb_mjit_min_header-2.7.0.h:5742
rb_obj_class
VALUE rb_obj_class(VALUE)
Equivalent to Object#class in Ruby.
Definition: object.c:217
issign
#define issign(c)
Definition: date_parse.c:60
rb_cNilClass
RUBY_EXTERN VALUE rb_cNilClass
Definition: ruby.h:2036
rb_float_numerator
VALUE rb_float_numerator(VALUE x)
Definition: rational.c:2081
f_mul
#define f_mul(x, y)
Definition: date_core.c:35
idMULT
@ idMULT
Definition: id.h:87
rb_int_mul
VALUE rb_int_mul(VALUE x, VALUE y)
Definition: numeric.c:3699
LIKELY
#define LIKELY(x)
Definition: ffi_common.h:125
rb_undef_methods_from
void rb_undef_methods_from(VALUE klass, VALUE super)
Definition: class.c:1589
rb_float_plus
VALUE rb_float_plus(VALUE x, VALUE y)
Definition: numeric.c:1024
ALLOCV_END
#define ALLOCV_END(v)
Definition: ruby.h:1750
rb_must_asciicompat
void rb_must_asciicompat(VALUE)
Definition: string.c:2166
rb_complex_uminus
VALUE rb_complex_uminus(VALUE self)
Definition: complex.c:758
get_dat1
#define get_dat1(x)
Definition: complex.c:382
f_div
#define f_div(x, y)
Definition: date_core.c:36
ALLOCV_N
#define ALLOCV_N(type, v, n)
Definition: ruby.h:1749
rb_lcm
VALUE rb_lcm(VALUE x, VALUE y)
Definition: rational.c:1913
RCOMPLEX_SET_IMAG
#define RCOMPLEX_SET_IMAG(cmp, i)
Definition: internal.h:815
rb_complex_imag
VALUE rb_complex_imag(VALUE self)
Definition: complex.c:743
imp1
#define imp1(n)
Definition: complex.c:572
rb_Complex
VALUE rb_Complex(VALUE x, VALUE y)
Definition: complex.c:1545
st_index_t
st_data_t st_index_t
Definition: st.h:50
f_quo
#define f_quo(x, y)
Definition: date_core.c:37
rb_complex_new
VALUE rb_complex_new(VALUE x, VALUE y)
Definition: complex.c:1527
isnan
#define isnan(x)
Definition: win32.h:369
rb_eTypeError
VALUE rb_eTypeError
Definition: error.c:922
rb_complex_arg
VALUE rb_complex_arg(VALUE self)
Definition: complex.c:1208
rb_copy_generic_ivar
void rb_copy_generic_ivar(VALUE, VALUE)
Definition: variable.c:1447
idPLUS
@ idPLUS
Definition: id.h:85
cosh
double cosh(double x)
Definition: math.c:228
RARRAY_AREF
#define RARRAY_AREF(a, i)
Definition: ruby.h:1101
id_to_f
#define id_to_f
Definition: complex.c:44
FIXNUM_P
#define FIXNUM_P(f)
Definition: ruby.h:396
rb_num_coerce_bin
VALUE rb_num_coerce_bin(VALUE, VALUE, ID)
Definition: numeric.c:446
rb_intern
#define rb_intern(str)
f_add
#define f_add(x, y)
Definition: date_core.c:33
k_exact_zero_p
#define k_exact_zero_p(x)
Definition: complex.c:380
rb_float_div
VALUE rb_float_div(VALUE x, VALUE y)
Definition: numeric.c:1126
CLASS_OF
#define CLASS_OF(v)
Definition: ruby.h:484
signbit
#define signbit(__x)
Definition: rb_mjit_min_header-2.7.0.h:3676
id_to_i
#define id_to_i
Definition: complex.c:40
cos
double cos(double)
RARRAY_LEN
#define RARRAY_LEN(a)
Definition: ruby.h:1070
rb_cObject
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:2010
TWO
#define TWO
Definition: complex.c:22
rb_float_mul
VALUE rb_float_mul(VALUE x, VALUE y)
Definition: numeric.c:1072
buf
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4322
n
const char size_t n
Definition: rb_mjit_min_header-2.7.0.h:5456
str2num
#define str2num(s)
Definition: date_parse.c:48
T_BIGNUM
#define T_BIGNUM
Definition: ruby.h:533
rb_funcall
#define rb_funcall(recv, mid, argc,...)
Definition: rb_mjit_min_header-2.7.0.h:6585
RCOMPLEX_SET_REAL
#define RCOMPLEX_SET_REAL(cmp, r)
Definition: internal.h:814
rb_provide
void rb_provide(const char *)
Definition: load.c:563
internal.h
T_ARRAY
#define T_ARRAY
Definition: ruby.h:530
arg
VALUE arg
Definition: rb_mjit_min_header-2.7.0.h:5601
argv
char ** argv
Definition: ruby.c:223
f
#define f
rb_rational_abs
VALUE rb_rational_abs(VALUE self)
Definition: rational.c:1255
strpbrk
char * strpbrk(const char *, const char *)
M_PI_2
#define M_PI_2
Definition: missing.h:44
klass
VALUE klass
Definition: rb_mjit_min_header-2.7.0.h:13254
rb_complex_raw
VALUE rb_complex_raw(VALUE x, VALUE y)
Definition: complex.c:1521
id_negate
#define id_negate
Definition: complex.c:42
rb_hash
VALUE rb_hash(VALUE obj)
Definition: hash.c:129
rb_complex_new2
#define rb_complex_new2(x, y)
Definition: intern.h:194
modf
double modf(double, double *)
exp
double exp(double)
rb_num_pow
VALUE rb_num_pow(VALUE x, VALUE y)
Definition: numeric.c:4118
rb_convert_type
VALUE rb_convert_type(VALUE, int, const char *, const char *)
Converts an object into another type.
Definition: object.c:2900
rb_mComparable
VALUE rb_mComparable
Definition: compar.c:16
rb_math_atan2
VALUE rb_math_atan2(VALUE, VALUE)
get_dat2
#define get_dat2(x, y)
Definition: complex.c:385
rb_mMath
RUBY_EXTERN VALUE rb_mMath
Definition: ruby.h:2004
f_abs
#define f_abs(x)
Definition: date_core.c:31
rb_cString
RUBY_EXTERN VALUE rb_cString
Definition: ruby.h:2044
RComplex
Definition: internal.h:805
sinh
double sinh(double x)
Definition: math.c:256
rb_cstr_to_rat
VALUE rb_cstr_to_rat(const char *, int)
Definition: rational.c:2541
rb_complex_real
VALUE rb_complex_real(VALUE self)
Definition: complex.c:726
NIL_P
#define NIL_P(v)
Definition: ruby.h:482
OBJ_FREEZE_RAW
#define OBJ_FREEZE_RAW(x)
Definition: ruby.h:1376
rb_complex_new1
#define rb_complex_new1(x)
Definition: intern.h:193
argc
int argc
Definition: ruby.c:222
st
enum ruby_tag_type st
Definition: rb_mjit_min_header-2.7.0.h:11111
rb_complex_conjugate
VALUE rb_complex_conjugate(VALUE self)
Definition: complex.c:1254
rb_define_const
void rb_define_const(VALUE, const char *, VALUE)
Definition: variable.c:2880
RFLOAT_VALUE
#define RFLOAT_VALUE(v)
Definition: ruby.h:966
rb_String
VALUE rb_String(VALUE)
Equivalent to Kernel#String in Ruby.
Definition: object.c:3652
rb_int_gt
VALUE rb_int_gt(VALUE x, VALUE y)
Definition: numeric.c:4252
rb_rational_canonicalize
VALUE rb_rational_canonicalize(VALUE x)
Definition: rational.c:2034
Qtrue
#define Qtrue
Definition: ruby.h:468
f_numerator
#define f_numerator(x)
Definition: rational.c:1972
rb_cComplex
VALUE rb_cComplex
Definition: complex.c:33
idCmp
@ idCmp
Definition: id.h:84
f_boolcast
#define f_boolcast(x)
Definition: complex.c:48
rb_usascii_str_new2
#define rb_usascii_str_new2
Definition: intern.h:909
f_negate
#define f_negate(x)
Definition: date_core.c:32
ONE
#define ONE
Definition: complex.c:21
f_gt_p
#define f_gt_p(x, y)
Definition: date_parse.c:27
rb_complex_minus
VALUE rb_complex_minus(VALUE self, VALUE other)
Definition: complex.c:812
LONG2FIX
#define LONG2FIX(i)
Definition: ruby.h:265
rb_ivar_set
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1300
rb_complex_plus
VALUE rb_complex_plus(VALUE self, VALUE other)
Definition: complex.c:778
T_STRING
#define T_STRING
Definition: ruby.h:528
rb_complex_abs
VALUE rb_complex_abs(VALUE self)
Definition: complex.c:1161
rb_define_class_under
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:698
rb_float_uminus
VALUE rb_float_uminus(VALUE num)
Definition: numeric.c:1011
f_denominator
#define f_denominator(x)
Definition: rational.c:1975
RB_INTEGER_TYPE_P
#define RB_INTEGER_TYPE_P(obj)
Definition: ruby_missing.h:15
rb_rational_mul
VALUE rb_rational_mul(VALUE self, VALUE other)
Definition: rational.c:874
ST2FIX
#define ST2FIX(h)
Definition: ruby_missing.h:21
f_sub
#define f_sub(x, y)
Definition: date_core.c:34
NEWOBJ_OF
#define NEWOBJ_OF(obj, type, klass, flags)
Definition: ruby.h:785
Qnil
#define Qnil
Definition: ruby.h:469
f_to_r
#define f_to_r(x)
Definition: date_core.c:48
NUM2DBL
#define NUM2DBL(x)
Definition: ruby.h:774
h
size_t st_index_t h
Definition: rb_mjit_min_header-2.7.0.h:5462
rb_int_plus
VALUE rb_int_plus(VALUE x, VALUE y)
Definition: numeric.c:3610
RSTRING_LEN
#define RSTRING_LEN(str)
Definition: ruby.h:1005
ruby_assert.h
rb_define_private_method
void rb_define_private_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1569
ZERO
#define ZERO
Definition: complex.c:20
rb_obj_is_kind_of
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Determines if obj is a kind of c.
Definition: object.c:692
rb_define_alloc_func
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
id_numerator
#define id_numerator
Definition: rational.c:1971
RTEST
#define RTEST(v)
Definition: ruby.h:481
fun2
#define fun2(n)
Definition: complex.c:57
f_expt
#define f_expt(x, y)
Definition: date_core.c:41
RB_FLOAT_TYPE_P
#define RB_FLOAT_TYPE_P(obj)
Definition: ruby.h:556
memchr
void * memchr(const void *, int, size_t)
rb_const_get
VALUE rb_const_get(VALUE, ID)
Definition: variable.c:2387