(linenum→info "unix/slp.c:2238")

ruby/1.9.0/math.c

    1: /**********************************************************************
    2: 
    3:   math.c -
    4: 
    5:   $Author: naruse $
    6:   $Date: 2007-11-28 18:22:57 +0900 (Wed, 28 Nov 2007) $
    7:   created at: Tue Jan 25 14:12:56 JST 1994
    8: 
    9:   Copyright (C) 1993-2007 Yukihiro Matsumoto
   10: 
   11: **********************************************************************/
   12: 
   13: #include "ruby/ruby.h"
   14: #include <math.h>
   15: #include <errno.h>
   16: 
   17: VALUE rb_mMath;
   18: 
   19: #define Need_Float(x) (x) = rb_Float(x)
   20: #define Need_Float2(x,y) do {\
   21:     Need_Float(x);\
   22:     Need_Float(y);\
   23: } while (0)
   24: 
   25: static void
   26: domain_check(double x, char *msg)
   27: {
   28:     while(1) {
   29:         if (errno) {
   30:             rb_sys_fail(msg);
   31:         }
   32:         if (isnan(x)) {
   33: #if defined(EDOM)
   34:             errno = EDOM;
   35: #elif defined(ERANGE)
   36:             errno = ERANGE;
   37: #endif
   38:             continue;
   39:         }
   40:         break;
   41:     }
   42: }
   43: 
   44: 
   45: /*
   46:  *  call-seq:
   47:  *     Math.atan2(y, x)  => float
   48:  *  
   49:  *  Computes the arc tangent given <i>y</i> and <i>x</i>. Returns
   50:  *  -PI..PI.
   51:  *     
   52:  */
   53: 
   54: static VALUE
   55: math_atan2(VALUE obj, VALUE y, VALUE x)
   56: {
   57:     Need_Float2(y, x);
   58:     return DOUBLE2NUM(atan2(RFLOAT_VALUE(y), RFLOAT_VALUE(x)));
   59: }
   60: 
   61: 
   62: /*
   63:  *  call-seq:
   64:  *     Math.cos(x)    => float
   65:  *  
   66:  *  Computes the cosine of <i>x</i> (expressed in radians). Returns
   67:  *  -1..1.
   68:  */
   69: 
   70: static VALUE
   71: math_cos(VALUE obj, VALUE x)
   72: {
   73:     Need_Float(x);
   74:     return DOUBLE2NUM(cos(RFLOAT_VALUE(x)));
   75: }
   76: 
   77: /*
   78:  *  call-seq:
   79:  *     Math.sin(x)    => float
   80:  *  
   81:  *  Computes the sine of <i>x</i> (expressed in radians). Returns
   82:  *  -1..1.
   83:  */
   84: 
   85: static VALUE
   86: math_sin(VALUE obj, VALUE x)
   87: {
   88:     Need_Float(x);
   89: 
   90:     return DOUBLE2NUM(sin(RFLOAT_VALUE(x)));
   91: }
   92: 
   93: 
   94: /*
   95:  *  call-seq:
   96:  *     Math.tan(x)    => float
   97:  *  
   98:  *  Returns the tangent of <i>x</i> (expressed in radians).
   99:  */
  100: 
  101: static VALUE
  102: math_tan(VALUE obj, VALUE x)
  103: {
  104:     Need_Float(x);
  105: 
  106:     return DOUBLE2NUM(tan(RFLOAT_VALUE(x)));
  107: }
  108: 
  109: /*
  110:  *  call-seq:
  111:  *     Math.acos(x)    => float
  112:  *  
  113:  *  Computes the arc cosine of <i>x</i>. Returns 0..PI.
  114:  */
  115: 
  116: static VALUE
  117: math_acos(VALUE obj, VALUE x)
  118: {
  119:     double d;
  120: 
  121:     Need_Float(x);
  122:     errno = 0;
  123:     d = acos(RFLOAT_VALUE(x));
  124:     domain_check(d, "acos");
  125:     return DOUBLE2NUM(d);
  126: }
  127: 
  128: /*
  129:  *  call-seq:
  130:  *     Math.asin(x)    => float
  131:  *  
  132:  *  Computes the arc sine of <i>x</i>. Returns 0..PI.
  133:  */
  134: 
  135: static VALUE
  136: math_asin(VALUE obj, VALUE x)
  137: {
  138:     double d;
  139: 
  140:     Need_Float(x);
  141:     errno = 0;
  142:     d = asin(RFLOAT_VALUE(x));
  143:     domain_check(d, "asin");
  144:     return DOUBLE2NUM(d);
  145: }
  146: 
  147: /*
  148:  *  call-seq:
  149:  *     Math.atan(x)    => float
  150:  *  
  151:  *  Computes the arc tangent of <i>x</i>. Returns -{PI/2} .. {PI/2}.
  152:  */
  153: 
  154: static VALUE
  155: math_atan(VALUE obj, VALUE x)
  156: {
  157:     Need_Float(x);
  158:     return DOUBLE2NUM(atan(RFLOAT_VALUE(x)));
  159: }
  160: 
  161: #ifndef HAVE_COSH
  162: double
  163: cosh(double x)
  164: {
  165:     return (exp(x) + exp(-x)) / 2;
  166: }
  167: #endif
  168: 
  169: /*
  170:  *  call-seq:
  171:  *     Math.cosh(x)    => float
  172:  *  
  173:  *  Computes the hyperbolic cosine of <i>x</i> (expressed in radians).
  174:  */
  175: 
  176: static VALUE
  177: math_cosh(VALUE obj, VALUE x)
  178: {
  179:     Need_Float(x);
  180:     
  181:     return DOUBLE2NUM(cosh(RFLOAT_VALUE(x)));
  182: }
  183: 
  184: #ifndef HAVE_SINH
  185: double
  186: sinh(double x)
  187: {
  188:     return (exp(x) - exp(-x)) / 2;
  189: }
  190: #endif
  191: 
  192: /*
  193:  *  call-seq:
  194:  *     Math.sinh(x)    => float
  195:  *  
  196:  *  Computes the hyperbolic sine of <i>x</i> (expressed in
  197:  *  radians).
  198:  */
  199: 
  200: static VALUE
  201: math_sinh(VALUE obj, VALUE x)
  202: {
  203:     Need_Float(x);
  204:     return DOUBLE2NUM(sinh(RFLOAT_VALUE(x)));
  205: }
  206: 
  207: #ifndef HAVE_TANH
  208: double
  209: tanh(double x)
  210: {
  211:     return sinh(x) / cosh(x);
  212: }
  213: #endif
  214: 
  215: /*
  216:  *  call-seq:
  217:  *     Math.tanh()    => float
  218:  *  
  219:  *  Computes the hyperbolic tangent of <i>x</i> (expressed in
  220:  *  radians).
  221:  */
  222: 
  223: static VALUE
  224: math_tanh(VALUE obj, VALUE x)
  225: {
  226:     Need_Float(x);
  227:     return DOUBLE2NUM(tanh(RFLOAT_VALUE(x)));
  228: }
  229: 
  230: /*
  231:  *  call-seq:
  232:  *     Math.acosh(x)    => float
  233:  *  
  234:  *  Computes the inverse hyperbolic cosine of <i>x</i>.
  235:  */
  236: 
  237: static VALUE
  238: math_acosh(VALUE obj, VALUE x)
  239: {
  240:     double d;
  241: 
  242:     Need_Float(x);
  243:     errno = 0;
  244:     d = acosh(RFLOAT_VALUE(x));
  245:     domain_check(d, "acosh");
  246:     return DOUBLE2NUM(d);
  247: }
  248: 
  249: /*
  250:  *  call-seq:
  251:  *     Math.asinh(x)    => float
  252:  *  
  253:  *  Computes the inverse hyperbolic sine of <i>x</i>.
  254:  */
  255: 
  256: static VALUE
  257: math_asinh(VALUE obj, VALUE x)
  258: {
  259:     Need_Float(x);
  260:     return DOUBLE2NUM(asinh(RFLOAT_VALUE(x)));
  261: }
  262: 
  263: /*
  264:  *  call-seq:
  265:  *     Math.atanh(x)    => float
  266:  *  
  267:  *  Computes the inverse hyperbolic tangent of <i>x</i>.
  268:  */
  269: 
  270: static VALUE
  271: math_atanh(VALUE obj, VALUE x)
  272: {
  273:     double d;
  274: 
  275:     Need_Float(x);
  276:     errno = 0;
  277:     d = atanh(RFLOAT_VALUE(x));
  278:     domain_check(d, "atanh");
  279:     return DOUBLE2NUM(d);
  280: }
  281: 
  282: /*
  283:  *  call-seq:
  284:  *     Math.exp(x)    => float
  285:  *  
  286:  *  Returns e**x.
  287:  */
  288: 
  289: static VALUE
  290: math_exp(VALUE obj, VALUE x)
  291: {
  292:     Need_Float(x);
  293:     return DOUBLE2NUM(exp(RFLOAT_VALUE(x)));
  294: }
  295: 
  296: #if defined __CYGWIN__
  297: # include <cygwin/version.h>
  298: # if CYGWIN_VERSION_DLL_MAJOR < 1005
  299: #  define nan(x) nan()
  300: # endif
  301: # define log(x) ((x) < 0.0 ? nan("") : log(x))
  302: # define log10(x) ((x) < 0.0 ? nan("") : log10(x))
  303: #endif
  304: 
  305: /*
  306:  *  call-seq:
  307:  *     Math.log(numeric)    => float
  308:  *     Math.log(num,base)   => float
  309:  *  
  310:  *  Returns the natural logarithm of <i>numeric</i>.
  311:  *  If additional second argument is given, it will be the base
  312:  *  of logarithm.
  313:  */
  314: 
  315: static VALUE
  316: math_log(int argc, VALUE *argv)
  317: {
  318:     VALUE x, base;
  319:     double d;
  320: 
  321:     rb_scan_args(argc, argv, "11", &x, &base);
  322:     Need_Float(x);
  323:     errno = 0;
  324:     d = log(RFLOAT_VALUE(x));
  325:     if (!NIL_P(base)) {
  326:         Need_Float(base);
  327:         d /= log(RFLOAT_VALUE(base));
  328:     }
  329:     domain_check(d, "log");
  330:     return DOUBLE2NUM(d);
  331: }
  332: 
  333: #ifndef log2
  334: #ifndef HAVE_LOG2
  335: double
  336: log2(double x)
  337: {
  338:     return log10(x)/log10(2.0);
  339: }
  340: #else
  341: extern double log2(double);
  342: #endif
  343: #endif
  344: 
  345: /*
  346:  *  call-seq:
  347:  *     Math.log2(numeric)    => float
  348:  *  
  349:  *  Returns the base 2 logarithm of <i>numeric</i>.
  350:  */
  351: 
  352: static VALUE
  353: math_log2(VALUE obj, VALUE x)
  354: {
  355:     double d;
  356: 
  357:     Need_Float(x);
  358:     errno = 0;
  359:     d = log2(RFLOAT_VALUE(x));
  360:     if (errno) {
  361:         rb_sys_fail("log2");
  362:     }
  363:     return DOUBLE2NUM(d);
  364: }
  365: 
  366: /*
  367:  *  call-seq:
  368:  *     Math.log10(numeric)    => float
  369:  *  
  370:  *  Returns the base 10 logarithm of <i>numeric</i>.
  371:  */
  372: 
  373: static VALUE
  374: math_log10(VALUE obj, VALUE x)
  375: {
  376:     double d;
  377: 
  378:     Need_Float(x);
  379:     errno = 0;
  380:     d = log10(RFLOAT_VALUE(x));
  381:     domain_check(d, "log10");
  382:     return DOUBLE2NUM(d);
  383: }
  384: 
  385: /*
  386:  *  call-seq:
  387:  *     Math.sqrt(numeric)    => float
  388:  *  
  389:  *  Returns the non-negative square root of <i>numeric</i>.
  390:  */
  391: 
  392: static VALUE
  393: math_sqrt(VALUE obj, VALUE x)
  394: {
  395:     double d;
  396: 
  397:     Need_Float(x);
  398:     errno = 0;
  399:     d = sqrt(RFLOAT_VALUE(x));
  400:     domain_check(d, "sqrt");
  401:     return DOUBLE2NUM(d);
  402: }
  403: 
  404: /*
  405:  *  call-seq:
  406:  *     Math.frexp(numeric)    => [ fraction, exponent ]
  407:  *  
  408:  *  Returns a two-element array containing the normalized fraction (a
  409:  *  <code>Float</code>) and exponent (a <code>Fixnum</code>) of
  410:  *  <i>numeric</i>.
  411:  *     
  412:  *     fraction, exponent = Math.frexp(1234)   #=> [0.6025390625, 11]
  413:  *     fraction * 2**exponent                  #=> 1234.0
  414:  */
  415: 
  416: static VALUE
  417: math_frexp(VALUE obj, VALUE x)
  418: {
  419:     double d;
  420:     int exp;
  421: 
  422:     Need_Float(x);
  423:     
  424:     d = frexp(RFLOAT_VALUE(x), &exp);
  425:     return rb_assoc_new(DOUBLE2NUM(d), INT2NUM(exp));
  426: }
  427: 
  428: /*
  429:  *  call-seq:
  430:  *     Math.ldexp(flt, int) -> float
  431:  *  
  432:  *  Returns the value of <i>flt</i>*(2**<i>int</i>).
  433:  *     
  434:  *     fraction, exponent = Math.frexp(1234)
  435:  *     Math.ldexp(fraction, exponent)   #=> 1234.0
  436:  */
  437: 
  438: static VALUE
  439: math_ldexp(VALUE obj, VALUE x, VALUE n)
  440: {
  441:     Need_Float(x);
  442:     return DOUBLE2NUM(ldexp(RFLOAT_VALUE(x), NUM2INT(n)));
  443: }
  444: 
  445: /*
  446:  *  call-seq:
  447:  *     Math.hypot(x, y)    => float
  448:  *  
  449:  *  Returns sqrt(x**2 + y**2), the hypotenuse of a right-angled triangle
  450:  *  with sides <i>x</i> and <i>y</i>.
  451:  *     
  452:  *     Math.hypot(3, 4)   #=> 5.0
  453:  */
  454: 
  455: static VALUE
  456: math_hypot(VALUE obj, VALUE x, VALUE y)
  457: {
  458:     Need_Float2(x, y);
  459:     return DOUBLE2NUM(hypot(RFLOAT_VALUE(x), RFLOAT_VALUE(y)));
  460: }
  461: 
  462: /*
  463:  * call-seq:
  464:  *    Math.erf(x)  => float
  465:  *
  466:  *  Calculates the error function of x.
  467:  */
  468: 
  469: static VALUE
  470: math_erf(VALUE obj, VALUE x)
  471: {
  472:     Need_Float(x);
  473:     return DOUBLE2NUM(erf(RFLOAT_VALUE(x)));
  474: }
  475: 
  476: /*
  477:  * call-seq:
  478:  *    Math.erfc(x)  => float
  479:  *
  480:  *  Calculates the complementary error function of x.
  481:  */
  482: 
  483: static VALUE
  484: math_erfc(VALUE obj, VALUE x)
  485: {
  486:     Need_Float(x);
  487:     return DOUBLE2NUM(erfc(RFLOAT_VALUE(x)));
  488: }
  489: 
  490: /*
  491:  *  The <code>Math</code> module contains module functions for basic
  492:  *  trigonometric and transcendental functions. See class
  493:  *  <code>Float</code> for a list of constants that
  494:  *  define Ruby's floating point accuracy.
  495:  */     
  496: 
  497: 
  498: void
  499: Init_Math(void)
  500: {
  501:     rb_mMath = rb_define_module("Math");
  502: 
  503: #ifdef M_PI
  504:     rb_define_const(rb_mMath, "PI", DOUBLE2NUM(M_PI));
  505: #else
  506:     rb_define_const(rb_mMath, "PI", DOUBLE2NUM(atan(1.0)*4.0));
  507: #endif
  508: 
  509: #ifdef M_E
  510:     rb_define_const(rb_mMath, "E", DOUBLE2NUM(M_E));
  511: #else
  512:     rb_define_const(rb_mMath, "E", DOUBLE2NUM(exp(1.0)));
  513: #endif
  514: 
  515:     rb_define_module_function(rb_mMath, "atan2", math_atan2, 2);
  516:     rb_define_module_function(rb_mMath, "cos", math_cos, 1);
  517:     rb_define_module_function(rb_mMath, "sin", math_sin, 1);
  518:     rb_define_module_function(rb_mMath, "tan", math_tan, 1);
  519: 
  520:     rb_define_module_function(rb_mMath, "acos", math_acos, 1);
  521:     rb_define_module_function(rb_mMath, "asin", math_asin, 1);
  522:     rb_define_module_function(rb_mMath, "atan", math_atan, 1);
  523: 
  524:     rb_define_module_function(rb_mMath, "cosh", math_cosh, 1);
  525:     rb_define_module_function(rb_mMath, "sinh", math_sinh, 1);
  526:     rb_define_module_function(rb_mMath, "tanh", math_tanh, 1);
  527: 
  528:     rb_define_module_function(rb_mMath, "acosh", math_acosh, 1);
  529:     rb_define_module_function(rb_mMath, "asinh", math_asinh, 1);
  530:     rb_define_module_function(rb_mMath, "atanh", math_atanh, 1);
  531: 
  532:     rb_define_module_function(rb_mMath, "exp", math_exp, 1);
  533:     rb_define_module_function(rb_mMath, "log", math_log, -1);
  534:     rb_define_module_function(rb_mMath, "log2", math_log2, 1);
  535:     rb_define_module_function(rb_mMath, "log10", math_log10, 1);
  536:     rb_define_module_function(rb_mMath, "sqrt", math_sqrt, 1);
  537: 
  538:     rb_define_module_function(rb_mMath, "frexp", math_frexp, 1);
  539:     rb_define_module_function(rb_mMath, "ldexp", math_ldexp, 2);
  540: 
  541:     rb_define_module_function(rb_mMath, "hypot", math_hypot, 2);
  542: 
  543:     rb_define_module_function(rb_mMath, "erf",  math_erf,  1);
  544:     rb_define_module_function(rb_mMath, "erfc", math_erfc, 1);
  545: }
1
Syntax (Markdown)