• Main Page
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

math.c

Go to the documentation of this file.
00001 /**********************************************************************
00002 
00003   math.c -
00004 
00005   $Author: marcandre $
00006   created at: Tue Jan 25 14:12:56 JST 1994
00007 
00008   Copyright (C) 1993-2007 Yukihiro Matsumoto
00009 
00010 **********************************************************************/
00011 
00012 #include "ruby/ruby.h"
00013 #include <math.h>
00014 #include <errno.h>
00015 
00016 #define numberof(array) (int)(sizeof(array) / sizeof((array)[0]))
00017 
00018 VALUE rb_mMath;
00019 VALUE rb_eMathDomainError;
00020 
00021 extern VALUE rb_to_float(VALUE val);
00022 #define Need_Float(x) do {if (TYPE(x) != T_FLOAT) {(x) = rb_to_float(x);}} while(0)
00023 #define Need_Float2(x,y) do {\
00024     Need_Float(x);\
00025     Need_Float(y);\
00026 } while (0)
00027 
00028 #define domain_error(msg) \
00029     rb_raise(rb_eMathDomainError, "Numerical argument is out of domain - " #msg);
00030 
00031 /*
00032  *  call-seq:
00033  *     Math.atan2(y, x)  -> float
00034  *
00035  *  Computes the arc tangent given <i>y</i> and <i>x</i>. Returns
00036  *  -PI..PI.
00037  *
00038  *    Math.atan2(-0.0, -1.0) #=> -3.141592653589793
00039  *    Math.atan2(-1.0, -1.0) #=> -2.356194490192345
00040  *    Math.atan2(-1.0, 0.0)  #=> -1.5707963267948966
00041  *    Math.atan2(-1.0, 1.0)  #=> -0.7853981633974483
00042  *    Math.atan2(-0.0, 1.0)  #=> -0.0
00043  *    Math.atan2(0.0, 1.0)   #=> 0.0
00044  *    Math.atan2(1.0, 1.0)   #=> 0.7853981633974483
00045  *    Math.atan2(1.0, 0.0)   #=> 1.5707963267948966
00046  *    Math.atan2(1.0, -1.0)  #=> 2.356194490192345
00047  *    Math.atan2(0.0, -1.0)  #=> 3.141592653589793
00048  *
00049  */
00050 
00051 static VALUE
00052 math_atan2(VALUE obj, VALUE y, VALUE x)
00053 {
00054     double dx, dy;
00055     Need_Float2(y, x);
00056     dx = RFLOAT_VALUE(x);
00057     dy = RFLOAT_VALUE(y);
00058     if (dx == 0.0 && dy == 0.0) domain_error("atan2");
00059     if (isinf(dx) && isinf(dy)) domain_error("atan2");
00060     return DBL2NUM(atan2(dy, dx));
00061 }
00062 
00063 
00064 /*
00065  *  call-seq:
00066  *     Math.cos(x)    -> float
00067  *
00068  *  Computes the cosine of <i>x</i> (expressed in radians). Returns
00069  *  -1..1.
00070  */
00071 
00072 static VALUE
00073 math_cos(VALUE obj, VALUE x)
00074 {
00075     Need_Float(x);
00076     return DBL2NUM(cos(RFLOAT_VALUE(x)));
00077 }
00078 
00079 /*
00080  *  call-seq:
00081  *     Math.sin(x)    -> float
00082  *
00083  *  Computes the sine of <i>x</i> (expressed in radians). Returns
00084  *  -1..1.
00085  */
00086 
00087 static VALUE
00088 math_sin(VALUE obj, VALUE x)
00089 {
00090     Need_Float(x);
00091 
00092     return DBL2NUM(sin(RFLOAT_VALUE(x)));
00093 }
00094 
00095 
00096 /*
00097  *  call-seq:
00098  *     Math.tan(x)    -> float
00099  *
00100  *  Returns the tangent of <i>x</i> (expressed in radians).
00101  */
00102 
00103 static VALUE
00104 math_tan(VALUE obj, VALUE x)
00105 {
00106     Need_Float(x);
00107 
00108     return DBL2NUM(tan(RFLOAT_VALUE(x)));
00109 }
00110 
00111 /*
00112  *  call-seq:
00113  *     Math.acos(x)    -> float
00114  *
00115  *  Computes the arc cosine of <i>x</i>. Returns 0..PI.
00116  */
00117 
00118 static VALUE
00119 math_acos(VALUE obj, VALUE x)
00120 {
00121     double d0, d;
00122 
00123     Need_Float(x);
00124     d0 = RFLOAT_VALUE(x);
00125     /* check for domain error */
00126     if (d0 < -1.0 || 1.0 < d0) domain_error("acos");
00127     d = acos(d0);
00128     return DBL2NUM(d);
00129 }
00130 
00131 /*
00132  *  call-seq:
00133  *     Math.asin(x)    -> float
00134  *
00135  *  Computes the arc sine of <i>x</i>. Returns -{PI/2} .. {PI/2}.
00136  */
00137 
00138 static VALUE
00139 math_asin(VALUE obj, VALUE x)
00140 {
00141     double d0, d;
00142 
00143     Need_Float(x);
00144     d0 = RFLOAT_VALUE(x);
00145     /* check for domain error */
00146     if (d0 < -1.0 || 1.0 < d0) domain_error("asin");
00147     d = asin(d0);
00148     return DBL2NUM(d);
00149 }
00150 
00151 /*
00152  *  call-seq:
00153  *     Math.atan(x)    -> float
00154  *
00155  *  Computes the arc tangent of <i>x</i>. Returns -{PI/2} .. {PI/2}.
00156  */
00157 
00158 static VALUE
00159 math_atan(VALUE obj, VALUE x)
00160 {
00161     Need_Float(x);
00162     return DBL2NUM(atan(RFLOAT_VALUE(x)));
00163 }
00164 
00165 #ifndef HAVE_COSH
00166 double
00167 cosh(double x)
00168 {
00169     return (exp(x) + exp(-x)) / 2;
00170 }
00171 #endif
00172 
00173 /*
00174  *  call-seq:
00175  *     Math.cosh(x)    -> float
00176  *
00177  *  Computes the hyperbolic cosine of <i>x</i> (expressed in radians).
00178  */
00179 
00180 static VALUE
00181 math_cosh(VALUE obj, VALUE x)
00182 {
00183     Need_Float(x);
00184 
00185     return DBL2NUM(cosh(RFLOAT_VALUE(x)));
00186 }
00187 
00188 #ifndef HAVE_SINH
00189 double
00190 sinh(double x)
00191 {
00192     return (exp(x) - exp(-x)) / 2;
00193 }
00194 #endif
00195 
00196 /*
00197  *  call-seq:
00198  *     Math.sinh(x)    -> float
00199  *
00200  *  Computes the hyperbolic sine of <i>x</i> (expressed in
00201  *  radians).
00202  */
00203 
00204 static VALUE
00205 math_sinh(VALUE obj, VALUE x)
00206 {
00207     Need_Float(x);
00208     return DBL2NUM(sinh(RFLOAT_VALUE(x)));
00209 }
00210 
00211 #ifndef HAVE_TANH
00212 double
00213 tanh(double x)
00214 {
00215     return sinh(x) / cosh(x);
00216 }
00217 #endif
00218 
00219 /*
00220  *  call-seq:
00221  *     Math.tanh()    -> float
00222  *
00223  *  Computes the hyperbolic tangent of <i>x</i> (expressed in
00224  *  radians).
00225  */
00226 
00227 static VALUE
00228 math_tanh(VALUE obj, VALUE x)
00229 {
00230     Need_Float(x);
00231     return DBL2NUM(tanh(RFLOAT_VALUE(x)));
00232 }
00233 
00234 /*
00235  *  call-seq:
00236  *     Math.acosh(x)    -> float
00237  *
00238  *  Computes the inverse hyperbolic cosine of <i>x</i>.
00239  */
00240 
00241 static VALUE
00242 math_acosh(VALUE obj, VALUE x)
00243 {
00244     double d0, d;
00245 
00246     Need_Float(x);
00247     d0 = RFLOAT_VALUE(x);
00248     /* check for domain error */
00249     if (d0 < 1.0) domain_error("acosh");
00250     d = acosh(d0);
00251     return DBL2NUM(d);
00252 }
00253 
00254 /*
00255  *  call-seq:
00256  *     Math.asinh(x)    -> float
00257  *
00258  *  Computes the inverse hyperbolic sine of <i>x</i>.
00259  */
00260 
00261 static VALUE
00262 math_asinh(VALUE obj, VALUE x)
00263 {
00264     Need_Float(x);
00265     return DBL2NUM(asinh(RFLOAT_VALUE(x)));
00266 }
00267 
00268 /*
00269  *  call-seq:
00270  *     Math.atanh(x)    -> float
00271  *
00272  *  Computes the inverse hyperbolic tangent of <i>x</i>.
00273  */
00274 
00275 static VALUE
00276 math_atanh(VALUE obj, VALUE x)
00277 {
00278     double d0, d;
00279 
00280     Need_Float(x);
00281     d0 = RFLOAT_VALUE(x);
00282     /* check for domain error */
00283     if (d0 <  -1.0 || +1.0 <  d0) domain_error("atanh");
00284     /* check for pole error */
00285     if (d0 == -1.0) return DBL2NUM(-INFINITY);
00286     if (d0 == +1.0) return DBL2NUM(+INFINITY);
00287     d = atanh(d0);
00288     return DBL2NUM(d);
00289 }
00290 
00291 /*
00292  *  call-seq:
00293  *     Math.exp(x)    -> float
00294  *
00295  *  Returns e**x.
00296  *
00297  *    Math.exp(0)       #=> 1.0
00298  *    Math.exp(1)       #=> 2.718281828459045
00299  *    Math.exp(1.5)     #=> 4.4816890703380645
00300  *
00301  */
00302 
00303 static VALUE
00304 math_exp(VALUE obj, VALUE x)
00305 {
00306     Need_Float(x);
00307     return DBL2NUM(exp(RFLOAT_VALUE(x)));
00308 }
00309 
00310 #if defined __CYGWIN__
00311 # include <cygwin/version.h>
00312 # if CYGWIN_VERSION_DLL_MAJOR < 1005
00313 #  define nan(x) nan()
00314 # endif
00315 # define log(x) ((x) < 0.0 ? nan("") : log(x))
00316 # define log10(x) ((x) < 0.0 ? nan("") : log10(x))
00317 #endif
00318 
00319 /*
00320  *  call-seq:
00321  *     Math.log(numeric)    -> float
00322  *     Math.log(num,base)   -> float
00323  *
00324  *  Returns the natural logarithm of <i>numeric</i>.
00325  *  If additional second argument is given, it will be the base
00326  *  of logarithm.
00327  *
00328  *    Math.log(1)          #=> 0.0
00329  *    Math.log(Math::E)    #=> 1.0
00330  *    Math.log(Math::E**3) #=> 3.0
00331  *    Math.log(12,3)       #=> 2.2618595071429146
00332  *
00333  */
00334 
00335 static VALUE
00336 math_log(int argc, VALUE *argv)
00337 {
00338     VALUE x, base;
00339     double d0, d;
00340 
00341     rb_scan_args(argc, argv, "11", &x, &base);
00342     Need_Float(x);
00343     d0 = RFLOAT_VALUE(x);
00344     /* check for domain error */
00345     if (d0 < 0.0) domain_error("log");
00346     /* check for pole error */
00347     if (d0 == 0.0) return DBL2NUM(-INFINITY);
00348     d = log(d0);
00349     if (argc == 2) {
00350         Need_Float(base);
00351         d /= log(RFLOAT_VALUE(base));
00352     }
00353     return DBL2NUM(d);
00354 }
00355 
00356 #ifndef log2
00357 #ifndef HAVE_LOG2
00358 double
00359 log2(double x)
00360 {
00361     return log10(x)/log10(2.0);
00362 }
00363 #else
00364 extern double log2(double);
00365 #endif
00366 #endif
00367 
00368 /*
00369  *  call-seq:
00370  *     Math.log2(numeric)    -> float
00371  *
00372  *  Returns the base 2 logarithm of <i>numeric</i>.
00373  *
00374  *    Math.log2(1)      #=> 0.0
00375  *    Math.log2(2)      #=> 1.0
00376  *    Math.log2(32768)  #=> 15.0
00377  *    Math.log2(65536)  #=> 16.0
00378  *
00379  */
00380 
00381 static VALUE
00382 math_log2(VALUE obj, VALUE x)
00383 {
00384     double d0, d;
00385 
00386     Need_Float(x);
00387     d0 = RFLOAT_VALUE(x);
00388     /* check for domain error */
00389     if (d0 < 0.0) domain_error("log2");
00390     /* check for pole error */
00391     if (d0 == 0.0) return DBL2NUM(-INFINITY);
00392     d = log2(d0);
00393     return DBL2NUM(d);
00394 }
00395 
00396 /*
00397  *  call-seq:
00398  *     Math.log10(numeric)    -> float
00399  *
00400  *  Returns the base 10 logarithm of <i>numeric</i>.
00401  *
00402  *    Math.log10(1)       #=> 0.0
00403  *    Math.log10(10)      #=> 1.0
00404  *    Math.log10(10**100) #=> 100.0
00405  *
00406  */
00407 
00408 static VALUE
00409 math_log10(VALUE obj, VALUE x)
00410 {
00411     double d0, d;
00412 
00413     Need_Float(x);
00414     d0 = RFLOAT_VALUE(x);
00415     /* check for domain error */
00416     if (d0 < 0.0) domain_error("log10");
00417     /* check for pole error */
00418     if (d0 == 0.0) return DBL2NUM(-INFINITY);
00419     d = log10(d0);
00420     return DBL2NUM(d);
00421 }
00422 
00423 /*
00424  *  call-seq:
00425  *     Math.sqrt(numeric)    -> float
00426  *
00427  *  Returns the non-negative square root of <i>numeric</i>.
00428  *
00429  *    0.upto(10) {|x|
00430  *      p [x, Math.sqrt(x), Math.sqrt(x)**2]
00431  *    }
00432  *    #=>
00433  *    [0, 0.0, 0.0]
00434  *    [1, 1.0, 1.0]
00435  *    [2, 1.4142135623731, 2.0]
00436  *    [3, 1.73205080756888, 3.0]
00437  *    [4, 2.0, 4.0]
00438  *    [5, 2.23606797749979, 5.0]
00439  *    [6, 2.44948974278318, 6.0]
00440  *    [7, 2.64575131106459, 7.0]
00441  *    [8, 2.82842712474619, 8.0]
00442  *    [9, 3.0, 9.0]
00443  *    [10, 3.16227766016838, 10.0]
00444  *
00445  */
00446 
00447 static VALUE
00448 math_sqrt(VALUE obj, VALUE x)
00449 {
00450     double d0, d;
00451 
00452     Need_Float(x);
00453     d0 = RFLOAT_VALUE(x);
00454     /* check for domain error */
00455     if (d0 < 0.0) domain_error("sqrt");
00456     if (d0 == 0.0) return DBL2NUM(0.0);
00457     d = sqrt(d0);
00458     return DBL2NUM(d);
00459 }
00460 
00461 /*
00462  *  call-seq:
00463  *     Math.cbrt(numeric)    -> float
00464  *
00465  *  Returns the cube root of <i>numeric</i>.
00466  *
00467  *    -9.upto(9) {|x|
00468  *      p [x, Math.cbrt(x), Math.cbrt(x)**3]
00469  *    }
00470  *    #=>
00471  *    [-9, -2.0800838230519, -9.0]
00472  *    [-8, -2.0, -8.0]
00473  *    [-7, -1.91293118277239, -7.0]
00474  *    [-6, -1.81712059283214, -6.0]
00475  *    [-5, -1.7099759466767, -5.0]
00476  *    [-4, -1.5874010519682, -4.0]
00477  *    [-3, -1.44224957030741, -3.0]
00478  *    [-2, -1.25992104989487, -2.0]
00479  *    [-1, -1.0, -1.0]
00480  *    [0, 0.0, 0.0]
00481  *    [1, 1.0, 1.0]
00482  *    [2, 1.25992104989487, 2.0]
00483  *    [3, 1.44224957030741, 3.0]
00484  *    [4, 1.5874010519682, 4.0]
00485  *    [5, 1.7099759466767, 5.0]
00486  *    [6, 1.81712059283214, 6.0]
00487  *    [7, 1.91293118277239, 7.0]
00488  *    [8, 2.0, 8.0]
00489  *    [9, 2.0800838230519, 9.0]
00490  *
00491  */
00492 
00493 static VALUE
00494 math_cbrt(VALUE obj, VALUE x)
00495 {
00496     Need_Float(x);
00497     return DBL2NUM(cbrt(RFLOAT_VALUE(x)));
00498 }
00499 
00500 /*
00501  *  call-seq:
00502  *     Math.frexp(numeric)    -> [ fraction, exponent ]
00503  *
00504  *  Returns a two-element array containing the normalized fraction (a
00505  *  <code>Float</code>) and exponent (a <code>Fixnum</code>) of
00506  *  <i>numeric</i>.
00507  *
00508  *     fraction, exponent = Math.frexp(1234)   #=> [0.6025390625, 11]
00509  *     fraction * 2**exponent                  #=> 1234.0
00510  */
00511 
00512 static VALUE
00513 math_frexp(VALUE obj, VALUE x)
00514 {
00515     double d;
00516     int exp;
00517 
00518     Need_Float(x);
00519 
00520     d = frexp(RFLOAT_VALUE(x), &exp);
00521     return rb_assoc_new(DBL2NUM(d), INT2NUM(exp));
00522 }
00523 
00524 /*
00525  *  call-seq:
00526  *     Math.ldexp(flt, int) -> float
00527  *
00528  *  Returns the value of <i>flt</i>*(2**<i>int</i>).
00529  *
00530  *     fraction, exponent = Math.frexp(1234)
00531  *     Math.ldexp(fraction, exponent)   #=> 1234.0
00532  */
00533 
00534 static VALUE
00535 math_ldexp(VALUE obj, VALUE x, VALUE n)
00536 {
00537     Need_Float(x);
00538     return DBL2NUM(ldexp(RFLOAT_VALUE(x), NUM2INT(n)));
00539 }
00540 
00541 /*
00542  *  call-seq:
00543  *     Math.hypot(x, y)    -> float
00544  *
00545  *  Returns sqrt(x**2 + y**2), the hypotenuse of a right-angled triangle
00546  *  with sides <i>x</i> and <i>y</i>.
00547  *
00548  *     Math.hypot(3, 4)   #=> 5.0
00549  */
00550 
00551 static VALUE
00552 math_hypot(VALUE obj, VALUE x, VALUE y)
00553 {
00554     Need_Float2(x, y);
00555     return DBL2NUM(hypot(RFLOAT_VALUE(x), RFLOAT_VALUE(y)));
00556 }
00557 
00558 /*
00559  * call-seq:
00560  *    Math.erf(x)  -> float
00561  *
00562  *  Calculates the error function of x.
00563  */
00564 
00565 static VALUE
00566 math_erf(VALUE obj, VALUE x)
00567 {
00568     Need_Float(x);
00569     return DBL2NUM(erf(RFLOAT_VALUE(x)));
00570 }
00571 
00572 /*
00573  * call-seq:
00574  *    Math.erfc(x)  -> float
00575  *
00576  *  Calculates the complementary error function of x.
00577  */
00578 
00579 static VALUE
00580 math_erfc(VALUE obj, VALUE x)
00581 {
00582     Need_Float(x);
00583     return DBL2NUM(erfc(RFLOAT_VALUE(x)));
00584 }
00585 
00586 /*
00587  * call-seq:
00588  *    Math.gamma(x)  -> float
00589  *
00590  *  Calculates the gamma function of x.
00591  *
00592  *  Note that gamma(n) is same as fact(n-1) for integer n > 0.
00593  *  However gamma(n) returns float and can be an approximation.
00594  *
00595  *   def fact(n) (1..n).inject(1) {|r,i| r*i } end
00596  *   1.upto(26) {|i| p [i, Math.gamma(i), fact(i-1)] }
00597  *   #=> [1, 1.0, 1]
00598  *   #   [2, 1.0, 1]
00599  *   #   [3, 2.0, 2]
00600  *   #   [4, 6.0, 6]
00601  *   #   [5, 24.0, 24]
00602  *   #   [6, 120.0, 120]
00603  *   #   [7, 720.0, 720]
00604  *   #   [8, 5040.0, 5040]
00605  *   #   [9, 40320.0, 40320]
00606  *   #   [10, 362880.0, 362880]
00607  *   #   [11, 3628800.0, 3628800]
00608  *   #   [12, 39916800.0, 39916800]
00609  *   #   [13, 479001600.0, 479001600]
00610  *   #   [14, 6227020800.0, 6227020800]
00611  *   #   [15, 87178291200.0, 87178291200]
00612  *   #   [16, 1307674368000.0, 1307674368000]
00613  *   #   [17, 20922789888000.0, 20922789888000]
00614  *   #   [18, 355687428096000.0, 355687428096000]
00615  *   #   [19, 6.402373705728e+15, 6402373705728000]
00616  *   #   [20, 1.21645100408832e+17, 121645100408832000]
00617  *   #   [21, 2.43290200817664e+18, 2432902008176640000]
00618  *   #   [22, 5.109094217170944e+19, 51090942171709440000]
00619  *   #   [23, 1.1240007277776077e+21, 1124000727777607680000]
00620  *   #   [24, 2.5852016738885062e+22, 25852016738884976640000]
00621  *   #   [25, 6.204484017332391e+23, 620448401733239439360000]
00622  *   #   [26, 1.5511210043330954e+25, 15511210043330985984000000]
00623  *
00624  */
00625 
00626 static VALUE
00627 math_gamma(VALUE obj, VALUE x)
00628 {
00629     static const double fact_table[] = {
00630         /* fact(0) */ 1.0,
00631         /* fact(1) */ 1.0,
00632         /* fact(2) */ 2.0,
00633         /* fact(3) */ 6.0,
00634         /* fact(4) */ 24.0,
00635         /* fact(5) */ 120.0,
00636         /* fact(6) */ 720.0,
00637         /* fact(7) */ 5040.0,
00638         /* fact(8) */ 40320.0,
00639         /* fact(9) */ 362880.0,
00640         /* fact(10) */ 3628800.0,
00641         /* fact(11) */ 39916800.0,
00642         /* fact(12) */ 479001600.0,
00643         /* fact(13) */ 6227020800.0,
00644         /* fact(14) */ 87178291200.0,
00645         /* fact(15) */ 1307674368000.0,
00646         /* fact(16) */ 20922789888000.0,
00647         /* fact(17) */ 355687428096000.0,
00648         /* fact(18) */ 6402373705728000.0,
00649         /* fact(19) */ 121645100408832000.0,
00650         /* fact(20) */ 2432902008176640000.0,
00651         /* fact(21) */ 51090942171709440000.0,
00652         /* fact(22) */ 1124000727777607680000.0,
00653         /* fact(23)=25852016738884976640000 needs 56bit mantissa which is
00654          * impossible to represent exactly in IEEE 754 double which have
00655          * 53bit mantissa. */
00656     };
00657     double d0, d;
00658     double intpart, fracpart;
00659     Need_Float(x);
00660     d0 = RFLOAT_VALUE(x);
00661     /* check for domain error */
00662     if (isinf(d0) && signbit(d0)) domain_error("gamma");
00663     fracpart = modf(d0, &intpart);
00664     if (fracpart == 0.0) {
00665         if (intpart < 0) domain_error("gamma");
00666         if (0 < intpart &&
00667             intpart - 1 < (double)numberof(fact_table)) {
00668             return DBL2NUM(fact_table[(int)intpart - 1]);
00669         }
00670     }
00671     d = tgamma(d0);
00672     return DBL2NUM(d);
00673 }
00674 
00675 /*
00676  * call-seq:
00677  *    Math.lgamma(x)  -> [float, -1 or 1]
00678  *
00679  *  Calculates the logarithmic gamma of x and
00680  *  the sign of gamma of x.
00681  *
00682  *  Math.lgamma(x) is same as
00683  *   [Math.log(Math.gamma(x).abs), Math.gamma(x) < 0 ? -1 : 1]
00684  *  but avoid overflow by Math.gamma(x) for large x.
00685  */
00686 
00687 static VALUE
00688 math_lgamma(VALUE obj, VALUE x)
00689 {
00690     double d0, d;
00691     int sign=1;
00692     VALUE v;
00693     Need_Float(x);
00694     d0 = RFLOAT_VALUE(x);
00695     /* check for domain error */
00696     if (isinf(d0)) {
00697         if (signbit(d0)) domain_error("lgamma");
00698         return rb_assoc_new(DBL2NUM(INFINITY), INT2FIX(1));
00699     }
00700     d = lgamma_r(d0, &sign);
00701     v = DBL2NUM(d);
00702     return rb_assoc_new(v, INT2FIX(sign));
00703 }
00704 
00705 
00706 #define exp1(n) \
00707 VALUE \
00708 rb_math_##n(VALUE x)\
00709 {\
00710     return math_##n(rb_mMath, x);\
00711 }
00712 
00713 #define exp2(n) \
00714 VALUE \
00715 rb_math_##n(VALUE x, VALUE y)\
00716 {\
00717     return math_##n(rb_mMath, x, y);\
00718 }
00719 
00720 exp2(atan2)
00721 exp1(cos)
00722 exp1(cosh)
00723 exp1(exp)
00724 exp2(hypot)
00725 
00726 VALUE
00727 rb_math_log(int argc, VALUE *argv)
00728 {
00729     return math_log(argc, argv);
00730 }
00731 
00732 exp1(sin)
00733 exp1(sinh)
00734 exp1(sqrt)
00735 
00736 
00737 /*
00738  *  Document-class: Math::DomainError
00739  *
00740  *  Raised when a mathematical function is evaluated outside of its
00741  *  domain of definition.
00742  *
00743  *  For example, since +cos+ returns values in the range -1..1,
00744  *  its inverse function +acos+ is only defined on that interval:
00745  *
00746  *     Math.acos(42)
00747  *
00748  *  <em>produces:</em>
00749  *
00750  *     Math::DomainError: Numerical argument is out of domain - "acos"
00751  */
00752 
00753 /*
00754  *  The <code>Math</code> module contains module functions for basic
00755  *  trigonometric and transcendental functions. See class
00756  *  <code>Float</code> for a list of constants that
00757  *  define Ruby's floating point accuracy.
00758  */
00759 
00760 
00761 void
00762 Init_Math(void)
00763 {
00764     rb_mMath = rb_define_module("Math");
00765     rb_eMathDomainError = rb_define_class_under(rb_mMath, "DomainError", rb_eStandardError);
00766 
00767 #ifdef M_PI
00768     rb_define_const(rb_mMath, "PI", DBL2NUM(M_PI));
00769 #else
00770     rb_define_const(rb_mMath, "PI", DBL2NUM(atan(1.0)*4.0));
00771 #endif
00772 
00773 #ifdef M_E
00774     rb_define_const(rb_mMath, "E", DBL2NUM(M_E));
00775 #else
00776     rb_define_const(rb_mMath, "E", DBL2NUM(exp(1.0)));
00777 #endif
00778 
00779     rb_define_module_function(rb_mMath, "atan2", math_atan2, 2);
00780     rb_define_module_function(rb_mMath, "cos", math_cos, 1);
00781     rb_define_module_function(rb_mMath, "sin", math_sin, 1);
00782     rb_define_module_function(rb_mMath, "tan", math_tan, 1);
00783 
00784     rb_define_module_function(rb_mMath, "acos", math_acos, 1);
00785     rb_define_module_function(rb_mMath, "asin", math_asin, 1);
00786     rb_define_module_function(rb_mMath, "atan", math_atan, 1);
00787 
00788     rb_define_module_function(rb_mMath, "cosh", math_cosh, 1);
00789     rb_define_module_function(rb_mMath, "sinh", math_sinh, 1);
00790     rb_define_module_function(rb_mMath, "tanh", math_tanh, 1);
00791 
00792     rb_define_module_function(rb_mMath, "acosh", math_acosh, 1);
00793     rb_define_module_function(rb_mMath, "asinh", math_asinh, 1);
00794     rb_define_module_function(rb_mMath, "atanh", math_atanh, 1);
00795 
00796     rb_define_module_function(rb_mMath, "exp", math_exp, 1);
00797     rb_define_module_function(rb_mMath, "log", math_log, -1);
00798     rb_define_module_function(rb_mMath, "log2", math_log2, 1);
00799     rb_define_module_function(rb_mMath, "log10", math_log10, 1);
00800     rb_define_module_function(rb_mMath, "sqrt", math_sqrt, 1);
00801     rb_define_module_function(rb_mMath, "cbrt", math_cbrt, 1);
00802 
00803     rb_define_module_function(rb_mMath, "frexp", math_frexp, 1);
00804     rb_define_module_function(rb_mMath, "ldexp", math_ldexp, 2);
00805 
00806     rb_define_module_function(rb_mMath, "hypot", math_hypot, 2);
00807 
00808     rb_define_module_function(rb_mMath, "erf",  math_erf,  1);
00809     rb_define_module_function(rb_mMath, "erfc", math_erfc, 1);
00810 
00811     rb_define_module_function(rb_mMath, "gamma", math_gamma, 1);
00812     rb_define_module_function(rb_mMath, "lgamma", math_lgamma, 1);
00813 }
00814 

Generated on Wed Sep 8 2010 09:55:56 for Ruby by  doxygen 1.7.1