Ruby  2.7.1p83(2020-03-31revisiona0c7c23c9cec0d0ffcba012279cd652d28ad5bf3)
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 
34 
35 static ID id_abs, id_arg,
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) &&
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) &&
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) &&
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) &&
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) &&
133  if (y == ONE) return x;
134  return rb_float_mul(x, y);
135  }
136  else if (RB_TYPE_P(x, T_RATIONAL) &&
138  if (y == ONE) return x;
139  return rb_rational_mul(x, y);
140  }
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) &&
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
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
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 
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 
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 {
392 
393  RCOMPLEX_SET_REAL(obj, real);
394  RCOMPLEX_SET_IMAG(obj, imag);
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 
425 nucomp_canonicalization(int f)
426 {
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 
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 
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;
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
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) {
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
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_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
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_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
1522 {
1523  return nucomp_s_new_internal(rb_cComplex, x, y);
1524 }
1525 
1526 VALUE
1528 {
1529  return nucomp_s_canonicalize_internal(rb_cComplex, x, y);
1530 }
1531 
1532 VALUE
1534 {
1535  return f_complex_polar(rb_cComplex, x, y);
1536 }
1537 
1538 VALUE
1540 {
1541  return rb_complex_new_polar(x, y);
1542 }
1543 
1544 VALUE
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
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 
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 
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");
2352 
2354  rb_define_method(rb_cComplex, "imaginary", rb_complex_imag, 0);
2356 
2363  rb_define_method(rb_cComplex, "fdiv", nucomp_fdiv, 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 
2371  rb_define_method(rb_cComplex, "magnitude", rb_complex_abs, 0);
2372  rb_define_method(rb_cComplex, "abs2", nucomp_abs2, 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);
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  */
2442  f_complex_new_bang2(rb_cComplex, ZERO, ONE));
2443 
2444 #if !USE_FLONUM
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:1780
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
obj
const VALUE VALUE obj
Definition: rb_mjit_min_header-2.7.1.h:5742
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
rb_assoc_new
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:896
assert
#define assert(x)
Definition: dlmalloc.c:1176
klass
VALUE klass
Definition: rb_mjit_min_header-2.7.1.h:13259
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
exp
double exp(double)
rb_gc_register_mark_object
void rb_gc_register_mark_object(VALUE obj)
Definition: gc.c:7065
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_funcall
#define rb_funcall(recv, mid, argc,...)
Definition: rb_mjit_min_header-2.7.1.h:6585
INT2FIX
#define INT2FIX(i)
Definition: ruby.h:263
n
const char size_t n
Definition: rb_mjit_min_header-2.7.1.h:5456
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
st
enum ruby_tag_type st
Definition: rb_mjit_min_header-2.7.1.h:11116
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
modf
double modf(double, double *)
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:1778
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
cos
double cos(double)
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
rb_inspect
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
Definition: object.c:551
arg
VALUE arg
Definition: rb_mjit_min_header-2.7.1.h:5601
strpbrk
char * strpbrk(const char *, const char *)
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:1782
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:1072
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
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
void
void
Definition: rb_mjit_min_header-2.7.1.h:13278
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
h
size_t st_index_t h
Definition: rb_mjit_min_header-2.7.1.h:5462
rb_method_basic_definition_p
#define rb_method_basic_definition_p(klass, mid)
Definition: rb_mjit_min_header-2.7.1.h:7905
RCOMPLEX_SET_IMAG
#define RCOMPLEX_SET_IMAG(cmp, i)
Definition: internal.h:815
abs
int abs(int)
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
memchr
void * memchr(const void *, int, size_t)
CLASS_OF
#define CLASS_OF(v)
Definition: ruby.h:484
id_to_i
#define id_to_i
Definition: complex.c:40
RARRAY_LEN
#define RARRAY_LEN(a)
Definition: ruby.h:1070
rb_scan_args
#define rb_scan_args(argc, argvp, fmt,...)
Definition: rb_mjit_min_header-2.7.1.h:6372
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
str2num
#define str2num(s)
Definition: date_parse.c:48
T_BIGNUM
#define T_BIGNUM
Definition: ruby.h:533
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
argv
char ** argv
Definition: ruby.c:223
f
#define f
rb_rational_abs
VALUE rb_rational_abs(VALUE self)
Definition: rational.c:1255
M_PI_2
#define M_PI_2
Definition: missing.h:44
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
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
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
v
int VALUE v
Definition: rb_mjit_min_header-2.7.1.h:12337
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
sin
double sin(double)
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
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
signbit
#define signbit(__x)
Definition: rb_mjit_min_header-2.7.1.h:3676
rb_funcallv
#define rb_funcallv(recv, mid, argc, argv)
Definition: rb_mjit_min_header-2.7.1.h:7904
rb_const_get
VALUE rb_const_get(VALUE, ID)
Definition: variable.c:2387