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)