8 #include "ruby/config.h"    11 # define _USE_MATH_DEFINES 1    19 #define ZERO INT2FIX(0)    20 #define ONE INT2FIX(1)    21 #define TWO INT2FIX(2)    22 #define RFLOAT_0 DBL2NUM(0)    23 #if defined(HAVE_SIGNBIT) && defined(__GNUC__) && defined(__sun) && \    33 static ID id_abs, id_arg,
    38     id_finite_p, id_infinite_p, id_rationalize,
    41 #define f_boolcast(x) ((x) ? Qtrue : Qfalse)    45 f_##n(VALUE x, VALUE y)\    47     return rb_funcall(x, (op), 1, y);\    54     return rb_funcall(x, id_##n, 0);\    59 f_##n(VALUE x, VALUE y)\    61     return rb_funcall(x, id_##n, 1, y);\    68     return rb_funcall(rb_mMath, id_##n, 1, x);\    73 m_##n(VALUE x, VALUE y)\    75     return rb_funcall(rb_mMath, id_##n, 2, x, y);\    78 #define PRESERVE_SIGNEDZERO    83 #ifndef PRESERVE_SIGNEDZERO   120 #ifndef PRESERVE_SIGNEDZERO   146 #ifndef PRESERVE_SIGNEDZERO   172         return nucomp_negate(x);
   212 f_negative_p(
VALUE x)
   223 #define f_positive_p(x) (!f_negative_p(x))   238 #define f_nonzero_p(x) (!f_zero_p(x))   258 f_infinite_p(
VALUE x)
   284 #define k_exact_p(x) (!RB_FLOAT_TYPE_P(x))   286 #define k_exact_zero_p(x) (k_exact_p(x) && f_zero_p(x))   288 #define get_dat1(x) \   289     struct RComplex *dat = RCOMPLEX(x)   291 #define get_dat2(x,y) \   292     struct RComplex *adat = RCOMPLEX(x), *bdat = RCOMPLEX(y)   307 nucomp_s_alloc(
VALUE klass)
   309     return nucomp_s_new_internal(klass, 
ZERO, 
ZERO);
   320         if (!k_numeric_p(real))
   325         if (!k_numeric_p(real))
   327         if (!k_numeric_p(imag))
   332     return nucomp_s_new_internal(klass, real, imag);
   340     return nucomp_s_new_internal(klass, x, 
ZERO);
   348     return nucomp_s_new_internal(klass, x, y);
   351 #ifdef CANONICALIZATION_FOR_MATHN   359 nucomp_canonicalization(
int f)
   361     canonicalization = 
f;
   364 #define canonicalization 0   368 nucomp_real_check(
VALUE num)
   373         if (!k_numeric_p(num) || !f_real_p(num))
   387     if (f_zero_p(imag) && canonicalization)
   391     if (f_real_p(real) && f_real_p(imag))
   392         return nucomp_s_new_internal(klass, real, imag);
   393     else if (f_real_p(real)) {
   396         return nucomp_s_new_internal(klass,
   397                                      f_sub(real, dat->imag),
   400     else if (f_real_p(imag)) {
   403         return nucomp_s_new_internal(klass,
   405                                      f_add(dat->imag, imag));
   410         return nucomp_s_new_internal(klass,
   411                                      f_sub(adat->real, bdat->imag),
   412                                      f_add(adat->imag, bdat->real));
   426 nucomp_s_new(
int argc, 
VALUE *argv, 
VALUE klass)
   432         nucomp_real_check(real);
   436         nucomp_real_check(real);
   437         nucomp_real_check(imag);
   441     return nucomp_s_canonicalize_internal(klass, real, imag);
   448     return nucomp_s_canonicalize_internal(klass, x, y);
   487 nucomp_f_complex(
int argc, 
VALUE *argv, 
VALUE klass)
   493 inline static VALUE \   494 m_##n##_bang(VALUE x)\   496     return rb_math_##n(x);\   516         return m_cos_bang(x);
   520                               f_mul(m_cos_bang(dat->real),
   521                                     m_cosh_bang(dat->imag)),
   523                                     m_sinh_bang(dat->imag)));
   531         return m_sin_bang(x);
   535                               f_mul(m_sin_bang(dat->real),
   536                                     m_cosh_bang(dat->imag)),
   537                               f_mul(m_cos_bang(dat->real),
   538                                     m_sinh_bang(dat->imag)));
   565             return m_sqrt_bang(x);
   577     if (f_zero_p(x) || f_zero_p(y)) {
   578         if (canonicalization) 
return x;
   579         return nucomp_s_new_internal(klass, x, 
RFLOAT_0);
   585             if (canonicalization) 
return x;
   598             const double real = abs * cos(arg), imag = abs * sin(arg);
   600             if (canonicalization && imag == 0.0) 
return x;
   606             if (canonicalization && f_zero_p(y)) 
return x;
   608         return nucomp_s_new_internal(klass, x, y);
   610     return nucomp_s_canonicalize_internal(klass,
   627 nucomp_s_polar(
int argc, 
VALUE *argv, 
VALUE klass)
   633         nucomp_real_check(abs);
   634         if (canonicalization) 
return abs;
   635         return nucomp_s_new_internal(klass, abs, 
ZERO);
   637         nucomp_real_check(abs);
   638         nucomp_real_check(arg);
   641     return f_complex_polar(klass, abs, arg);
   654 nucomp_real(
VALUE self)
   671 nucomp_imag(
VALUE self)
   686 nucomp_negate(
VALUE self)
   689   return f_complex_new2(
CLASS_OF(
self),
   713         real = 
f_add(adat->real, bdat->real);
   714         imag = 
f_add(adat->imag, bdat->imag);
   716         return f_complex_new2(
CLASS_OF(
self), real, imag);
   718     if (k_numeric_p(other) && f_real_p(other)) {
   721         return f_complex_new2(
CLASS_OF(
self),
   722                               f_add(dat->real, other), dat->imag);
   747         real = 
f_sub(adat->real, bdat->real);
   748         imag = 
f_sub(adat->imag, bdat->imag);
   750         return f_complex_new2(
CLASS_OF(
self), real, imag);
   752     if (k_numeric_p(other) && f_real_p(other)) {
   755         return f_complex_new2(
CLASS_OF(
self),
   756                               f_sub(dat->real, other), dat->imag);
   791         VALUE areal, aimag, breal, bimag;
   792         int arzero, aizero, brzero, bizero;
   796         arzero = f_zero_p(areal = adat->real);
   797         aizero = f_zero_p(aimag = adat->imag);
   798         brzero = f_zero_p(breal = bdat->real);
   799         bizero = f_zero_p(bimag = bdat->imag);
   800         real = 
f_sub(safe_mul(areal, breal, arzero, brzero),
   801                      safe_mul(aimag, bimag, aizero, bizero));
   802         imag = 
f_add(safe_mul(areal, bimag, arzero, bizero),
   803                      safe_mul(aimag, breal, aizero, brzero));
   805         return f_complex_new2(
CLASS_OF(
self), real, imag);
   807     if (k_numeric_p(other) && f_real_p(other)) {
   810         return f_complex_new2(
CLASS_OF(
self),
   811                               f_mul(dat->real, other),
   812                               f_mul(dat->imag, other));
   816 #define nucomp_mul rb_complex_mul   832             r = (*func)(bdat->imag, bdat->real);
   835                 return f_complex_new2(
CLASS_OF(
self),
   838             return f_complex_new2(
CLASS_OF(
self),
   839                                   (*func)(
f_add(adat->real,
   840                                                 f_mul(adat->imag, r)), n),
   841                                   (*func)(
f_sub(adat->imag,
   842                                                 f_mul(adat->real, r)), n));
   847             r = (*func)(bdat->real, bdat->imag);
   850                 return f_complex_new2(
CLASS_OF(
self),
   851                                       (*func)(
f_mul(
self, r), n),
   853             return f_complex_new2(
CLASS_OF(
self),
   860     if (k_numeric_p(other) && f_real_p(other)) {
   863         return f_complex_new2(
CLASS_OF(
self),
   864                               (*func)(dat->real, other),
   865                               (*func)(dat->imag, other));
   870 #define rb_raise_zerodiv() rb_raise(rb_eZeroDivError, "divided by 0")   891 #define nucomp_quo nucomp_div   904     return f_divide(
self, other, f_fdiv, id_fdiv);
   939         VALUE r, theta, nr, ntheta;
   946         nr = m_exp_bang(
f_sub(
f_mul(dat->real, m_log_bang(r)),
   947                               f_mul(dat->imag, theta)));
   949                        f_mul(dat->imag, m_log_bang(r)));
   950         return f_complex_polar(
CLASS_OF(
self), nr, ntheta);
   973                     x = nucomp_s_new_internal(
CLASS_OF(
self),
   975                                              f_mul(dat->imag, dat->imag)),
   986     if (k_numeric_p(other) && f_real_p(other)) {
   990             rb_warn(
"in a**b, b may be too big");
   996                                f_mul(theta, other));
  1019         return f_boolcast(f_eqeq_p(adat->real, bdat->real) &&
  1020                           f_eqeq_p(adat->imag, bdat->imag));
  1022     if (k_numeric_p(other) && f_real_p(other)) {
  1025         return f_boolcast(f_eqeq_p(dat->real, other) && f_zero_p(dat->imag));
  1034     if (k_numeric_p(other) && f_real_p(other))
  1055 nucomp_abs(
VALUE self)
  1059     if (f_zero_p(dat->real)) {
  1065     if (f_zero_p(dat->imag)) {
  1084 nucomp_abs2(
VALUE self)
  1088                  f_mul(dat->imag, dat->imag));
  1102 nucomp_arg(
VALUE self)
  1118 nucomp_rect(
VALUE self)
  1133 nucomp_polar(
VALUE self)
  1148 nucomp_conj(
VALUE self)
  1157 nucomp_true(
VALUE self)
  1170 nucomp_false(
VALUE self)
  1178 nucomp_exact_p(
VALUE self)
  1186 nucomp_inexact_p(
VALUE self)
  1201 nucomp_denominator(
VALUE self)
  1226 nucomp_numerator(
VALUE self)
  1233     return f_complex_new2(
CLASS_OF(
self),
  1242 nucomp_hash(
VALUE self)
  1265                           f_eqeq_p(
self, other));
  1278     return f_negative_p(x);
  1282 f_tpositive_p(
VALUE x)
  1284     return !f_signbit(x);
  1295     impos = f_tpositive_p(dat->imag);
  1297     s = (*func)(dat->real);
  1321 nucomp_to_s(
VALUE self)
  1339 nucomp_inspect(
VALUE self)
  1350 #define FINITE_TYPE_P(v) (RB_INTEGER_TYPE_P(v) || RB_TYPE_P(v, T_RATIONAL))  1360 rb_complex_finite_p(
VALUE self)
  1364     if (f_finite_p(dat->real) && f_finite_p(dat->imag)) {
  1385 rb_complex_infinite_p(
VALUE self)
  1389     if (
NIL_P(f_infinite_p(dat->real)) && 
NIL_P(f_infinite_p(dat->imag))) {
  1397 nucomp_dumper(
VALUE self)
  1417 nucomp_marshal_dump(
VALUE self)
  1450     return nucomp_s_canonicalize_internal(
rb_cComplex, x, y);
  1471     return nucomp_abs(cmp);
  1486 nucomp_to_i(
VALUE self)
  1494     return f_to_i(dat->real);
  1509 nucomp_to_f(
VALUE self)
  1517     return f_to_f(dat->real);
  1534 nucomp_to_r(
VALUE self)
  1542     return f_to_r(dat->real);
  1559 nucomp_rationalize(
int argc, 
VALUE *argv, 
VALUE self)
  1569     return rb_funcallv(dat->real, id_rationalize, argc, argv);
  1582 nucomp_to_c(
VALUE self)
  1594 nilclass_to_c(
VALUE self)
  1606 numeric_to_c(
VALUE self)
  1616     return (c == 
'-' || c == 
'+');
  1620 read_sign(
const char **s,
  1636     return isdigit((
unsigned char)c);
  1640 read_digits(
const char **s, 
int strict,
  1645     if (!isdecimal(**s))
  1648     while (isdecimal(**s) || **s == 
'_') {
  1666         } 
while (**s == 
'_');
  1673     return (c == 
'e' || c == 
'E');
  1677 read_num(
const char **s, 
int strict,
  1681         if (!read_digits(s, strict, b))
  1689         if (!read_digits(s, strict, b)) {
  1695     if (islettere(**s)) {
  1700         if (!read_digits(s, strict, b)) {
  1709 read_den(
const char **s, 
int strict,
  1712     if (!read_digits(s, strict, b))
  1718 read_rat_nos(
const char **s, 
int strict,
  1721     if (!read_num(s, strict, b))
  1727         if (!read_den(s, strict, b)) {
  1736 read_rat(
const char **s, 
int strict,
  1740     if (!read_rat_nos(s, strict, b))
  1748     return (c == 
'i' || c == 
'I' ||
  1749             c == 
'j' || c == 
'J');
  1757     if (strpbrk(s, 
".eE"))
  1763 read_comp(
const char **s, 
int strict,
  1764           VALUE *ret, 
char **b)
  1772     sign = read_sign(s, b);
  1774     if (isimagunit(**s)) {
  1776         num = 
INT2FIX((sign == 
'-') ? -1 : + 1);
  1781     if (!read_rat_nos(s, strict, b)) {
  1790     if (isimagunit(**s)) {
  1801         st = read_rat(s, strict, b);
  1804             !isdecimal(*(bb + 
strlen(bb) - 1))) {
  1818         sign = read_sign(s, b);
  1819         if (isimagunit(**s))
  1820             num2 = 
INT2FIX((sign == 
'-') ? -1 : + 1);
  1822             if (!read_rat_nos(s, strict, b)) {
  1829         if (!isimagunit(**s)) {
  1845 skip_ws(
const char **s)
  1847     while (isspace((
unsigned char)**s))
  1852 parse_comp(
const char *s, 
int strict,
  1863     if (!read_comp(&s, strict, num, &b)) {
  1879 string_to_c_strict(
VALUE self)
  1900     if (!parse_comp(s, 1, &num)) {
  1932 string_to_c(
VALUE self)
  1950     (void)parse_comp(s, 0, &num);
  1956 nucomp_s_convert(
int argc, 
VALUE *argv, 
VALUE klass)
  1958     VALUE a1, a2, backref;
  1969         a1 = string_to_c_strict(a1);
  1973         a2 = string_to_c_strict(a2);
  2002         if (k_numeric_p(a1) && !f_real_p(a1))
  2005         if (!k_numeric_p(a1))
  2009         if ((k_numeric_p(a1) && k_numeric_p(a2)) &&
  2010             (!f_real_p(a1) || !f_real_p(a2)))
  2020         return nucomp_s_new(argc, argv2, klass);
  2033 numeric_real(
VALUE self)
  2046 numeric_imag(
VALUE self)
  2058 numeric_abs2(
VALUE self)
  2060     return f_mul(
self, 
self);
  2072 numeric_arg(
VALUE self)
  2087 numeric_rect(
VALUE self)
  2101 numeric_polar(
VALUE self)
  2107         arg = numeric_arg(
self);
  2111         arg = float_arg(
self);
  2115         arg = numeric_arg(
self);
  2132 numeric_conj(
VALUE self)
  2146 float_arg(
VALUE self)
  2150     if (f_tpositive_p(
self))
  2193 #define rb_intern(str) rb_intern_const(str)  2195     assert(fprintf(stderr, 
"assert() is now active\n"));
  2213     id_rationalize = 
rb_intern(
"rationalize");
 RUBY_EXTERN VALUE rb_cString
 
VALUE rb_rational_cmp(VALUE self, VALUE other)
 
VALUE rb_flo_is_finite_p(VALUE num)
 
VALUE rb_int_uminus(VALUE num)
 
void rb_warn(const char *fmt,...)
 
RUBY_EXTERN VALUE rb_cFloat
 
VALUE rb_num_coerce_bin(VALUE, VALUE, ID)
 
size_t strlen(const char *)
 
void rb_backref_set(VALUE)
 
VALUE rb_cstr_to_rat(const char *, int)
 
RUBY_EXTERN int signbit(double x)
 
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj. 
 
#define rb_usascii_str_new2
 
void rb_raise(VALUE exc, const char *fmt,...)
 
VALUE rb_float_abs(VALUE flt)
 
VALUE rb_complex_polar(VALUE x, VALUE y)
 
void rb_define_private_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
 
void rb_must_asciicompat(VALUE)
 
VALUE rb_str_concat(VALUE, VALUE)
 
st_index_t rb_memhash(const void *ptr, long len)
 
double rb_cstr_to_dbl(const char *, int)
Parses a string representation of a floating point number. 
 
VALUE rb_lcm(VALUE x, VALUE y)
 
VALUE rb_String(VALUE)
Equivalent to Kernel#String in Ruby. 
 
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method. 
 
VALUE rb_backref_get(void)
 
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer. 
 
VALUE rb_ivar_get(VALUE, ID)
 
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
 
VALUE rb_flo_is_infinite_p(VALUE num)
 
VALUE rb_int_gt(VALUE x, VALUE y)
 
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function. 
 
RUBY_EXTERN VALUE rb_mMath
 
#define RCOMPLEX_SET_IMAG(cmp, i)
 
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect. 
 
void rb_undef_method(VALUE klass, const char *name)
 
#define rb_complex_new1(x)
 
#define NEWOBJ_OF(obj, type, klass, flags)
 
VALUE rb_obj_class(VALUE)
call-seq: obj.class -> class 
 
#define RB_TYPE_P(obj, type)
 
VALUE rb_obj_is_kind_of(VALUE, VALUE)
call-seq: obj.is_a?(class) -> true or false obj.kind_of?(class) -> true or false 
 
VALUE rb_equal(VALUE, VALUE)
call-seq: obj === other -> true or false 
 
VALUE rb_complex_mul(VALUE self, VALUE other)
 
RUBY_EXTERN VALUE rb_cObject
 
VALUE rb_str_to_inum(VALUE str, int base, int badcheck)
 
VALUE rb_str_cat2(VALUE, const char *)
 
#define INT_NEGATIVE_P(x)
 
int rb_num_negative_p(VALUE)
 
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class. 
 
VALUE rb_complex_sqrt(VALUE x)
 
void rb_define_const(VALUE, const char *, VALUE)
 
#define k_exact_zero_p(x)
 
#define ALLOCV_N(type, v, n)
 
#define RUBY_FUNC_EXPORTED
 
#define OBJ_FREEZE_RAW(x)
 
VALUE rb_int_abs(VALUE num)
 
VALUE rb_const_get(VALUE, ID)
 
VALUE rb_float_gt(VALUE x, VALUE y)
 
#define rb_complex_new2(x, y)
 
VALUE rb_math_atan2(VALUE, VALUE)
 
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
 
VALUE rb_ivar_set(VALUE, ID, VALUE)
 
unsigned char buf[MIME_BUF_SIZE]
 
VALUE rb_assoc_new(VALUE car, VALUE cdr)
 
void rb_undef_methods_from(VALUE klass, VALUE super)
 
#define RGENGC_WB_PROTECTED_COMPLEX
 
char * strchr(char *, char)
 
void rb_match_busy(VALUE)
 
VALUE rb_Complex(VALUE x, VALUE y)
 
#define rb_cmpint(cmp, a, b)
 
RUBY_EXTERN VALUE rb_cNumeric
 
VALUE rb_complex_new(VALUE x, VALUE y)
 
#define RB_FLOAT_TYPE_P(obj)
 
void rb_str_modify(VALUE)
 
#define RARRAY_AREF(a, i)
 
double rb_str_to_dbl(VALUE, int)
Parses a string representation of a floating point number. 
 
#define FIXNUM_ZERO_P(num)
 
VALUE rb_complex_raw(VALUE x, VALUE y)
 
VALUE rb_convert_type(VALUE, int, const char *, const char *)
Converts an object into another type. 
 
VALUE rb_rational_uminus(VALUE self)
 
void rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE(*dumper)(VALUE), VALUE(*loader)(VALUE, VALUE))
 
VALUE rb_rational_abs(VALUE self)
 
VALUE rb_complex_plus(VALUE self, VALUE other)
 
VALUE rb_complex_abs(VALUE cmp)
 
#define RCOMPLEX_SET_REAL(cmp, r)
 
void rb_copy_generic_ivar(VALUE, VALUE)
 
VALUE rb_math_hypot(VALUE, VALUE)
 
VALUE rb_cstr_to_inum(const char *str, int base, int badcheck)
 
VALUE rb_math_log(int argc, const VALUE *argv)
 
#define RB_INTEGER_TYPE_P(obj)
 
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
 
void rb_provide(const char *)
 
RUBY_EXTERN VALUE rb_cNilClass
 
VALUE rb_float_uminus(VALUE num)