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