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