12 #include "ruby/internal/config.h"
15 # define _USE_MATH_DEFINES 1
23 #include "internal/bignum.h"
24 #include "internal/complex.h"
25 #include "internal/math.h"
26 #include "internal/object.h"
27 #include "internal/vm.h"
32 #define Get_Double(x) rb_num_to_dbl(x)
34 #define domain_error(msg) \
35 rb_raise(rb_eMathDomainError, "Numerical argument is out of domain - " msg)
36 #define domain_check_min(val, min, msg) \
37 ((val) < (min) ? domain_error(msg) : (void)0)
38 #define domain_check_range(val, min, max, msg) \
39 ((val) < (min) || (max) < (val) ? domain_error(msg) : (void)0)
67 if (dx == 0.0 && dy == 0.0) {
75 if (isinf(dx) && isinf(dy)) {
78 const double dz = (3.0 * M_PI / 4.0);
82 const double dz = (M_PI / 4.0);
115 return DBL2NUM(cos(Get_Double(x)));
142 return DBL2NUM(sin(Get_Double(x)));
170 return DBL2NUM(tan(Get_Double(x)));
173 #define math_arc(num, func) \
175 d = Get_Double((num)); \
176 domain_check_range(d, -1.0, 1.0, #func); \
177 return DBL2NUM(func(d));
249 return DBL2NUM(atan(Get_Double(x)));
256 return (exp(x) + exp(-x)) / 2;
281 return DBL2NUM(cosh(Get_Double(x)));
288 return (exp(x) - exp(-x)) / 2;
313 return DBL2NUM(sinh(Get_Double(x)));
320 # if defined(HAVE_SINH) && defined(HAVE_COSH)
321 const double c = cosh(x);
322 if (!isinf(c))
return sinh(x) / c;
324 const double e = exp(x+x);
325 if (!isinf(e))
return (e - 1) / (e + 1);
327 return x > 0 ? 1.0 : -1.0;
352 return DBL2NUM(tanh(Get_Double(x)));
377 domain_check_min(d, 1.0,
"acosh");
401 return DBL2NUM(asinh(Get_Double(x)));
427 domain_check_range(d, -1.0, +1.0,
"atanh");
429 if (d == -1.0)
return DBL2NUM(-HUGE_VAL);
430 if (d == +1.0)
return DBL2NUM(+HUGE_VAL);
458 return DBL2NUM(exp(Get_Double(x)));
461 #if defined __CYGWIN__
462 # include <cygwin/version.h>
463 # if CYGWIN_VERSION_DLL_MAJOR < 1005
464 # define nan(x) nan()
466 # define log(x) ((x) < 0.0 ? nan("") : log(x))
467 # define log10(x) ((x) < 0.0 ? nan("") : log10(x))
471 # define M_LN2 0.693147180559945309417232121458176568
474 # define M_LN10 2.30258509299404568401799145468436421
506 math_log(
int argc,
const VALUE *argv,
VALUE unused_obj)
508 return rb_math_log(argc, argv);
512 get_double_rshift(
VALUE x,
size_t *pnumbits)
516 if (RB_BIGNUM_TYPE_P(x) && BIGNUM_POSITIVE_P(x) &&
518 numbits -= DBL_MANT_DIG;
525 return Get_Double(x);
529 math_log_split(
VALUE x,
size_t *numbits)
531 double d = get_double_rshift(x, numbits);
533 domain_check_min(d, 0.0,
"log");
537 #if defined(log2) || defined(HAVE_LOG2)
538 # define log_intermediate log2
540 # define log_intermediate log10
541 double log2(
double x);
545 rb_math_log(
int argc,
const VALUE *argv)
552 d = math_log_split(x, &numbits);
555 double b = math_log_split(base, &numbits_2);
564 d = log_intermediate(d) / log_intermediate(b);
565 d += (numbits - numbits_2) / log2(b);
569 if (d == 0.0)
return DBL2NUM(-HUGE_VAL);
571 d += numbits * M_LN2;
581 return log10(x)/log10(2.0);
584 extern double log2(
double);
610 double d = get_double_rshift(x, &numbits);
612 domain_check_min(d, 0.0,
"log2");
614 if (d == 0.0)
return DBL2NUM(-HUGE_VAL);
616 return DBL2NUM(log2(d) + numbits);
641 double d = get_double_rshift(x, &numbits);
643 domain_check_min(d, 0.0,
"log10");
645 if (d == 0.0)
return DBL2NUM(-HUGE_VAL);
647 return DBL2NUM(log10(d) + numbits * log10(2));
676 return rb_math_sqrt(x);
680 f_negative_p(
VALUE x)
691 return RBOOL(!isnan(f) && signbit(f));
693 return f_negative_p(x);
697 rb_math_sqrt(
VALUE x)
702 VALUE neg = f_signbit(RCOMPLEX(x)->imag);
703 double re = Get_Double(RCOMPLEX(x)->real), im;
705 im = sqrt((d - re) / 2.0);
706 re = sqrt((d + re) / 2.0);
711 domain_check_min(d, 0.0,
"sqrt");
712 if (d == 0.0)
return DBL2NUM(0.0);
744 double f = Get_Double(x);
746 #if defined __GLIBC__
747 if (isfinite(r) && !(f == 0.0 && r == 0.0)) {
748 r = (2.0 * r + (f / r / r)) / 3.0;
788 d = frexp(Get_Double(x), &exp);
852 return DBL2NUM(hypot(Get_Double(x), Get_Double(y)));
877 return DBL2NUM(erf(Get_Double(x)));
902 return DBL2NUM(erfc(Get_Double(x)));
933 static const double fact_table[] = {
953 121645100408832000.0,
954 2432902008176640000.0,
955 51090942171709440000.0,
956 1124000727777607680000.0,
961 enum {NFACT_TABLE = numberof(fact_table)};
966 if (signbit(d)) domain_error(
"gamma");
973 domain_check_min(d, 0.0,
"gamma");
974 if (1.0 <= d && d <= (
double)NFACT_TABLE) {
975 return DBL2NUM(fact_table[(
int)d - 1]);
1028 if (signbit(d)) domain_error(
"lgamma");
1035 v =
DBL2NUM(lgamma_r(d, &sign));
1042 rb_math_##n(VALUE x)\
1044 return math_##n(0, x);\
1049 rb_math_##n(VALUE x, VALUE y)\
1051 return math_##n(0, x, y);\
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
VALUE rb_define_module(const char *name)
Defines a top-level module.
void rb_define_module_function(VALUE module, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a module function for a module.
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.
#define T_COMPLEX
Old name of RUBY_T_COMPLEX.
#define RFLOAT_VALUE
Old name of rb_float_value.
#define INT2FIX
Old name of RB_INT2FIX.
#define SIZET2NUM
Old name of RB_SIZE2NUM.
#define NUM2INT
Old name of RB_NUM2INT.
#define INT2NUM
Old name of RB_INT2NUM.
#define FIX2LONG
Old name of RB_FIX2LONG.
#define DBL2NUM
Old name of rb_float_new.
#define FIXNUM_P
Old name of RB_FIXNUM_P.
VALUE rb_eStandardError
StandardError exception.
VALUE rb_eMathDomainError
Math::DomainError exception.
VALUE rb_mMath
Math module.
VALUE rb_funcall(VALUE recv, ID mid, int n,...)
Calls a method.
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Identical to rb_ary_new_from_values(), except it expects exactly two parameters.
size_t rb_absint_numwords(VALUE val, size_t word_numbits, size_t *nlz_bits_ret)
Calculates the number of words needed represent the absolute value of the passed integer.
VALUE rb_big_rshift(VALUE x, VALUE y)
Performs shift right.
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.
VALUE rb_complex_abs(VALUE z)
Queries the absolute (or the magnitude) of the passed object.
void rb_define_const(VALUE klass, const char *name, VALUE val)
Defines a Ruby level constant under a namespace.
#define InitVM(ext)
This macro is for internal use.
uintptr_t VALUE
Type that represents a Ruby object.
static bool RB_FLOAT_TYPE_P(VALUE obj)
Queries if the object is an instance of rb_cFloat.
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.