Ruby  3.1.4p223 (2023-03-30 revision HEAD)
complex.c
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/internal/config.h"
9 
10 #if defined _MSC_VER
11 /* Microsoft Visual C does not define M_PI and others by default */
12 # define _USE_MATH_DEFINES 1
13 #endif
14 
15 #include <ctype.h>
16 #include <math.h>
17 
18 #include "id.h"
19 #include "internal.h"
20 #include "internal/array.h"
21 #include "internal/class.h"
22 #include "internal/complex.h"
23 #include "internal/math.h"
24 #include "internal/numeric.h"
25 #include "internal/object.h"
26 #include "internal/rational.h"
27 #include "ruby_assert.h"
28 
29 #define ZERO INT2FIX(0)
30 #define ONE INT2FIX(1)
31 #define TWO INT2FIX(2)
32 #if USE_FLONUM
33 #define RFLOAT_0 DBL2NUM(0)
34 #else
35 static VALUE RFLOAT_0;
36 #endif
37 
39 
40 static ID id_abs, id_arg,
41  id_denominator, id_numerator,
42  id_real_p, id_i_real, id_i_imag,
43  id_finite_p, id_infinite_p, id_rationalize,
44  id_PI;
45 #define id_to_i idTo_i
46 #define id_to_r idTo_r
47 #define id_negate idUMinus
48 #define id_expt idPow
49 #define id_to_f idTo_f
50 #define id_quo idQuo
51 #define id_fdiv idFdiv
52 
53 #define fun1(n) \
54 inline static VALUE \
55 f_##n(VALUE x)\
56 {\
57  return rb_funcall(x, id_##n, 0);\
58 }
59 
60 #define fun2(n) \
61 inline static VALUE \
62 f_##n(VALUE x, VALUE y)\
63 {\
64  return rb_funcall(x, id_##n, 1, y);\
65 }
66 
67 #define PRESERVE_SIGNEDZERO
68 
69 inline static VALUE
70 f_add(VALUE x, VALUE y)
71 {
72  if (RB_INTEGER_TYPE_P(x) &&
73  LIKELY(rb_method_basic_definition_p(rb_cInteger, idPLUS))) {
74  if (FIXNUM_ZERO_P(x))
75  return y;
76  if (FIXNUM_ZERO_P(y))
77  return x;
78  return rb_int_plus(x, y);
79  }
80  else if (RB_FLOAT_TYPE_P(x) &&
81  LIKELY(rb_method_basic_definition_p(rb_cFloat, idPLUS))) {
82  if (FIXNUM_ZERO_P(y))
83  return x;
84  return rb_float_plus(x, y);
85  }
86  else if (RB_TYPE_P(x, T_RATIONAL) &&
87  LIKELY(rb_method_basic_definition_p(rb_cRational, idPLUS))) {
88  if (FIXNUM_ZERO_P(y))
89  return x;
90  return rb_rational_plus(x, y);
91  }
92 
93  return rb_funcall(x, '+', 1, y);
94 }
95 
96 inline static VALUE
97 f_div(VALUE x, VALUE y)
98 {
99  if (FIXNUM_P(y) && FIX2LONG(y) == 1)
100  return x;
101  return rb_funcall(x, '/', 1, y);
102 }
103 
104 inline static int
105 f_gt_p(VALUE x, VALUE y)
106 {
107  if (RB_INTEGER_TYPE_P(x)) {
108  if (FIXNUM_P(x) && FIXNUM_P(y))
109  return (SIGNED_VALUE)x > (SIGNED_VALUE)y;
110  return RTEST(rb_int_gt(x, y));
111  }
112  else if (RB_FLOAT_TYPE_P(x))
113  return RTEST(rb_float_gt(x, y));
114  else if (RB_TYPE_P(x, T_RATIONAL)) {
115  int const cmp = rb_cmpint(rb_rational_cmp(x, y), x, y);
116  return cmp > 0;
117  }
118  return RTEST(rb_funcall(x, '>', 1, y));
119 }
120 
121 inline static VALUE
122 f_mul(VALUE x, VALUE y)
123 {
124  if (RB_INTEGER_TYPE_P(x) &&
125  LIKELY(rb_method_basic_definition_p(rb_cInteger, idMULT))) {
126  if (FIXNUM_ZERO_P(y))
127  return ZERO;
128  if (FIXNUM_ZERO_P(x) && RB_INTEGER_TYPE_P(y))
129  return ZERO;
130  if (x == ONE) return y;
131  if (y == ONE) return x;
132  return rb_int_mul(x, y);
133  }
134  else if (RB_FLOAT_TYPE_P(x) &&
135  LIKELY(rb_method_basic_definition_p(rb_cFloat, idMULT))) {
136  if (y == ONE) return x;
137  return rb_float_mul(x, y);
138  }
139  else if (RB_TYPE_P(x, T_RATIONAL) &&
140  LIKELY(rb_method_basic_definition_p(rb_cRational, idMULT))) {
141  if (y == ONE) return x;
142  return rb_rational_mul(x, y);
143  }
144  else if (LIKELY(rb_method_basic_definition_p(CLASS_OF(x), idMULT))) {
145  if (y == ONE) return x;
146  }
147  return rb_funcall(x, '*', 1, y);
148 }
149 
150 inline static VALUE
151 f_sub(VALUE x, VALUE y)
152 {
153  if (FIXNUM_ZERO_P(y) &&
154  LIKELY(rb_method_basic_definition_p(CLASS_OF(x), idMINUS))) {
155  return x;
156  }
157  return rb_funcall(x, '-', 1, y);
158 }
159 
160 inline static VALUE
161 f_abs(VALUE x)
162 {
163  if (RB_INTEGER_TYPE_P(x)) {
164  return rb_int_abs(x);
165  }
166  else if (RB_FLOAT_TYPE_P(x)) {
167  return rb_float_abs(x);
168  }
169  else if (RB_TYPE_P(x, T_RATIONAL)) {
170  return rb_rational_abs(x);
171  }
172  else if (RB_TYPE_P(x, T_COMPLEX)) {
173  return rb_complex_abs(x);
174  }
175  return rb_funcall(x, id_abs, 0);
176 }
177 
178 static VALUE numeric_arg(VALUE self);
179 static VALUE float_arg(VALUE self);
180 
181 inline static VALUE
182 f_arg(VALUE x)
183 {
184  if (RB_INTEGER_TYPE_P(x)) {
185  return numeric_arg(x);
186  }
187  else if (RB_FLOAT_TYPE_P(x)) {
188  return float_arg(x);
189  }
190  else if (RB_TYPE_P(x, T_RATIONAL)) {
191  return numeric_arg(x);
192  }
193  else if (RB_TYPE_P(x, T_COMPLEX)) {
194  return rb_complex_arg(x);
195  }
196  return rb_funcall(x, id_arg, 0);
197 }
198 
199 inline static VALUE
200 f_numerator(VALUE x)
201 {
202  if (RB_TYPE_P(x, T_RATIONAL)) {
203  return RRATIONAL(x)->num;
204  }
205  if (RB_FLOAT_TYPE_P(x)) {
206  return rb_float_numerator(x);
207  }
208  return x;
209 }
210 
211 inline static VALUE
212 f_denominator(VALUE x)
213 {
214  if (RB_TYPE_P(x, T_RATIONAL)) {
215  return RRATIONAL(x)->den;
216  }
217  if (RB_FLOAT_TYPE_P(x)) {
218  return rb_float_denominator(x);
219  }
220  return INT2FIX(1);
221 }
222 
223 inline static VALUE
224 f_negate(VALUE x)
225 {
226  if (RB_INTEGER_TYPE_P(x)) {
227  return rb_int_uminus(x);
228  }
229  else if (RB_FLOAT_TYPE_P(x)) {
230  return rb_float_uminus(x);
231  }
232  else if (RB_TYPE_P(x, T_RATIONAL)) {
233  return rb_rational_uminus(x);
234  }
235  else if (RB_TYPE_P(x, T_COMPLEX)) {
236  return rb_complex_uminus(x);
237  }
238  return rb_funcall(x, id_negate, 0);
239 }
240 
241 static bool nucomp_real_p(VALUE self);
242 
243 static inline bool
244 f_real_p(VALUE x)
245 {
246  if (RB_INTEGER_TYPE_P(x)) {
247  return true;
248  }
249  else if (RB_FLOAT_TYPE_P(x)) {
250  return true;
251  }
252  else if (RB_TYPE_P(x, T_RATIONAL)) {
253  return true;
254  }
255  else if (RB_TYPE_P(x, T_COMPLEX)) {
256  return nucomp_real_p(x);
257  }
258  return rb_funcall(x, id_real_p, 0);
259 }
260 
261 inline static VALUE
262 f_to_i(VALUE x)
263 {
264  if (RB_TYPE_P(x, T_STRING))
265  return rb_str_to_inum(x, 10, 0);
266  return rb_funcall(x, id_to_i, 0);
267 }
268 
269 inline static VALUE
270 f_to_f(VALUE x)
271 {
272  if (RB_TYPE_P(x, T_STRING))
273  return DBL2NUM(rb_str_to_dbl(x, 0));
274  return rb_funcall(x, id_to_f, 0);
275 }
276 
277 fun1(to_r)
278 
279 inline static int
280 f_eqeq_p(VALUE x, VALUE y)
281 {
282  if (FIXNUM_P(x) && FIXNUM_P(y))
283  return x == y;
284  else if (RB_FLOAT_TYPE_P(x) || RB_FLOAT_TYPE_P(y))
285  return NUM2DBL(x) == NUM2DBL(y);
286  return (int)rb_equal(x, y);
287 }
288 
289 fun2(expt)
290 fun2(fdiv)
291 
292 static VALUE
293 f_quo(VALUE x, VALUE y)
294 {
295  if (RB_INTEGER_TYPE_P(x))
296  return rb_numeric_quo(x, y);
297  if (RB_FLOAT_TYPE_P(x))
298  return rb_float_div(x, y);
299  if (RB_TYPE_P(x, T_RATIONAL))
300  return rb_numeric_quo(x, y);
301 
302  return rb_funcallv(x, id_quo, 1, &y);
303 }
304 
305 inline static int
306 f_negative_p(VALUE x)
307 {
308  if (RB_INTEGER_TYPE_P(x))
309  return INT_NEGATIVE_P(x);
310  else if (RB_FLOAT_TYPE_P(x))
311  return RFLOAT_VALUE(x) < 0.0;
312  else if (RB_TYPE_P(x, T_RATIONAL))
313  return INT_NEGATIVE_P(RRATIONAL(x)->num);
314  return rb_num_negative_p(x);
315 }
316 
317 #define f_positive_p(x) (!f_negative_p(x))
318 
319 inline static int
320 f_zero_p(VALUE x)
321 {
322  if (RB_FLOAT_TYPE_P(x)) {
323  return FLOAT_ZERO_P(x);
324  }
325  else if (RB_INTEGER_TYPE_P(x)) {
326  return FIXNUM_ZERO_P(x);
327  }
328  else if (RB_TYPE_P(x, T_RATIONAL)) {
329  const VALUE num = RRATIONAL(x)->num;
330  return FIXNUM_ZERO_P(num);
331  }
332  return (int)rb_equal(x, ZERO);
333 }
334 
335 #define f_nonzero_p(x) (!f_zero_p(x))
336 
337 static inline bool
338 always_finite_type_p(VALUE x)
339 {
340  if (FIXNUM_P(x)) return true;
341  if (FLONUM_P(x)) return true; /* Infinity can't be a flonum */
342  return (RB_INTEGER_TYPE_P(x) || RB_TYPE_P(x, T_RATIONAL));
343 }
344 
345 inline static int
346 f_finite_p(VALUE x)
347 {
348  if (always_finite_type_p(x)) {
349  return TRUE;
350  }
351  else if (RB_FLOAT_TYPE_P(x)) {
352  return isfinite(RFLOAT_VALUE(x));
353  }
354  return RTEST(rb_funcallv(x, id_finite_p, 0, 0));
355 }
356 
357 inline static int
358 f_infinite_p(VALUE x)
359 {
360  if (always_finite_type_p(x)) {
361  return FALSE;
362  }
363  else if (RB_FLOAT_TYPE_P(x)) {
364  return isinf(RFLOAT_VALUE(x));
365  }
366  return RTEST(rb_funcallv(x, id_infinite_p, 0, 0));
367 }
368 
369 inline static int
370 f_kind_of_p(VALUE x, VALUE c)
371 {
372  return (int)rb_obj_is_kind_of(x, c);
373 }
374 
375 inline static int
376 k_numeric_p(VALUE x)
377 {
378  return f_kind_of_p(x, rb_cNumeric);
379 }
380 
381 #define k_exact_p(x) (!RB_FLOAT_TYPE_P(x))
382 
383 #define k_exact_zero_p(x) (k_exact_p(x) && f_zero_p(x))
384 
385 #define get_dat1(x) \
386  struct RComplex *dat = RCOMPLEX(x)
387 
388 #define get_dat2(x,y) \
389  struct RComplex *adat = RCOMPLEX(x), *bdat = RCOMPLEX(y)
390 
391 inline static VALUE
392 nucomp_s_new_internal(VALUE klass, VALUE real, VALUE imag)
393 {
395 
396  RCOMPLEX_SET_REAL(obj, real);
397  RCOMPLEX_SET_IMAG(obj, imag);
398  OBJ_FREEZE_RAW((VALUE)obj);
399 
400  return (VALUE)obj;
401 }
402 
403 static VALUE
404 nucomp_s_alloc(VALUE klass)
405 {
406  return nucomp_s_new_internal(klass, ZERO, ZERO);
407 }
408 
409 inline static VALUE
410 f_complex_new_bang1(VALUE klass, VALUE x)
411 {
412  assert(!RB_TYPE_P(x, T_COMPLEX));
413  return nucomp_s_new_internal(klass, x, ZERO);
414 }
415 
416 inline static VALUE
417 f_complex_new_bang2(VALUE klass, VALUE x, VALUE y)
418 {
419  assert(!RB_TYPE_P(x, T_COMPLEX));
420  assert(!RB_TYPE_P(y, T_COMPLEX));
421  return nucomp_s_new_internal(klass, x, y);
422 }
423 
424 inline static void
425 nucomp_real_check(VALUE num)
426 {
427  if (!RB_INTEGER_TYPE_P(num) &&
428  !RB_FLOAT_TYPE_P(num) &&
429  !RB_TYPE_P(num, T_RATIONAL)) {
430  if (!k_numeric_p(num) || !f_real_p(num))
431  rb_raise(rb_eTypeError, "not a real");
432  }
433 }
434 
435 inline static VALUE
436 nucomp_s_canonicalize_internal(VALUE klass, VALUE real, VALUE imag)
437 {
438  int complex_r, complex_i;
439  complex_r = RB_TYPE_P(real, T_COMPLEX);
440  complex_i = RB_TYPE_P(imag, T_COMPLEX);
441  if (!complex_r && !complex_i) {
442  return nucomp_s_new_internal(klass, real, imag);
443  }
444  else if (!complex_r) {
445  get_dat1(imag);
446 
447  return nucomp_s_new_internal(klass,
448  f_sub(real, dat->imag),
449  f_add(ZERO, dat->real));
450  }
451  else if (!complex_i) {
452  get_dat1(real);
453 
454  return nucomp_s_new_internal(klass,
455  dat->real,
456  f_add(dat->imag, imag));
457  }
458  else {
459  get_dat2(real, imag);
460 
461  return nucomp_s_new_internal(klass,
462  f_sub(adat->real, bdat->imag),
463  f_add(adat->imag, bdat->real));
464  }
465 }
466 
467 /*
468  * call-seq:
469  * Complex.rect(real[, imag]) -> complex
470  * Complex.rectangular(real[, imag]) -> complex
471  *
472  * Returns a complex object which denotes the given rectangular form.
473  *
474  * Complex.rectangular(1, 2) #=> (1+2i)
475  */
476 static VALUE
477 nucomp_s_new(int argc, VALUE *argv, VALUE klass)
478 {
479  VALUE real, imag;
480 
481  switch (rb_scan_args(argc, argv, "11", &real, &imag)) {
482  case 1:
483  nucomp_real_check(real);
484  imag = ZERO;
485  break;
486  default:
487  nucomp_real_check(real);
488  nucomp_real_check(imag);
489  break;
490  }
491 
492  return nucomp_s_canonicalize_internal(klass, real, imag);
493 }
494 
495 inline static VALUE
496 f_complex_new2(VALUE klass, VALUE x, VALUE y)
497 {
498  assert(!RB_TYPE_P(x, T_COMPLEX));
499  return nucomp_s_canonicalize_internal(klass, x, y);
500 }
501 
502 static VALUE nucomp_convert(VALUE klass, VALUE a1, VALUE a2, int raise);
503 static VALUE nucomp_s_convert(int argc, VALUE *argv, VALUE klass);
504 
505 /*
506  * call-seq:
507  * Complex(x[, y], exception: true) -> numeric or nil
508  *
509  * Returns x+i*y;
510  *
511  * Complex(1, 2) #=> (1+2i)
512  * Complex('1+2i') #=> (1+2i)
513  * Complex(nil) #=> TypeError
514  * Complex(1, nil) #=> TypeError
515  *
516  * Complex(1, nil, exception: false) #=> nil
517  * Complex('1+2', exception: false) #=> nil
518  *
519  * Syntax of string form:
520  *
521  * string form = extra spaces , complex , extra spaces ;
522  * complex = real part | [ sign ] , imaginary part
523  * | real part , sign , imaginary part
524  * | rational , "@" , rational ;
525  * real part = rational ;
526  * imaginary part = imaginary unit | unsigned rational , imaginary unit ;
527  * rational = [ sign ] , unsigned rational ;
528  * unsigned rational = numerator | numerator , "/" , denominator ;
529  * numerator = integer part | fractional part | integer part , fractional part ;
530  * denominator = digits ;
531  * integer part = digits ;
532  * fractional part = "." , digits , [ ( "e" | "E" ) , [ sign ] , digits ] ;
533  * imaginary unit = "i" | "I" | "j" | "J" ;
534  * sign = "-" | "+" ;
535  * digits = digit , { digit | "_" , digit };
536  * digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
537  * extra spaces = ? \s* ? ;
538  *
539  * See String#to_c.
540  */
541 static VALUE
542 nucomp_f_complex(int argc, VALUE *argv, VALUE klass)
543 {
544  VALUE a1, a2, opts = Qnil;
545  int raise = TRUE;
546 
547  if (rb_scan_args(argc, argv, "11:", &a1, &a2, &opts) == 1) {
548  a2 = Qundef;
549  }
550  if (!NIL_P(opts)) {
551  raise = rb_opts_exception_p(opts, raise);
552  }
553  if (argc > 0 && CLASS_OF(a1) == rb_cComplex && a2 == Qundef) {
554  return a1;
555  }
556  return nucomp_convert(rb_cComplex, a1, a2, raise);
557 }
558 
559 #define imp1(n) \
560 inline static VALUE \
561 m_##n##_bang(VALUE x)\
562 {\
563  return rb_math_##n(x);\
564 }
565 
566 imp1(cos)
567 imp1(cosh)
568 imp1(exp)
569 
570 static VALUE
571 m_log_bang(VALUE x)
572 {
573  return rb_math_log(1, &x);
574 }
575 
576 imp1(sin)
577 imp1(sinh)
578 
579 static VALUE
580 m_cos(VALUE x)
581 {
582  if (!RB_TYPE_P(x, T_COMPLEX))
583  return m_cos_bang(x);
584  {
585  get_dat1(x);
586  return f_complex_new2(rb_cComplex,
587  f_mul(m_cos_bang(dat->real),
588  m_cosh_bang(dat->imag)),
589  f_mul(f_negate(m_sin_bang(dat->real)),
590  m_sinh_bang(dat->imag)));
591  }
592 }
593 
594 static VALUE
595 m_sin(VALUE x)
596 {
597  if (!RB_TYPE_P(x, T_COMPLEX))
598  return m_sin_bang(x);
599  {
600  get_dat1(x);
601  return f_complex_new2(rb_cComplex,
602  f_mul(m_sin_bang(dat->real),
603  m_cosh_bang(dat->imag)),
604  f_mul(m_cos_bang(dat->real),
605  m_sinh_bang(dat->imag)));
606  }
607 }
608 
609 static VALUE
610 f_complex_polar(VALUE klass, VALUE x, VALUE y)
611 {
612  assert(!RB_TYPE_P(x, T_COMPLEX));
613  assert(!RB_TYPE_P(y, T_COMPLEX));
614  if (f_zero_p(x) || f_zero_p(y)) {
615  return nucomp_s_new_internal(klass, x, RFLOAT_0);
616  }
617  if (RB_FLOAT_TYPE_P(y)) {
618  const double arg = RFLOAT_VALUE(y);
619  if (arg == M_PI) {
620  x = f_negate(x);
621  y = RFLOAT_0;
622  }
623  else if (arg == M_PI_2) {
624  y = x;
625  x = RFLOAT_0;
626  }
627  else if (arg == M_PI_2+M_PI) {
628  y = f_negate(x);
629  x = RFLOAT_0;
630  }
631  else if (RB_FLOAT_TYPE_P(x)) {
632  const double abs = RFLOAT_VALUE(x);
633  const double real = abs * cos(arg), imag = abs * sin(arg);
634  x = DBL2NUM(real);
635  y = DBL2NUM(imag);
636  }
637  else {
638  const double ax = sin(arg), ay = cos(arg);
639  y = f_mul(x, DBL2NUM(ax));
640  x = f_mul(x, DBL2NUM(ay));
641  }
642  return nucomp_s_new_internal(klass, x, y);
643  }
644  return nucomp_s_canonicalize_internal(klass,
645  f_mul(x, m_cos(y)),
646  f_mul(x, m_sin(y)));
647 }
648 
649 #ifdef HAVE___COSPI
650 # define cospi(x) __cospi(x)
651 #else
652 # define cospi(x) cos((x) * M_PI)
653 #endif
654 #ifdef HAVE___SINPI
655 # define sinpi(x) __sinpi(x)
656 #else
657 # define sinpi(x) sin((x) * M_PI)
658 #endif
659 /* returns a Complex or Float of ang*PI-rotated abs */
660 VALUE
661 rb_dbl_complex_new_polar_pi(double abs, double ang)
662 {
663  double fi;
664  const double fr = modf(ang, &fi);
665  int pos = fr == +0.5;
666 
667  if (pos || fr == -0.5) {
668  if ((modf(fi / 2.0, &fi) != fr) ^ pos) abs = -abs;
669  return rb_complex_new(RFLOAT_0, DBL2NUM(abs));
670  }
671  else if (fr == 0.0) {
672  if (modf(fi / 2.0, &fi) != 0.0) abs = -abs;
673  return DBL2NUM(abs);
674  }
675  else {
676  const double real = abs * cospi(ang), imag = abs * sinpi(ang);
677  return rb_complex_new(DBL2NUM(real), DBL2NUM(imag));
678  }
679 }
680 
681 /*
682  * call-seq:
683  * Complex.polar(abs[, arg]) -> complex
684  *
685  * Returns a complex object which denotes the given polar form.
686  *
687  * Complex.polar(3, 0) #=> (3.0+0.0i)
688  * Complex.polar(3, Math::PI/2) #=> (1.836909530733566e-16+3.0i)
689  * Complex.polar(3, Math::PI) #=> (-3.0+3.673819061467132e-16i)
690  * Complex.polar(3, -Math::PI/2) #=> (1.836909530733566e-16-3.0i)
691  */
692 static VALUE
693 nucomp_s_polar(int argc, VALUE *argv, VALUE klass)
694 {
695  VALUE abs, arg;
696 
697  argc = rb_scan_args(argc, argv, "11", &abs, &arg);
698  nucomp_real_check(abs);
699  if (argc == 2) {
700  nucomp_real_check(arg);
701  }
702  else {
703  arg = ZERO;
704  }
705  if (RB_TYPE_P(abs, T_COMPLEX)) {
706  get_dat1(abs);
707  abs = dat->real;
708  }
709  if (RB_TYPE_P(arg, T_COMPLEX)) {
710  get_dat1(arg);
711  arg = dat->real;
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
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
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
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
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
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
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
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
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_BIGNUM_TYPE_P(other))
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 RBOOL(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 RBOOL(f_eqeq_p(dat->real, other) && f_zero_p(dat->imag));
1095  }
1096  return RBOOL(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
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
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
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_real_p_m(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 st_index_t
1323 rb_complex_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 v;
1335 }
1336 
1337 static VALUE
1338 nucomp_hash(VALUE self)
1339 {
1340  return ST2FIX(rb_complex_hash(self));
1341 }
1342 
1343 /* :nodoc: */
1344 static VALUE
1345 nucomp_eql_p(VALUE self, VALUE other)
1346 {
1347  if (RB_TYPE_P(other, T_COMPLEX)) {
1348  get_dat2(self, other);
1349 
1350  return RBOOL((CLASS_OF(adat->real) == CLASS_OF(bdat->real)) &&
1351  (CLASS_OF(adat->imag) == CLASS_OF(bdat->imag)) &&
1352  f_eqeq_p(self, other));
1353 
1354  }
1355  return Qfalse;
1356 }
1357 
1358 inline static int
1359 f_signbit(VALUE x)
1360 {
1361  if (RB_FLOAT_TYPE_P(x)) {
1362  double f = RFLOAT_VALUE(x);
1363  return !isnan(f) && signbit(f);
1364  }
1365  return f_negative_p(x);
1366 }
1367 
1368 inline static int
1369 f_tpositive_p(VALUE x)
1370 {
1371  return !f_signbit(x);
1372 }
1373 
1374 static VALUE
1375 f_format(VALUE self, VALUE (*func)(VALUE))
1376 {
1377  VALUE s;
1378  int impos;
1379 
1380  get_dat1(self);
1381 
1382  impos = f_tpositive_p(dat->imag);
1383 
1384  s = (*func)(dat->real);
1385  rb_str_cat2(s, !impos ? "-" : "+");
1386 
1387  rb_str_concat(s, (*func)(f_abs(dat->imag)));
1388  if (!rb_isdigit(RSTRING_PTR(s)[RSTRING_LEN(s) - 1]))
1389  rb_str_cat2(s, "*");
1390  rb_str_cat2(s, "i");
1391 
1392  return s;
1393 }
1394 
1395 /*
1396  * call-seq:
1397  * cmp.to_s -> string
1398  *
1399  * Returns the value as a string.
1400  *
1401  * Complex(2).to_s #=> "2+0i"
1402  * Complex('-8/6').to_s #=> "-4/3+0i"
1403  * Complex('1/2i').to_s #=> "0+1/2i"
1404  * Complex(0, Float::INFINITY).to_s #=> "0+Infinity*i"
1405  * Complex(Float::NAN, Float::NAN).to_s #=> "NaN+NaN*i"
1406  */
1407 static VALUE
1408 nucomp_to_s(VALUE self)
1409 {
1410  return f_format(self, rb_String);
1411 }
1412 
1413 /*
1414  * call-seq:
1415  * cmp.inspect -> string
1416  *
1417  * Returns the value as a string for inspection.
1418  *
1419  * Complex(2).inspect #=> "(2+0i)"
1420  * Complex('-8/6').inspect #=> "((-4/3)+0i)"
1421  * Complex('1/2i').inspect #=> "(0+(1/2)*i)"
1422  * Complex(0, Float::INFINITY).inspect #=> "(0+Infinity*i)"
1423  * Complex(Float::NAN, Float::NAN).inspect #=> "(NaN+NaN*i)"
1424  */
1425 static VALUE
1426 nucomp_inspect(VALUE self)
1427 {
1428  VALUE s;
1429 
1430  s = rb_usascii_str_new2("(");
1431  rb_str_concat(s, f_format(self, rb_inspect));
1432  rb_str_cat2(s, ")");
1433 
1434  return s;
1435 }
1436 
1437 #define FINITE_TYPE_P(v) (RB_INTEGER_TYPE_P(v) || RB_TYPE_P(v, T_RATIONAL))
1438 
1439 /*
1440  * call-seq:
1441  * cmp.finite? -> true or false
1442  *
1443  * Returns +true+ if +cmp+'s real and imaginary parts are both finite numbers,
1444  * otherwise returns +false+.
1445  */
1446 static VALUE
1447 rb_complex_finite_p(VALUE self)
1448 {
1449  get_dat1(self);
1450 
1451  return RBOOL(f_finite_p(dat->real) && f_finite_p(dat->imag));
1452 }
1453 
1454 /*
1455  * call-seq:
1456  * cmp.infinite? -> nil or 1
1457  *
1458  * Returns +1+ if +cmp+'s real or imaginary part is an infinite number,
1459  * otherwise returns +nil+.
1460  *
1461  * For example:
1462  *
1463  * (1+1i).infinite? #=> nil
1464  * (Float::INFINITY + 1i).infinite? #=> 1
1465  */
1466 static VALUE
1467 rb_complex_infinite_p(VALUE self)
1468 {
1469  get_dat1(self);
1470 
1471  if (!f_infinite_p(dat->real) && !f_infinite_p(dat->imag)) {
1472  return Qnil;
1473  }
1474  return ONE;
1475 }
1476 
1477 /* :nodoc: */
1478 static VALUE
1479 nucomp_dumper(VALUE self)
1480 {
1481  return self;
1482 }
1483 
1484 /* :nodoc: */
1485 static VALUE
1486 nucomp_loader(VALUE self, VALUE a)
1487 {
1488  get_dat1(self);
1489 
1490  RCOMPLEX_SET_REAL(dat, rb_ivar_get(a, id_i_real));
1491  RCOMPLEX_SET_IMAG(dat, rb_ivar_get(a, id_i_imag));
1492  OBJ_FREEZE_RAW(self);
1493 
1494  return self;
1495 }
1496 
1497 /* :nodoc: */
1498 static VALUE
1499 nucomp_marshal_dump(VALUE self)
1500 {
1501  VALUE a;
1502  get_dat1(self);
1503 
1504  a = rb_assoc_new(dat->real, dat->imag);
1505  rb_copy_generic_ivar(a, self);
1506  return a;
1507 }
1508 
1509 /* :nodoc: */
1510 static VALUE
1511 nucomp_marshal_load(VALUE self, VALUE a)
1512 {
1513  Check_Type(a, T_ARRAY);
1514  if (RARRAY_LEN(a) != 2)
1515  rb_raise(rb_eArgError, "marshaled complex must have an array whose length is 2 but %ld", RARRAY_LEN(a));
1516  rb_ivar_set(self, id_i_real, RARRAY_AREF(a, 0));
1517  rb_ivar_set(self, id_i_imag, RARRAY_AREF(a, 1));
1518  return self;
1519 }
1520 
1521 VALUE
1523 {
1524  return nucomp_s_new_internal(rb_cComplex, x, y);
1525 }
1526 
1527 VALUE
1529 {
1530  return nucomp_s_canonicalize_internal(rb_cComplex, x, y);
1531 }
1532 
1533 VALUE
1535 {
1536  return f_complex_polar(rb_cComplex, x, y);
1537 }
1538 
1539 VALUE
1541 {
1542  return rb_complex_new_polar(x, y);
1543 }
1544 
1545 VALUE
1547 {
1548  VALUE a[2];
1549  a[0] = x;
1550  a[1] = y;
1551  return nucomp_s_convert(2, a, rb_cComplex);
1552 }
1553 
1554 VALUE
1555 rb_dbl_complex_new(double real, double imag)
1556 {
1557  return rb_complex_raw(DBL2NUM(real), DBL2NUM(imag));
1558 }
1559 
1560 /*
1561  * call-seq:
1562  * cmp.to_i -> integer
1563  *
1564  * Returns the value as an integer if possible (the imaginary part
1565  * should be exactly zero).
1566  *
1567  * Complex(1, 0).to_i #=> 1
1568  * Complex(1, 0.0).to_i # RangeError
1569  * Complex(1, 2).to_i # RangeError
1570  */
1571 static VALUE
1572 nucomp_to_i(VALUE self)
1573 {
1574  get_dat1(self);
1575 
1576  if (!k_exact_zero_p(dat->imag)) {
1577  rb_raise(rb_eRangeError, "can't convert %"PRIsVALUE" into Integer",
1578  self);
1579  }
1580  return f_to_i(dat->real);
1581 }
1582 
1583 /*
1584  * call-seq:
1585  * cmp.to_f -> float
1586  *
1587  * Returns the value as a float if possible (the imaginary part should
1588  * be exactly zero).
1589  *
1590  * Complex(1, 0).to_f #=> 1.0
1591  * Complex(1, 0.0).to_f # RangeError
1592  * Complex(1, 2).to_f # RangeError
1593  */
1594 static VALUE
1595 nucomp_to_f(VALUE self)
1596 {
1597  get_dat1(self);
1598 
1599  if (!k_exact_zero_p(dat->imag)) {
1600  rb_raise(rb_eRangeError, "can't convert %"PRIsVALUE" into Float",
1601  self);
1602  }
1603  return f_to_f(dat->real);
1604 }
1605 
1606 /*
1607  * call-seq:
1608  * cmp.to_r -> rational
1609  *
1610  * Returns the value as a rational if possible (the imaginary part
1611  * should be exactly zero).
1612  *
1613  * Complex(1, 0).to_r #=> (1/1)
1614  * Complex(1, 0.0).to_r # RangeError
1615  * Complex(1, 2).to_r # RangeError
1616  *
1617  * See rationalize.
1618  */
1619 static VALUE
1620 nucomp_to_r(VALUE self)
1621 {
1622  get_dat1(self);
1623 
1624  if (!k_exact_zero_p(dat->imag)) {
1625  rb_raise(rb_eRangeError, "can't convert %"PRIsVALUE" into Rational",
1626  self);
1627  }
1628  return f_to_r(dat->real);
1629 }
1630 
1631 /*
1632  * call-seq:
1633  * cmp.rationalize([eps]) -> rational
1634  *
1635  * Returns the value as a rational if possible (the imaginary part
1636  * should be exactly zero).
1637  *
1638  * Complex(1.0/3, 0).rationalize #=> (1/3)
1639  * Complex(1, 0.0).rationalize # RangeError
1640  * Complex(1, 2).rationalize # RangeError
1641  *
1642  * See to_r.
1643  */
1644 static VALUE
1645 nucomp_rationalize(int argc, VALUE *argv, VALUE self)
1646 {
1647  get_dat1(self);
1648 
1649  rb_check_arity(argc, 0, 1);
1650 
1651  if (!k_exact_zero_p(dat->imag)) {
1652  rb_raise(rb_eRangeError, "can't convert %"PRIsVALUE" into Rational",
1653  self);
1654  }
1655  return rb_funcallv(dat->real, id_rationalize, argc, argv);
1656 }
1657 
1658 /*
1659  * call-seq:
1660  * complex.to_c -> self
1661  *
1662  * Returns self.
1663  *
1664  * Complex(2).to_c #=> (2+0i)
1665  * Complex(-8, 6).to_c #=> (-8+6i)
1666  */
1667 static VALUE
1668 nucomp_to_c(VALUE self)
1669 {
1670  return self;
1671 }
1672 
1673 /*
1674  * call-seq:
1675  * nil.to_c -> (0+0i)
1676  *
1677  * Returns zero as a complex.
1678  */
1679 static VALUE
1680 nilclass_to_c(VALUE self)
1681 {
1682  return rb_complex_new1(INT2FIX(0));
1683 }
1684 
1685 /*
1686  * call-seq:
1687  * num.to_c -> complex
1688  *
1689  * Returns the value as a complex.
1690  */
1691 static VALUE
1692 numeric_to_c(VALUE self)
1693 {
1694  return rb_complex_new1(self);
1695 }
1696 
1697 inline static int
1698 issign(int c)
1699 {
1700  return (c == '-' || c == '+');
1701 }
1702 
1703 static int
1704 read_sign(const char **s,
1705  char **b)
1706 {
1707  int sign = '?';
1708 
1709  if (issign(**s)) {
1710  sign = **b = **s;
1711  (*s)++;
1712  (*b)++;
1713  }
1714  return sign;
1715 }
1716 
1717 inline static int
1718 isdecimal(int c)
1719 {
1720  return isdigit((unsigned char)c);
1721 }
1722 
1723 static int
1724 read_digits(const char **s, int strict,
1725  char **b)
1726 {
1727  int us = 1;
1728 
1729  if (!isdecimal(**s))
1730  return 0;
1731 
1732  while (isdecimal(**s) || **s == '_') {
1733  if (**s == '_') {
1734  if (strict) {
1735  if (us)
1736  return 0;
1737  }
1738  us = 1;
1739  }
1740  else {
1741  **b = **s;
1742  (*b)++;
1743  us = 0;
1744  }
1745  (*s)++;
1746  }
1747  if (us)
1748  do {
1749  (*s)--;
1750  } while (**s == '_');
1751  return 1;
1752 }
1753 
1754 inline static int
1755 islettere(int c)
1756 {
1757  return (c == 'e' || c == 'E');
1758 }
1759 
1760 static int
1761 read_num(const char **s, int strict,
1762  char **b)
1763 {
1764  if (**s != '.') {
1765  if (!read_digits(s, strict, b))
1766  return 0;
1767  }
1768 
1769  if (**s == '.') {
1770  **b = **s;
1771  (*s)++;
1772  (*b)++;
1773  if (!read_digits(s, strict, b)) {
1774  (*b)--;
1775  return 0;
1776  }
1777  }
1778 
1779  if (islettere(**s)) {
1780  **b = **s;
1781  (*s)++;
1782  (*b)++;
1783  read_sign(s, b);
1784  if (!read_digits(s, strict, b)) {
1785  (*b)--;
1786  return 0;
1787  }
1788  }
1789  return 1;
1790 }
1791 
1792 inline static int
1793 read_den(const char **s, int strict,
1794  char **b)
1795 {
1796  if (!read_digits(s, strict, b))
1797  return 0;
1798  return 1;
1799 }
1800 
1801 static int
1802 read_rat_nos(const char **s, int strict,
1803  char **b)
1804 {
1805  if (!read_num(s, strict, b))
1806  return 0;
1807  if (**s == '/') {
1808  **b = **s;
1809  (*s)++;
1810  (*b)++;
1811  if (!read_den(s, strict, b)) {
1812  (*b)--;
1813  return 0;
1814  }
1815  }
1816  return 1;
1817 }
1818 
1819 static int
1820 read_rat(const char **s, int strict,
1821  char **b)
1822 {
1823  read_sign(s, b);
1824  if (!read_rat_nos(s, strict, b))
1825  return 0;
1826  return 1;
1827 }
1828 
1829 inline static int
1830 isimagunit(int c)
1831 {
1832  return (c == 'i' || c == 'I' ||
1833  c == 'j' || c == 'J');
1834 }
1835 
1836 static VALUE
1837 str2num(char *s)
1838 {
1839  if (strchr(s, '/'))
1840  return rb_cstr_to_rat(s, 0);
1841  if (strpbrk(s, ".eE"))
1842  return DBL2NUM(rb_cstr_to_dbl(s, 0));
1843  return rb_cstr_to_inum(s, 10, 0);
1844 }
1845 
1846 static int
1847 read_comp(const char **s, int strict,
1848  VALUE *ret, char **b)
1849 {
1850  char *bb;
1851  int sign;
1852  VALUE num, num2;
1853 
1854  bb = *b;
1855 
1856  sign = read_sign(s, b);
1857 
1858  if (isimagunit(**s)) {
1859  (*s)++;
1860  num = INT2FIX((sign == '-') ? -1 : + 1);
1861  *ret = rb_complex_new2(ZERO, num);
1862  return 1; /* e.g. "i" */
1863  }
1864 
1865  if (!read_rat_nos(s, strict, b)) {
1866  **b = '\0';
1867  num = str2num(bb);
1868  *ret = rb_complex_new2(num, ZERO);
1869  return 0; /* e.g. "-" */
1870  }
1871  **b = '\0';
1872  num = str2num(bb);
1873 
1874  if (isimagunit(**s)) {
1875  (*s)++;
1876  *ret = rb_complex_new2(ZERO, num);
1877  return 1; /* e.g. "3i" */
1878  }
1879 
1880  if (**s == '@') {
1881  int st;
1882 
1883  (*s)++;
1884  bb = *b;
1885  st = read_rat(s, strict, b);
1886  **b = '\0';
1887  if (strlen(bb) < 1 ||
1888  !isdecimal(*(bb + strlen(bb) - 1))) {
1889  *ret = rb_complex_new2(num, ZERO);
1890  return 0; /* e.g. "1@-" */
1891  }
1892  num2 = str2num(bb);
1893  *ret = rb_complex_new_polar(num, num2);
1894  if (!st)
1895  return 0; /* e.g. "1@2." */
1896  else
1897  return 1; /* e.g. "1@2" */
1898  }
1899 
1900  if (issign(**s)) {
1901  bb = *b;
1902  sign = read_sign(s, b);
1903  if (isimagunit(**s))
1904  num2 = INT2FIX((sign == '-') ? -1 : + 1);
1905  else {
1906  if (!read_rat_nos(s, strict, b)) {
1907  *ret = rb_complex_new2(num, ZERO);
1908  return 0; /* e.g. "1+xi" */
1909  }
1910  **b = '\0';
1911  num2 = str2num(bb);
1912  }
1913  if (!isimagunit(**s)) {
1914  *ret = rb_complex_new2(num, ZERO);
1915  return 0; /* e.g. "1+3x" */
1916  }
1917  (*s)++;
1918  *ret = rb_complex_new2(num, num2);
1919  return 1; /* e.g. "1+2i" */
1920  }
1921  /* !(@, - or +) */
1922  {
1923  *ret = rb_complex_new2(num, ZERO);
1924  return 1; /* e.g. "3" */
1925  }
1926 }
1927 
1928 inline static void
1929 skip_ws(const char **s)
1930 {
1931  while (isspace((unsigned char)**s))
1932  (*s)++;
1933 }
1934 
1935 static int
1936 parse_comp(const char *s, int strict, VALUE *num)
1937 {
1938  char *buf, *b;
1939  VALUE tmp;
1940  int ret = 1;
1941 
1942  buf = ALLOCV_N(char, tmp, strlen(s) + 1);
1943  b = buf;
1944 
1945  skip_ws(&s);
1946  if (!read_comp(&s, strict, num, &b)) {
1947  ret = 0;
1948  }
1949  else {
1950  skip_ws(&s);
1951 
1952  if (strict)
1953  if (*s != '\0')
1954  ret = 0;
1955  }
1956  ALLOCV_END(tmp);
1957 
1958  return ret;
1959 }
1960 
1961 static VALUE
1962 string_to_c_strict(VALUE self, int raise)
1963 {
1964  char *s;
1965  VALUE num;
1966 
1967  rb_must_asciicompat(self);
1968 
1969  s = RSTRING_PTR(self);
1970 
1971  if (!s || memchr(s, '\0', RSTRING_LEN(self))) {
1972  if (!raise) return Qnil;
1973  rb_raise(rb_eArgError, "string contains null byte");
1974  }
1975 
1976  if (s && s[RSTRING_LEN(self)]) {
1977  rb_str_modify(self);
1978  s = RSTRING_PTR(self);
1979  s[RSTRING_LEN(self)] = '\0';
1980  }
1981 
1982  if (!s)
1983  s = (char *)"";
1984 
1985  if (!parse_comp(s, 1, &num)) {
1986  if (!raise) return Qnil;
1987  rb_raise(rb_eArgError, "invalid value for convert(): %+"PRIsVALUE,
1988  self);
1989  }
1990 
1991  return num;
1992 }
1993 
1994 /*
1995  * call-seq:
1996  * str.to_c -> complex
1997  *
1998  * Returns a complex which denotes the string form. The parser
1999  * ignores leading whitespaces and trailing garbage. Any digit
2000  * sequences can be separated by an underscore. Returns zero for null
2001  * or garbage string.
2002  *
2003  * '9'.to_c #=> (9+0i)
2004  * '2.5'.to_c #=> (2.5+0i)
2005  * '2.5/1'.to_c #=> ((5/2)+0i)
2006  * '-3/2'.to_c #=> ((-3/2)+0i)
2007  * '-i'.to_c #=> (0-1i)
2008  * '45i'.to_c #=> (0+45i)
2009  * '3-4i'.to_c #=> (3-4i)
2010  * '-4e2-4e-2i'.to_c #=> (-400.0-0.04i)
2011  * '-0.0-0.0i'.to_c #=> (-0.0-0.0i)
2012  * '1/2+3/4i'.to_c #=> ((1/2)+(3/4)*i)
2013  * 'ruby'.to_c #=> (0+0i)
2014  *
2015  * See Kernel.Complex.
2016  */
2017 static VALUE
2018 string_to_c(VALUE self)
2019 {
2020  char *s;
2021  VALUE num;
2022 
2023  rb_must_asciicompat(self);
2024 
2025  s = RSTRING_PTR(self);
2026 
2027  if (s && s[RSTRING_LEN(self)]) {
2028  rb_str_modify(self);
2029  s = RSTRING_PTR(self);
2030  s[RSTRING_LEN(self)] = '\0';
2031  }
2032 
2033  if (!s)
2034  s = (char *)"";
2035 
2036  (void)parse_comp(s, 0, &num);
2037 
2038  return num;
2039 }
2040 
2041 static VALUE
2042 to_complex(VALUE val)
2043 {
2044  return rb_convert_type(val, T_COMPLEX, "Complex", "to_c");
2045 }
2046 
2047 static VALUE
2048 nucomp_convert(VALUE klass, VALUE a1, VALUE a2, int raise)
2049 {
2050  if (NIL_P(a1) || NIL_P(a2)) {
2051  if (!raise) return Qnil;
2052  rb_raise(rb_eTypeError, "can't convert nil into Complex");
2053  }
2054 
2055  if (RB_TYPE_P(a1, T_STRING)) {
2056  a1 = string_to_c_strict(a1, raise);
2057  if (NIL_P(a1)) return Qnil;
2058  }
2059 
2060  if (RB_TYPE_P(a2, T_STRING)) {
2061  a2 = string_to_c_strict(a2, raise);
2062  if (NIL_P(a2)) return Qnil;
2063  }
2064 
2065  if (RB_TYPE_P(a1, T_COMPLEX)) {
2066  {
2067  get_dat1(a1);
2068 
2069  if (k_exact_zero_p(dat->imag))
2070  a1 = dat->real;
2071  }
2072  }
2073 
2074  if (RB_TYPE_P(a2, T_COMPLEX)) {
2075  {
2076  get_dat1(a2);
2077 
2078  if (k_exact_zero_p(dat->imag))
2079  a2 = dat->real;
2080  }
2081  }
2082 
2083  if (RB_TYPE_P(a1, T_COMPLEX)) {
2084  if (a2 == Qundef || (k_exact_zero_p(a2)))
2085  return a1;
2086  }
2087 
2088  if (a2 == Qundef) {
2089  if (k_numeric_p(a1) && !f_real_p(a1))
2090  return a1;
2091  /* should raise exception for consistency */
2092  if (!k_numeric_p(a1)) {
2093  if (!raise)
2094  return rb_protect(to_complex, a1, NULL);
2095  return to_complex(a1);
2096  }
2097  }
2098  else {
2099  if ((k_numeric_p(a1) && k_numeric_p(a2)) &&
2100  (!f_real_p(a1) || !f_real_p(a2)))
2101  return f_add(a1,
2102  f_mul(a2,
2103  f_complex_new_bang2(rb_cComplex, ZERO, ONE)));
2104  }
2105 
2106  {
2107  int argc;
2108  VALUE argv2[2];
2109  argv2[0] = a1;
2110  if (a2 == Qundef) {
2111  argv2[1] = Qnil;
2112  argc = 1;
2113  }
2114  else {
2115  if (!raise && !RB_INTEGER_TYPE_P(a2) && !RB_FLOAT_TYPE_P(a2) && !RB_TYPE_P(a2, T_RATIONAL))
2116  return Qnil;
2117  argv2[1] = a2;
2118  argc = 2;
2119  }
2120  return nucomp_s_new(argc, argv2, klass);
2121  }
2122 }
2123 
2124 static VALUE
2125 nucomp_s_convert(int argc, VALUE *argv, VALUE klass)
2126 {
2127  VALUE a1, a2;
2128 
2129  if (rb_scan_args(argc, argv, "11", &a1, &a2) == 1) {
2130  a2 = Qundef;
2131  }
2132 
2133  return nucomp_convert(klass, a1, a2, TRUE);
2134 }
2135 
2136 /*
2137  * call-seq:
2138  * num.real -> self
2139  *
2140  * Returns self.
2141  */
2142 static VALUE
2143 numeric_real(VALUE self)
2144 {
2145  return self;
2146 }
2147 
2148 /*
2149  * call-seq:
2150  * num.imag -> 0
2151  * num.imaginary -> 0
2152  *
2153  * Returns zero.
2154  */
2155 static VALUE
2156 numeric_imag(VALUE self)
2157 {
2158  return INT2FIX(0);
2159 }
2160 
2161 /*
2162  * call-seq:
2163  * num.abs2 -> real
2164  *
2165  * Returns square of self.
2166  */
2167 static VALUE
2168 numeric_abs2(VALUE self)
2169 {
2170  return f_mul(self, self);
2171 }
2172 
2173 /*
2174  * call-seq:
2175  * num.arg -> 0 or float
2176  * num.angle -> 0 or float
2177  * num.phase -> 0 or float
2178  *
2179  * Returns 0 if the value is positive, pi otherwise.
2180  */
2181 static VALUE
2182 numeric_arg(VALUE self)
2183 {
2184  if (f_positive_p(self))
2185  return INT2FIX(0);
2186  return DBL2NUM(M_PI);
2187 }
2188 
2189 /*
2190  * call-seq:
2191  * num.rect -> array
2192  * num.rectangular -> array
2193  *
2194  * Returns an array; [num, 0].
2195  */
2196 static VALUE
2197 numeric_rect(VALUE self)
2198 {
2199  return rb_assoc_new(self, INT2FIX(0));
2200 }
2201 
2202 /*
2203  * call-seq:
2204  * num.polar -> array
2205  *
2206  * Returns an array; [num.abs, num.arg].
2207  */
2208 static VALUE
2209 numeric_polar(VALUE self)
2210 {
2211  VALUE abs, arg;
2212 
2213  if (RB_INTEGER_TYPE_P(self)) {
2214  abs = rb_int_abs(self);
2215  arg = numeric_arg(self);
2216  }
2217  else if (RB_FLOAT_TYPE_P(self)) {
2218  abs = rb_float_abs(self);
2219  arg = float_arg(self);
2220  }
2221  else if (RB_TYPE_P(self, T_RATIONAL)) {
2222  abs = rb_rational_abs(self);
2223  arg = numeric_arg(self);
2224  }
2225  else {
2226  abs = f_abs(self);
2227  arg = f_arg(self);
2228  }
2229  return rb_assoc_new(abs, arg);
2230 }
2231 
2232 /*
2233  * call-seq:
2234  * num.conj -> self
2235  * num.conjugate -> self
2236  *
2237  * Returns self.
2238  */
2239 static VALUE
2240 numeric_conj(VALUE self)
2241 {
2242  return self;
2243 }
2244 
2245 /*
2246  * call-seq:
2247  * flo.arg -> 0 or float
2248  * flo.angle -> 0 or float
2249  * flo.phase -> 0 or float
2250  *
2251  * Returns 0 if the value is positive, pi otherwise.
2252  */
2253 static VALUE
2254 float_arg(VALUE self)
2255 {
2256  if (isnan(RFLOAT_VALUE(self)))
2257  return self;
2258  if (f_tpositive_p(self))
2259  return INT2FIX(0);
2260  return rb_const_get(rb_mMath, id_PI);
2261 }
2262 
2263 /*
2264  * A complex number can be represented as a paired real number with
2265  * imaginary unit; a+bi. Where a is real part, b is imaginary part
2266  * and i is imaginary unit. Real a equals complex a+0i
2267  * mathematically.
2268  *
2269  * You can create a \Complex object explicitly with:
2270  *
2271  * - A {complex literal}[doc/syntax/literals_rdoc.html#label-Complex+Literals].
2272  *
2273  * You can convert certain objects to \Complex objects with:
2274  *
2275  * - \Method {Complex}[Kernel.html#method-i-Complex].
2276  *
2277  * Complex object can be created as literal, and also by using
2278  * Kernel#Complex, Complex::rect, Complex::polar or to_c method.
2279  *
2280  * 2+1i #=> (2+1i)
2281  * Complex(1) #=> (1+0i)
2282  * Complex(2, 3) #=> (2+3i)
2283  * Complex.polar(2, 3) #=> (-1.9799849932008908+0.2822400161197344i)
2284  * 3.to_c #=> (3+0i)
2285  *
2286  * You can also create complex object from floating-point numbers or
2287  * strings.
2288  *
2289  * Complex(0.3) #=> (0.3+0i)
2290  * Complex('0.3-0.5i') #=> (0.3-0.5i)
2291  * Complex('2/3+3/4i') #=> ((2/3)+(3/4)*i)
2292  * Complex('1@2') #=> (-0.4161468365471424+0.9092974268256817i)
2293  *
2294  * 0.3.to_c #=> (0.3+0i)
2295  * '0.3-0.5i'.to_c #=> (0.3-0.5i)
2296  * '2/3+3/4i'.to_c #=> ((2/3)+(3/4)*i)
2297  * '1@2'.to_c #=> (-0.4161468365471424+0.9092974268256817i)
2298  *
2299  * A complex object is either an exact or an inexact number.
2300  *
2301  * Complex(1, 1) / 2 #=> ((1/2)+(1/2)*i)
2302  * Complex(1, 1) / 2.0 #=> (0.5+0.5i)
2303  */
2304 void
2305 Init_Complex(void)
2306 {
2307  VALUE compat;
2308  id_abs = rb_intern_const("abs");
2309  id_arg = rb_intern_const("arg");
2310  id_denominator = rb_intern_const("denominator");
2311  id_numerator = rb_intern_const("numerator");
2312  id_real_p = rb_intern_const("real?");
2313  id_i_real = rb_intern_const("@real");
2314  id_i_imag = rb_intern_const("@image"); /* @image, not @imag */
2315  id_finite_p = rb_intern_const("finite?");
2316  id_infinite_p = rb_intern_const("infinite?");
2317  id_rationalize = rb_intern_const("rationalize");
2318  id_PI = rb_intern_const("PI");
2319 
2320  rb_cComplex = rb_define_class("Complex", rb_cNumeric);
2321 
2322  rb_define_alloc_func(rb_cComplex, nucomp_s_alloc);
2323  rb_undef_method(CLASS_OF(rb_cComplex), "allocate");
2324 
2326 
2327  rb_define_singleton_method(rb_cComplex, "rectangular", nucomp_s_new, -1);
2328  rb_define_singleton_method(rb_cComplex, "rect", nucomp_s_new, -1);
2329  rb_define_singleton_method(rb_cComplex, "polar", nucomp_s_polar, -1);
2330 
2331  rb_define_global_function("Complex", nucomp_f_complex, -1);
2332 
2333  rb_undef_methods_from(rb_cComplex, RCLASS_ORIGIN(rb_mComparable));
2335  rb_undef_method(rb_cComplex, "div");
2336  rb_undef_method(rb_cComplex, "divmod");
2337  rb_undef_method(rb_cComplex, "floor");
2338  rb_undef_method(rb_cComplex, "ceil");
2339  rb_undef_method(rb_cComplex, "modulo");
2340  rb_undef_method(rb_cComplex, "remainder");
2341  rb_undef_method(rb_cComplex, "round");
2342  rb_undef_method(rb_cComplex, "step");
2343  rb_undef_method(rb_cComplex, "truncate");
2345 
2347  rb_define_method(rb_cComplex, "imaginary", rb_complex_imag, 0);
2349 
2355  rb_define_method(rb_cComplex, "quo", nucomp_quo, 1);
2356  rb_define_method(rb_cComplex, "fdiv", nucomp_fdiv, 1);
2358 
2359  rb_define_method(rb_cComplex, "==", nucomp_eqeq_p, 1);
2360  rb_define_method(rb_cComplex, "<=>", nucomp_cmp, 1);
2361  rb_define_method(rb_cComplex, "coerce", nucomp_coerce, 1);
2362 
2364  rb_define_method(rb_cComplex, "magnitude", rb_complex_abs, 0);
2365  rb_define_method(rb_cComplex, "abs2", nucomp_abs2, 0);
2369  rb_define_method(rb_cComplex, "rectangular", nucomp_rect, 0);
2370  rb_define_method(rb_cComplex, "rect", nucomp_rect, 0);
2371  rb_define_method(rb_cComplex, "polar", nucomp_polar, 0);
2374 
2375  rb_define_method(rb_cComplex, "real?", nucomp_real_p_m, 0);
2376 
2377  rb_define_method(rb_cComplex, "numerator", nucomp_numerator, 0);
2378  rb_define_method(rb_cComplex, "denominator", nucomp_denominator, 0);
2379 
2380  rb_define_method(rb_cComplex, "hash", nucomp_hash, 0);
2381  rb_define_method(rb_cComplex, "eql?", nucomp_eql_p, 1);
2382 
2383  rb_define_method(rb_cComplex, "to_s", nucomp_to_s, 0);
2384  rb_define_method(rb_cComplex, "inspect", nucomp_inspect, 0);
2385 
2386  rb_undef_method(rb_cComplex, "positive?");
2387  rb_undef_method(rb_cComplex, "negative?");
2388 
2389  rb_define_method(rb_cComplex, "finite?", rb_complex_finite_p, 0);
2390  rb_define_method(rb_cComplex, "infinite?", rb_complex_infinite_p, 0);
2391 
2392  rb_define_private_method(rb_cComplex, "marshal_dump", nucomp_marshal_dump, 0);
2393  /* :nodoc: */
2394  compat = rb_define_class_under(rb_cComplex, "compatible", rb_cObject);
2395  rb_define_private_method(compat, "marshal_load", nucomp_marshal_load, 1);
2396  rb_marshal_define_compat(rb_cComplex, compat, nucomp_dumper, nucomp_loader);
2397 
2398  rb_define_method(rb_cComplex, "to_i", nucomp_to_i, 0);
2399  rb_define_method(rb_cComplex, "to_f", nucomp_to_f, 0);
2400  rb_define_method(rb_cComplex, "to_r", nucomp_to_r, 0);
2401  rb_define_method(rb_cComplex, "rationalize", nucomp_rationalize, -1);
2402  rb_define_method(rb_cComplex, "to_c", nucomp_to_c, 0);
2403  rb_define_method(rb_cNilClass, "to_c", nilclass_to_c, 0);
2404  rb_define_method(rb_cNumeric, "to_c", numeric_to_c, 0);
2405 
2406  rb_define_method(rb_cString, "to_c", string_to_c, 0);
2407 
2408  rb_define_private_method(CLASS_OF(rb_cComplex), "convert", nucomp_s_convert, -1);
2409 
2410  rb_define_method(rb_cNumeric, "real", numeric_real, 0);
2411  rb_define_method(rb_cNumeric, "imaginary", numeric_imag, 0);
2412  rb_define_method(rb_cNumeric, "imag", numeric_imag, 0);
2413  rb_define_method(rb_cNumeric, "abs2", numeric_abs2, 0);
2414  rb_define_method(rb_cNumeric, "arg", numeric_arg, 0);
2415  rb_define_method(rb_cNumeric, "angle", numeric_arg, 0);
2416  rb_define_method(rb_cNumeric, "phase", numeric_arg, 0);
2417  rb_define_method(rb_cNumeric, "rectangular", numeric_rect, 0);
2418  rb_define_method(rb_cNumeric, "rect", numeric_rect, 0);
2419  rb_define_method(rb_cNumeric, "polar", numeric_polar, 0);
2420  rb_define_method(rb_cNumeric, "conjugate", numeric_conj, 0);
2421  rb_define_method(rb_cNumeric, "conj", numeric_conj, 0);
2422 
2423  rb_define_method(rb_cFloat, "arg", float_arg, 0);
2424  rb_define_method(rb_cFloat, "angle", float_arg, 0);
2425  rb_define_method(rb_cFloat, "phase", float_arg, 0);
2426 
2427  /*
2428  * The imaginary unit.
2429  */
2431  f_complex_new_bang2(rb_cComplex, ZERO, ONE));
2432 
2433 #if !USE_FLONUM
2434  rb_gc_register_mark_object(RFLOAT_0 = DBL2NUM(0.0));
2435 #endif
2436 
2437  rb_provide("complex.so"); /* for backward compatibility */
2438 }
static int rb_isdigit(int c)
Our own locale-insensitive version of isdigit(3).
Definition: ctype.h:302
#define rb_define_singleton_method(klass, mid, func, arity)
Defines klass.mid.
Definition: cxxanyargs.hpp:685
#define rb_define_private_method(klass, mid, func, arity)
Defines klass#mid and makes it private.
Definition: cxxanyargs.hpp:677
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:837
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:869
void rb_undef_method(VALUE klass, const char *name)
Defines an undef of a method.
Definition: class.c:1938
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Retrieves argument from argc and argv to given VALUE references according to the format string.
Definition: class.c:2406
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a method.
Definition: class.c:1914
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
Definition: class.c:2110
#define T_COMPLEX
Old name of RUBY_T_COMPLEX.
Definition: value_type.h:59
#define NEWOBJ_OF
Old name of RB_NEWOBJ_OF.
Definition: newobj.h:61
#define RB_INTEGER_TYPE_P
Old name of rb_integer_type_p.
Definition: value_type.h:87
#define RFLOAT_VALUE
Old name of rb_float_value.
Definition: double.h:28
#define T_STRING
Old name of RUBY_T_STRING.
Definition: value_type.h:78
#define Qundef
Old name of RUBY_Qundef.
#define INT2FIX
Old name of RB_INT2FIX.
Definition: long.h:48
#define OBJ_FREEZE_RAW
Old name of RB_OBJ_FREEZE_RAW.
Definition: fl_type.h:144
#define CLASS_OF
Old name of rb_class_of.
Definition: globals.h:203
#define LONG2FIX
Old name of RB_INT2FIX.
Definition: long.h:49
#define T_RATIONAL
Old name of RUBY_T_RATIONAL.
Definition: value_type.h:76
#define NUM2DBL
Old name of rb_num2dbl.
Definition: double.h:27
VALUE rb_complex_polar(VALUE x, VALUE y)
Old name of rb_complex_new_polar.
Definition: complex.c:1540
#define rb_usascii_str_new2
Old name of rb_usascii_str_new_cstr.
Definition: string.h:1744
#define FLONUM_P
Old name of RB_FLONUM_P.
#define ST2FIX
Old name of RB_ST2FIX.
Definition: st_data_t.h:33
#define Qnil
Old name of RUBY_Qnil.
#define Qfalse
Old name of RUBY_Qfalse.
#define FIX2LONG
Old name of RB_FIX2LONG.
Definition: long.h:46
#define T_ARRAY
Old name of RUBY_T_ARRAY.
Definition: value_type.h:56
#define NIL_P
Old name of RB_NIL_P.
#define ALLOCV_N
Old name of RB_ALLOCV_N.
Definition: memory.h:399
#define FL_WB_PROTECTED
Old name of RUBY_FL_WB_PROTECTED.
Definition: fl_type.h:59
#define DBL2NUM
Old name of rb_float_new.
Definition: double.h:29
#define NUM2LONG
Old name of RB_NUM2LONG.
Definition: long.h:51
#define FIXNUM_P
Old name of RB_FIXNUM_P.
#define ALLOCV_END
Old name of RB_ALLOCV_END.
Definition: memory.h:400
void rb_raise(VALUE exc, const char *fmt,...)
Exception entry point.
Definition: error.c:3025
VALUE rb_eRangeError
RangeError exception.
Definition: error.c:1103
VALUE rb_eTypeError
TypeError exception.
Definition: error.c:1099
void rb_warn(const char *fmt,...)
Identical to rb_warning(), except it reports always regardless of runtime -W flag.
Definition: error.c:418
VALUE rb_eArgError
ArgumentError exception.
Definition: error.c:1100
VALUE rb_cRational
Rational class.
Definition: rational.c:41
VALUE rb_convert_type(VALUE val, int type, const char *name, const char *mid)
Converts an object into another type.
Definition: object.c:2906
VALUE rb_cComplex
Complex class.
Definition: complex.c:38
VALUE rb_mMath
Math module.
Definition: math.c:29
VALUE rb_cInteger
Module class.
Definition: numeric.c:192
VALUE rb_cNilClass
NilClass class.
Definition: object.c:55
double rb_str_to_dbl(VALUE str, int mode)
Identical to rb_cstr_to_dbl(), except it accepts a Ruby's string instead of C's.
Definition: object.c:3325
VALUE rb_cNumeric
Numeric class.
Definition: numeric.c:190
VALUE rb_obj_class(VALUE obj)
Queries the class of an object.
Definition: object.c:188
VALUE rb_inspect(VALUE obj)
Generates a human-readable textual representation of the given object.
Definition: object.c:564
VALUE rb_equal(VALUE lhs, VALUE rhs)
This function is an optimised version of calling #==.
Definition: object.c:120
VALUE rb_obj_is_kind_of(VALUE obj, VALUE klass)
Queries if the given object is an instance (of possibly descendants) of the given class.
Definition: object.c:731
double rb_cstr_to_dbl(const char *str, int mode)
Converts a textual representation of a real number into a numeric, which is the nearest value that th...
Definition: object.c:3284
VALUE rb_mComparable
Comparable module.
Definition: compar.c:19
VALUE rb_cFloat
Float class.
Definition: numeric.c:191
VALUE rb_String(VALUE val)
This is the logic behind Kernel#String.
Definition: object.c:3564
VALUE rb_cString
String class.
Definition: string.c:80
VALUE rb_funcall(VALUE recv, ID mid, int n,...)
Calls a method.
Definition: vm_eval.c:1102
VALUE rb_funcallv(VALUE recv, ID mid, int argc, const VALUE *argv)
Identical to rb_funcall(), except it takes the method arguments as a C array.
Definition: vm_eval.c:1061
void rb_gc_register_mark_object(VALUE object)
Inform the garbage collector that object is a live Ruby object that should not be moved.
Definition: gc.c:8687
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Identical to rb_ary_new_from_values(), except it expects exactly two parameters.
Definition: array.c:976
VALUE rb_str_to_inum(VALUE str, int base, int badcheck)
Identical to rb_cstr2inum(), except it takes Ruby's strings instead of C's.
Definition: bignum.c:4280
VALUE rb_cstr_to_inum(const char *str, int base, int badcheck)
Parses C's string to convert into a Ruby's integer.
Definition: bignum.c:4022
int rb_cmpint(VALUE val, VALUE a, VALUE b)
Canonicalises the passed val, which is the return value of a <=> b, into C's {-1, 0,...
Definition: bignum.c:2935
VALUE rb_complex_uminus(VALUE z)
Performs negation of the passed object.
Definition: complex.c:758
VALUE rb_complex_div(VALUE x, VALUE y)
Performs division of the passed two objects.
Definition: complex.c:948
VALUE rb_complex_new(VALUE real, VALUE imag)
Constructs a Complex, by first multiplying the imaginary part with 1i then adds it to the real part.
Definition: complex.c:1528
VALUE rb_complex_plus(VALUE x, VALUE y)
Performs addition of the passed two objects.
Definition: complex.c:778
VALUE rb_complex_new_polar(VALUE abs, VALUE arg)
Constructs a Complex using polar representations.
Definition: complex.c:1534
VALUE rb_complex_arg(VALUE z)
Queries the argument (or the angle) of the passed object.
Definition: complex.c:1208
#define rb_complex_new2(x, y)
Just another name of rb_complex_new.
Definition: complex.h:77
VALUE rb_complex_raw(VALUE real, VALUE imag)
Identical to rb_complex_new(), except it assumes both arguments are not instances of rb_cComplex.
Definition: complex.c:1522
VALUE rb_dbl_complex_new(double real, double imag)
Identical to rb_complex_new(), except it takes the arguments as C's double instead of Ruby's object.
Definition: complex.c:1555
VALUE rb_complex_abs(VALUE z)
Queries the absolute (or the magnitude) of the passed object.
Definition: complex.c:1161
VALUE rb_complex_real(VALUE z)
Queries the real part of the passed Complex.
Definition: complex.c:726
VALUE rb_complex_mul(VALUE x, VALUE y)
Performs multiplication of the passed two objects.
Definition: complex.c:872
VALUE rb_complex_conjugate(VALUE z)
Performs complex conjugation of the passed object.
Definition: complex.c:1254
VALUE rb_Complex(VALUE real, VALUE imag)
Converts various values into a Complex.
Definition: complex.c:1546
VALUE rb_complex_minus(VALUE x, VALUE y)
Performs subtraction of the passed two objects.
Definition: complex.c:812
#define rb_complex_new1(x)
Shorthand of x+0i.
Definition: complex.h:74
VALUE rb_complex_pow(VALUE base, VALUE exp)
Performs exponentiation of the passed two objects.
Definition: complex.c:985
VALUE rb_complex_imag(VALUE z)
Queries the imaginary part of the passed Complex.
Definition: complex.c:743
static int rb_check_arity(int argc, int min, int max)
Ensures that the passed integer is in the passed range.
Definition: error.h:294
VALUE rb_hash(VALUE obj)
Calculates a message authentication code of the passed object.
Definition: hash.c:227
void rb_provide(const char *feature)
Declares that the given feature is already provided by someone else.
Definition: load.c:638
VALUE rb_num_coerce_bin(VALUE lhs, VALUE rhs, ID op)
Coerced binary operation.
Definition: numeric.c:471
VALUE rb_protect(VALUE(*func)(VALUE args), VALUE args, int *state)
Protects a function call from potential global escapes from the function.
st_index_t rb_memhash(const void *ptr, long len)
This is a universal hash function.
Definition: random.c:1720
VALUE rb_str_cat2(VALUE, const char *)
Just another name of rb_str_cat_cstr.
void rb_str_modify(VALUE str)
Declares that the string is about to be modified.
Definition: string.c:2459
void rb_must_asciicompat(VALUE obj)
Asserts that the given string's encoding is (Ruby's definition of) ASCII compatible.
Definition: string.c:2511
VALUE rb_str_concat(VALUE dst, VALUE src)
Identical to rb_str_append(), except it also accepts an integer as a codepoint.
Definition: string.c:3418
VALUE rb_const_get(VALUE space, ID name)
Identical to rb_const_defined(), except it returns the actual defined value.
Definition: variable.c:2733
VALUE rb_ivar_set(VALUE obj, ID name, VALUE val)
Identical to rb_iv_set(), except it accepts the name as an ID instead of a C string.
Definition: variable.c:1575
VALUE rb_ivar_get(VALUE obj, ID name)
Identical to rb_iv_get(), except it accepts the name as an ID instead of a C string.
Definition: variable.c:1285
int rb_method_basic_definition_p(VALUE klass, ID mid)
Well...
Definition: vm_method.c:2643
void rb_define_alloc_func(VALUE klass, rb_alloc_func_t func)
Sets the allocator function of a class.
static ID rb_intern_const(const char *str)
This is a "tiny optimisation" over rb_intern().
Definition: symbol.h:276
void rb_define_const(VALUE klass, const char *name, VALUE val)
Defines a Ruby level constant under a namespace.
Definition: variable.c:3253
void rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE(*dumper)(VALUE), VALUE(*loader)(VALUE, VALUE))
Marshal format compatibility layer.
Definition: marshal.c:148
void rb_copy_generic_ivar(VALUE clone, VALUE obj)
Copies the list of instance variables.
Definition: variable.c:1719
#define RARRAY_LEN
Just another name of rb_array_len.
Definition: rarray.h:68
#define RARRAY_AREF(a, i)
Definition: rarray.h:588
#define RGENGC_WB_PROTECTED_COMPLEX
This is a compile-time flag to enable/disable write barrier for struct RComplex.
Definition: rgengc.h:162
static char * RSTRING_PTR(VALUE str)
Queries the contents pointer of the string.
Definition: rstring.h:497
static long RSTRING_LEN(VALUE str)
Queries the length of the string.
Definition: rstring.h:483
#define RTEST
This is an old name of RB_TEST.
Internal header for Complex.
Definition: complex.h:13
intptr_t SIGNED_VALUE
A signed integer type that has the same width with VALUE.
Definition: value.h:63
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
Definition: value.h:52
uintptr_t VALUE
Type that represents a Ruby object.
Definition: value.h:40
static bool RB_FLOAT_TYPE_P(VALUE obj)
Queries if the object is an instance of rb_cFloat.
Definition: value_type.h:263
static void Check_Type(VALUE v, enum ruby_value_type t)
Identical to RB_TYPE_P(), except it raises exceptions on predication failure.
Definition: value_type.h:432
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.
Definition: value_type.h:375