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)));
196 domain_check_range(d, -1.0, 1.0,
"acos");
223 domain_check_range(d, -1.0, 1.0,
"asin");
251 return DBL2NUM(atan(Get_Double(x)));
258 return (exp(x) + exp(-x)) / 2;
283 return DBL2NUM(cosh(Get_Double(x)));
290 return (exp(x) - exp(-x)) / 2;
315 return DBL2NUM(sinh(Get_Double(x)));
322# if defined(HAVE_SINH) && defined(HAVE_COSH)
323 const double c = cosh(x);
324 if (!isinf(c))
return sinh(x) / c;
326 const double e = exp(x+x);
327 if (!isinf(e))
return (e - 1) / (e + 1);
329 return x > 0 ? 1.0 : -1.0;
354 return DBL2NUM(tanh(Get_Double(x)));
379 domain_check_min(d, 1.0,
"acosh");
403 return DBL2NUM(asinh(Get_Double(x)));
429 domain_check_range(d, -1.0, +1.0,
"atanh");
431 if (d == -1.0)
return DBL2NUM(-HUGE_VAL);
432 if (d == +1.0)
return DBL2NUM(+HUGE_VAL);
460 return DBL2NUM(exp(Get_Double(x)));
463#if defined __CYGWIN__
464# include <cygwin/version.h>
465# if CYGWIN_VERSION_DLL_MAJOR < 1005
468# define log(x) ((x) < 0.0 ? nan("") : log(x))
469# define log10(x) ((x) < 0.0 ? nan("") : log10(x))
473# define M_LN2 0.693147180559945309417232121458176568
476# define M_LN10 2.30258509299404568401799145468436421
479static double math_log1(
VALUE x);
509math_log(
int argc,
const VALUE *argv,
VALUE unused_obj)
511 return rb_math_log(argc, argv);
515rb_math_log(
int argc,
const VALUE *argv)
523 d /= math_log1(base);
529get_double_rshift(
VALUE x,
size_t *pnumbits)
533 if (RB_BIGNUM_TYPE_P(x) && BIGNUM_POSITIVE_P(x) &&
534 DBL_MAX_EXP <= (numbits = rb_absint_numwords(x, 1, NULL))) {
535 numbits -= DBL_MANT_DIG;
536 x = rb_big_rshift(x,
SIZET2NUM(numbits));
542 return Get_Double(x);
549 double d = get_double_rshift(x, &numbits);
551 domain_check_min(d, 0.0,
"log");
553 if (d == 0.0)
return -HUGE_VAL;
555 return log(d) + numbits * M_LN2;
563 return log10(x)/log10(2.0);
566extern double log2(
double);
592 double d = get_double_rshift(x, &numbits);
594 domain_check_min(d, 0.0,
"log2");
596 if (d == 0.0)
return DBL2NUM(-HUGE_VAL);
598 return DBL2NUM(log2(d) + numbits);
623 double d = get_double_rshift(x, &numbits);
625 domain_check_min(d, 0.0,
"log10");
627 if (d == 0.0)
return DBL2NUM(-HUGE_VAL);
629 return DBL2NUM(log10(d) + numbits * log10(2));
658 return rb_math_sqrt(x);
673 return RBOOL(!isnan(f) && signbit(f));
675 return f_negative_p(x);
684 VALUE neg = f_signbit(RCOMPLEX(x)->imag);
685 double re = Get_Double(RCOMPLEX(x)->real), im;
686 d = Get_Double(rb_complex_abs(x));
687 im = sqrt((d - re) / 2.0);
688 re = sqrt((d + re) / 2.0);
693 domain_check_min(d, 0.0,
"sqrt");
694 if (d == 0.0)
return DBL2NUM(0.0);
726 double f = Get_Double(x);
729 if (isfinite(r) && !(f == 0.0 && r == 0.0)) {
730 r = (2.0 * r + (f / r / r)) / 3.0;
770 d = frexp(Get_Double(x), &exp);
834 return DBL2NUM(hypot(Get_Double(x), Get_Double(y)));
859 return DBL2NUM(erf(Get_Double(x)));
884 return DBL2NUM(erfc(Get_Double(x)));
915 static const double fact_table[] = {
935 121645100408832000.0,
936 2432902008176640000.0,
937 51090942171709440000.0,
938 1124000727777607680000.0,
943 enum {NFACT_TABLE = numberof(fact_table)};
948 if (signbit(d)) domain_error(
"gamma");
955 domain_check_min(d, 0.0,
"gamma");
956 if (1.0 <= d && d <= (
double)NFACT_TABLE) {
957 return DBL2NUM(fact_table[(
int)d - 1]);
1010 if (signbit(d)) domain_error(
"lgamma");
1015 return rb_assoc_new(
DBL2NUM(HUGE_VAL), vsign);
1017 v =
DBL2NUM(lgamma_r(d, &sign));
1018 return rb_assoc_new(v,
INT2FIX(sign));
1024rb_math_##n(VALUE x)\
1026 return math_##n(0, x);\
1031rb_math_##n(VALUE x, VALUE y)\
1033 return math_##n(0, x, y);\
#define rb_define_module_function(klass, mid, func, arity)
Defines klass#mid and makes it a module function.
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.
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.
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.