12# define _USE_MATH_DEFINES 1
31#define ZERO INT2FIX(0)
35#define RFLOAT_0 DBL2NUM(0)
39#if defined(HAVE_SIGNBIT) && defined(__GNUC__) && defined(__sun) && \
46static ID id_abs, id_arg,
48 id_real_p, id_i_real, id_i_imag,
49 id_finite_p, id_infinite_p, id_rationalize,
53#define id_negate idUMinus
59#define f_boolcast(x) ((x) ? Qtrue : Qfalse)
65 return rb_funcall(x, id_##n, 0);\
70f_##n(VALUE x, VALUE y)\
72 return rb_funcall(x, id_##n, 1, y);\
75#define PRESERVE_SIGNEDZERO
88 else if (RB_FLOAT_TYPE_P(x) &&
120 else if (RB_FLOAT_TYPE_P(x))
134 if (FIXNUM_ZERO_P(y))
138 if (x ==
ONE)
return y;
139 if (y ==
ONE)
return x;
142 else if (RB_FLOAT_TYPE_P(x) &&
144 if (y ==
ONE)
return x;
149 if (y ==
ONE)
return x;
153 if (y ==
ONE)
return x;
161 if (FIXNUM_ZERO_P(y) &&
174 else if (RB_FLOAT_TYPE_P(x)) {
193 return numeric_arg(x);
195 else if (RB_FLOAT_TYPE_P(x)) {
199 return numeric_arg(x);
213 if (RB_FLOAT_TYPE_P(x)) {
225 if (RB_FLOAT_TYPE_P(x)) {
237 else if (RB_FLOAT_TYPE_P(x)) {
249static bool nucomp_real_p(
VALUE self);
257 else if (RB_FLOAT_TYPE_P(x)) {
264 return nucomp_real_p(x);
292 else if (RB_FLOAT_TYPE_P(x) || RB_FLOAT_TYPE_P(y))
305 if (RB_FLOAT_TYPE_P(x))
317 return INT_NEGATIVE_P(x);
318 else if (RB_FLOAT_TYPE_P(x))
325#define f_positive_p(x) (!f_negative_p(x))
330 if (RB_FLOAT_TYPE_P(x)) {
331 return FLOAT_ZERO_P(x);
334 return FIXNUM_ZERO_P(x);
338 return FIXNUM_ZERO_P(
num);
343#define f_nonzero_p(x) (!f_zero_p(x))
352 else if (RB_FLOAT_TYPE_P(x)) {
368 else if (RB_FLOAT_TYPE_P(x)) {
389#define k_exact_p(x) (!RB_FLOAT_TYPE_P(x))
391#define k_exact_zero_p(x) (k_exact_p(x) && f_zero_p(x))
394 struct RComplex *dat = RCOMPLEX(x)
396#define get_dat2(x,y) \
397 struct RComplex *adat = RCOMPLEX(x), *bdat = RCOMPLEX(y)
412nucomp_s_alloc(
VALUE klass)
414 return nucomp_s_new_internal(klass,
ZERO,
ZERO);
421 return nucomp_s_new_internal(klass, x,
ZERO);
429 return nucomp_s_new_internal(klass, x, y);
436 !RB_FLOAT_TYPE_P(
num) &&
438 if (!k_numeric_p(
num) || !f_real_p(
num))
446 int complex_r, complex_i;
449 if (!complex_r && !complex_i) {
450 return nucomp_s_new_internal(klass, real, imag);
452 else if (!complex_r) {
455 return nucomp_s_new_internal(klass,
456 f_sub(real, dat->imag),
459 else if (!complex_i) {
462 return nucomp_s_new_internal(klass,
464 f_add(dat->imag, imag));
469 return nucomp_s_new_internal(klass,
470 f_sub(adat->real, bdat->imag),
471 f_add(adat->imag, bdat->real));
491 nucomp_real_check(real);
495 nucomp_real_check(real);
496 nucomp_real_check(imag);
500 return nucomp_s_canonicalize_internal(klass, real, imag);
507 return nucomp_s_canonicalize_internal(klass, x, y);
569m_##n##_bang(VALUE x)\
571 return rb_math_##n(x);\
591 return m_cos_bang(x);
595 f_mul(m_cos_bang(dat->real),
596 m_cosh_bang(dat->imag)),
598 m_sinh_bang(dat->imag)));
606 return m_sin_bang(x);
610 f_mul(m_sin_bang(dat->real),
611 m_cosh_bang(dat->imag)),
612 f_mul(m_cos_bang(dat->real),
613 m_sinh_bang(dat->imag)));
622 if (f_zero_p(x) || f_zero_p(y)) {
623 return nucomp_s_new_internal(klass, x, RFLOAT_0);
625 if (RB_FLOAT_TYPE_P(y)) {
639 else if (RB_FLOAT_TYPE_P(x)) {
641 const double real = abs * cos(arg), imag = abs * sin(arg);
646 const double ax = sin(arg), ay = cos(arg);
650 return nucomp_s_new_internal(klass, x, y);
652 return nucomp_s_canonicalize_internal(klass,
658# define cospi(x) __cospi(x)
660# define cospi(x) cos((x) * M_PI)
663# define sinpi(x) __sinpi(x)
665# define sinpi(x) sin((x) * M_PI)
672 const double fr = modf(ang, &fi);
673 int pos = fr == +0.5;
675 if (pos || fr == -0.5) {
676 if ((modf(fi / 2.0, &fi) != fr) ^ pos) abs = -abs;
679 else if (fr == 0.0) {
680 if (modf(fi / 2.0, &fi) != 0.0) abs = -abs;
684 const double real = abs *
cospi(ang), imag = abs *
sinpi(ang);
707 nucomp_real_check(abs);
708 return nucomp_s_new_internal(klass, abs,
ZERO);
710 nucomp_real_check(abs);
711 nucomp_real_check(arg);
722 return f_complex_polar(klass, abs, arg);
770 return f_complex_new2(
CLASS_OF(self),
794 real =
f_add(adat->real, bdat->real);
795 imag =
f_add(adat->imag, bdat->imag);
797 return f_complex_new2(
CLASS_OF(self), real, imag);
799 if (k_numeric_p(other) && f_real_p(other)) {
802 return f_complex_new2(
CLASS_OF(self),
803 f_add(dat->real, other), dat->imag);
828 real =
f_sub(adat->real, bdat->real);
829 imag =
f_sub(adat->imag, bdat->imag);
831 return f_complex_new2(
CLASS_OF(self), real, imag);
833 if (k_numeric_p(other) && f_real_p(other)) {
836 return f_complex_new2(
CLASS_OF(self),
837 f_sub(dat->real, other), dat->imag);
858 int arzero = f_zero_p(areal);
859 int aizero = f_zero_p(aimag);
860 int brzero = f_zero_p(breal);
861 int bizero = f_zero_p(bimag);
862 *real =
f_sub(safe_mul(areal, breal, arzero, brzero),
863 safe_mul(aimag, bimag, aizero, bizero));
864 *imag =
f_add(safe_mul(areal, bimag, arzero, bizero),
865 safe_mul(aimag, breal, aizero, brzero));
887 comp_mul(adat->real, adat->imag, bdat->real, bdat->imag, &real, &imag);
889 return f_complex_new2(
CLASS_OF(self), real, imag);
891 if (k_numeric_p(other) && f_real_p(other)) {
894 return f_complex_new2(
CLASS_OF(self),
895 f_mul(dat->real, other),
896 f_mul(dat->imag, other));
910 flo = (RB_FLOAT_TYPE_P(adat->real) || RB_FLOAT_TYPE_P(adat->imag) ||
911 RB_FLOAT_TYPE_P(bdat->real) || RB_FLOAT_TYPE_P(bdat->imag));
914 r = (*func)(bdat->imag, bdat->real);
916 x = (*func)(
f_add(adat->real,
f_mul(adat->imag, r)), n);
917 y = (*func)(
f_sub(adat->imag,
f_mul(adat->real, r)), n);
920 r = (*func)(bdat->real, bdat->imag);
922 x = (*func)(
f_add(
f_mul(adat->real, r), adat->imag), n);
923 y = (*func)(
f_sub(
f_mul(adat->imag, r), adat->real), n);
929 return f_complex_new2(
CLASS_OF(self), x, y);
931 if (k_numeric_p(other) && f_real_p(other)) {
936 return f_complex_new2(
CLASS_OF(self), x, y);
941#define rb_raise_zerodiv() rb_raise(rb_eZeroDivError, "divided by 0")
962#define nucomp_quo rb_complex_div
975 return f_divide(self, other, f_fdiv,
id_fdiv);
1010 VALUE r, theta, nr, ntheta;
1015 theta = f_arg(self);
1017 nr = m_exp_bang(
f_sub(
f_mul(dat->real, m_log_bang(r)),
1018 f_mul(dat->imag, theta)));
1020 f_mul(dat->imag, m_log_bang(r)));
1021 return f_complex_polar(
CLASS_OF(self), nr, ntheta);
1035 VALUE xr = dat->real, xi = dat->imag, zr = xr, zi = xi;
1040 else if (f_zero_p(xr)) {
1053 for (; q = n / 2, r = n % 2, r == 0; n = q) {
1058 comp_mul(zr, zi, xr, xi, &zr, &zi);
1061 return nucomp_s_new_internal(
CLASS_OF(self), zr, zi);
1064 if (k_numeric_p(other) && f_real_p(other)) {
1068 rb_warn(
"in a**b, b may be too big");
1071 theta = f_arg(self);
1074 f_mul(theta, other));
1097 return f_boolcast(f_eqeq_p(adat->real, bdat->real) &&
1098 f_eqeq_p(adat->imag, bdat->imag));
1100 if (k_numeric_p(other) && f_real_p(other)) {
1103 return f_boolcast(f_eqeq_p(dat->real, other) && f_zero_p(dat->imag));
1109nucomp_real_p(
VALUE self)
1112 return(f_zero_p(dat->imag) ?
true :
false);
1132 if (nucomp_real_p(self) && k_numeric_p(other)) {
1133 if (RB_TYPE_P(other,
T_COMPLEX) && nucomp_real_p(other)) {
1137 else if (f_real_p(other)) {
1151 if (k_numeric_p(other) && f_real_p(other))
1174 if (f_zero_p(dat->real)) {
1176 if (RB_FLOAT_TYPE_P(dat->real) && !RB_FLOAT_TYPE_P(dat->imag))
1180 if (f_zero_p(dat->imag)) {
1182 if (!RB_FLOAT_TYPE_P(dat->real) && RB_FLOAT_TYPE_P(dat->imag))
1199nucomp_abs2(
VALUE self)
1203 f_mul(dat->imag, dat->imag));
1233nucomp_rect(
VALUE self)
1248nucomp_polar(
VALUE self)
1277nucomp_false(
VALUE self)
1291nucomp_denominator(
VALUE self)
1316nucomp_numerator(
VALUE self)
1322 cd = nucomp_denominator(self);
1323 return f_complex_new2(
CLASS_OF(self),
1347nucomp_hash(
VALUE self)
1361 f_eqeq_p(self, other));
1370 if (RB_FLOAT_TYPE_P(x)) {
1374 return f_negative_p(x);
1378f_tpositive_p(
VALUE x)
1380 return !f_signbit(x);
1391 impos = f_tpositive_p(dat->imag);
1393 s = (*func)(dat->real);
1417nucomp_to_s(
VALUE self)
1435nucomp_inspect(
VALUE self)
1446#define FINITE_TYPE_P(v) (RB_INTEGER_TYPE_P(v) || RB_TYPE_P(v, T_RATIONAL))
1456rb_complex_finite_p(
VALUE self)
1460 if (f_finite_p(dat->real) && f_finite_p(dat->imag)) {
1479rb_complex_infinite_p(
VALUE self)
1483 if (
NIL_P(f_infinite_p(dat->real)) &&
NIL_P(f_infinite_p(dat->imag))) {
1491nucomp_dumper(
VALUE self)
1511nucomp_marshal_dump(
VALUE self)
1544 return nucomp_s_canonicalize_internal(
rb_cComplex, x, y);
1593nucomp_to_i(
VALUE self)
1601 return f_to_i(dat->real);
1616nucomp_to_f(
VALUE self)
1624 return f_to_f(dat->real);
1641nucomp_to_r(
VALUE self)
1649 return f_to_r(dat->real);
1689nucomp_to_c(
VALUE self)
1701nilclass_to_c(
VALUE self)
1713numeric_to_c(
VALUE self)
1721 return (c ==
'-' || c ==
'+');
1725read_sign(
const char **s,
1741 return isdigit((
unsigned char)c);
1745read_digits(
const char **s,
int strict,
1750 if (!isdecimal(**s))
1753 while (isdecimal(**s) || **s ==
'_') {
1771 }
while (**s ==
'_');
1778 return (c ==
'e' || c ==
'E');
1782read_num(
const char **s,
int strict,
1786 if (!read_digits(s, strict, b))
1794 if (!read_digits(s, strict, b)) {
1800 if (islettere(**s)) {
1805 if (!read_digits(s, strict, b)) {
1814read_den(
const char **s,
int strict,
1817 if (!read_digits(s, strict, b))
1823read_rat_nos(
const char **s,
int strict,
1826 if (!read_num(s, strict, b))
1832 if (!read_den(s, strict, b)) {
1841read_rat(
const char **s,
int strict,
1845 if (!read_rat_nos(s, strict, b))
1853 return (c ==
'i' || c ==
'I' ||
1854 c ==
'j' || c ==
'J');
1862 if (strpbrk(s,
".eE"))
1868read_comp(
const char **s,
int strict,
1869 VALUE *ret,
char **b)
1877 sign = read_sign(s, b);
1879 if (isimagunit(**s)) {
1886 if (!read_rat_nos(s, strict, b)) {
1895 if (isimagunit(**s)) {
1906 st = read_rat(s, strict, b);
1909 !isdecimal(*(bb +
strlen(bb) - 1))) {
1923 sign = read_sign(s, b);
1924 if (isimagunit(**s))
1925 num2 =
INT2FIX((sign ==
'-') ? -1 : + 1);
1927 if (!read_rat_nos(s, strict, b)) {
1934 if (!isimagunit(**s)) {
1950skip_ws(
const char **s)
1952 while (isspace((
unsigned char)**s))
1957parse_comp(
const char *s,
int strict,
VALUE *
num)
1967 if (!read_comp(&s, strict,
num, &b)) {
1983string_to_c_strict(
VALUE self,
int raise)
1993 if (!raise)
return Qnil;
2006 if (!parse_comp(s, 1, &
num)) {
2007 if (!raise)
return Qnil;
2039string_to_c(
VALUE self)
2057 (void)parse_comp(s, 0, &
num);
2063to_complex(
VALUE val)
2072 if (!raise)
return Qnil;
2077 a1 = string_to_c_strict(a1, raise);
2082 a2 = string_to_c_strict(a2, raise);
2110 if (k_numeric_p(a1) && !f_real_p(a1))
2113 if (!k_numeric_p(a1)) {
2116 return to_complex(a1);
2120 if ((k_numeric_p(a1) && k_numeric_p(a2)) &&
2121 (!f_real_p(a1) || !f_real_p(a2)))
2141 return nucomp_s_new(
argc, argv2, klass);
2154 return nucomp_convert(klass, a1, a2,
TRUE);
2166numeric_real(
VALUE self)
2179numeric_imag(
VALUE self)
2191numeric_abs2(
VALUE self)
2193 return f_mul(self, self);
2205numeric_arg(
VALUE self)
2220numeric_rect(
VALUE self)
2234numeric_polar(
VALUE self)
2240 arg = numeric_arg(self);
2242 else if (RB_FLOAT_TYPE_P(self)) {
2244 arg = float_arg(self);
2248 arg = numeric_arg(self);
2265numeric_conj(
VALUE self)
2279float_arg(
VALUE self)
2283 if (f_tpositive_p(self))
2325 id_abs = rb_intern_const(
"abs");
2326 id_arg = rb_intern_const(
"arg");
2329 id_real_p = rb_intern_const(
"real?");
2330 id_i_real = rb_intern_const(
"@real");
2331 id_i_imag = rb_intern_const(
"@image");
2332 id_finite_p = rb_intern_const(
"finite?");
2333 id_infinite_p = rb_intern_const(
"infinite?");
2334 id_rationalize = rb_intern_const(
"rationalize");
2335 id_PI = rb_intern_const(
"PI");
VALUE rb_assoc_new(VALUE car, VALUE cdr)
VALUE rb_str_to_inum(VALUE str, int base, int badcheck)
VALUE rb_cstr_to_inum(const char *str, int base, int badcheck)
#define k_exact_zero_p(x)
VALUE rb_complex_real(VALUE self)
VALUE rb_complex_uminus(VALUE self)
VALUE rb_complex_minus(VALUE self, VALUE other)
VALUE rb_Complex(VALUE x, VALUE y)
VALUE rb_complex_new_polar(VALUE x, VALUE y)
VALUE rb_complex_div(VALUE self, VALUE other)
VALUE rb_complex_plus(VALUE self, VALUE other)
VALUE rb_complex_raw(VALUE x, VALUE y)
VALUE rb_complex_pow(VALUE self, VALUE other)
VALUE rb_complex_arg(VALUE self)
VALUE rb_complex_abs(VALUE self)
VALUE rb_dbl_complex_new(double real, double imag)
Creates a Complex object.
VALUE rb_dbl_complex_new_polar_pi(double abs, double ang)
VALUE rb_flo_is_finite_p(VALUE num)
VALUE rb_complex_imag(VALUE self)
VALUE rb_flo_is_infinite_p(VALUE num)
VALUE rb_complex_new(VALUE x, VALUE y)
VALUE rb_complex_mul(VALUE self, VALUE other)
st_index_t rb_complex_hash(VALUE self)
VALUE rb_complex_conjugate(VALUE self)
VALUE rb_complex_polar(VALUE x, VALUE y)
Our own, locale independent, character handling routines.
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
#define rb_define_singleton_method(klass, mid, func, arity)
Defines klass.mid.
#define rb_define_private_method(klass, mid, func, arity)
Defines klass#mid and makes it private.
#define rb_define_global_function(mid, func, arity)
Defines rb_mKernel #mid.
char * strchr(char *, char)
#define rb_cmpint(cmp, a, b)
#define RSTRING_LEN(string)
#define RSTRING_PTR(string)
void rb_gc_register_mark_object(VALUE obj)
Inform the garbage collector that object is a live Ruby object that should not be moved.
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
void rb_undef_method(VALUE klass, const char *name)
void rb_undef_methods_from(VALUE klass, VALUE super)
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
void rb_raise(VALUE exc, const char *fmt,...)
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *pstate)
Protects a function call from potential global escapes from the function.
void rb_warn(const char *fmt,...)
VALUE rb_convert_type(VALUE, int, const char *, const char *)
Converts an object into another type.
VALUE rb_cObject
Object class.
int rb_opts_exception_p(VALUE opts, int default_value)
VALUE rb_cNilClass
NilClass class.
double rb_str_to_dbl(VALUE, int)
Parses a string representation of a floating point number.
VALUE rb_obj_class(VALUE)
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
VALUE rb_equal(VALUE, VALUE)
This function is an optimized version of calling #==.
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Determines if obj is a kind of c.
double rb_cstr_to_dbl(const char *, int)
Parses a string representation of a floating point number.
VALUE rb_String(VALUE)
Equivalent to Kernel#String in Ruby.
Thin wrapper to ruby/config.h.
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
#define rb_complex_new2(x, y)
#define rb_complex_new1(x)
void rb_provide(const char *)
VALUE rb_num_coerce_bin(VALUE, VALUE, ID)
void rb_must_asciicompat(VALUE)
VALUE rb_str_concat(VALUE, VALUE)
st_index_t rb_memhash(const void *ptr, long len)
void rb_str_modify(VALUE)
#define rb_usascii_str_new2
VALUE rb_const_get(VALUE, ID)
void rb_copy_generic_ivar(VALUE, VALUE)
VALUE rb_ivar_get(VALUE, ID)
VALUE rb_ivar_set(VALUE, ID, VALUE)
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
void rb_define_const(VALUE, const char *, VALUE)
Internal header for Array.
Internal header for Class.
Internal header for Complex.
#define RCOMPLEX_SET_IMAG(cmp, i)
#define RCOMPLEX_SET_REAL(cmp, r)
Internal header for Numeric.
VALUE rb_num_pow(VALUE x, VALUE y)
VALUE rb_int_abs(VALUE num)
VALUE rb_int_uminus(VALUE num)
VALUE rb_float_mul(VALUE x, VALUE y)
VALUE rb_float_plus(VALUE x, VALUE y)
VALUE rb_float_abs(VALUE flt)
VALUE rb_float_uminus(VALUE num)
VALUE rb_float_gt(VALUE x, VALUE y)
int rb_num_negative_p(VALUE)
VALUE rb_float_div(VALUE x, VALUE y)
VALUE rb_int_plus(VALUE x, VALUE y)
VALUE rb_int_gt(VALUE x, VALUE y)
VALUE rb_int_mul(VALUE x, VALUE y)
Internal header for Object.
Internal header for Rational.
VALUE rb_rational_cmp(VALUE self, VALUE other)
VALUE rb_rational_uminus(VALUE self)
VALUE rb_rational_plus(VALUE self, VALUE other)
VALUE rb_float_numerator(VALUE x)
VALUE rb_float_denominator(VALUE x)
VALUE rb_rational_abs(VALUE self)
VALUE rb_cstr_to_rat(const char *, int)
VALUE rb_lcm(VALUE x, VALUE y)
VALUE rb_rational_canonicalize(VALUE x)
VALUE rb_rational_mul(VALUE self, VALUE other)
VALUE rb_numeric_quo(VALUE x, VALUE y)
#define rb_method_basic_definition_p(...)
void rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE(*dumper)(VALUE), VALUE(*loader)(VALUE, VALUE))
Internal header for Math.
VALUE rb_math_log(int argc, const VALUE *argv)
VALUE rb_math_atan2(VALUE, VALUE)
VALUE rb_math_hypot(VALUE, VALUE)
#define RARRAY_AREF(a, i)
#define RGENGC_WB_PROTECTED_COMPLEX
#define RB_INTEGER_TYPE_P(obj)
size_t strlen(const char *)