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