Ruby  3.4.0dev (2024-11-05 revision 348a53415339076afc4a02fcd09f3ae36e9c4c61)
complex.c (348a53415339076afc4a02fcd09f3ae36e9c4c61)
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/internal/config.h"
9 
10 #if defined _MSC_VER
11 /* Microsoft Visual C does not define M_PI and others by default */
12 # define _USE_MATH_DEFINES 1
13 #endif
14 
15 #include <ctype.h>
16 #include <math.h>
17 
18 #include "id.h"
19 #include "internal.h"
20 #include "internal/array.h"
21 #include "internal/class.h"
22 #include "internal/complex.h"
23 #include "internal/math.h"
24 #include "internal/numeric.h"
25 #include "internal/object.h"
26 #include "internal/rational.h"
27 #include "internal/string.h"
28 #include "ruby_assert.h"
29 
30 #define ZERO INT2FIX(0)
31 #define ONE INT2FIX(1)
32 #define TWO INT2FIX(2)
33 #if USE_FLONUM
34 #define RFLOAT_0 DBL2NUM(0)
35 #else
36 static VALUE RFLOAT_0;
37 #endif
38 
40 
41 static ID id_abs, id_arg,
42  id_denominator, id_numerator,
43  id_real_p, id_i_real, id_i_imag,
44  id_finite_p, id_infinite_p, id_rationalize,
45  id_PI;
46 #define id_to_i idTo_i
47 #define id_to_r idTo_r
48 #define id_negate idUMinus
49 #define id_expt idPow
50 #define id_to_f idTo_f
51 #define id_quo idQuo
52 #define id_fdiv idFdiv
53 
54 #define fun1(n) \
55 inline static VALUE \
56 f_##n(VALUE x)\
57 {\
58  return rb_funcall(x, id_##n, 0);\
59 }
60 
61 #define fun2(n) \
62 inline static VALUE \
63 f_##n(VALUE x, VALUE y)\
64 {\
65  return rb_funcall(x, id_##n, 1, y);\
66 }
67 
68 #define PRESERVE_SIGNEDZERO
69 
70 inline static VALUE
71 f_add(VALUE x, VALUE y)
72 {
73  if (RB_INTEGER_TYPE_P(x) &&
74  LIKELY(rb_method_basic_definition_p(rb_cInteger, idPLUS))) {
75  if (FIXNUM_ZERO_P(x))
76  return y;
77  if (FIXNUM_ZERO_P(y))
78  return x;
79  return rb_int_plus(x, y);
80  }
81  else if (RB_FLOAT_TYPE_P(x) &&
82  LIKELY(rb_method_basic_definition_p(rb_cFloat, idPLUS))) {
83  if (FIXNUM_ZERO_P(y))
84  return x;
85  return rb_float_plus(x, y);
86  }
87  else if (RB_TYPE_P(x, T_RATIONAL) &&
88  LIKELY(rb_method_basic_definition_p(rb_cRational, idPLUS))) {
89  if (FIXNUM_ZERO_P(y))
90  return x;
91  return rb_rational_plus(x, y);
92  }
93 
94  return rb_funcall(x, '+', 1, y);
95 }
96 
97 inline static VALUE
98 f_div(VALUE x, VALUE y)
99 {
100  if (FIXNUM_P(y) && FIX2LONG(y) == 1)
101  return x;
102  return rb_funcall(x, '/', 1, y);
103 }
104 
105 inline static int
106 f_gt_p(VALUE x, VALUE y)
107 {
108  if (RB_INTEGER_TYPE_P(x)) {
109  if (FIXNUM_P(x) && FIXNUM_P(y))
110  return (SIGNED_VALUE)x > (SIGNED_VALUE)y;
111  return RTEST(rb_int_gt(x, y));
112  }
113  else if (RB_FLOAT_TYPE_P(x))
114  return RTEST(rb_float_gt(x, y));
115  else if (RB_TYPE_P(x, T_RATIONAL)) {
116  int const cmp = rb_cmpint(rb_rational_cmp(x, y), x, y);
117  return cmp > 0;
118  }
119  return RTEST(rb_funcall(x, '>', 1, y));
120 }
121 
122 inline static VALUE
123 f_mul(VALUE x, VALUE y)
124 {
125  if (RB_INTEGER_TYPE_P(x) &&
126  LIKELY(rb_method_basic_definition_p(rb_cInteger, idMULT))) {
127  if (FIXNUM_ZERO_P(y))
128  return ZERO;
129  if (FIXNUM_ZERO_P(x) && RB_INTEGER_TYPE_P(y))
130  return ZERO;
131  if (x == ONE) return y;
132  if (y == ONE) return x;
133  return rb_int_mul(x, y);
134  }
135  else if (RB_FLOAT_TYPE_P(x) &&
136  LIKELY(rb_method_basic_definition_p(rb_cFloat, idMULT))) {
137  if (y == ONE) return x;
138  return rb_float_mul(x, y);
139  }
140  else if (RB_TYPE_P(x, T_RATIONAL) &&
141  LIKELY(rb_method_basic_definition_p(rb_cRational, idMULT))) {
142  if (y == ONE) return x;
143  return rb_rational_mul(x, y);
144  }
145  else if (LIKELY(rb_method_basic_definition_p(CLASS_OF(x), idMULT))) {
146  if (y == ONE) return x;
147  }
148  return rb_funcall(x, '*', 1, y);
149 }
150 
151 inline static VALUE
152 f_sub(VALUE x, VALUE y)
153 {
154  if (FIXNUM_ZERO_P(y) &&
155  LIKELY(rb_method_basic_definition_p(CLASS_OF(x), idMINUS))) {
156  return x;
157  }
158  return rb_funcall(x, '-', 1, y);
159 }
160 
161 inline static VALUE
162 f_abs(VALUE x)
163 {
164  if (RB_INTEGER_TYPE_P(x)) {
165  return rb_int_abs(x);
166  }
167  else if (RB_FLOAT_TYPE_P(x)) {
168  return rb_float_abs(x);
169  }
170  else if (RB_TYPE_P(x, T_RATIONAL)) {
171  return rb_rational_abs(x);
172  }
173  else if (RB_TYPE_P(x, T_COMPLEX)) {
174  return rb_complex_abs(x);
175  }
176  return rb_funcall(x, id_abs, 0);
177 }
178 
179 static VALUE numeric_arg(VALUE self);
180 static VALUE float_arg(VALUE self);
181 
182 inline static VALUE
183 f_arg(VALUE x)
184 {
185  if (RB_INTEGER_TYPE_P(x)) {
186  return numeric_arg(x);
187  }
188  else if (RB_FLOAT_TYPE_P(x)) {
189  return float_arg(x);
190  }
191  else if (RB_TYPE_P(x, T_RATIONAL)) {
192  return numeric_arg(x);
193  }
194  else if (RB_TYPE_P(x, T_COMPLEX)) {
195  return rb_complex_arg(x);
196  }
197  return rb_funcall(x, id_arg, 0);
198 }
199 
200 inline static VALUE
201 f_numerator(VALUE x)
202 {
203  if (RB_TYPE_P(x, T_RATIONAL)) {
204  return RRATIONAL(x)->num;
205  }
206  if (RB_FLOAT_TYPE_P(x)) {
207  return rb_float_numerator(x);
208  }
209  return x;
210 }
211 
212 inline static VALUE
213 f_denominator(VALUE x)
214 {
215  if (RB_TYPE_P(x, T_RATIONAL)) {
216  return RRATIONAL(x)->den;
217  }
218  if (RB_FLOAT_TYPE_P(x)) {
219  return rb_float_denominator(x);
220  }
221  return INT2FIX(1);
222 }
223 
224 inline static VALUE
225 f_negate(VALUE x)
226 {
227  if (RB_INTEGER_TYPE_P(x)) {
228  return rb_int_uminus(x);
229  }
230  else if (RB_FLOAT_TYPE_P(x)) {
231  return rb_float_uminus(x);
232  }
233  else if (RB_TYPE_P(x, T_RATIONAL)) {
234  return rb_rational_uminus(x);
235  }
236  else if (RB_TYPE_P(x, T_COMPLEX)) {
237  return rb_complex_uminus(x);
238  }
239  return rb_funcall(x, id_negate, 0);
240 }
241 
242 static bool nucomp_real_p(VALUE self);
243 
244 static inline bool
245 f_real_p(VALUE x)
246 {
247  if (RB_INTEGER_TYPE_P(x)) {
248  return true;
249  }
250  else if (RB_FLOAT_TYPE_P(x)) {
251  return true;
252  }
253  else if (RB_TYPE_P(x, T_RATIONAL)) {
254  return true;
255  }
256  else if (RB_TYPE_P(x, T_COMPLEX)) {
257  return nucomp_real_p(x);
258  }
259  return rb_funcall(x, id_real_p, 0);
260 }
261 
262 inline static VALUE
263 f_to_i(VALUE x)
264 {
265  if (RB_TYPE_P(x, T_STRING))
266  return rb_str_to_inum(x, 10, 0);
267  return rb_funcall(x, id_to_i, 0);
268 }
269 
270 inline static VALUE
271 f_to_f(VALUE x)
272 {
273  if (RB_TYPE_P(x, T_STRING))
274  return DBL2NUM(rb_str_to_dbl(x, 0));
275  return rb_funcall(x, id_to_f, 0);
276 }
277 
278 fun1(to_r)
279 
280 inline static int
281 f_eqeq_p(VALUE x, VALUE y)
282 {
283  if (FIXNUM_P(x) && FIXNUM_P(y))
284  return x == y;
285  else if (RB_FLOAT_TYPE_P(x) || RB_FLOAT_TYPE_P(y))
286  return NUM2DBL(x) == NUM2DBL(y);
287  return (int)rb_equal(x, y);
288 }
289 
290 fun2(expt)
291 fun2(fdiv)
292 
293 static VALUE
294 f_quo(VALUE x, VALUE y)
295 {
296  if (RB_INTEGER_TYPE_P(x))
297  return rb_numeric_quo(x, y);
298  if (RB_FLOAT_TYPE_P(x))
299  return rb_float_div(x, y);
300  if (RB_TYPE_P(x, T_RATIONAL))
301  return rb_numeric_quo(x, y);
302 
303  return rb_funcallv(x, id_quo, 1, &y);
304 }
305 
306 inline static int
307 f_negative_p(VALUE x)
308 {
309  if (RB_INTEGER_TYPE_P(x))
310  return INT_NEGATIVE_P(x);
311  else if (RB_FLOAT_TYPE_P(x))
312  return RFLOAT_VALUE(x) < 0.0;
313  else if (RB_TYPE_P(x, T_RATIONAL))
314  return INT_NEGATIVE_P(RRATIONAL(x)->num);
315  return rb_num_negative_p(x);
316 }
317 
318 #define f_positive_p(x) (!f_negative_p(x))
319 
320 inline static bool
321 f_zero_p(VALUE x)
322 {
323  if (RB_FLOAT_TYPE_P(x)) {
324  return FLOAT_ZERO_P(x);
325  }
326  else if (RB_INTEGER_TYPE_P(x)) {
327  return FIXNUM_ZERO_P(x);
328  }
329  else if (RB_TYPE_P(x, T_RATIONAL)) {
330  const VALUE num = RRATIONAL(x)->num;
331  return FIXNUM_ZERO_P(num);
332  }
333  return rb_equal(x, ZERO) != 0;
334 }
335 
336 #define f_nonzero_p(x) (!f_zero_p(x))
337 
338 static inline bool
339 always_finite_type_p(VALUE x)
340 {
341  if (FIXNUM_P(x)) return true;
342  if (FLONUM_P(x)) return true; /* Infinity can't be a flonum */
343  return (RB_INTEGER_TYPE_P(x) || RB_TYPE_P(x, T_RATIONAL));
344 }
345 
346 inline static int
347 f_finite_p(VALUE x)
348 {
349  if (always_finite_type_p(x)) {
350  return TRUE;
351  }
352  else if (RB_FLOAT_TYPE_P(x)) {
353  return isfinite(RFLOAT_VALUE(x));
354  }
355  return RTEST(rb_funcallv(x, id_finite_p, 0, 0));
356 }
357 
358 inline static int
359 f_infinite_p(VALUE x)
360 {
361  if (always_finite_type_p(x)) {
362  return FALSE;
363  }
364  else if (RB_FLOAT_TYPE_P(x)) {
365  return isinf(RFLOAT_VALUE(x));
366  }
367  return RTEST(rb_funcallv(x, id_infinite_p, 0, 0));
368 }
369 
370 inline static int
371 f_kind_of_p(VALUE x, VALUE c)
372 {
373  return (int)rb_obj_is_kind_of(x, c);
374 }
375 
376 inline static int
377 k_numeric_p(VALUE x)
378 {
379  return f_kind_of_p(x, rb_cNumeric);
380 }
381 
382 #define k_exact_p(x) (!RB_FLOAT_TYPE_P(x))
383 
384 #define k_exact_zero_p(x) (k_exact_p(x) && f_zero_p(x))
385 
386 #define get_dat1(x) \
387  struct RComplex *dat = RCOMPLEX(x)
388 
389 #define get_dat2(x,y) \
390  struct RComplex *adat = RCOMPLEX(x), *bdat = RCOMPLEX(y)
391 
392 inline static VALUE
393 nucomp_s_new_internal(VALUE klass, VALUE real, VALUE imag)
394 {
395  NEWOBJ_OF(obj, struct RComplex, klass,
396  T_COMPLEX | (RGENGC_WB_PROTECTED_COMPLEX ? FL_WB_PROTECTED : 0), sizeof(struct RComplex), 0);
397 
398  RCOMPLEX_SET_REAL(obj, real);
399  RCOMPLEX_SET_IMAG(obj, imag);
400  OBJ_FREEZE((VALUE)obj);
401 
402  return (VALUE)obj;
403 }
404 
405 static VALUE
406 nucomp_s_alloc(VALUE klass)
407 {
408  return nucomp_s_new_internal(klass, ZERO, ZERO);
409 }
410 
411 inline static VALUE
412 f_complex_new_bang1(VALUE klass, VALUE x)
413 {
415  return nucomp_s_new_internal(klass, x, ZERO);
416 }
417 
418 inline static VALUE
419 f_complex_new_bang2(VALUE klass, VALUE x, VALUE y)
420 {
423  return nucomp_s_new_internal(klass, x, y);
424 }
425 
426 WARN_UNUSED_RESULT(inline static VALUE nucomp_real_check(VALUE num));
427 inline static VALUE
428 nucomp_real_check(VALUE num)
429 {
430  if (!RB_INTEGER_TYPE_P(num) &&
431  !RB_FLOAT_TYPE_P(num) &&
432  !RB_TYPE_P(num, T_RATIONAL)) {
433  if (RB_TYPE_P(num, T_COMPLEX) && nucomp_real_p(num)) {
434  VALUE real = RCOMPLEX(num)->real;
436  return real;
437  }
438  if (!k_numeric_p(num) || !f_real_p(num))
439  rb_raise(rb_eTypeError, "not a real");
440  }
441  return num;
442 }
443 
444 inline static VALUE
445 nucomp_s_canonicalize_internal(VALUE klass, VALUE real, VALUE imag)
446 {
447  int complex_r, complex_i;
448  complex_r = RB_TYPE_P(real, T_COMPLEX);
449  complex_i = RB_TYPE_P(imag, T_COMPLEX);
450  if (!complex_r && !complex_i) {
451  return nucomp_s_new_internal(klass, real, imag);
452  }
453  else if (!complex_r) {
454  get_dat1(imag);
455 
456  return nucomp_s_new_internal(klass,
457  f_sub(real, dat->imag),
458  f_add(ZERO, dat->real));
459  }
460  else if (!complex_i) {
461  get_dat1(real);
462 
463  return nucomp_s_new_internal(klass,
464  dat->real,
465  f_add(dat->imag, imag));
466  }
467  else {
468  get_dat2(real, imag);
469 
470  return nucomp_s_new_internal(klass,
471  f_sub(adat->real, bdat->imag),
472  f_add(adat->imag, bdat->real));
473  }
474 }
475 
476 /*
477  * call-seq:
478  * Complex.rect(real, imag = 0) -> complex
479  *
480  * Returns a new \Complex object formed from the arguments,
481  * each of which must be an instance of Numeric,
482  * or an instance of one of its subclasses:
483  * \Complex, Float, Integer, Rational;
484  * see {Rectangular Coordinates}[rdoc-ref:Complex@Rectangular+Coordinates]:
485  *
486  * Complex.rect(3) # => (3+0i)
487  * Complex.rect(3, Math::PI) # => (3+3.141592653589793i)
488  * Complex.rect(-3, -Math::PI) # => (-3-3.141592653589793i)
489  *
490  * \Complex.rectangular is an alias for \Complex.rect.
491  */
492 static VALUE
493 nucomp_s_new(int argc, VALUE *argv, VALUE klass)
494 {
495  VALUE real, imag;
496 
497  switch (rb_scan_args(argc, argv, "11", &real, &imag)) {
498  case 1:
499  real = nucomp_real_check(real);
500  imag = ZERO;
501  break;
502  default:
503  real = nucomp_real_check(real);
504  imag = nucomp_real_check(imag);
505  break;
506  }
507 
508  return nucomp_s_new_internal(klass, real, imag);
509 }
510 
511 inline static VALUE
512 f_complex_new2(VALUE klass, VALUE x, VALUE y)
513 {
514  if (RB_TYPE_P(x, T_COMPLEX)) {
515  get_dat1(x);
516  x = dat->real;
517  y = f_add(dat->imag, y);
518  }
519  return nucomp_s_canonicalize_internal(klass, x, y);
520 }
521 
522 static VALUE nucomp_convert(VALUE klass, VALUE a1, VALUE a2, int raise);
523 static VALUE nucomp_s_convert(int argc, VALUE *argv, VALUE klass);
524 
525 /*
526  * call-seq:
527  * Complex(real, imag = 0, exception: true) -> complex or nil
528  * Complex(s, exception: true) -> complex or nil
529  *
530  * Returns a new \Complex object if the arguments are valid;
531  * otherwise raises an exception if +exception+ is +true+;
532  * otherwise returns +nil+.
533  *
534  * With Numeric arguments +real+ and +imag+,
535  * returns <tt>Complex.rect(real, imag)</tt> if the arguments are valid.
536  *
537  * With string argument +s+, returns a new \Complex object if the argument is valid;
538  * the string may have:
539  *
540  * - One or two numeric substrings,
541  * each of which specifies a Complex, Float, Integer, Numeric, or Rational value,
542  * specifying {rectangular coordinates}[rdoc-ref:Complex@Rectangular+Coordinates]:
543  *
544  * - Sign-separated real and imaginary numeric substrings
545  * (with trailing character <tt>'i'</tt>):
546  *
547  * Complex('1+2i') # => (1+2i)
548  * Complex('+1+2i') # => (1+2i)
549  * Complex('+1-2i') # => (1-2i)
550  * Complex('-1+2i') # => (-1+2i)
551  * Complex('-1-2i') # => (-1-2i)
552  *
553  * - Real-only numeric string (without trailing character <tt>'i'</tt>):
554  *
555  * Complex('1') # => (1+0i)
556  * Complex('+1') # => (1+0i)
557  * Complex('-1') # => (-1+0i)
558  *
559  * - Imaginary-only numeric string (with trailing character <tt>'i'</tt>):
560  *
561  * Complex('1i') # => (0+1i)
562  * Complex('+1i') # => (0+1i)
563  * Complex('-1i') # => (0-1i)
564  *
565  * - At-sign separated real and imaginary rational substrings,
566  * each of which specifies a Rational value,
567  * specifying {polar coordinates}[rdoc-ref:Complex@Polar+Coordinates]:
568  *
569  * Complex('1/2@3/4') # => (0.36584443443691045+0.34081938001166706i)
570  * Complex('+1/2@+3/4') # => (0.36584443443691045+0.34081938001166706i)
571  * Complex('+1/2@-3/4') # => (0.36584443443691045-0.34081938001166706i)
572  * Complex('-1/2@+3/4') # => (-0.36584443443691045-0.34081938001166706i)
573  * Complex('-1/2@-3/4') # => (-0.36584443443691045+0.34081938001166706i)
574  *
575  */
576 static VALUE
577 nucomp_f_complex(int argc, VALUE *argv, VALUE klass)
578 {
579  VALUE a1, a2, opts = Qnil;
580  int raise = TRUE;
581 
582  if (rb_scan_args(argc, argv, "11:", &a1, &a2, &opts) == 1) {
583  a2 = Qundef;
584  }
585  if (!NIL_P(opts)) {
586  raise = rb_opts_exception_p(opts, raise);
587  }
588  if (argc > 0 && CLASS_OF(a1) == rb_cComplex && UNDEF_P(a2)) {
589  return a1;
590  }
591  return nucomp_convert(rb_cComplex, a1, a2, raise);
592 }
593 
594 #define imp1(n) \
595 inline static VALUE \
596 m_##n##_bang(VALUE x)\
597 {\
598  return rb_math_##n(x);\
599 }
600 
601 imp1(cos)
602 imp1(cosh)
603 imp1(exp)
604 
605 static VALUE
606 m_log_bang(VALUE x)
607 {
608  return rb_math_log(1, &x);
609 }
610 
611 imp1(sin)
612 imp1(sinh)
613 
614 static VALUE
615 m_cos(VALUE x)
616 {
617  if (!RB_TYPE_P(x, T_COMPLEX))
618  return m_cos_bang(x);
619  {
620  get_dat1(x);
621  return f_complex_new2(rb_cComplex,
622  f_mul(m_cos_bang(dat->real),
623  m_cosh_bang(dat->imag)),
624  f_mul(f_negate(m_sin_bang(dat->real)),
625  m_sinh_bang(dat->imag)));
626  }
627 }
628 
629 static VALUE
630 m_sin(VALUE x)
631 {
632  if (!RB_TYPE_P(x, T_COMPLEX))
633  return m_sin_bang(x);
634  {
635  get_dat1(x);
636  return f_complex_new2(rb_cComplex,
637  f_mul(m_sin_bang(dat->real),
638  m_cosh_bang(dat->imag)),
639  f_mul(m_cos_bang(dat->real),
640  m_sinh_bang(dat->imag)));
641  }
642 }
643 
644 static VALUE
645 f_complex_polar_real(VALUE klass, VALUE x, VALUE y)
646 {
647  if (f_zero_p(x) || f_zero_p(y)) {
648  return nucomp_s_new_internal(klass, x, RFLOAT_0);
649  }
650  if (RB_FLOAT_TYPE_P(y)) {
651  const double arg = RFLOAT_VALUE(y);
652  if (arg == M_PI) {
653  x = f_negate(x);
654  y = RFLOAT_0;
655  }
656  else if (arg == M_PI_2) {
657  y = x;
658  x = RFLOAT_0;
659  }
660  else if (arg == M_PI_2+M_PI) {
661  y = f_negate(x);
662  x = RFLOAT_0;
663  }
664  else if (RB_FLOAT_TYPE_P(x)) {
665  const double abs = RFLOAT_VALUE(x);
666  const double real = abs * cos(arg), imag = abs * sin(arg);
667  x = DBL2NUM(real);
668  y = DBL2NUM(imag);
669  }
670  else {
671  const double ax = sin(arg), ay = cos(arg);
672  y = f_mul(x, DBL2NUM(ax));
673  x = f_mul(x, DBL2NUM(ay));
674  }
675  return nucomp_s_new_internal(klass, x, y);
676  }
677  return nucomp_s_canonicalize_internal(klass,
678  f_mul(x, m_cos(y)),
679  f_mul(x, m_sin(y)));
680 }
681 
682 static VALUE
683 f_complex_polar(VALUE klass, VALUE x, VALUE y)
684 {
685  x = nucomp_real_check(x);
686  y = nucomp_real_check(y);
687  return f_complex_polar_real(klass, x, y);
688 }
689 
690 #ifdef HAVE___COSPI
691 # define cospi(x) __cospi(x)
692 #else
693 # define cospi(x) cos((x) * M_PI)
694 #endif
695 #ifdef HAVE___SINPI
696 # define sinpi(x) __sinpi(x)
697 #else
698 # define sinpi(x) sin((x) * M_PI)
699 #endif
700 /* returns a Complex or Float of ang*PI-rotated abs */
701 VALUE
702 rb_dbl_complex_new_polar_pi(double abs, double ang)
703 {
704  double fi;
705  const double fr = modf(ang, &fi);
706  int pos = fr == +0.5;
707 
708  if (pos || fr == -0.5) {
709  if ((modf(fi / 2.0, &fi) != fr) ^ pos) abs = -abs;
710  return rb_complex_new(RFLOAT_0, DBL2NUM(abs));
711  }
712  else if (fr == 0.0) {
713  if (modf(fi / 2.0, &fi) != 0.0) abs = -abs;
714  return DBL2NUM(abs);
715  }
716  else {
717  const double real = abs * cospi(ang), imag = abs * sinpi(ang);
718  return rb_complex_new(DBL2NUM(real), DBL2NUM(imag));
719  }
720 }
721 
722 /*
723  * call-seq:
724  * Complex.polar(abs, arg = 0) -> complex
725  *
726  * Returns a new \Complex object formed from the arguments,
727  * each of which must be an instance of Numeric,
728  * or an instance of one of its subclasses:
729  * \Complex, Float, Integer, Rational.
730  * Argument +arg+ is given in radians;
731  * see {Polar Coordinates}[rdoc-ref:Complex@Polar+Coordinates]:
732  *
733  * Complex.polar(3) # => (3+0i)
734  * Complex.polar(3, 2.0) # => (-1.2484405096414273+2.727892280477045i)
735  * Complex.polar(-3, -2.0) # => (1.2484405096414273+2.727892280477045i)
736  *
737  */
738 static VALUE
739 nucomp_s_polar(int argc, VALUE *argv, VALUE klass)
740 {
741  VALUE abs, arg;
742 
743  argc = rb_scan_args(argc, argv, "11", &abs, &arg);
744  abs = nucomp_real_check(abs);
745  if (argc == 2) {
746  arg = nucomp_real_check(arg);
747  }
748  else {
749  arg = ZERO;
750  }
751  return f_complex_polar_real(klass, abs, arg);
752 }
753 
754 /*
755  * call-seq:
756  * real -> numeric
757  *
758  * Returns the real value for +self+:
759  *
760  * Complex.rect(7).real # => 7
761  * Complex.rect(9, -4).real # => 9
762  *
763  * If +self+ was created with
764  * {polar coordinates}[rdoc-ref:Complex@Polar+Coordinates], the returned value
765  * is computed, and may be inexact:
766  *
767  * Complex.polar(1, Math::PI/4).real # => 0.7071067811865476 # Square root of 2.
768  *
769  */
770 VALUE
772 {
773  get_dat1(self);
774  return dat->real;
775 }
776 
777 /*
778  * call-seq:
779  * imag -> numeric
780  *
781  * Returns the imaginary value for +self+:
782  *
783  * Complex.rect(7).imag # => 0
784  * Complex.rect(9, -4).imag # => -4
785  *
786  * If +self+ was created with
787  * {polar coordinates}[rdoc-ref:Complex@Polar+Coordinates], the returned value
788  * is computed, and may be inexact:
789  *
790  * Complex.polar(1, Math::PI/4).imag # => 0.7071067811865476 # Square root of 2.
791  *
792  */
793 VALUE
795 {
796  get_dat1(self);
797  return dat->imag;
798 }
799 
800 /*
801  * call-seq:
802  * -complex -> new_complex
803  *
804  * Returns the negation of +self+, which is the negation of each of its parts:
805  *
806  * -Complex.rect(1, 2) # => (-1-2i)
807  * -Complex.rect(-1, -2) # => (1+2i)
808  *
809  */
810 VALUE
812 {
813  get_dat1(self);
814  return f_complex_new2(CLASS_OF(self),
815  f_negate(dat->real), f_negate(dat->imag));
816 }
817 
818 /*
819  * call-seq:
820  * complex + numeric -> new_complex
821  *
822  * Returns the sum of +self+ and +numeric+:
823  *
824  * Complex.rect(2, 3) + Complex.rect(2, 3) # => (4+6i)
825  * Complex.rect(900) + Complex.rect(1) # => (901+0i)
826  * Complex.rect(-2, 9) + Complex.rect(-9, 2) # => (-11+11i)
827  * Complex.rect(9, 8) + 4 # => (13+8i)
828  * Complex.rect(20, 9) + 9.8 # => (29.8+9i)
829  *
830  */
831 VALUE
833 {
834  if (RB_TYPE_P(other, T_COMPLEX)) {
835  VALUE real, imag;
836 
837  get_dat2(self, other);
838 
839  real = f_add(adat->real, bdat->real);
840  imag = f_add(adat->imag, bdat->imag);
841 
842  return f_complex_new2(CLASS_OF(self), real, imag);
843  }
844  if (k_numeric_p(other) && f_real_p(other)) {
845  get_dat1(self);
846 
847  return f_complex_new2(CLASS_OF(self),
848  f_add(dat->real, other), dat->imag);
849  }
850  return rb_num_coerce_bin(self, other, '+');
851 }
852 
853 /*
854  * call-seq:
855  * complex - numeric -> new_complex
856  *
857  * Returns the difference of +self+ and +numeric+:
858  *
859  * Complex.rect(2, 3) - Complex.rect(2, 3) # => (0+0i)
860  * Complex.rect(900) - Complex.rect(1) # => (899+0i)
861  * Complex.rect(-2, 9) - Complex.rect(-9, 2) # => (7+7i)
862  * Complex.rect(9, 8) - 4 # => (5+8i)
863  * Complex.rect(20, 9) - 9.8 # => (10.2+9i)
864  *
865  */
866 VALUE
868 {
869  if (RB_TYPE_P(other, T_COMPLEX)) {
870  VALUE real, imag;
871 
872  get_dat2(self, other);
873 
874  real = f_sub(adat->real, bdat->real);
875  imag = f_sub(adat->imag, bdat->imag);
876 
877  return f_complex_new2(CLASS_OF(self), real, imag);
878  }
879  if (k_numeric_p(other) && f_real_p(other)) {
880  get_dat1(self);
881 
882  return f_complex_new2(CLASS_OF(self),
883  f_sub(dat->real, other), dat->imag);
884  }
885  return rb_num_coerce_bin(self, other, '-');
886 }
887 
888 static VALUE
889 safe_mul(VALUE a, VALUE b, bool az, bool bz)
890 {
891  double v;
892  if (!az && bz && RB_FLOAT_TYPE_P(a) && (v = RFLOAT_VALUE(a), !isnan(v))) {
893  a = signbit(v) ? DBL2NUM(-1.0) : DBL2NUM(1.0);
894  }
895  if (!bz && az && RB_FLOAT_TYPE_P(b) && (v = RFLOAT_VALUE(b), !isnan(v))) {
896  b = signbit(v) ? DBL2NUM(-1.0) : DBL2NUM(1.0);
897  }
898  return f_mul(a, b);
899 }
900 
901 static void
902 comp_mul(VALUE areal, VALUE aimag, VALUE breal, VALUE bimag, VALUE *real, VALUE *imag)
903 {
904  bool arzero = f_zero_p(areal);
905  bool aizero = f_zero_p(aimag);
906  bool brzero = f_zero_p(breal);
907  bool bizero = f_zero_p(bimag);
908  *real = f_sub(safe_mul(areal, breal, arzero, brzero),
909  safe_mul(aimag, bimag, aizero, bizero));
910  *imag = f_add(safe_mul(areal, bimag, arzero, bizero),
911  safe_mul(aimag, breal, aizero, brzero));
912 }
913 
914 /*
915  * call-seq:
916  * complex * numeric -> new_complex
917  *
918  * Returns the product of +self+ and +numeric+:
919  *
920  * Complex.rect(2, 3) * Complex.rect(2, 3) # => (-5+12i)
921  * Complex.rect(900) * Complex.rect(1) # => (900+0i)
922  * Complex.rect(-2, 9) * Complex.rect(-9, 2) # => (0-85i)
923  * Complex.rect(9, 8) * 4 # => (36+32i)
924  * Complex.rect(20, 9) * 9.8 # => (196.0+88.2i)
925  *
926  */
927 VALUE
929 {
930  if (RB_TYPE_P(other, T_COMPLEX)) {
931  VALUE real, imag;
932  get_dat2(self, other);
933 
934  comp_mul(adat->real, adat->imag, bdat->real, bdat->imag, &real, &imag);
935 
936  return f_complex_new2(CLASS_OF(self), real, imag);
937  }
938  if (k_numeric_p(other) && f_real_p(other)) {
939  get_dat1(self);
940 
941  return f_complex_new2(CLASS_OF(self),
942  f_mul(dat->real, other),
943  f_mul(dat->imag, other));
944  }
945  return rb_num_coerce_bin(self, other, '*');
946 }
947 
948 inline static VALUE
949 f_divide(VALUE self, VALUE other,
950  VALUE (*func)(VALUE, VALUE), ID id)
951 {
952  if (RB_TYPE_P(other, T_COMPLEX)) {
953  VALUE r, n, x, y;
954  int flo;
955  get_dat2(self, other);
956 
957  flo = (RB_FLOAT_TYPE_P(adat->real) || RB_FLOAT_TYPE_P(adat->imag) ||
958  RB_FLOAT_TYPE_P(bdat->real) || RB_FLOAT_TYPE_P(bdat->imag));
959 
960  if (f_gt_p(f_abs(bdat->real), f_abs(bdat->imag))) {
961  r = (*func)(bdat->imag, bdat->real);
962  n = f_mul(bdat->real, f_add(ONE, f_mul(r, r)));
963  x = (*func)(f_add(adat->real, f_mul(adat->imag, r)), n);
964  y = (*func)(f_sub(adat->imag, f_mul(adat->real, r)), n);
965  }
966  else {
967  r = (*func)(bdat->real, bdat->imag);
968  n = f_mul(bdat->imag, f_add(ONE, f_mul(r, r)));
969  x = (*func)(f_add(f_mul(adat->real, r), adat->imag), n);
970  y = (*func)(f_sub(f_mul(adat->imag, r), adat->real), n);
971  }
972  if (!flo) {
973  x = rb_rational_canonicalize(x);
974  y = rb_rational_canonicalize(y);
975  }
976  return f_complex_new2(CLASS_OF(self), x, y);
977  }
978  if (k_numeric_p(other) && f_real_p(other)) {
979  VALUE x, y;
980  get_dat1(self);
981  x = rb_rational_canonicalize((*func)(dat->real, other));
982  y = rb_rational_canonicalize((*func)(dat->imag, other));
983  return f_complex_new2(CLASS_OF(self), x, y);
984  }
985  return rb_num_coerce_bin(self, other, id);
986 }
987 
988 #define rb_raise_zerodiv() rb_raise(rb_eZeroDivError, "divided by 0")
989 
990 /*
991  * call-seq:
992  * complex / numeric -> new_complex
993  *
994  * Returns the quotient of +self+ and +numeric+:
995  *
996  * Complex.rect(2, 3) / Complex.rect(2, 3) # => (1+0i)
997  * Complex.rect(900) / Complex.rect(1) # => (900+0i)
998  * Complex.rect(-2, 9) / Complex.rect(-9, 2) # => ((36/85)-(77/85)*i)
999  * Complex.rect(9, 8) / 4 # => ((9/4)+2i)
1000  * Complex.rect(20, 9) / 9.8 # => (2.0408163265306123+0.9183673469387754i)
1001  *
1002  */
1003 VALUE
1005 {
1006  return f_divide(self, other, f_quo, id_quo);
1007 }
1008 
1009 #define nucomp_quo rb_complex_div
1010 
1011 /*
1012  * call-seq:
1013  * fdiv(numeric) -> new_complex
1014  *
1015  * Returns <tt>Complex.rect(self.real/numeric, self.imag/numeric)</tt>:
1016  *
1017  * Complex.rect(11, 22).fdiv(3) # => (3.6666666666666665+7.333333333333333i)
1018  *
1019  */
1020 static VALUE
1021 nucomp_fdiv(VALUE self, VALUE other)
1022 {
1023  return f_divide(self, other, f_fdiv, id_fdiv);
1024 }
1025 
1026 inline static VALUE
1027 f_reciprocal(VALUE x)
1028 {
1029  return f_quo(ONE, x);
1030 }
1031 
1032 static VALUE
1033 zero_for(VALUE x)
1034 {
1035  if (RB_FLOAT_TYPE_P(x))
1036  return DBL2NUM(0);
1037  if (RB_TYPE_P(x, T_RATIONAL))
1038  return rb_rational_new(INT2FIX(0), INT2FIX(1));
1039 
1040  return INT2FIX(0);
1041 }
1042 
1043 static VALUE
1044 complex_pow_for_special_angle(VALUE self, VALUE other)
1045 {
1046  if (!rb_integer_type_p(other)) {
1047  return Qundef;
1048  }
1049 
1050  get_dat1(self);
1051  VALUE x = Qundef;
1052  int dir;
1053  if (f_zero_p(dat->imag)) {
1054  x = dat->real;
1055  dir = 0;
1056  }
1057  else if (f_zero_p(dat->real)) {
1058  x = dat->imag;
1059  dir = 2;
1060  }
1061  else if (f_eqeq_p(dat->real, dat->imag)) {
1062  x = dat->real;
1063  dir = 1;
1064  }
1065  else if (f_eqeq_p(dat->real, f_negate(dat->imag))) {
1066  x = dat->imag;
1067  dir = 3;
1068  } else {
1069  dir = 0;
1070  }
1071 
1072  if (UNDEF_P(x)) return x;
1073 
1074  if (f_negative_p(x)) {
1075  x = f_negate(x);
1076  dir += 4;
1077  }
1078 
1079  VALUE zx;
1080  if (dir % 2 == 0) {
1081  zx = rb_num_pow(x, other);
1082  }
1083  else {
1084  zx = rb_num_pow(
1085  rb_funcall(rb_int_mul(TWO, x), '*', 1, x),
1086  rb_int_div(other, TWO)
1087  );
1088  if (rb_int_odd_p(other)) {
1089  zx = rb_funcall(zx, '*', 1, x);
1090  }
1091  }
1092  static const int dirs[][2] = {
1093  {1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0}, {-1, -1}, {0, -1}, {1, -1}
1094  };
1095  int z_dir = FIX2INT(rb_int_modulo(rb_int_mul(INT2FIX(dir), other), INT2FIX(8)));
1096 
1097  VALUE zr = Qfalse, zi = Qfalse;
1098  switch (dirs[z_dir][0]) {
1099  case 0: zr = zero_for(zx); break;
1100  case 1: zr = zx; break;
1101  case -1: zr = f_negate(zx); break;
1102  }
1103  switch (dirs[z_dir][1]) {
1104  case 0: zi = zero_for(zx); break;
1105  case 1: zi = zx; break;
1106  case -1: zi = f_negate(zx); break;
1107  }
1108  return nucomp_s_new_internal(CLASS_OF(self), zr, zi);
1109 }
1110 
1111 
1112 /*
1113  * call-seq:
1114  * complex ** numeric -> new_complex
1115  *
1116  * Returns +self+ raised to power +numeric+:
1117  *
1118  * Complex.rect(0, 1) ** 2 # => (-1+0i)
1119  * Complex.rect(-8) ** Rational(1, 3) # => (1.0000000000000002+1.7320508075688772i)
1120  *
1121  */
1122 VALUE
1124 {
1125  if (k_numeric_p(other) && k_exact_zero_p(other))
1126  return f_complex_new_bang1(CLASS_OF(self), ONE);
1127 
1128  if (RB_TYPE_P(other, T_RATIONAL) && RRATIONAL(other)->den == LONG2FIX(1))
1129  other = RRATIONAL(other)->num; /* c14n */
1130 
1131  if (RB_TYPE_P(other, T_COMPLEX)) {
1132  get_dat1(other);
1133 
1134  if (k_exact_zero_p(dat->imag))
1135  other = dat->real; /* c14n */
1136  }
1137 
1138  if (other == ONE) {
1139  get_dat1(self);
1140  return nucomp_s_new_internal(CLASS_OF(self), dat->real, dat->imag);
1141  }
1142 
1143  VALUE result = complex_pow_for_special_angle(self, other);
1144  if (!UNDEF_P(result)) return result;
1145 
1146  if (RB_TYPE_P(other, T_COMPLEX)) {
1147  VALUE r, theta, nr, ntheta;
1148 
1149  get_dat1(other);
1150 
1151  r = f_abs(self);
1152  theta = f_arg(self);
1153 
1154  nr = m_exp_bang(f_sub(f_mul(dat->real, m_log_bang(r)),
1155  f_mul(dat->imag, theta)));
1156  ntheta = f_add(f_mul(theta, dat->real),
1157  f_mul(dat->imag, m_log_bang(r)));
1158  return f_complex_polar(CLASS_OF(self), nr, ntheta);
1159  }
1160  if (FIXNUM_P(other)) {
1161  long n = FIX2LONG(other);
1162  if (n == 0) {
1163  return nucomp_s_new_internal(CLASS_OF(self), ONE, ZERO);
1164  }
1165  if (n < 0) {
1166  self = f_reciprocal(self);
1167  other = rb_int_uminus(other);
1168  n = -n;
1169  }
1170  {
1171  get_dat1(self);
1172  VALUE xr = dat->real, xi = dat->imag, zr = xr, zi = xi;
1173 
1174  if (f_zero_p(xi)) {
1175  zr = rb_num_pow(zr, other);
1176  }
1177  else if (f_zero_p(xr)) {
1178  zi = rb_num_pow(zi, other);
1179  if (n & 2) zi = f_negate(zi);
1180  if (!(n & 1)) {
1181  VALUE tmp = zr;
1182  zr = zi;
1183  zi = tmp;
1184  }
1185  }
1186  else {
1187  while (--n) {
1188  long q, r;
1189 
1190  for (; q = n / 2, r = n % 2, r == 0; n = q) {
1191  VALUE tmp = f_sub(f_mul(xr, xr), f_mul(xi, xi));
1192  xi = f_mul(f_mul(TWO, xr), xi);
1193  xr = tmp;
1194  }
1195  comp_mul(zr, zi, xr, xi, &zr, &zi);
1196  }
1197  }
1198  return nucomp_s_new_internal(CLASS_OF(self), zr, zi);
1199  }
1200  }
1201  if (k_numeric_p(other) && f_real_p(other)) {
1202  VALUE r, theta;
1203 
1204  if (RB_BIGNUM_TYPE_P(other))
1205  rb_warn("in a**b, b may be too big");
1206 
1207  r = f_abs(self);
1208  theta = f_arg(self);
1209 
1210  return f_complex_polar(CLASS_OF(self), f_expt(r, other),
1211  f_mul(theta, other));
1212  }
1213  return rb_num_coerce_bin(self, other, id_expt);
1214 }
1215 
1216 /*
1217  * call-seq:
1218  * complex == object -> true or false
1219  *
1220  * Returns +true+ if <tt>self.real == object.real</tt>
1221  * and <tt>self.imag == object.imag</tt>:
1222  *
1223  * Complex.rect(2, 3) == Complex.rect(2.0, 3.0) # => true
1224  *
1225  */
1226 static VALUE
1227 nucomp_eqeq_p(VALUE self, VALUE other)
1228 {
1229  if (RB_TYPE_P(other, T_COMPLEX)) {
1230  get_dat2(self, other);
1231 
1232  return RBOOL(f_eqeq_p(adat->real, bdat->real) &&
1233  f_eqeq_p(adat->imag, bdat->imag));
1234  }
1235  if (k_numeric_p(other) && f_real_p(other)) {
1236  get_dat1(self);
1237 
1238  return RBOOL(f_eqeq_p(dat->real, other) && f_zero_p(dat->imag));
1239  }
1240  return RBOOL(f_eqeq_p(other, self));
1241 }
1242 
1243 static bool
1244 nucomp_real_p(VALUE self)
1245 {
1246  get_dat1(self);
1247  return f_zero_p(dat->imag);
1248 }
1249 
1250 /*
1251  * call-seq:
1252  * complex <=> object -> -1, 0, 1, or nil
1253  *
1254  * Returns:
1255  *
1256  * - <tt>self.real <=> object.real</tt> if both of the following are true:
1257  *
1258  * - <tt>self.imag == 0</tt>.
1259  * - <tt>object.imag == 0</tt>. # Always true if object is numeric but not complex.
1260  *
1261  * - +nil+ otherwise.
1262  *
1263  * Examples:
1264  *
1265  * Complex.rect(2) <=> 3 # => -1
1266  * Complex.rect(2) <=> 2 # => 0
1267  * Complex.rect(2) <=> 1 # => 1
1268  * Complex.rect(2, 1) <=> 1 # => nil # self.imag not zero.
1269  * Complex.rect(1) <=> Complex.rect(1, 1) # => nil # object.imag not zero.
1270  * Complex.rect(1) <=> 'Foo' # => nil # object.imag not defined.
1271  *
1272  */
1273 static VALUE
1274 nucomp_cmp(VALUE self, VALUE other)
1275 {
1276  if (!k_numeric_p(other)) {
1277  return rb_num_coerce_cmp(self, other, idCmp);
1278  }
1279  if (!nucomp_real_p(self)) {
1280  return Qnil;
1281  }
1282  if (RB_TYPE_P(other, T_COMPLEX)) {
1283  if (nucomp_real_p(other)) {
1284  get_dat2(self, other);
1285  return rb_funcall(adat->real, idCmp, 1, bdat->real);
1286  }
1287  }
1288  else {
1289  get_dat1(self);
1290  if (f_real_p(other)) {
1291  return rb_funcall(dat->real, idCmp, 1, other);
1292  }
1293  else {
1294  return rb_num_coerce_cmp(dat->real, other, idCmp);
1295  }
1296  }
1297  return Qnil;
1298 }
1299 
1300 /* :nodoc: */
1301 static VALUE
1302 nucomp_coerce(VALUE self, VALUE other)
1303 {
1304  if (RB_TYPE_P(other, T_COMPLEX))
1305  return rb_assoc_new(other, self);
1306  if (k_numeric_p(other) && f_real_p(other))
1307  return rb_assoc_new(f_complex_new_bang1(CLASS_OF(self), other), self);
1308 
1309  rb_raise(rb_eTypeError, "%"PRIsVALUE" can't be coerced into %"PRIsVALUE,
1310  rb_obj_class(other), rb_obj_class(self));
1311  return Qnil;
1312 }
1313 
1314 /*
1315  * call-seq:
1316  * abs -> float
1317  *
1318  * Returns the absolute value (magnitude) for +self+;
1319  * see {polar coordinates}[rdoc-ref:Complex@Polar+Coordinates]:
1320  *
1321  * Complex.polar(-1, 0).abs # => 1.0
1322  *
1323  * If +self+ was created with
1324  * {rectangular coordinates}[rdoc-ref:Complex@Rectangular+Coordinates], the returned value
1325  * is computed, and may be inexact:
1326  *
1327  * Complex.rectangular(1, 1).abs # => 1.4142135623730951 # The square root of 2.
1328  *
1329  */
1330 VALUE
1332 {
1333  get_dat1(self);
1334 
1335  if (f_zero_p(dat->real)) {
1336  VALUE a = f_abs(dat->imag);
1337  if (RB_FLOAT_TYPE_P(dat->real) && !RB_FLOAT_TYPE_P(dat->imag))
1338  a = f_to_f(a);
1339  return a;
1340  }
1341  if (f_zero_p(dat->imag)) {
1342  VALUE a = f_abs(dat->real);
1343  if (!RB_FLOAT_TYPE_P(dat->real) && RB_FLOAT_TYPE_P(dat->imag))
1344  a = f_to_f(a);
1345  return a;
1346  }
1347  return rb_math_hypot(dat->real, dat->imag);
1348 }
1349 
1350 /*
1351  * call-seq:
1352  * abs2 -> float
1353  *
1354  * Returns square of the absolute value (magnitude) for +self+;
1355  * see {polar coordinates}[rdoc-ref:Complex@Polar+Coordinates]:
1356  *
1357  * Complex.polar(2, 2).abs2 # => 4.0
1358  *
1359  * If +self+ was created with
1360  * {rectangular coordinates}[rdoc-ref:Complex@Rectangular+Coordinates], the returned value
1361  * is computed, and may be inexact:
1362  *
1363  * Complex.rectangular(1.0/3, 1.0/3).abs2 # => 0.2222222222222222
1364  *
1365  */
1366 static VALUE
1367 nucomp_abs2(VALUE self)
1368 {
1369  get_dat1(self);
1370  return f_add(f_mul(dat->real, dat->real),
1371  f_mul(dat->imag, dat->imag));
1372 }
1373 
1374 /*
1375  * call-seq:
1376  * arg -> float
1377  *
1378  * Returns the argument (angle) for +self+ in radians;
1379  * see {polar coordinates}[rdoc-ref:Complex@Polar+Coordinates]:
1380  *
1381  * Complex.polar(3, Math::PI/2).arg # => 1.57079632679489660
1382  *
1383  * If +self+ was created with
1384  * {rectangular coordinates}[rdoc-ref:Complex@Rectangular+Coordinates], the returned value
1385  * is computed, and may be inexact:
1386  *
1387  * Complex.polar(1, 1.0/3).arg # => 0.33333333333333326
1388  *
1389  */
1390 VALUE
1392 {
1393  get_dat1(self);
1394  return rb_math_atan2(dat->imag, dat->real);
1395 }
1396 
1397 /*
1398  * call-seq:
1399  * rect -> array
1400  *
1401  * Returns the array <tt>[self.real, self.imag]</tt>:
1402  *
1403  * Complex.rect(1, 2).rect # => [1, 2]
1404  *
1405  * See {Rectangular Coordinates}[rdoc-ref:Complex@Rectangular+Coordinates].
1406  *
1407  * If +self+ was created with
1408  * {polar coordinates}[rdoc-ref:Complex@Polar+Coordinates], the returned value
1409  * is computed, and may be inexact:
1410  *
1411  * Complex.polar(1.0, 1.0).rect # => [0.5403023058681398, 0.8414709848078965]
1412  *
1413  *
1414  * Complex#rectangular is an alias for Complex#rect.
1415  */
1416 static VALUE
1417 nucomp_rect(VALUE self)
1418 {
1419  get_dat1(self);
1420  return rb_assoc_new(dat->real, dat->imag);
1421 }
1422 
1423 /*
1424  * call-seq:
1425  * polar -> array
1426  *
1427  * Returns the array <tt>[self.abs, self.arg]</tt>:
1428  *
1429  * Complex.polar(1, 2).polar # => [1.0, 2.0]
1430  *
1431  * See {Polar Coordinates}[rdoc-ref:Complex@Polar+Coordinates].
1432  *
1433  * If +self+ was created with
1434  * {rectangular coordinates}[rdoc-ref:Complex@Rectangular+Coordinates], the returned value
1435  * is computed, and may be inexact:
1436  *
1437  * Complex.rect(1, 1).polar # => [1.4142135623730951, 0.7853981633974483]
1438  *
1439  */
1440 static VALUE
1441 nucomp_polar(VALUE self)
1442 {
1443  return rb_assoc_new(f_abs(self), f_arg(self));
1444 }
1445 
1446 /*
1447  * call-seq:
1448  * conj -> complex
1449  *
1450  * Returns the conjugate of +self+, <tt>Complex.rect(self.imag, self.real)</tt>:
1451  *
1452  * Complex.rect(1, 2).conj # => (1-2i)
1453  *
1454  */
1455 VALUE
1457 {
1458  get_dat1(self);
1459  return f_complex_new2(CLASS_OF(self), dat->real, f_negate(dat->imag));
1460 }
1461 
1462 /*
1463  * call-seq:
1464  * real? -> false
1465  *
1466  * Returns +false+; for compatibility with Numeric#real?.
1467  */
1468 static VALUE
1469 nucomp_real_p_m(VALUE self)
1470 {
1471  return Qfalse;
1472 }
1473 
1474 /*
1475  * call-seq:
1476  * denominator -> integer
1477  *
1478  * Returns the denominator of +self+, which is
1479  * the {least common multiple}[https://en.wikipedia.org/wiki/Least_common_multiple]
1480  * of <tt>self.real.denominator</tt> and <tt>self.imag.denominator</tt>:
1481  *
1482  * Complex.rect(Rational(1, 2), Rational(2, 3)).denominator # => 6
1483  *
1484  * Note that <tt>n.denominator</tt> of a non-rational numeric is +1+.
1485  *
1486  * Related: Complex#numerator.
1487  */
1488 static VALUE
1489 nucomp_denominator(VALUE self)
1490 {
1491  get_dat1(self);
1492  return rb_lcm(f_denominator(dat->real), f_denominator(dat->imag));
1493 }
1494 
1495 /*
1496  * call-seq:
1497  * numerator -> new_complex
1498  *
1499  * Returns the \Complex object created from the numerators
1500  * of the real and imaginary parts of +self+,
1501  * after converting each part to the
1502  * {lowest common denominator}[https://en.wikipedia.org/wiki/Lowest_common_denominator]
1503  * of the two:
1504  *
1505  * c = Complex.rect(Rational(2, 3), Rational(3, 4)) # => ((2/3)+(3/4)*i)
1506  * c.numerator # => (8+9i)
1507  *
1508  * In this example, the lowest common denominator of the two parts is 12;
1509  * the two converted parts may be thought of as \Rational(8, 12) and \Rational(9, 12),
1510  * whose numerators, respectively, are 8 and 9;
1511  * so the returned value of <tt>c.numerator</tt> is <tt>Complex.rect(8, 9)</tt>.
1512  *
1513  * Related: Complex#denominator.
1514  */
1515 static VALUE
1516 nucomp_numerator(VALUE self)
1517 {
1518  VALUE cd;
1519 
1520  get_dat1(self);
1521 
1522  cd = nucomp_denominator(self);
1523  return f_complex_new2(CLASS_OF(self),
1524  f_mul(f_numerator(dat->real),
1525  f_div(cd, f_denominator(dat->real))),
1526  f_mul(f_numerator(dat->imag),
1527  f_div(cd, f_denominator(dat->imag))));
1528 }
1529 
1530 /* :nodoc: */
1531 st_index_t
1532 rb_complex_hash(VALUE self)
1533 {
1534  st_index_t v, h[2];
1535  VALUE n;
1536 
1537  get_dat1(self);
1538  n = rb_hash(dat->real);
1539  h[0] = NUM2LONG(n);
1540  n = rb_hash(dat->imag);
1541  h[1] = NUM2LONG(n);
1542  v = rb_memhash(h, sizeof(h));
1543  return v;
1544 }
1545 
1546 /*
1547  * :call-seq:
1548  * hash -> integer
1549  *
1550  * Returns the integer hash value for +self+.
1551  *
1552  * Two \Complex objects created from the same values will have the same hash value
1553  * (and will compare using #eql?):
1554  *
1555  * Complex.rect(1, 2).hash == Complex.rect(1, 2).hash # => true
1556  *
1557  */
1558 static VALUE
1559 nucomp_hash(VALUE self)
1560 {
1561  return ST2FIX(rb_complex_hash(self));
1562 }
1563 
1564 /* :nodoc: */
1565 static VALUE
1566 nucomp_eql_p(VALUE self, VALUE other)
1567 {
1568  if (RB_TYPE_P(other, T_COMPLEX)) {
1569  get_dat2(self, other);
1570 
1571  return RBOOL((CLASS_OF(adat->real) == CLASS_OF(bdat->real)) &&
1572  (CLASS_OF(adat->imag) == CLASS_OF(bdat->imag)) &&
1573  f_eqeq_p(self, other));
1574 
1575  }
1576  return Qfalse;
1577 }
1578 
1579 inline static int
1580 f_signbit(VALUE x)
1581 {
1582  if (RB_FLOAT_TYPE_P(x)) {
1583  double f = RFLOAT_VALUE(x);
1584  return !isnan(f) && signbit(f);
1585  }
1586  return f_negative_p(x);
1587 }
1588 
1589 inline static int
1590 f_tpositive_p(VALUE x)
1591 {
1592  return !f_signbit(x);
1593 }
1594 
1595 static VALUE
1596 f_format(VALUE self, VALUE s, VALUE (*func)(VALUE))
1597 {
1598  int impos;
1599 
1600  get_dat1(self);
1601 
1602  impos = f_tpositive_p(dat->imag);
1603 
1604  rb_str_concat(s, (*func)(dat->real));
1605  rb_str_cat2(s, !impos ? "-" : "+");
1606 
1607  rb_str_concat(s, (*func)(f_abs(dat->imag)));
1608  if (!rb_isdigit(RSTRING_PTR(s)[RSTRING_LEN(s) - 1]))
1609  rb_str_cat2(s, "*");
1610  rb_str_cat2(s, "i");
1611 
1612  return s;
1613 }
1614 
1615 /*
1616  * call-seq:
1617  * to_s -> string
1618  *
1619  * Returns a string representation of +self+:
1620  *
1621  * Complex.rect(2).to_s # => "2+0i"
1622  * Complex.rect(-8, 6).to_s # => "-8+6i"
1623  * Complex.rect(0, Rational(1, 2)).to_s # => "0+1/2i"
1624  * Complex.rect(0, Float::INFINITY).to_s # => "0+Infinity*i"
1625  * Complex.rect(Float::NAN, Float::NAN).to_s # => "NaN+NaN*i"
1626  *
1627  */
1628 static VALUE
1629 nucomp_to_s(VALUE self)
1630 {
1631  return f_format(self, rb_usascii_str_new2(""), rb_String);
1632 }
1633 
1634 /*
1635  * call-seq:
1636  * inspect -> string
1637  *
1638  * Returns a string representation of +self+:
1639  *
1640  * Complex.rect(2).inspect # => "(2+0i)"
1641  * Complex.rect(-8, 6).inspect # => "(-8+6i)"
1642  * Complex.rect(0, Rational(1, 2)).inspect # => "(0+(1/2)*i)"
1643  * Complex.rect(0, Float::INFINITY).inspect # => "(0+Infinity*i)"
1644  * Complex.rect(Float::NAN, Float::NAN).inspect # => "(NaN+NaN*i)"
1645  *
1646  */
1647 static VALUE
1648 nucomp_inspect(VALUE self)
1649 {
1650  VALUE s;
1651 
1652  s = rb_usascii_str_new2("(");
1653  f_format(self, s, rb_inspect);
1654  rb_str_cat2(s, ")");
1655 
1656  return s;
1657 }
1658 
1659 #define FINITE_TYPE_P(v) (RB_INTEGER_TYPE_P(v) || RB_TYPE_P(v, T_RATIONAL))
1660 
1661 /*
1662  * call-seq:
1663  * finite? -> true or false
1664  *
1665  * Returns +true+ if both <tt>self.real.finite?</tt> and <tt>self.imag.finite?</tt>
1666  * are true, +false+ otherwise:
1667  *
1668  * Complex.rect(1, 1).finite? # => true
1669  * Complex.rect(Float::INFINITY, 0).finite? # => false
1670  *
1671  * Related: Numeric#finite?, Float#finite?.
1672  */
1673 static VALUE
1674 rb_complex_finite_p(VALUE self)
1675 {
1676  get_dat1(self);
1677 
1678  return RBOOL(f_finite_p(dat->real) && f_finite_p(dat->imag));
1679 }
1680 
1681 /*
1682  * call-seq:
1683  * infinite? -> 1 or nil
1684  *
1685  * Returns +1+ if either <tt>self.real.infinite?</tt> or <tt>self.imag.infinite?</tt>
1686  * is true, +nil+ otherwise:
1687  *
1688  * Complex.rect(Float::INFINITY, 0).infinite? # => 1
1689  * Complex.rect(1, 1).infinite? # => nil
1690  *
1691  * Related: Numeric#infinite?, Float#infinite?.
1692  */
1693 static VALUE
1694 rb_complex_infinite_p(VALUE self)
1695 {
1696  get_dat1(self);
1697 
1698  if (!f_infinite_p(dat->real) && !f_infinite_p(dat->imag)) {
1699  return Qnil;
1700  }
1701  return ONE;
1702 }
1703 
1704 /* :nodoc: */
1705 static VALUE
1706 nucomp_dumper(VALUE self)
1707 {
1708  return self;
1709 }
1710 
1711 /* :nodoc: */
1712 static VALUE
1713 nucomp_loader(VALUE self, VALUE a)
1714 {
1715  get_dat1(self);
1716 
1717  RCOMPLEX_SET_REAL(dat, rb_ivar_get(a, id_i_real));
1718  RCOMPLEX_SET_IMAG(dat, rb_ivar_get(a, id_i_imag));
1719  OBJ_FREEZE(self);
1720 
1721  return self;
1722 }
1723 
1724 /* :nodoc: */
1725 static VALUE
1726 nucomp_marshal_dump(VALUE self)
1727 {
1728  VALUE a;
1729  get_dat1(self);
1730 
1731  a = rb_assoc_new(dat->real, dat->imag);
1732  rb_copy_generic_ivar(a, self);
1733  return a;
1734 }
1735 
1736 /* :nodoc: */
1737 static VALUE
1738 nucomp_marshal_load(VALUE self, VALUE a)
1739 {
1740  Check_Type(a, T_ARRAY);
1741  if (RARRAY_LEN(a) != 2)
1742  rb_raise(rb_eArgError, "marshaled complex must have an array whose length is 2 but %ld", RARRAY_LEN(a));
1743  rb_ivar_set(self, id_i_real, RARRAY_AREF(a, 0));
1744  rb_ivar_set(self, id_i_imag, RARRAY_AREF(a, 1));
1745  return self;
1746 }
1747 
1748 VALUE
1750 {
1751  return nucomp_s_new_internal(rb_cComplex, x, y);
1752 }
1753 
1754 VALUE
1756 {
1757  return nucomp_s_canonicalize_internal(rb_cComplex, x, y);
1758 }
1759 
1760 VALUE
1762 {
1763  return f_complex_polar(rb_cComplex, x, y);
1764 }
1765 
1766 VALUE
1768 {
1769  return rb_complex_new_polar(x, y);
1770 }
1771 
1772 VALUE
1774 {
1775  VALUE a[2];
1776  a[0] = x;
1777  a[1] = y;
1778  return nucomp_s_convert(2, a, rb_cComplex);
1779 }
1780 
1781 VALUE
1782 rb_dbl_complex_new(double real, double imag)
1783 {
1784  return rb_complex_raw(DBL2NUM(real), DBL2NUM(imag));
1785 }
1786 
1787 /*
1788  * call-seq:
1789  * to_i -> integer
1790  *
1791  * Returns the value of <tt>self.real</tt> as an Integer, if possible:
1792  *
1793  * Complex.rect(1, 0).to_i # => 1
1794  * Complex.rect(1, Rational(0, 1)).to_i # => 1
1795  *
1796  * Raises RangeError if <tt>self.imag</tt> is not exactly zero
1797  * (either <tt>Integer(0)</tt> or <tt>Rational(0, _n_)</tt>).
1798  */
1799 static VALUE
1800 nucomp_to_i(VALUE self)
1801 {
1802  get_dat1(self);
1803 
1804  if (!k_exact_zero_p(dat->imag)) {
1805  rb_raise(rb_eRangeError, "can't convert %"PRIsVALUE" into Integer",
1806  self);
1807  }
1808  return f_to_i(dat->real);
1809 }
1810 
1811 /*
1812  * call-seq:
1813  * to_f -> float
1814  *
1815  * Returns the value of <tt>self.real</tt> as a Float, if possible:
1816  *
1817  * Complex.rect(1, 0).to_f # => 1.0
1818  * Complex.rect(1, Rational(0, 1)).to_f # => 1.0
1819  *
1820  * Raises RangeError if <tt>self.imag</tt> is not exactly zero
1821  * (either <tt>Integer(0)</tt> or <tt>Rational(0, _n_)</tt>).
1822  */
1823 static VALUE
1824 nucomp_to_f(VALUE self)
1825 {
1826  get_dat1(self);
1827 
1828  if (!k_exact_zero_p(dat->imag)) {
1829  rb_raise(rb_eRangeError, "can't convert %"PRIsVALUE" into Float",
1830  self);
1831  }
1832  return f_to_f(dat->real);
1833 }
1834 
1835 /*
1836  * call-seq:
1837  * to_r -> rational
1838  *
1839  * Returns the value of <tt>self.real</tt> as a Rational, if possible:
1840  *
1841  * Complex.rect(1, 0).to_r # => (1/1)
1842  * Complex.rect(1, Rational(0, 1)).to_r # => (1/1)
1843  * Complex.rect(1, 0.0).to_r # => (1/1)
1844  *
1845  * Raises RangeError if <tt>self.imag</tt> is not exactly zero
1846  * (either <tt>Integer(0)</tt> or <tt>Rational(0, _n_)</tt>)
1847  * and <tt>self.imag.to_r</tt> is not exactly zero.
1848  *
1849  * Related: Complex#rationalize.
1850  */
1851 static VALUE
1852 nucomp_to_r(VALUE self)
1853 {
1854  get_dat1(self);
1855 
1856  if (RB_FLOAT_TYPE_P(dat->imag) && FLOAT_ZERO_P(dat->imag)) {
1857  /* Do nothing here */
1858  }
1859  else if (!k_exact_zero_p(dat->imag)) {
1860  VALUE imag = rb_check_convert_type_with_id(dat->imag, T_RATIONAL, "Rational", idTo_r);
1861  if (NIL_P(imag) || !k_exact_zero_p(imag)) {
1862  rb_raise(rb_eRangeError, "can't convert %"PRIsVALUE" into Rational",
1863  self);
1864  }
1865  }
1866  return f_to_r(dat->real);
1867 }
1868 
1869 /*
1870  * call-seq:
1871  * rationalize(epsilon = nil) -> rational
1872  *
1873  * Returns a Rational object whose value is exactly or approximately
1874  * equivalent to that of <tt>self.real</tt>.
1875  *
1876  * With no argument +epsilon+ given, returns a \Rational object
1877  * whose value is exactly equal to that of <tt>self.real.rationalize</tt>:
1878  *
1879  * Complex.rect(1, 0).rationalize # => (1/1)
1880  * Complex.rect(1, Rational(0, 1)).rationalize # => (1/1)
1881  * Complex.rect(3.14159, 0).rationalize # => (314159/100000)
1882  *
1883  * With argument +epsilon+ given, returns a \Rational object
1884  * whose value is exactly or approximately equal to that of <tt>self.real</tt>
1885  * to the given precision:
1886  *
1887  * Complex.rect(3.14159, 0).rationalize(0.1) # => (16/5)
1888  * Complex.rect(3.14159, 0).rationalize(0.01) # => (22/7)
1889  * Complex.rect(3.14159, 0).rationalize(0.001) # => (201/64)
1890  * Complex.rect(3.14159, 0).rationalize(0.0001) # => (333/106)
1891  * Complex.rect(3.14159, 0).rationalize(0.00001) # => (355/113)
1892  * Complex.rect(3.14159, 0).rationalize(0.000001) # => (7433/2366)
1893  * Complex.rect(3.14159, 0).rationalize(0.0000001) # => (9208/2931)
1894  * Complex.rect(3.14159, 0).rationalize(0.00000001) # => (47460/15107)
1895  * Complex.rect(3.14159, 0).rationalize(0.000000001) # => (76149/24239)
1896  * Complex.rect(3.14159, 0).rationalize(0.0000000001) # => (314159/100000)
1897  * Complex.rect(3.14159, 0).rationalize(0.0) # => (3537115888337719/1125899906842624)
1898  *
1899  * Related: Complex#to_r.
1900  */
1901 static VALUE
1902 nucomp_rationalize(int argc, VALUE *argv, VALUE self)
1903 {
1904  get_dat1(self);
1905 
1906  rb_check_arity(argc, 0, 1);
1907 
1908  if (!k_exact_zero_p(dat->imag)) {
1909  rb_raise(rb_eRangeError, "can't convert %"PRIsVALUE" into Rational",
1910  self);
1911  }
1912  return rb_funcallv(dat->real, id_rationalize, argc, argv);
1913 }
1914 
1915 /*
1916  * call-seq:
1917  * to_c -> self
1918  *
1919  * Returns +self+.
1920  */
1921 static VALUE
1922 nucomp_to_c(VALUE self)
1923 {
1924  return self;
1925 }
1926 
1927 /*
1928  * call-seq:
1929  * to_c -> (0+0i)
1930  *
1931  * Returns zero as a Complex:
1932  *
1933  * nil.to_c # => (0+0i)
1934  *
1935  */
1936 static VALUE
1937 nilclass_to_c(VALUE self)
1938 {
1939  return rb_complex_new1(INT2FIX(0));
1940 }
1941 
1942 /*
1943  * call-seq:
1944  * to_c -> complex
1945  *
1946  * Returns +self+ as a Complex object.
1947  */
1948 static VALUE
1949 numeric_to_c(VALUE self)
1950 {
1951  return rb_complex_new1(self);
1952 }
1953 
1954 inline static int
1955 issign(int c)
1956 {
1957  return (c == '-' || c == '+');
1958 }
1959 
1960 static int
1961 read_sign(const char **s,
1962  char **b)
1963 {
1964  int sign = '?';
1965 
1966  if (issign(**s)) {
1967  sign = **b = **s;
1968  (*s)++;
1969  (*b)++;
1970  }
1971  return sign;
1972 }
1973 
1974 inline static int
1975 isdecimal(int c)
1976 {
1977  return isdigit((unsigned char)c);
1978 }
1979 
1980 static int
1981 read_digits(const char **s, int strict,
1982  char **b)
1983 {
1984  int us = 1;
1985 
1986  if (!isdecimal(**s))
1987  return 0;
1988 
1989  while (isdecimal(**s) || **s == '_') {
1990  if (**s == '_') {
1991  if (us) {
1992  if (strict) return 0;
1993  break;
1994  }
1995  us = 1;
1996  }
1997  else {
1998  **b = **s;
1999  (*b)++;
2000  us = 0;
2001  }
2002  (*s)++;
2003  }
2004  if (us)
2005  do {
2006  (*s)--;
2007  } while (**s == '_');
2008  return 1;
2009 }
2010 
2011 inline static int
2012 islettere(int c)
2013 {
2014  return (c == 'e' || c == 'E');
2015 }
2016 
2017 static int
2018 read_num(const char **s, int strict,
2019  char **b)
2020 {
2021  if (**s != '.') {
2022  if (!read_digits(s, strict, b))
2023  return 0;
2024  }
2025 
2026  if (**s == '.') {
2027  **b = **s;
2028  (*s)++;
2029  (*b)++;
2030  if (!read_digits(s, strict, b)) {
2031  (*b)--;
2032  return 0;
2033  }
2034  }
2035 
2036  if (islettere(**s)) {
2037  **b = **s;
2038  (*s)++;
2039  (*b)++;
2040  read_sign(s, b);
2041  if (!read_digits(s, strict, b)) {
2042  (*b)--;
2043  return 0;
2044  }
2045  }
2046  return 1;
2047 }
2048 
2049 inline static int
2050 read_den(const char **s, int strict,
2051  char **b)
2052 {
2053  if (!read_digits(s, strict, b))
2054  return 0;
2055  return 1;
2056 }
2057 
2058 static int
2059 read_rat_nos(const char **s, int strict,
2060  char **b)
2061 {
2062  if (!read_num(s, strict, b))
2063  return 0;
2064  if (**s == '/') {
2065  **b = **s;
2066  (*s)++;
2067  (*b)++;
2068  if (!read_den(s, strict, b)) {
2069  (*b)--;
2070  return 0;
2071  }
2072  }
2073  return 1;
2074 }
2075 
2076 static int
2077 read_rat(const char **s, int strict,
2078  char **b)
2079 {
2080  read_sign(s, b);
2081  if (!read_rat_nos(s, strict, b))
2082  return 0;
2083  return 1;
2084 }
2085 
2086 inline static int
2087 isimagunit(int c)
2088 {
2089  return (c == 'i' || c == 'I' ||
2090  c == 'j' || c == 'J');
2091 }
2092 
2093 static VALUE
2094 str2num(char *s)
2095 {
2096  if (strchr(s, '/'))
2097  return rb_cstr_to_rat(s, 0);
2098  if (strpbrk(s, ".eE"))
2099  return DBL2NUM(rb_cstr_to_dbl(s, 0));
2100  return rb_cstr_to_inum(s, 10, 0);
2101 }
2102 
2103 static int
2104 read_comp(const char **s, int strict,
2105  VALUE *ret, char **b)
2106 {
2107  char *bb;
2108  int sign;
2109  VALUE num, num2;
2110 
2111  bb = *b;
2112 
2113  sign = read_sign(s, b);
2114 
2115  if (isimagunit(**s)) {
2116  (*s)++;
2117  num = INT2FIX((sign == '-') ? -1 : + 1);
2118  *ret = rb_complex_new2(ZERO, num);
2119  return 1; /* e.g. "i" */
2120  }
2121 
2122  if (!read_rat_nos(s, strict, b)) {
2123  **b = '\0';
2124  num = str2num(bb);
2125  *ret = rb_complex_new2(num, ZERO);
2126  return 0; /* e.g. "-" */
2127  }
2128  **b = '\0';
2129  num = str2num(bb);
2130 
2131  if (isimagunit(**s)) {
2132  (*s)++;
2133  *ret = rb_complex_new2(ZERO, num);
2134  return 1; /* e.g. "3i" */
2135  }
2136 
2137  if (**s == '@') {
2138  int st;
2139 
2140  (*s)++;
2141  bb = *b;
2142  st = read_rat(s, strict, b);
2143  **b = '\0';
2144  if (strlen(bb) < 1 ||
2145  !isdecimal(*(bb + strlen(bb) - 1))) {
2146  *ret = rb_complex_new2(num, ZERO);
2147  return 0; /* e.g. "1@-" */
2148  }
2149  num2 = str2num(bb);
2150  *ret = rb_complex_new_polar(num, num2);
2151  if (!st)
2152  return 0; /* e.g. "1@2." */
2153  else
2154  return 1; /* e.g. "1@2" */
2155  }
2156 
2157  if (issign(**s)) {
2158  bb = *b;
2159  sign = read_sign(s, b);
2160  if (isimagunit(**s))
2161  num2 = INT2FIX((sign == '-') ? -1 : + 1);
2162  else {
2163  if (!read_rat_nos(s, strict, b)) {
2164  *ret = rb_complex_new2(num, ZERO);
2165  return 0; /* e.g. "1+xi" */
2166  }
2167  **b = '\0';
2168  num2 = str2num(bb);
2169  }
2170  if (!isimagunit(**s)) {
2171  *ret = rb_complex_new2(num, ZERO);
2172  return 0; /* e.g. "1+3x" */
2173  }
2174  (*s)++;
2175  *ret = rb_complex_new2(num, num2);
2176  return 1; /* e.g. "1+2i" */
2177  }
2178  /* !(@, - or +) */
2179  {
2180  *ret = rb_complex_new2(num, ZERO);
2181  return 1; /* e.g. "3" */
2182  }
2183 }
2184 
2185 inline static void
2186 skip_ws(const char **s)
2187 {
2188  while (isspace((unsigned char)**s))
2189  (*s)++;
2190 }
2191 
2192 static int
2193 parse_comp(const char *s, int strict, VALUE *num)
2194 {
2195  char *buf, *b;
2196  VALUE tmp;
2197  int ret = 1;
2198 
2199  buf = ALLOCV_N(char, tmp, strlen(s) + 1);
2200  b = buf;
2201 
2202  skip_ws(&s);
2203  if (!read_comp(&s, strict, num, &b)) {
2204  ret = 0;
2205  }
2206  else {
2207  skip_ws(&s);
2208 
2209  if (strict)
2210  if (*s != '\0')
2211  ret = 0;
2212  }
2213  ALLOCV_END(tmp);
2214 
2215  return ret;
2216 }
2217 
2218 static VALUE
2219 string_to_c_strict(VALUE self, int raise)
2220 {
2221  char *s;
2222  VALUE num;
2223 
2224  rb_must_asciicompat(self);
2225 
2226  if (raise) {
2227  s = StringValueCStr(self);
2228  }
2229  else if (!(s = rb_str_to_cstr(self))) {
2230  return Qnil;
2231  }
2232 
2233  if (!parse_comp(s, TRUE, &num)) {
2234  if (!raise) return Qnil;
2235  rb_raise(rb_eArgError, "invalid value for convert(): %+"PRIsVALUE,
2236  self);
2237  }
2238 
2239  return num;
2240 }
2241 
2242 /*
2243  * call-seq:
2244  * to_c -> complex
2245  *
2246  * Returns +self+ interpreted as a Complex object;
2247  * leading whitespace and trailing garbage are ignored:
2248  *
2249  * '9'.to_c # => (9+0i)
2250  * '2.5'.to_c # => (2.5+0i)
2251  * '2.5/1'.to_c # => ((5/2)+0i)
2252  * '-3/2'.to_c # => ((-3/2)+0i)
2253  * '-i'.to_c # => (0-1i)
2254  * '45i'.to_c # => (0+45i)
2255  * '3-4i'.to_c # => (3-4i)
2256  * '-4e2-4e-2i'.to_c # => (-400.0-0.04i)
2257  * '-0.0-0.0i'.to_c # => (-0.0-0.0i)
2258  * '1/2+3/4i'.to_c # => ((1/2)+(3/4)*i)
2259  * '1.0@0'.to_c # => (1+0.0i)
2260  * "1.0@#{Math::PI/2}".to_c # => (0.0+1i)
2261  * "1.0@#{Math::PI}".to_c # => (-1+0.0i)
2262  *
2263  * Returns \Complex zero if the string cannot be converted:
2264  *
2265  * 'ruby'.to_c # => (0+0i)
2266  *
2267  * See Kernel#Complex.
2268  */
2269 static VALUE
2270 string_to_c(VALUE self)
2271 {
2272  VALUE num;
2273 
2274  rb_must_asciicompat(self);
2275 
2276  (void)parse_comp(rb_str_fill_terminator(self, 1), FALSE, &num);
2277 
2278  return num;
2279 }
2280 
2281 static VALUE
2282 to_complex(VALUE val)
2283 {
2284  return rb_convert_type(val, T_COMPLEX, "Complex", "to_c");
2285 }
2286 
2287 static VALUE
2288 nucomp_convert(VALUE klass, VALUE a1, VALUE a2, int raise)
2289 {
2290  if (NIL_P(a1) || NIL_P(a2)) {
2291  if (!raise) return Qnil;
2292  rb_raise(rb_eTypeError, "can't convert nil into Complex");
2293  }
2294 
2295  if (RB_TYPE_P(a1, T_STRING)) {
2296  a1 = string_to_c_strict(a1, raise);
2297  if (NIL_P(a1)) return Qnil;
2298  }
2299 
2300  if (RB_TYPE_P(a2, T_STRING)) {
2301  a2 = string_to_c_strict(a2, raise);
2302  if (NIL_P(a2)) return Qnil;
2303  }
2304 
2305  if (RB_TYPE_P(a1, T_COMPLEX)) {
2306  {
2307  get_dat1(a1);
2308 
2309  if (k_exact_zero_p(dat->imag))
2310  a1 = dat->real;
2311  }
2312  }
2313 
2314  if (RB_TYPE_P(a2, T_COMPLEX)) {
2315  {
2316  get_dat1(a2);
2317 
2318  if (k_exact_zero_p(dat->imag))
2319  a2 = dat->real;
2320  }
2321  }
2322 
2323  if (RB_TYPE_P(a1, T_COMPLEX)) {
2324  if (UNDEF_P(a2) || (k_exact_zero_p(a2)))
2325  return a1;
2326  }
2327 
2328  if (UNDEF_P(a2)) {
2329  if (k_numeric_p(a1) && !f_real_p(a1))
2330  return a1;
2331  /* should raise exception for consistency */
2332  if (!k_numeric_p(a1)) {
2333  if (!raise) {
2334  a1 = rb_protect(to_complex, a1, NULL);
2336  return a1;
2337  }
2338  return to_complex(a1);
2339  }
2340  }
2341  else {
2342  if ((k_numeric_p(a1) && k_numeric_p(a2)) &&
2343  (!f_real_p(a1) || !f_real_p(a2)))
2344  return f_add(a1,
2345  f_mul(a2,
2346  f_complex_new_bang2(rb_cComplex, ZERO, ONE)));
2347  }
2348 
2349  {
2350  int argc;
2351  VALUE argv2[2];
2352  argv2[0] = a1;
2353  if (UNDEF_P(a2)) {
2354  argv2[1] = Qnil;
2355  argc = 1;
2356  }
2357  else {
2358  if (!raise && !RB_INTEGER_TYPE_P(a2) && !RB_FLOAT_TYPE_P(a2) && !RB_TYPE_P(a2, T_RATIONAL))
2359  return Qnil;
2360  argv2[1] = a2;
2361  argc = 2;
2362  }
2363  return nucomp_s_new(argc, argv2, klass);
2364  }
2365 }
2366 
2367 static VALUE
2368 nucomp_s_convert(int argc, VALUE *argv, VALUE klass)
2369 {
2370  VALUE a1, a2;
2371 
2372  if (rb_scan_args(argc, argv, "11", &a1, &a2) == 1) {
2373  a2 = Qundef;
2374  }
2375 
2376  return nucomp_convert(klass, a1, a2, TRUE);
2377 }
2378 
2379 /*
2380  * call-seq:
2381  * abs2 -> real
2382  *
2383  * Returns the square of +self+.
2384  */
2385 static VALUE
2386 numeric_abs2(VALUE self)
2387 {
2388  return f_mul(self, self);
2389 }
2390 
2391 /*
2392  * call-seq:
2393  * arg -> 0 or Math::PI
2394  *
2395  * Returns zero if +self+ is positive, Math::PI otherwise.
2396  */
2397 static VALUE
2398 numeric_arg(VALUE self)
2399 {
2400  if (f_positive_p(self))
2401  return INT2FIX(0);
2402  return DBL2NUM(M_PI);
2403 }
2404 
2405 /*
2406  * call-seq:
2407  * rect -> array
2408  *
2409  * Returns array <tt>[self, 0]</tt>.
2410  */
2411 static VALUE
2412 numeric_rect(VALUE self)
2413 {
2414  return rb_assoc_new(self, INT2FIX(0));
2415 }
2416 
2417 /*
2418  * call-seq:
2419  * polar -> array
2420  *
2421  * Returns array <tt>[self.abs, self.arg]</tt>.
2422  */
2423 static VALUE
2424 numeric_polar(VALUE self)
2425 {
2426  VALUE abs, arg;
2427 
2428  if (RB_INTEGER_TYPE_P(self)) {
2429  abs = rb_int_abs(self);
2430  arg = numeric_arg(self);
2431  }
2432  else if (RB_FLOAT_TYPE_P(self)) {
2433  abs = rb_float_abs(self);
2434  arg = float_arg(self);
2435  }
2436  else if (RB_TYPE_P(self, T_RATIONAL)) {
2437  abs = rb_rational_abs(self);
2438  arg = numeric_arg(self);
2439  }
2440  else {
2441  abs = f_abs(self);
2442  arg = f_arg(self);
2443  }
2444  return rb_assoc_new(abs, arg);
2445 }
2446 
2447 /*
2448  * call-seq:
2449  * arg -> 0 or Math::PI
2450  *
2451  * Returns 0 if +self+ is positive, Math::PI otherwise.
2452  */
2453 static VALUE
2454 float_arg(VALUE self)
2455 {
2456  if (isnan(RFLOAT_VALUE(self)))
2457  return self;
2458  if (f_tpositive_p(self))
2459  return INT2FIX(0);
2460  return rb_const_get(rb_mMath, id_PI);
2461 }
2462 
2463 /*
2464  * A \Complex object houses a pair of values,
2465  * given when the object is created as either <i>rectangular coordinates</i>
2466  * or <i>polar coordinates</i>.
2467  *
2468  * == Rectangular Coordinates
2469  *
2470  * The rectangular coordinates of a complex number
2471  * are called the _real_ and _imaginary_ parts;
2472  * see {Complex number definition}[https://en.wikipedia.org/wiki/Complex_number#Definition_and_basic_operations].
2473  *
2474  * You can create a \Complex object from rectangular coordinates with:
2475  *
2476  * - A {complex literal}[rdoc-ref:doc/syntax/literals.rdoc@Complex+Literals].
2477  * - \Method Complex.rect.
2478  * - \Method Kernel#Complex, either with numeric arguments or with certain string arguments.
2479  * - \Method String#to_c, for certain strings.
2480  *
2481  * Note that each of the stored parts may be a an instance one of the classes
2482  * Complex, Float, Integer, or Rational;
2483  * they may be retrieved:
2484  *
2485  * - Separately, with methods Complex#real and Complex#imaginary.
2486  * - Together, with method Complex#rect.
2487  *
2488  * The corresponding (computed) polar values may be retrieved:
2489  *
2490  * - Separately, with methods Complex#abs and Complex#arg.
2491  * - Together, with method Complex#polar.
2492  *
2493  * == Polar Coordinates
2494  *
2495  * The polar coordinates of a complex number
2496  * are called the _absolute_ and _argument_ parts;
2497  * see {Complex polar plane}[https://en.wikipedia.org/wiki/Complex_number#Polar_form].
2498  *
2499  * In this class, the argument part
2500  * in expressed {radians}[https://en.wikipedia.org/wiki/Radian]
2501  * (not {degrees}[https://en.wikipedia.org/wiki/Degree_(angle)]).
2502  *
2503  * You can create a \Complex object from polar coordinates with:
2504  *
2505  * - \Method Complex.polar.
2506  * - \Method Kernel#Complex, with certain string arguments.
2507  * - \Method String#to_c, for certain strings.
2508  *
2509  * Note that each of the stored parts may be a an instance one of the classes
2510  * Complex, Float, Integer, or Rational;
2511  * they may be retrieved:
2512  *
2513  * - Separately, with methods Complex#abs and Complex#arg.
2514  * - Together, with method Complex#polar.
2515  *
2516  * The corresponding (computed) rectangular values may be retrieved:
2517  *
2518  * - Separately, with methods Complex#real and Complex#imag.
2519  * - Together, with method Complex#rect.
2520  *
2521  * == What's Here
2522  *
2523  * First, what's elsewhere:
2524  *
2525  * - \Class \Complex inherits (directly or indirectly)
2526  * from classes {Numeric}[rdoc-ref:Numeric@What-27s+Here]
2527  * and {Object}[rdoc-ref:Object@What-27s+Here].
2528  * - Includes (indirectly) module {Comparable}[rdoc-ref:Comparable@What-27s+Here].
2529  *
2530  * Here, class \Complex has methods for:
2531  *
2532  * === Creating \Complex Objects
2533  *
2534  * - ::polar: Returns a new \Complex object based on given polar coordinates.
2535  * - ::rect (and its alias ::rectangular):
2536  * Returns a new \Complex object based on given rectangular coordinates.
2537  *
2538  * === Querying
2539  *
2540  * - #abs (and its alias #magnitude): Returns the absolute value for +self+.
2541  * - #arg (and its aliases #angle and #phase):
2542  * Returns the argument (angle) for +self+ in radians.
2543  * - #denominator: Returns the denominator of +self+.
2544  * - #finite?: Returns whether both +self.real+ and +self.image+ are finite.
2545  * - #hash: Returns the integer hash value for +self+.
2546  * - #imag (and its alias #imaginary): Returns the imaginary value for +self+.
2547  * - #infinite?: Returns whether +self.real+ or +self.image+ is infinite.
2548  * - #numerator: Returns the numerator of +self+.
2549  * - #polar: Returns the array <tt>[self.abs, self.arg]</tt>.
2550  * - #inspect: Returns a string representation of +self+.
2551  * - #real: Returns the real value for +self+.
2552  * - #real?: Returns +false+; for compatibility with Numeric#real?.
2553  * - #rect (and its alias #rectangular):
2554  * Returns the array <tt>[self.real, self.imag]</tt>.
2555  *
2556  * === Comparing
2557  *
2558  * - #<=>: Returns whether +self+ is less than, equal to, or greater than the given argument.
2559  * - #==: Returns whether +self+ is equal to the given argument.
2560  *
2561  * === Converting
2562  *
2563  * - #rationalize: Returns a Rational object whose value is exactly
2564  * or approximately equivalent to that of <tt>self.real</tt>.
2565  * - #to_c: Returns +self+.
2566  * - #to_d: Returns the value as a BigDecimal object.
2567  * - #to_f: Returns the value of <tt>self.real</tt> as a Float, if possible.
2568  * - #to_i: Returns the value of <tt>self.real</tt> as an Integer, if possible.
2569  * - #to_r: Returns the value of <tt>self.real</tt> as a Rational, if possible.
2570  * - #to_s: Returns a string representation of +self+.
2571  *
2572  * === Performing Complex Arithmetic
2573  *
2574  * - #*: Returns the product of +self+ and the given numeric.
2575  * - #**: Returns +self+ raised to power of the given numeric.
2576  * - #+: Returns the sum of +self+ and the given numeric.
2577  * - #-: Returns the difference of +self+ and the given numeric.
2578  * - #-@: Returns the negation of +self+.
2579  * - #/: Returns the quotient of +self+ and the given numeric.
2580  * - #abs2: Returns square of the absolute value (magnitude) for +self+.
2581  * - #conj (and its alias #conjugate): Returns the conjugate of +self+.
2582  * - #fdiv: Returns <tt>Complex.rect(self.real/numeric, self.imag/numeric)</tt>.
2583  *
2584  * === Working with JSON
2585  *
2586  * - ::json_create: Returns a new \Complex object,
2587  * deserialized from the given serialized hash.
2588  * - #as_json: Returns a serialized hash constructed from +self+.
2589  * - #to_json: Returns a JSON string representing +self+.
2590  *
2591  * These methods are provided by the {JSON gem}[https://github.com/ruby/json]. To make these methods available:
2592  *
2593  * require 'json/add/complex'
2594  *
2595  */
2596 void
2597 Init_Complex(void)
2598 {
2599  VALUE compat;
2600  id_abs = rb_intern_const("abs");
2601  id_arg = rb_intern_const("arg");
2602  id_denominator = rb_intern_const("denominator");
2603  id_numerator = rb_intern_const("numerator");
2604  id_real_p = rb_intern_const("real?");
2605  id_i_real = rb_intern_const("@real");
2606  id_i_imag = rb_intern_const("@image"); /* @image, not @imag */
2607  id_finite_p = rb_intern_const("finite?");
2608  id_infinite_p = rb_intern_const("infinite?");
2609  id_rationalize = rb_intern_const("rationalize");
2610  id_PI = rb_intern_const("PI");
2611 
2612  rb_cComplex = rb_define_class("Complex", rb_cNumeric);
2613 
2614  rb_define_alloc_func(rb_cComplex, nucomp_s_alloc);
2615  rb_undef_method(CLASS_OF(rb_cComplex), "allocate");
2616 
2618 
2619  rb_define_singleton_method(rb_cComplex, "rectangular", nucomp_s_new, -1);
2620  rb_define_singleton_method(rb_cComplex, "rect", nucomp_s_new, -1);
2621  rb_define_singleton_method(rb_cComplex, "polar", nucomp_s_polar, -1);
2622 
2623  rb_define_global_function("Complex", nucomp_f_complex, -1);
2624 
2625  rb_undef_methods_from(rb_cComplex, RCLASS_ORIGIN(rb_mComparable));
2627  rb_undef_method(rb_cComplex, "div");
2628  rb_undef_method(rb_cComplex, "divmod");
2629  rb_undef_method(rb_cComplex, "floor");
2630  rb_undef_method(rb_cComplex, "ceil");
2631  rb_undef_method(rb_cComplex, "modulo");
2632  rb_undef_method(rb_cComplex, "remainder");
2633  rb_undef_method(rb_cComplex, "round");
2634  rb_undef_method(rb_cComplex, "step");
2635  rb_undef_method(rb_cComplex, "truncate");
2637 
2639  rb_define_method(rb_cComplex, "imaginary", rb_complex_imag, 0);
2641 
2647  rb_define_method(rb_cComplex, "quo", nucomp_quo, 1);
2648  rb_define_method(rb_cComplex, "fdiv", nucomp_fdiv, 1);
2650 
2651  rb_define_method(rb_cComplex, "==", nucomp_eqeq_p, 1);
2652  rb_define_method(rb_cComplex, "<=>", nucomp_cmp, 1);
2653  rb_define_method(rb_cComplex, "coerce", nucomp_coerce, 1);
2654 
2656  rb_define_method(rb_cComplex, "magnitude", rb_complex_abs, 0);
2657  rb_define_method(rb_cComplex, "abs2", nucomp_abs2, 0);
2661  rb_define_method(rb_cComplex, "rectangular", nucomp_rect, 0);
2662  rb_define_method(rb_cComplex, "rect", nucomp_rect, 0);
2663  rb_define_method(rb_cComplex, "polar", nucomp_polar, 0);
2666 
2667  rb_define_method(rb_cComplex, "real?", nucomp_real_p_m, 0);
2668 
2669  rb_define_method(rb_cComplex, "numerator", nucomp_numerator, 0);
2670  rb_define_method(rb_cComplex, "denominator", nucomp_denominator, 0);
2671 
2672  rb_define_method(rb_cComplex, "hash", nucomp_hash, 0);
2673  rb_define_method(rb_cComplex, "eql?", nucomp_eql_p, 1);
2674 
2675  rb_define_method(rb_cComplex, "to_s", nucomp_to_s, 0);
2676  rb_define_method(rb_cComplex, "inspect", nucomp_inspect, 0);
2677 
2678  rb_undef_method(rb_cComplex, "positive?");
2679  rb_undef_method(rb_cComplex, "negative?");
2680 
2681  rb_define_method(rb_cComplex, "finite?", rb_complex_finite_p, 0);
2682  rb_define_method(rb_cComplex, "infinite?", rb_complex_infinite_p, 0);
2683 
2684  rb_define_private_method(rb_cComplex, "marshal_dump", nucomp_marshal_dump, 0);
2685  /* :nodoc: */
2686  compat = rb_define_class_under(rb_cComplex, "compatible", rb_cObject);
2687  rb_define_private_method(compat, "marshal_load", nucomp_marshal_load, 1);
2688  rb_marshal_define_compat(rb_cComplex, compat, nucomp_dumper, nucomp_loader);
2689 
2690  rb_define_method(rb_cComplex, "to_i", nucomp_to_i, 0);
2691  rb_define_method(rb_cComplex, "to_f", nucomp_to_f, 0);
2692  rb_define_method(rb_cComplex, "to_r", nucomp_to_r, 0);
2693  rb_define_method(rb_cComplex, "rationalize", nucomp_rationalize, -1);
2694  rb_define_method(rb_cComplex, "to_c", nucomp_to_c, 0);
2695  rb_define_method(rb_cNilClass, "to_c", nilclass_to_c, 0);
2696  rb_define_method(rb_cNumeric, "to_c", numeric_to_c, 0);
2697 
2698  rb_define_method(rb_cString, "to_c", string_to_c, 0);
2699 
2700  rb_define_private_method(CLASS_OF(rb_cComplex), "convert", nucomp_s_convert, -1);
2701 
2702  rb_define_method(rb_cNumeric, "abs2", numeric_abs2, 0);
2703  rb_define_method(rb_cNumeric, "arg", numeric_arg, 0);
2704  rb_define_method(rb_cNumeric, "angle", numeric_arg, 0);
2705  rb_define_method(rb_cNumeric, "phase", numeric_arg, 0);
2706  rb_define_method(rb_cNumeric, "rectangular", numeric_rect, 0);
2707  rb_define_method(rb_cNumeric, "rect", numeric_rect, 0);
2708  rb_define_method(rb_cNumeric, "polar", numeric_polar, 0);
2709 
2710  rb_define_method(rb_cFloat, "arg", float_arg, 0);
2711  rb_define_method(rb_cFloat, "angle", float_arg, 0);
2712  rb_define_method(rb_cFloat, "phase", float_arg, 0);
2713 
2714  /*
2715  * Equivalent
2716  * to <tt>Complex.rect(0, 1)</tt>:
2717  *
2718  * Complex::I # => (0+1i)
2719  *
2720  */
2722  f_complex_new_bang2(rb_cComplex, ZERO, ONE));
2723 
2724 #if !USE_FLONUM
2725  rb_vm_register_global_object(RFLOAT_0 = DBL2NUM(0.0));
2726 #endif
2727 
2728  rb_provide("complex.so"); /* for backward compatibility */
2729 }
#define RUBY_ASSERT(...)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
Definition: assert.h:219
static int rb_isdigit(int c)
Our own locale-insensitive version of isdigit(3).
Definition: ctype.h:302
#define rb_define_singleton_method(klass, mid, func, arity)
Defines klass.mid.
Definition: cxxanyargs.hpp:685
#define rb_define_private_method(klass, mid, func, arity)
Defines klass#mid and makes it private.
Definition: cxxanyargs.hpp:677
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:980
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:1012
void rb_undef_method(VALUE klass, const char *name)
Defines an undef of a method.
Definition: class.c:2166
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Retrieves argument from argc and argv to given VALUE references according to the format string.
Definition: class.c:2635
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a method.
Definition: class.c:2142
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
Definition: class.c:2339
#define T_COMPLEX
Old name of RUBY_T_COMPLEX.
Definition: value_type.h:59
#define RB_INTEGER_TYPE_P
Old name of rb_integer_type_p.
Definition: value_type.h:87
#define RFLOAT_VALUE
Old name of rb_float_value.
Definition: double.h:28
#define T_STRING
Old name of RUBY_T_STRING.
Definition: value_type.h:78
#define Qundef
Old name of RUBY_Qundef.
#define INT2FIX
Old name of RB_INT2FIX.
Definition: long.h:48
#define OBJ_FREEZE
Old name of RB_OBJ_FREEZE.
Definition: fl_type.h:135
#define CLASS_OF
Old name of rb_class_of.
Definition: globals.h:203
#define LONG2FIX
Old name of RB_INT2FIX.
Definition: long.h:49
#define FIX2INT
Old name of RB_FIX2INT.
Definition: int.h:41
#define T_RATIONAL
Old name of RUBY_T_RATIONAL.
Definition: value_type.h:76
#define NUM2DBL
Old name of rb_num2dbl.
Definition: double.h:27
VALUE rb_complex_polar(VALUE x, VALUE y)
Old name of rb_complex_new_polar.
Definition: complex.c:1767
#define rb_usascii_str_new2
Old name of rb_usascii_str_new_cstr.
Definition: string.h:1680
#define FLONUM_P
Old name of RB_FLONUM_P.
#define ST2FIX
Old name of RB_ST2FIX.
Definition: st_data_t.h:33
#define Qnil
Old name of RUBY_Qnil.
#define Qfalse
Old name of RUBY_Qfalse.
#define FIX2LONG
Old name of RB_FIX2LONG.
Definition: long.h:46
#define T_ARRAY
Old name of RUBY_T_ARRAY.
Definition: value_type.h:56
#define NIL_P
Old name of RB_NIL_P.
#define ALLOCV_N
Old name of RB_ALLOCV_N.
Definition: memory.h:400
#define FL_WB_PROTECTED
Old name of RUBY_FL_WB_PROTECTED.
Definition: fl_type.h:59
#define DBL2NUM
Old name of rb_float_new.
Definition: double.h:29
#define NUM2LONG
Old name of RB_NUM2LONG.
Definition: long.h:51
#define FIXNUM_P
Old name of RB_FIXNUM_P.
#define ALLOCV_END
Old name of RB_ALLOCV_END.
Definition: memory.h:401
void rb_raise(VALUE exc, const char *fmt,...)
Exception entry point.
Definition: error.c:3627
void rb_set_errinfo(VALUE err)
Sets the current exception ($!) to the given value.
Definition: eval.c:1941
VALUE rb_eRangeError
RangeError exception.
Definition: error.c:1407
VALUE rb_eTypeError
TypeError exception.
Definition: error.c:1403
void rb_warn(const char *fmt,...)
Identical to rb_warning(), except it reports unless $VERBOSE is nil.
Definition: error.c:465
VALUE rb_eArgError
ArgumentError exception.
Definition: error.c:1404
VALUE rb_cRational
Rational class.
Definition: rational.c:53
VALUE rb_convert_type(VALUE val, int type, const char *name, const char *mid)
Converts an object into another type.
Definition: object.c:3086
VALUE rb_cComplex
Complex class.
Definition: complex.c:39
VALUE rb_mMath
Math module.
Definition: math.c:29
VALUE rb_cInteger
Module class.
Definition: numeric.c:198
VALUE rb_cNilClass
NilClass class.
Definition: object.c:71
double rb_str_to_dbl(VALUE str, int mode)
Identical to rb_cstr_to_dbl(), except it accepts a Ruby's string instead of C's.
Definition: object.c:3477
VALUE rb_cNumeric
Numeric class.
Definition: numeric.c:196
VALUE rb_obj_class(VALUE obj)
Queries the class of an object.
Definition: object.c:247
VALUE rb_inspect(VALUE obj)
Generates a human-readable textual representation of the given object.
Definition: object.c:678
VALUE rb_equal(VALUE lhs, VALUE rhs)
This function is an optimised version of calling #==.
Definition: object.c:179
VALUE rb_obj_is_kind_of(VALUE obj, VALUE klass)
Queries if the given object is an instance (of possibly descendants) of the given class.
Definition: object.c:863
double rb_cstr_to_dbl(const char *str, int mode)
Converts a textual representation of a real number into a numeric, which is the nearest value that th...
Definition: object.c:3433
VALUE rb_mComparable
Comparable module.
Definition: compar.c:19
VALUE rb_cFloat
Float class.
Definition: numeric.c:197
VALUE rb_String(VALUE val)
This is the logic behind Kernel#String.
Definition: object.c:3716
VALUE rb_cString
String class.
Definition: string.c:78
VALUE rb_funcall(VALUE recv, ID mid, int n,...)
Calls a method.
Definition: vm_eval.c:1099
VALUE rb_funcallv(VALUE recv, ID mid, int argc, const VALUE *argv)
Identical to rb_funcall(), except it takes the method arguments as a C array.
Definition: vm_eval.c:1058
#define RGENGC_WB_PROTECTED_COMPLEX
This is a compile-time flag to enable/disable write barrier for struct RComplex.
Definition: gc.h:545
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Identical to rb_ary_new_from_values(), except it expects exactly two parameters.
Definition: array.c:1001
VALUE rb_str_to_inum(VALUE str, int base, int badcheck)
Identical to rb_cstr2inum(), except it takes Ruby's strings instead of C's.
Definition: bignum.c:4308
VALUE rb_cstr_to_inum(const char *str, int base, int badcheck)
Parses C's string to convert into a Ruby's integer.
Definition: bignum.c:4051
int rb_cmpint(VALUE val, VALUE a, VALUE b)
Canonicalises the passed val, which is the return value of a <=> b, into C's {-1, 0,...
Definition: bignum.c:2965
VALUE rb_complex_uminus(VALUE z)
Performs negation of the passed object.
Definition: complex.c:811
VALUE rb_complex_div(VALUE x, VALUE y)
Performs division of the passed two objects.
Definition: complex.c:1004
VALUE rb_complex_new(VALUE real, VALUE imag)
Constructs a Complex, by first multiplying the imaginary part with 1i then adds it to the real part.
Definition: complex.c:1755
VALUE rb_complex_plus(VALUE x, VALUE y)
Performs addition of the passed two objects.
Definition: complex.c:832
VALUE rb_complex_new_polar(VALUE abs, VALUE arg)
Constructs a Complex using polar representations.
Definition: complex.c:1761
VALUE rb_complex_arg(VALUE z)
Queries the argument (or the angle) of the passed object.
Definition: complex.c:1391
#define rb_complex_new2(x, y)
Just another name of rb_complex_new.
Definition: complex.h:77
VALUE rb_complex_raw(VALUE real, VALUE imag)
Identical to rb_complex_new(), except it assumes both arguments are not instances of rb_cComplex.
Definition: complex.c:1749
VALUE rb_dbl_complex_new(double real, double imag)
Identical to rb_complex_new(), except it takes the arguments as C's double instead of Ruby's object.
Definition: complex.c:1782
VALUE rb_complex_abs(VALUE z)
Queries the absolute (or the magnitude) of the passed object.
Definition: complex.c:1331
VALUE rb_complex_real(VALUE z)
Queries the real part of the passed Complex.
Definition: complex.c:771
VALUE rb_complex_mul(VALUE x, VALUE y)
Performs multiplication of the passed two objects.
Definition: complex.c:928
VALUE rb_complex_conjugate(VALUE z)
Performs complex conjugation of the passed object.
Definition: complex.c:1456
VALUE rb_Complex(VALUE real, VALUE imag)
Converts various values into a Complex.
Definition: complex.c:1773
VALUE rb_complex_minus(VALUE x, VALUE y)
Performs subtraction of the passed two objects.
Definition: complex.c:867
#define rb_complex_new1(x)
Shorthand of x+0i.
Definition: complex.h:74
VALUE rb_complex_pow(VALUE base, VALUE exp)
Performs exponentiation of the passed two objects.
Definition: complex.c:1123
VALUE rb_complex_imag(VALUE z)
Queries the imaginary part of the passed Complex.
Definition: complex.c:794
static int rb_check_arity(int argc, int min, int max)
Ensures that the passed integer is in the passed range.
Definition: error.h:284
VALUE rb_hash(VALUE obj)
Calculates a message authentication code of the passed object.
Definition: hash.c:267
void rb_provide(const char *feature)
Declares that the given feature is already provided by someone else.
Definition: load.c:714
VALUE rb_num_coerce_cmp(VALUE lhs, VALUE rhs, ID op)
Identical to rb_num_coerce_bin(), except for return values.
Definition: numeric.c:484
VALUE rb_num_coerce_bin(VALUE lhs, VALUE rhs, ID op)
Coerced binary operation.
Definition: numeric.c:477
VALUE rb_protect(VALUE(*func)(VALUE args), VALUE args, int *state)
Protects a function call from potential global escapes from the function.
VALUE rb_rational_new(VALUE num, VALUE den)
Constructs a Rational, with reduction.
Definition: rational.c:1975
st_index_t rb_memhash(const void *ptr, long len)
This is a universal hash function.
Definition: random.c:1752
VALUE rb_str_cat2(VALUE, const char *)
Just another name of rb_str_cat_cstr.
void rb_must_asciicompat(VALUE obj)
Asserts that the given string's encoding is (Ruby's definition of) ASCII compatible.
Definition: string.c:2694
VALUE rb_str_concat(VALUE dst, VALUE src)
Identical to rb_str_append(), except it also accepts an integer as a codepoint.
Definition: string.c:3904
VALUE rb_const_get(VALUE space, ID name)
Identical to rb_const_defined(), except it returns the actual defined value.
Definition: variable.c:3151
VALUE rb_ivar_set(VALUE obj, ID name, VALUE val)
Identical to rb_iv_set(), except it accepts the name as an ID instead of a C string.
Definition: variable.c:1859
VALUE rb_ivar_get(VALUE obj, ID name)
Identical to rb_iv_get(), except it accepts the name as an ID instead of a C string.
Definition: variable.c:1350
int rb_method_basic_definition_p(VALUE klass, ID mid)
Well...
Definition: vm_method.c:2833
void rb_define_alloc_func(VALUE klass, rb_alloc_func_t func)
Sets the allocator function of a class.
static ID rb_intern_const(const char *str)
This is a "tiny optimisation" over rb_intern().
Definition: symbol.h:276
void rb_define_const(VALUE klass, const char *name, VALUE val)
Defines a Ruby level constant under a namespace.
Definition: variable.c:3713
void rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE(*dumper)(VALUE), VALUE(*loader)(VALUE, VALUE))
Marshal format compatibility layer.
Definition: marshal.c:134
void rb_copy_generic_ivar(VALUE clone, VALUE obj)
Copies the list of instance variables.
Definition: variable.c:2036
#define RARRAY_LEN
Just another name of rb_array_len.
Definition: rarray.h:51
#define RARRAY_AREF(a, i)
Definition: rarray.h:403
static char * RSTRING_PTR(VALUE str)
Queries the contents pointer of the string.
Definition: rstring.h:416
static long RSTRING_LEN(VALUE str)
Queries the length of the string.
Definition: rstring.h:367
#define StringValueCStr(v)
Identical to StringValuePtr, except it additionally checks for the contents for viability as a C stri...
Definition: rstring.h:89
#define RTEST
This is an old name of RB_TEST.
Internal header for Complex.
Definition: complex.h:13
intptr_t SIGNED_VALUE
A signed integer type that has the same width with VALUE.
Definition: value.h:63
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
Definition: value.h:52
uintptr_t VALUE
Type that represents a Ruby object.
Definition: value.h:40
static bool RB_FLOAT_TYPE_P(VALUE obj)
Queries if the object is an instance of rb_cFloat.
Definition: value_type.h:264
static void Check_Type(VALUE v, enum ruby_value_type t)
Identical to RB_TYPE_P(), except it raises exceptions on predication failure.
Definition: value_type.h:433
static bool rb_integer_type_p(VALUE obj)
Queries if the object is an instance of rb_cInteger.
Definition: value_type.h:204
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.
Definition: value_type.h:376