Ruby
2.7.2p137(2020-10-01revision5445e0435260b449decf2ac16f9d09bae3cafe72)
|
Go to the documentation of this file.
8 #include "ruby/config.h"
11 # define _USE_MATH_DEFINES 1
20 #define ZERO INT2FIX(0)
21 #define ONE INT2FIX(1)
22 #define TWO INT2FIX(2)
24 #define RFLOAT_0 DBL2NUM(0)
28 #if defined(HAVE_SIGNBIT) && defined(__GNUC__) && defined(__sun) && \
35 static ID id_abs, id_arg,
37 id_real_p, id_i_real, id_i_imag,
38 id_finite_p, id_infinite_p, id_rationalize,
40 #define id_to_i idTo_i
41 #define id_to_r idTo_r
42 #define id_negate idUMinus
44 #define id_to_f idTo_f
46 #define id_fdiv idFdiv
48 #define f_boolcast(x) ((x) ? Qtrue : Qfalse)
54 return rb_funcall(x, id_##n, 0);\
59 f_##n(VALUE x, VALUE y)\
61 return rb_funcall(x, id_##n, 1, y);\
64 #define PRESERVE_SIGNEDZERO
127 if (x ==
ONE)
return y;
128 if (y ==
ONE)
return x;
133 if (y ==
ONE)
return x;
138 if (y ==
ONE)
return x;
142 if (y ==
ONE)
return x;
182 return numeric_arg(x);
188 return numeric_arg(x);
238 static bool nucomp_real_p(
VALUE self);
253 return nucomp_real_p(x);
303 f_negative_p(
VALUE x)
314 #define f_positive_p(x) (!f_negative_p(x))
332 #define f_nonzero_p(x) (!f_zero_p(x))
352 f_infinite_p(
VALUE x)
378 #define k_exact_p(x) (!RB_FLOAT_TYPE_P(x))
380 #define k_exact_zero_p(x) (k_exact_p(x) && f_zero_p(x))
382 #define get_dat1(x) \
383 struct RComplex *dat = RCOMPLEX(x)
385 #define get_dat2(x,y) \
386 struct RComplex *adat = RCOMPLEX(x), *bdat = RCOMPLEX(y)
410 return nucomp_s_new_internal(
klass, x,
ZERO);
418 return nucomp_s_new_internal(
klass, x, y);
421 #ifdef CANONICALIZATION_FOR_MATHN
425 nucomp_canonicalization(
int f)
430 #define canonicalization 0
434 nucomp_real_check(
VALUE num)
439 if (!k_numeric_p(num) || !f_real_p(num))
447 int complex_r, complex_i;
448 #ifdef CANONICALIZATION_FOR_MATHN
454 if (!complex_r && !complex_i) {
455 return nucomp_s_new_internal(
klass, real, imag);
457 else if (!complex_r) {
460 return nucomp_s_new_internal(
klass,
461 f_sub(real, dat->imag),
464 else if (!complex_i) {
467 return nucomp_s_new_internal(
klass,
469 f_add(dat->imag, imag));
474 return nucomp_s_new_internal(
klass,
475 f_sub(adat->real, bdat->imag),
476 f_add(adat->imag, bdat->real));
496 nucomp_real_check(real);
500 nucomp_real_check(real);
501 nucomp_real_check(imag);
505 return nucomp_s_canonicalize_internal(
klass, real, imag);
512 return nucomp_s_canonicalize_internal(
klass, x, y);
573 inline static VALUE \
574 m_##n##_bang(VALUE x)\
576 return rb_math_##n(x);\
596 return m_cos_bang(x);
600 f_mul(m_cos_bang(dat->real),
601 m_cosh_bang(dat->imag)),
603 m_sinh_bang(dat->imag)));
611 return m_sin_bang(x);
615 f_mul(m_sin_bang(dat->real),
616 m_cosh_bang(dat->imag)),
617 f_mul(m_cos_bang(dat->real),
618 m_sinh_bang(dat->imag)));
627 if (f_zero_p(x) || f_zero_p(y)) {
658 return nucomp_s_new_internal(
klass, x, y);
660 return nucomp_s_canonicalize_internal(
klass,
670 const double fr =
modf(ang, &fi);
671 int pos = fr == +0.5;
673 if (pos || fr == -0.5) {
674 if ((
modf(fi / 2.0, &fi) != fr) ^ pos)
abs = -
abs;
677 else if (fr == 0.0) {
705 nucomp_real_check(
abs);
709 nucomp_real_check(
abs);
710 nucomp_real_check(
arg);
761 return f_complex_new2(
CLASS_OF(
self),
785 real =
f_add(adat->real, bdat->real);
786 imag =
f_add(adat->imag, bdat->imag);
788 return f_complex_new2(
CLASS_OF(
self), real, imag);
790 if (k_numeric_p(other) && f_real_p(other)) {
793 return f_complex_new2(
CLASS_OF(
self),
794 f_add(dat->real, other), dat->imag);
819 real =
f_sub(adat->real, bdat->real);
820 imag =
f_sub(adat->imag, bdat->imag);
822 return f_complex_new2(
CLASS_OF(
self), real, imag);
824 if (k_numeric_p(other) && f_real_p(other)) {
827 return f_complex_new2(
CLASS_OF(
self),
828 f_sub(dat->real, other), dat->imag);
849 int arzero = f_zero_p(areal);
850 int aizero = f_zero_p(aimag);
851 int brzero = f_zero_p(breal);
852 int bizero = f_zero_p(bimag);
853 *real =
f_sub(safe_mul(areal, breal, arzero, brzero),
854 safe_mul(aimag, bimag, aizero, bizero));
855 *imag =
f_add(safe_mul(areal, bimag, arzero, bizero),
856 safe_mul(aimag, breal, aizero, brzero));
878 comp_mul(adat->real, adat->imag, bdat->real, bdat->imag, &real, &imag);
880 return f_complex_new2(
CLASS_OF(
self), real, imag);
882 if (k_numeric_p(other) && f_real_p(other)) {
885 return f_complex_new2(
CLASS_OF(
self),
886 f_mul(dat->real, other),
887 f_mul(dat->imag, other));
905 r = (*func)(bdat->imag, bdat->real);
907 x = (*func)(
f_add(adat->real,
f_mul(adat->imag, r)),
n);
908 y = (*func)(
f_sub(adat->imag,
f_mul(adat->real, r)),
n);
911 r = (*func)(bdat->real, bdat->imag);
913 x = (*func)(
f_add(
f_mul(adat->real, r), adat->imag),
n);
914 y = (*func)(
f_sub(
f_mul(adat->imag, r), adat->real),
n);
920 return f_complex_new2(
CLASS_OF(
self), x, y);
922 if (k_numeric_p(other) && f_real_p(other)) {
927 return f_complex_new2(
CLASS_OF(
self), x, y);
932 #define rb_raise_zerodiv() rb_raise(rb_eZeroDivError, "divided by 0")
953 #define nucomp_quo rb_complex_div
966 return f_divide(
self, other, f_fdiv,
id_fdiv);
1001 VALUE r, theta, nr, ntheta;
1006 theta = f_arg(
self);
1008 nr = m_exp_bang(
f_sub(
f_mul(dat->real, m_log_bang(r)),
1009 f_mul(dat->imag, theta)));
1011 f_mul(dat->imag, m_log_bang(r)));
1012 return f_complex_polar(
CLASS_OF(
self), nr, ntheta);
1026 VALUE xr = dat->real, xi = dat->imag, zr = xr, zi = xi;
1031 else if (f_zero_p(xr)) {
1044 for (; q =
n / 2, r =
n % 2, r == 0;
n = q) {
1049 comp_mul(zr, zi, xr, xi, &zr, &zi);
1052 return nucomp_s_new_internal(
CLASS_OF(
self), zr, zi);
1055 if (k_numeric_p(other) && f_real_p(other)) {
1059 rb_warn(
"in a**b, b may be too big");
1062 theta = f_arg(
self);
1065 f_mul(theta, other));
1088 return f_boolcast(f_eqeq_p(adat->real, bdat->real) &&
1089 f_eqeq_p(adat->imag, bdat->imag));
1091 if (k_numeric_p(other) && f_real_p(other)) {
1094 return f_boolcast(f_eqeq_p(dat->real, other) && f_zero_p(dat->imag));
1100 nucomp_real_p(
VALUE self)
1103 return(f_zero_p(dat->imag) ?
true :
false);
1123 if (nucomp_real_p(
self) && k_numeric_p(other)) {
1128 else if (f_real_p(other)) {
1142 if (k_numeric_p(other) && f_real_p(other))
1165 if (f_zero_p(dat->real)) {
1171 if (f_zero_p(dat->imag)) {
1190 nucomp_abs2(
VALUE self)
1194 f_mul(dat->imag, dat->imag));
1224 nucomp_rect(
VALUE self)
1239 nucomp_polar(
VALUE self)
1268 nucomp_false(
VALUE self)
1282 nucomp_denominator(
VALUE self)
1307 nucomp_numerator(
VALUE self)
1313 cd = nucomp_denominator(
self);
1314 return f_complex_new2(
CLASS_OF(
self),
1323 nucomp_hash(
VALUE self)
1346 f_eqeq_p(
self, other));
1359 return f_negative_p(x);
1363 f_tpositive_p(
VALUE x)
1365 return !f_signbit(x);
1376 impos = f_tpositive_p(dat->imag);
1378 s = (*func)(dat->real);
1402 nucomp_to_s(
VALUE self)
1420 nucomp_inspect(
VALUE self)
1431 #define FINITE_TYPE_P(v) (RB_INTEGER_TYPE_P(v) || RB_TYPE_P(v, T_RATIONAL))
1441 rb_complex_finite_p(
VALUE self)
1445 if (f_finite_p(dat->real) && f_finite_p(dat->imag)) {
1464 rb_complex_infinite_p(
VALUE self)
1468 if (
NIL_P(f_infinite_p(dat->real)) &&
NIL_P(f_infinite_p(dat->imag))) {
1476 nucomp_dumper(
VALUE self)
1496 nucomp_marshal_dump(
VALUE self)
1529 return nucomp_s_canonicalize_internal(
rb_cComplex, x, y);
1578 nucomp_to_i(
VALUE self)
1586 return f_to_i(dat->real);
1601 nucomp_to_f(
VALUE self)
1609 return f_to_f(dat->real);
1626 nucomp_to_r(
VALUE self)
1634 return f_to_r(dat->real);
1674 nucomp_to_c(
VALUE self)
1686 nilclass_to_c(
VALUE self)
1698 numeric_to_c(
VALUE self)
1708 return (c ==
'-' || c ==
'+');
1712 read_sign(
const char **s,
1728 return isdigit((
unsigned char)c);
1732 read_digits(
const char **s,
int strict,
1737 if (!isdecimal(**s))
1740 while (isdecimal(**s) || **s ==
'_') {
1758 }
while (**s ==
'_');
1765 return (c ==
'e' || c ==
'E');
1769 read_num(
const char **s,
int strict,
1773 if (!read_digits(s, strict, b))
1781 if (!read_digits(s, strict, b)) {
1787 if (islettere(**s)) {
1792 if (!read_digits(s, strict, b)) {
1801 read_den(
const char **s,
int strict,
1804 if (!read_digits(s, strict, b))
1810 read_rat_nos(
const char **s,
int strict,
1813 if (!read_num(s, strict, b))
1819 if (!read_den(s, strict, b)) {
1828 read_rat(
const char **s,
int strict,
1832 if (!read_rat_nos(s, strict, b))
1840 return (c ==
'i' || c ==
'I' ||
1841 c ==
'j' || c ==
'J');
1855 read_comp(
const char **s,
int strict,
1856 VALUE *ret,
char **b)
1864 sign = read_sign(s, b);
1866 if (isimagunit(**s)) {
1868 num =
INT2FIX((sign ==
'-') ? -1 : + 1);
1873 if (!read_rat_nos(s, strict, b)) {
1882 if (isimagunit(**s)) {
1893 st = read_rat(s, strict, b);
1896 !isdecimal(*(bb +
strlen(bb) - 1))) {
1910 sign = read_sign(s, b);
1911 if (isimagunit(**s))
1912 num2 =
INT2FIX((sign ==
'-') ? -1 : + 1);
1914 if (!read_rat_nos(s, strict, b)) {
1921 if (!isimagunit(**s)) {
1937 skip_ws(
const char **s)
1939 while (isspace((
unsigned char)**s))
1944 parse_comp(
const char *s,
int strict,
VALUE *num)
1954 if (!read_comp(&s, strict, num, &b)) {
1970 string_to_c_strict(
VALUE self,
int raise)
1980 if (!
raise)
return Qnil;
1993 if (!parse_comp(s, 1, &num)) {
1994 if (!
raise)
return Qnil;
2026 string_to_c(
VALUE self)
2044 (
void)parse_comp(s, 0, &num);
2050 to_complex(
VALUE val)
2059 if (!
raise)
return Qnil;
2064 a1 = string_to_c_strict(a1,
raise);
2069 a2 = string_to_c_strict(a2,
raise);
2097 if (k_numeric_p(a1) && !f_real_p(a1))
2100 if (!k_numeric_p(a1)) {
2103 return to_complex(a1);
2107 if ((k_numeric_p(a1) && k_numeric_p(a2)) &&
2108 (!f_real_p(a1) || !f_real_p(a2)))
2128 return nucomp_s_new(
argc, argv2,
klass);
2141 return nucomp_convert(
klass, a1, a2,
TRUE);
2153 numeric_real(
VALUE self)
2166 numeric_imag(
VALUE self)
2178 numeric_abs2(
VALUE self)
2180 return f_mul(
self,
self);
2192 numeric_arg(
VALUE self)
2207 numeric_rect(
VALUE self)
2221 numeric_polar(
VALUE self)
2227 arg = numeric_arg(
self);
2231 arg = float_arg(
self);
2235 arg = numeric_arg(
self);
2252 numeric_conj(
VALUE self)
2266 float_arg(
VALUE self)
2270 if (f_tpositive_p(
self))
2313 #define rb_intern(str) rb_intern_const(str)
2324 id_rationalize =
rb_intern(
"rationalize");
VALUE rb_rational_cmp(VALUE self, VALUE other)
VALUE rb_dbl_complex_new_polar_pi(double abs, double ang)
#define INT_NEGATIVE_P(x)
VALUE rb_str_concat(VALUE, VALUE)
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
VALUE rb_assoc_new(VALUE car, VALUE cdr)
VALUE rb_flo_is_finite_p(VALUE num)
int rb_opts_exception_p(VALUE opts, int default_value)
VALUE rb_complex_pow(VALUE self, VALUE other)
void rb_gc_register_mark_object(VALUE obj)
VALUE rb_complex_new_polar(VALUE x, VALUE y)
void rb_warn(const char *fmt,...)
VALUE rb_complex_polar(VALUE x, VALUE y)
VALUE rb_int_abs(VALUE num)
RUBY_EXTERN VALUE rb_cNumeric
char * strchr(char *, char)
VALUE rb_float_gt(VALUE x, VALUE y)
void rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE(*dumper)(VALUE), VALUE(*loader)(VALUE, VALUE))
VALUE rb_complex_div(VALUE self, VALUE other)
double rb_cstr_to_dbl(const char *, int)
Parses a string representation of a floating point number.
VALUE rb_equal(VALUE, VALUE)
Same as Object#===, case equality.
VALUE rb_rational_uminus(VALUE self)
#define RB_TYPE_P(obj, type)
VALUE rb_rational_plus(VALUE self, VALUE other)
#define FIXNUM_ZERO_P(num)
VALUE rb_math_log(int argc, const VALUE *argv)
int rb_num_negative_p(VALUE)
RUBY_EXTERN VALUE rb_cFloat
#define RGENGC_WB_PROTECTED_COMPLEX
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
void rb_str_modify(VALUE)
VALUE rb_complex_mul(VALUE self, VALUE other)
double rb_str_to_dbl(VALUE, int)
Parses a string representation of a floating point number.
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
VALUE rb_cstr_to_inum(const char *str, int base, int badcheck)
VALUE rb_float_abs(VALUE flt)
RUBY_EXTERN VALUE rb_cRational
VALUE rb_numeric_quo(VALUE x, VALUE y)
VALUE rb_flo_is_infinite_p(VALUE num)
RUBY_EXTERN VALUE rb_cInteger
#define rb_cmpint(cmp, a, b)
size_t strlen(const char *)
VALUE rb_math_hypot(VALUE, VALUE)
VALUE rb_int_uminus(VALUE num)
void rb_undef_method(VALUE klass, const char *name)
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *pstate)
Protects a function call from potential global escapes from the function.
#define RUBY_FUNC_EXPORTED
st_index_t rb_memhash(const void *ptr, long len)
VALUE rb_dbl_complex_new(double real, double imag)
Creates a Complex object.
VALUE rb_float_denominator(VALUE x)
void rb_raise(VALUE exc, const char *fmt,...)
VALUE rb_ivar_get(VALUE, ID)
VALUE rb_str_to_inum(VALUE str, int base, int badcheck)
VALUE rb_obj_class(VALUE)
Equivalent to Object#class in Ruby.
RUBY_EXTERN VALUE rb_cNilClass
VALUE rb_float_numerator(VALUE x)
VALUE rb_int_mul(VALUE x, VALUE y)
void rb_undef_methods_from(VALUE klass, VALUE super)
VALUE rb_float_plus(VALUE x, VALUE y)
void rb_must_asciicompat(VALUE)
VALUE rb_complex_uminus(VALUE self)
#define ALLOCV_N(type, v, n)
VALUE rb_lcm(VALUE x, VALUE y)
#define RCOMPLEX_SET_IMAG(cmp, i)
VALUE rb_complex_imag(VALUE self)
VALUE rb_Complex(VALUE x, VALUE y)
VALUE rb_complex_new(VALUE x, VALUE y)
#define RARRAY_AREF(a, i)
VALUE rb_complex_arg(VALUE self)
void rb_copy_generic_ivar(VALUE, VALUE)
VALUE rb_num_coerce_bin(VALUE, VALUE, ID)
#define k_exact_zero_p(x)
VALUE rb_float_div(VALUE x, VALUE y)
RUBY_EXTERN VALUE rb_cObject
VALUE rb_float_mul(VALUE x, VALUE y)
unsigned char buf[MIME_BUF_SIZE]
#define RCOMPLEX_SET_REAL(cmp, r)
void rb_provide(const char *)
VALUE rb_rational_abs(VALUE self)
VALUE rb_complex_raw(VALUE x, VALUE y)
#define rb_complex_new2(x, y)
VALUE rb_num_pow(VALUE x, VALUE y)
VALUE rb_convert_type(VALUE, int, const char *, const char *)
Converts an object into another type.
VALUE rb_math_atan2(VALUE, VALUE)
RUBY_EXTERN VALUE rb_mMath
RUBY_EXTERN VALUE rb_cString
VALUE rb_cstr_to_rat(const char *, int)
VALUE rb_complex_real(VALUE self)
#define OBJ_FREEZE_RAW(x)
#define rb_complex_new1(x)
VALUE rb_complex_conjugate(VALUE self)
void rb_define_const(VALUE, const char *, VALUE)
VALUE rb_String(VALUE)
Equivalent to Kernel#String in Ruby.
VALUE rb_int_gt(VALUE x, VALUE y)
VALUE rb_rational_canonicalize(VALUE x)
#define rb_usascii_str_new2
VALUE rb_complex_minus(VALUE self, VALUE other)
VALUE rb_ivar_set(VALUE, ID, VALUE)
VALUE rb_complex_plus(VALUE self, VALUE other)
VALUE rb_complex_abs(VALUE self)
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
VALUE rb_float_uminus(VALUE num)
#define RB_INTEGER_TYPE_P(obj)
VALUE rb_rational_mul(VALUE self, VALUE other)
#define NEWOBJ_OF(obj, type, klass, flags)
VALUE rb_int_plus(VALUE x, VALUE y)
void rb_define_private_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Determines if obj is a kind of c.
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
#define RB_FLOAT_TYPE_P(obj)
VALUE rb_const_get(VALUE, ID)