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