[ruby-list:45861] numeric.c に Float#copysign を書き加えてみました
From:
NISHIMATSU Takeshi <t_nissie@...>
Date:
2009-02-08 12:02:32 UTC
List:
ruby-list #45861
西松と申します。
練習がてらnumeric.cにFloat#copysignを書き加えてみました。
こんなことができます:
$ ./miniruby -e 'p 32.1.copysign(1.0)'
32.1
$ ./miniruby -e 'p 32.1.copysign(0.0)'
32.1
$ ./miniruby -e 'p 32.1.copysign(-0.0)'
-32.1
$ ./miniruby -e 'p 32.1.copysign('-0.0')'
-32.1
$ ./miniruby -e 'p 32.1.copysign('123')'
32.1
$ ./miniruby -e 'p 32.1.copysign('-123')'
-32.1
$ ./miniruby -e 'p 32.1.copysign(-123)'
-32.1
$ ./miniruby -e 'p -32.1.copysign(0.0)'
32.1
$ ./miniruby -e 'p -32.1.copysign(Rational(1,2))'' ; echo $?
1
$
質問なのですが、Rationalのようなto_fが定義されているものが引数に
来たときにも動くようにするには、下のexit(1);にしているところを
どのように書けばよいのでしょうか。
あと、numeric.cのコメントに1つtypo(+→-)を見つけました。
$ svn diff
Index: numeric.c
===================================================================
--- numeric.c (revision 22120)
+++ numeric.c (working copy)
@@ -595,7 +595,7 @@
/*
* call-seq:
- * float + other => float
+ * float - other => float
*
* Returns a new float which is the difference of <code>float</code>
* and <code>other</code>.
@@ -1141,6 +1141,44 @@
/*
* call-seq:
+ * x.copysign(y) => float
+ *
+ * Returns a value whose absolute value matches that of x, but whose sign matches that of <i>y</i>.
+ *
+ * ( 34.56).copysign(-0.0) #=> -34.56
+ * (-34.56).copysign( 1.0) #=> 34.56
+ * (-34.56).copysign( 1 ) #=> 34.56
+ * (-34.56).copysign( 1111111111111111111111111111111111111111111111111111111111111111111111111)
+ * #=> 34.56
+ *
+ */
+
+static VALUE
+flo_copysign(VALUE x, VALUE y)
+{
+ double yd, val;
+ switch (TYPE(y)) {
+ case T_FIXNUM:
+ yd = (double)FIX2LONG(y);
+ break;
+ case T_BIGNUM:
+ yd = rb_big2dbl(y);
+ break;
+ case T_FLOAT:
+ yd = RFLOAT_VALUE(y);
+ break;
+ case T_STRING:
+ yd = rb_str_to_dbl(y, Qfalse);
+ break;
+ default:
+ exit(1); /* rb_funcall(y, 'to_f', 0, 0)??? */
+ }
+ val = copysign(RFLOAT_VALUE(x),yd);
+ return DBL2NUM(val);
+}
+
+/*
+ * call-seq:
* flt.zero? -> true or false
*
* Returns <code>true</code> if <i>flt</i> is 0.0.
@@ -3262,6 +3300,7 @@
rb_define_method(rb_cFloat, "hash", flo_hash, 0);
rb_define_method(rb_cFloat, "to_f", flo_to_f, 0);
rb_define_method(rb_cFloat, "abs", flo_abs, 0);
+ rb_define_method(rb_cFloat, "copysign", flo_copysign, 1);
rb_define_method(rb_cFloat, "magnitude", flo_abs, 0);
rb_define_method(rb_cFloat, "zero?", flo_zero_p, 0);