Main Page | Modules | Alphabetical List | Data Structures | File List | Data Fields | Globals

math.c

Go to the documentation of this file.
00001 /**********************************************************************
00002 
00003   math.c -
00004 
00005   $Author: dave $
00006   $Date: 2003/12/28 15:43:33 $
00007   created at: Tue Jan 25 14:12:56 JST 1994
00008 
00009   Copyright (C) 1993-2003 Yukihiro Matsumoto
00010 
00011 **********************************************************************/
00012 
00013 #include "ruby.h"
00014 #include <math.h>
00015 #include <errno.h>
00016 
00017 VALUE rb_mMath;
00018 
00019 #define Need_Float(x) (x) = rb_Float(x)
00020 #define Need_Float2(x,y) do {\
00021     Need_Float(x);\
00022     Need_Float(y);\
00023 } while (0)
00024 
00025 
00026 /*
00027  *  call-seq:
00028  *     Math.atan2(y, x)  => float
00029  *  
00030  *  Computes the arc tangent given <i>y</i> and <i>x</i>. Returns
00031  *  -PI..PI.
00032  *     
00033  */
00034 
00035 static VALUE
00036 math_atan2(obj, y, x)
00037     VALUE obj, x, y;
00038 {
00039     Need_Float2(y, x);
00040     return rb_float_new(atan2(RFLOAT(y)->value, RFLOAT(x)->value));
00041 }
00042 
00043 
00044 
00045 /*
00046  *  call-seq:
00047  *     Math.cos(x)    => float
00048  *  
00049  *  Computes the cosine of <i>x</i> (expressed in radians). Returns
00050  *  -1..1.
00051  */
00052 
00053 static VALUE
00054 math_cos(obj, x)
00055     VALUE obj, x;
00056 {
00057     Need_Float(x);
00058     return rb_float_new(cos(RFLOAT(x)->value));
00059 }
00060 
00061 /*
00062  *  call-seq:
00063  *     Math.sin(x)    => float
00064  *  
00065  *  Computes the sine of <i>x</i> (expressed in radians). Returns
00066  *  -1..1.
00067  */
00068 
00069 static VALUE
00070 math_sin(obj, x)
00071     VALUE obj, x;
00072 {
00073     Need_Float(x);
00074 
00075     return rb_float_new(sin(RFLOAT(x)->value));
00076 }
00077 
00078 
00079 /*
00080  *  call-seq:
00081  *     Math.tan(x)    => float
00082  *  
00083  *  Returns the tangent of <i>x</i> (expressed in radians).
00084  */
00085 
00086 static VALUE
00087 math_tan(obj, x)
00088     VALUE obj, x;
00089 {
00090     Need_Float(x);
00091 
00092     return rb_float_new(tan(RFLOAT(x)->value));
00093 }
00094 
00095 /*
00096  *  call-seq:
00097  *     Math.acos(x)    => float
00098  *  
00099  *  Computes the arc cosine of <i>x</i>. Returns 0..PI.
00100  */
00101 
00102 static VALUE
00103 math_acos(obj, x)
00104     VALUE obj, x;
00105 {
00106     double d;
00107 
00108     Need_Float(x);
00109     errno = 0;
00110     d = acos(RFLOAT(x)->value);
00111     if (errno) {
00112         rb_sys_fail("acos");
00113     }
00114     return rb_float_new(d);
00115 }
00116 
00117 /*
00118  *  call-seq:
00119  *     Math.asin(x)    => float
00120  *  
00121  *  Computes the arc sine of <i>x</i>. Returns 0..PI.
00122  */
00123 
00124 static VALUE
00125 math_asin(obj, x)
00126     VALUE obj, x;
00127 {
00128     double d;
00129 
00130     Need_Float(x);
00131     errno = 0;
00132     d = asin(RFLOAT(x)->value);
00133     if (errno) {
00134         rb_sys_fail("asin");
00135     }
00136     return rb_float_new(d);
00137 }
00138 
00139 /*
00140  *  call-seq:
00141  *     Math.atan(x)    => float
00142  *  
00143  *  Computes the arc tangent of <i>x</i>. Returns -{PI/2} .. {PI/2}.
00144  */
00145 
00146 static VALUE
00147 math_atan(obj, x)
00148     VALUE obj, x;
00149 {
00150     Need_Float(x);
00151     return rb_float_new(atan(RFLOAT(x)->value));
00152 }
00153 
00154 #ifndef HAVE_COSH
00155 double
00156 cosh(x)
00157     double x;
00158 {
00159     return (exp(x) + exp(-x)) / 2;
00160 }
00161 #endif
00162 
00163 /*
00164  *  call-seq:
00165  *     Math.cosh(x)    => float
00166  *  
00167  *  Computes the hyperbolic cosine of <i>x</i> (expressed in radians).
00168  */
00169 
00170 static VALUE
00171 math_cosh(obj, x)
00172     VALUE obj, x;
00173 {
00174     Need_Float(x);
00175     
00176     return rb_float_new(cosh(RFLOAT(x)->value));
00177 }
00178 
00179 #ifndef HAVE_SINH
00180 double
00181 sinh(x)
00182     double x;
00183 {
00184     return (exp(x) - exp(-x)) / 2;
00185 }
00186 #endif
00187 
00188 /*
00189  *  call-seq:
00190  *     Math.sinh(x)    => float
00191  *  
00192  *  Computes the hyperbolic sine of <i>x</i> (expressed in
00193  *  radians).
00194  */
00195 
00196 static VALUE
00197 math_sinh(obj, x)
00198     VALUE obj, x;
00199 {
00200     Need_Float(x);
00201     return rb_float_new(sinh(RFLOAT(x)->value));
00202 }
00203 
00204 #ifndef HAVE_TANH
00205 double
00206 tanh(x)
00207     double x;
00208 {
00209     return sinh(x) / cosh(x);
00210 }
00211 #endif
00212 
00213 /*
00214  *  call-seq:
00215  *     Math.tanh()    => float
00216  *  
00217  *  Computes the hyperbolic tangent of <i>x</i> (expressed in
00218  *  radians).
00219  */
00220 
00221 static VALUE
00222 math_tanh(obj, x)
00223     VALUE obj, x;
00224 {
00225     Need_Float(x);
00226     return rb_float_new(tanh(RFLOAT(x)->value));
00227 }
00228 
00229 /*
00230  *  call-seq:
00231  *     Math.acosh(x)    => float
00232  *  
00233  *  Computes the inverse hyperbolic cosine of <i>x</i>.
00234  */
00235 
00236 static VALUE
00237 math_acosh(obj, x)
00238     VALUE obj, x;
00239 {
00240     double d;
00241 
00242     Need_Float(x);
00243     errno = 0;
00244     d = acosh(RFLOAT(x)->value);
00245     if (errno) {
00246         rb_sys_fail("acosh");
00247     }
00248     return rb_float_new(d);
00249 }
00250 
00251 /*
00252  *  call-seq:
00253  *     Math.asinh(x)    => float
00254  *  
00255  *  Computes the inverse hyperbolic sine of <i>x</i>.
00256  */
00257 
00258 static VALUE
00259 math_asinh(obj, x)
00260     VALUE obj, x;
00261 {
00262     Need_Float(x);
00263     return rb_float_new(asinh(RFLOAT(x)->value));
00264 }
00265 
00266 /*
00267  *  call-seq:
00268  *     Math.atanh(x)    => float
00269  *  
00270  *  Computes the inverse hyperbolic tangent of <i>x</i>.
00271  */
00272 
00273 static VALUE
00274 math_atanh(obj, x)
00275     VALUE obj, x;
00276 {
00277     double d;
00278 
00279     Need_Float(x);
00280     errno = 0;
00281     d = atanh(RFLOAT(x)->value);
00282     if (errno) {
00283         rb_sys_fail("atanh");
00284     }
00285     return rb_float_new(d);
00286 }
00287 
00288 /*
00289  *  call-seq:
00290  *     Math.exp(x)    => float
00291  *  
00292  *  Returns e**x.
00293  */
00294 
00295 static VALUE
00296 math_exp(obj, x)
00297     VALUE obj, x;
00298 {
00299     Need_Float(x);
00300     return rb_float_new(exp(RFLOAT(x)->value));
00301 }
00302 
00303 #if defined __CYGWIN__
00304 # include <cygwin/version.h>
00305 # if CYGWIN_VERSION_DLL_MAJOR < 1005
00306 #  define nan(x) nan()
00307 # endif
00308 # define log(x) ((x) < 0.0 ? nan("") : log(x))
00309 # define log10(x) ((x) < 0.0 ? nan("") : log10(x))
00310 #endif
00311 
00312 /*
00313  *  call-seq:
00314  *     Math.log(numeric)    => float
00315  *  
00316  *  Returns the natural logarithm of <i>numeric</i>.
00317  */
00318 
00319 static VALUE
00320 math_log(obj, x)
00321     VALUE obj, x;
00322 {
00323     double d;
00324 
00325     Need_Float(x);
00326     errno = 0;
00327     d = log(RFLOAT(x)->value);
00328     if (errno) {
00329         rb_sys_fail("log");
00330     }
00331     return rb_float_new(d);
00332 }
00333 
00334 /*
00335  *  call-seq:
00336  *     Math.log10(numeric)    => float
00337  *  
00338  *  Returns the base 10 logarithm of <i>numeric</i>.
00339  */
00340 
00341 static VALUE
00342 math_log10(obj, x)
00343     VALUE obj, x;
00344 {
00345     double d;
00346 
00347     Need_Float(x);
00348     errno = 0;
00349     d = log10(RFLOAT(x)->value);
00350     if (errno) {
00351         rb_sys_fail("log10");
00352     }
00353     return rb_float_new(d);
00354 }
00355 
00356 /*
00357  *  call-seq:
00358  *     Math.sqrt(numeric)    => float
00359  *  
00360  *  Returns the non-negative square root of <i>numeric</i>. Raises
00361  *  <code>ArgError</code> if <i>numeric</i> is less than zero.
00362  */
00363 
00364 static VALUE
00365 math_sqrt(obj, x)
00366     VALUE obj, x;
00367 {
00368     double d;
00369 
00370     Need_Float(x);
00371     errno = 0;
00372     d = sqrt(RFLOAT(x)->value);
00373     if (errno) {
00374         rb_sys_fail("sqrt");
00375     }
00376     return rb_float_new(d);
00377 }
00378 
00379 /*
00380  *  call-seq:
00381  *     Math.frexp(numeric)    => [ fraction, exponent ]
00382  *  
00383  *  Returns a two-element array containing the normalized fraction (a
00384  *  <code>Float</code>) and exponent (a <code>Fixnum</code>) of
00385  *  <i>numeric</i>.
00386  *     
00387  *     fraction, exponent = Math.frexp(1234)   #=> [0.6025390625, 11]
00388  *     fraction * 2**exponent                  #=> 1234.0
00389  */
00390 
00391 static VALUE
00392 math_frexp(obj, x)
00393     VALUE obj, x;
00394 {
00395     double d;
00396     int exp;
00397 
00398     Need_Float(x);
00399     
00400     d = frexp(RFLOAT(x)->value, &exp);
00401     return rb_assoc_new(rb_float_new(d), INT2NUM(exp));
00402 }
00403 
00404 /*
00405  *  call-seq:
00406  *     Math.ldexp(flt, int) -> float
00407  *  
00408  *  Returns the value of <i>flt</i>*(2**<i>int</i>).
00409  *     
00410  *     fraction, exponent = Math.frexp(1234)
00411  *     Math.ldexp(fraction, exponent)   #=> 1234.0
00412  */
00413 
00414 static VALUE
00415 math_ldexp(obj, x, n)
00416     VALUE obj, x, n;
00417 {
00418     Need_Float(x);
00419     return rb_float_new(ldexp(RFLOAT(x)->value, NUM2INT(n)));
00420 }
00421 
00422 /*
00423  *  call-seq:
00424  *     Math.hypot(x, y)    => float
00425  *  
00426  *  Returns sqrt(x**2 + y**2), the hypotenuse of a right-angled triangle
00427  *  with sides <i>x</i> and <i>y</i>.
00428  *     
00429  *     Math.hypot(3, 4)   #=> 5.0
00430  */
00431 
00432 static VALUE
00433 math_hypot(obj, x, y)
00434     VALUE obj, x, y;
00435 {
00436     Need_Float2(x, y);
00437     return rb_float_new(hypot(RFLOAT(x)->value, RFLOAT(y)->value));
00438 }
00439 
00440 /*
00441  * call-seq:
00442  *    Math.erf(x)  => float
00443  *
00444  *  Calculates the error function of x.
00445  */
00446 
00447 static VALUE
00448 math_erf(obj, x)
00449     VALUE obj, x;
00450 {
00451     Need_Float(x);
00452     return rb_float_new(erf(RFLOAT(x)->value));
00453 }
00454 
00455 /*
00456  * call-seq:
00457  *    Math.erfc(x)  => float
00458  *
00459  *  Calculates the complementary error function of x.
00460  */
00461 
00462 static VALUE
00463 math_erfc(obj, x)
00464     VALUE obj, x;
00465 {
00466     Need_Float(x);
00467     return rb_float_new(erfc(RFLOAT(x)->value));
00468 }
00469 
00470 /*
00471  *  The <code>Math</code> module contains module functions for basic
00472  *  trigonometric and transcendental functions. See class
00473  *  <code>Float</code> for a list of constants that
00474  *  define Ruby's floating point accuracy.
00475  */     
00476 
00477 
00478 void
00479 Init_Math()
00480 {
00481     rb_mMath = rb_define_module("Math");
00482 
00483 #ifdef M_PI
00484     rb_define_const(rb_mMath, "PI", rb_float_new(M_PI));
00485 #else
00486     rb_define_const(rb_mMath, "PI", rb_float_new(atan(1.0)*4.0));
00487 #endif
00488 
00489 #ifdef M_E
00490     rb_define_const(rb_mMath, "E", rb_float_new(M_E));
00491 #else
00492     rb_define_const(rb_mMath, "E", rb_float_new(exp(1.0)));
00493 #endif
00494 
00495     rb_define_module_function(rb_mMath, "atan2", math_atan2, 2);
00496     rb_define_module_function(rb_mMath, "cos", math_cos, 1);
00497     rb_define_module_function(rb_mMath, "sin", math_sin, 1);
00498     rb_define_module_function(rb_mMath, "tan", math_tan, 1);
00499 
00500     rb_define_module_function(rb_mMath, "acos", math_acos, 1);
00501     rb_define_module_function(rb_mMath, "asin", math_asin, 1);
00502     rb_define_module_function(rb_mMath, "atan", math_atan, 1);
00503 
00504     rb_define_module_function(rb_mMath, "cosh", math_cosh, 1);
00505     rb_define_module_function(rb_mMath, "sinh", math_sinh, 1);
00506     rb_define_module_function(rb_mMath, "tanh", math_tanh, 1);
00507 
00508     rb_define_module_function(rb_mMath, "acosh", math_acosh, 1);
00509     rb_define_module_function(rb_mMath, "asinh", math_asinh, 1);
00510     rb_define_module_function(rb_mMath, "atanh", math_atanh, 1);
00511 
00512     rb_define_module_function(rb_mMath, "exp", math_exp, 1);
00513     rb_define_module_function(rb_mMath, "log", math_log, 1);
00514     rb_define_module_function(rb_mMath, "log10", math_log10, 1);
00515     rb_define_module_function(rb_mMath, "sqrt", math_sqrt, 1);
00516 
00517     rb_define_module_function(rb_mMath, "frexp", math_frexp, 1);
00518     rb_define_module_function(rb_mMath, "ldexp", math_ldexp, 2);
00519 
00520     rb_define_module_function(rb_mMath, "hypot", math_hypot, 2);
00521 
00522     rb_define_module_function(rb_mMath, "erf",  math_erf,  1);
00523     rb_define_module_function(rb_mMath, "erfc", math_erfc, 1);
00524 }
00525 

Generated on Wed Jan 18 23:32:04 2006 for Ruby by doxygen 1.3.5