斎藤です。

BigDecimalにはBigDecimal#dupが存在しますが、1.8の方針から見ると
望ましくないと思います。
また、BigDecimal#to_fはdupのaliasとして、つまりself(と同じ値)を
そのまま返すよう定義されていますが、やはりFloatを返すべきでしょう。

以上2点を修正してみました。パッチではとりあえず、dupを
USE_MUTABLE_METHODの中に入れる形にして、ドキュメントからは
削除しました。

以下、ドキュメントの修正とまとめてパッチです。小林さん、
取り込んでいただけますでしょうか。

# 値がFloatに収まらないときは、RangeErrorより警告のみの方が
# 良かったりするのでしょうか…エラーにしている箇所が多そう
# だったので、とりあえずそうしてみました。


Index: bigdecimal.c
===================================================================
RCS file: /src/ruby/ext/bigdecimal/bigdecimal.c,v
retrieving revision 1.9
diff -u -r1.9 bigdecimal.c
--- bigdecimal.c 1 Jul 2003 14:14:18 -0000 1.9
+++ bigdecimal.c 12 Jul 2003 17:58:50 -0000
@@ -31,11 +31,13 @@
  */

 #include <ctype.h>
+#include <errno.h>
+#include <float.h>
+#include <math.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include "ruby.h"
-#include "math.h"
 #include "version.h"

 /* #define USE_MUTABLE_METHOD */
@@ -442,6 +444,30 @@
 }

 static VALUE
+BigDecimal_to_f(VALUE self)
+{
+    ENTER(1);
+    Real *p;
+    double d, d2;
+    S_LONG e;
+
+    GUARD_OBJ(p,GetVpValue(self,1));
+    VpVtoD(&d, &e, p);
+    if(d == 0.0 || isinf(d) || isnan(d))
+        return rb_float_new(d);
+    errno = 0;
+    d2 = pow(10.0, e);
+    if(errno == ERANGE || (d2 == 0.0 && d != 0.0)
+       || d > DBL_MAX / d2 || d < DBL_MIN / d2) {
+        U_LONG nc = VpNumOfChars(p)+1;
+        char *psz = ALLOCA_N(char, nc);
+        VpToString(p, psz, 0);
+        rb_raise(rb_eRangeError, "BigDecimal %s out of Float range", psz);
+    }
+    return rb_float_new(d*d2);
+}
+
+static VALUE
 BigDecimal_induced_from(VALUE self, VALUE x)
 {
     Real *p = GetVpValue(x,1);
@@ -867,19 +893,6 @@
 }

 static VALUE
-BigDecimal_dup(VALUE self)
-{
-    ENTER(5);
-    Real *c, *a;
-    U_LONG mx;
-    GUARD_OBJ(a,GetVpValue(self,1));
-    mx = a->Prec *(VpBaseFig() + 1);
-    GUARD_OBJ(c,VpCreateRbObject(mx, "0"));
-    VpAsgn(c, a, 1);
-    return ToValue(c);
-}
-
-static VALUE
 BigDecimal_abs(VALUE self)
 {
     ENTER(5);
@@ -1348,6 +1361,19 @@
     f = VpMult(cv,av,bv);
     return INT2NUM(f);
 }
+
+static VALUE
+BigDecimal_dup(VALUE self)
+{
+    ENTER(5);
+    Real *c, *a;
+    U_LONG mx;
+    GUARD_OBJ(a,GetVpValue(self,1));
+    mx = a->Prec *(VpBaseFig() + 1);
+    GUARD_OBJ(c,VpCreateRbObject(mx, "0"));
+    VpAsgn(c, a, 1);
+    return ToValue(c);
+}
 #endif /* USE_MUTABLE_METHOD */

 void
@@ -1417,8 +1443,7 @@
     rb_define_method(rb_cBigDecimal, "modulo", BigDecimal_mod, 1);
     rb_define_method(rb_cBigDecimal, "remainder", BigDecimal_remainder, 1);
     rb_define_method(rb_cBigDecimal, "divmod", BigDecimal_divmod, 1);
-    rb_define_method(rb_cBigDecimal, "dup", BigDecimal_dup, 0);
-    rb_define_method(rb_cBigDecimal, "to_f", BigDecimal_dup, 0); /* to_f
=== dup */
+    rb_define_method(rb_cBigDecimal, "to_f", BigDecimal_to_f, 0);
     rb_define_method(rb_cBigDecimal, "abs", BigDecimal_abs, 0);
     rb_define_method(rb_cBigDecimal, "sqrt", BigDecimal_sqrt, 1);
     rb_define_method(rb_cBigDecimal, "fix", BigDecimal_fix, 0);
@@ -1457,6 +1482,7 @@
     rb_define_singleton_method(rb_cBigDecimal, "sub!", BigDecimal_sub3, 3);
     rb_define_singleton_method(rb_cBigDecimal, "mult!", BigDecimal_mult3,
3);
     rb_define_singleton_method(rb_cBigDecimal, "div!",BigDecimal_divmod4,
4);
+    rb_define_method(rb_cBigDecimal, "dup", BigDecimal_dup, 0);
 #endif /* USE_MUTABLE_METHOD */
 }

@@ -3415,6 +3441,21 @@
         *d = VpGetDoubleNegZero();
         *e = 0;
         goto Exit;
+    } else
+    if(VpIsPosInf(m)) {
+        *d = VpGetDoublePosInf();
+        *e = 0;
+        goto Exit;
+    } else
+    if(VpIsNegInf(m)) {
+        *d = VpGetDoubleNegInf();
+        *e = 0;
+        goto Exit;
+    } else
+    if(VpIsNaN(m)) {
+        *d = VpGetDoubleNaN();
+        *e = 0;
+        goto Exit;
     }
     ind_m = 0;
     mm = Min(fig,(m->Prec));
Index: bigdecimal_en.html
===================================================================
RCS file: /src/ruby/ext/bigdecimal/bigdecimal_en.html,v
retrieving revision 1.4
diff -u -r1.4 bigdecimal_en.html
--- bigdecimal_en.html 27 Jun 2003 04:38:57 -0000 1.4
+++ bigdecimal_en.html 12 Jul 2003 17:58:50 -0000
@@ -394,8 +394,7 @@

 </BLOCKQUOTE>
 <LI><B>to_f</B></LI><BLOCKQUOTE>
-same as dup method.
-creates a new BigDecimal object having same value.
+creates a new Float object having same value.
 </BLOCKQUOTE>

 </BLOCKQUOTE>
@@ -455,10 +454,6 @@
 '0.314E1' is the value,4 is the number of the significant digits,
 and 12 is the maximum number of the significant digits
 the object can hold.
-
-</BLOCKQUOTE>
-<LI><B>dup</B></LI><BLOCKQUOTE>
-creates a new BigDecimal object having same value.

 </BLOCKQUOTE>
 <LI><B>sqrt</B></LI><BLOCKQUOTE>
Index: bigdecimal_ja.html
===================================================================
RCS file: /src/ruby/ext/bigdecimal/bigdecimal_ja.html,v
retrieving revision 1.4
diff -u -r1.4 bigdecimal_ja.html
--- bigdecimal_ja.html 27 Jun 2003 04:38:57 -0000 1.4
+++ bigdecimal_ja.html 12 Jul 2003 17:58:51 -0000
@@ -374,8 +374,7 @@
 a が Infinity や NaN のとき、i は nil になります。
 </BLOCKQUOTE>
 <LI><B>to_f</B></LI><BLOCKQUOTE>
-dup と全く同じです。
-同じ値の BigDecimal オブジェクトを生成します。
+同じ値の Float オブジェクトを生成します。
 </BLOCKQUOTE>
 <LI><B>to_s[(n)]</B></LI><BLOCKQUOTE>
 文字列に変換します("0.xxxxxEn"の形になります)。<BR>
@@ -444,9 +443,6 @@
 次の4は現在の有効桁数(表示より若干大きいことがあります)、
 最後はオブジェクトが取り得る最大桁数になります。

-</BLOCKQUOTE>
-<LI><B>dup</B></LI><BLOCKQUOTE>
-同じ値の BigDecimal オブジェクトを生成します。
 </BLOCKQUOTE>
 <LI><B>sqrt</B></LI><BLOCKQUOTE>
 aの有効桁 n 桁の平方根(n の平方根ではありません)。


---
斎藤ただし