Forum: Ruby lacking in mathematical functions

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Takeshi NISHIMATSU (Guest)
on 2009-05-06 10:43
(Received via mailing list)
Do you want more mathematical functions in Ruby?
I do! Here is a list of mathematical functions
Ruby does not have. Please add your favorites.

This issue was discussed in Japanese in
[ruby-list:44246], [ruby-list:45859] and
[ruby-dev:37947].


C99 has, Ruby does not:
 cbrt      cube root function.
 expm1     exp(x)-1.
 lgamma    log(|Gamma(x)|). How should we
           treat "extern int signgam" in <math.h>?
 tgamma    Gamma(x)
 cproj     project into Riemann Sphere

Other special functions:
 Bessel functions (Gnuplot has Bessel functions.)
 Beta function
 Zeta function

Bug in sqrt(Complex):
 Math::sqrt(Complex(-4.0,-0.0)) => (0.0+2.0i)
 Math::sqrt(Complex(-4.0, 0.0)) => (0.0+2.0i)
 It can be fixed easily with signbit or copysign.

Sign (treatment of -0.0, especially):
 signbit   test sign. Already implemented in complex.c.
           x.negative? and x.positive? may be a good idea.
 copysign  copy sign of a number


Here is my quick hack of copysign:
--- numeric.c   (revision 23350)
+++ numeric.c   (working copy)
@@ -439,6 +439,46 @@

 /*
  *  call-seq:
+ *     num.copysign(other)   => num
+ *
+ *  Copy the sign of other to num
+ *
+ */
+
+static VALUE
+num_copysign(VALUE x, VALUE y)
+{
+    double fy;
+
+    switch (TYPE(y)) {
+      case T_FIXNUM:
+       fy = (double)FIX2LONG(y);
+       break;
+      case T_BIGNUM:
+       fy = rb_big2dbl(y);
+       break;
+      case T_FLOAT:
+       fy = RFLOAT_VALUE(y);
+       break;
+      default:
+       return rb_num_coerce_bin(x, y, 'copysign');
+    }
+
+    switch (TYPE(x)) {
+      case T_FLOAT:
+       return DBL2NUM(copysign(RFLOAT_VALUE(x), fy));
+       break;
+      default:
+       if (copysign(1.0,fy)<0.0) {
+    return rb_funcall(rb_funcall(x, rb_intern("abs"), 0),
rb_intern("-@"), 0);
+  } else {
+    return rb_funcall(x, rb_intern("abs"), 0);
+  }
+    }
+}
+
+/*
+ *  call-seq:
  *     num.zero?    => true or false
  *
  *  Returns <code>true</code> if <i>num</i> has a zero value.
@@ -3184,6 +3224,8 @@
     rb_define_method(rb_cNumeric, "magnitude", num_abs, 0);
     rb_define_method(rb_cNumeric, "to_int", num_to_int, 0);

+    rb_define_method(rb_cNumeric, "copysign", num_copysign, 1);
+
     rb_define_method(rb_cNumeric, "real?", num_real_p, 0);
     rb_define_method(rb_cNumeric, "integer?", num_int_p, 0);
     rb_define_method(rb_cNumeric, "zero?", num_zero_p, 0);

Ciao, ciao,
This topic is locked and can not be replied to.