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