T
Takeshi NISHIMATSU
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,
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,