diff options
-rw-r--r-- | ext/bigdecimal/bigdecimal.c | 76 | ||||
-rw-r--r-- | ext/bigdecimal/bigdecimal.h | 7 | ||||
-rw-r--r-- | ext/bigdecimal/bigdecimal_en.html | 42 | ||||
-rw-r--r-- | ext/bigdecimal/bigdecimal_ja.html | 36 |
4 files changed, 87 insertions, 74 deletions
diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c index d01dbc4f5..2acc0e67c 100644 --- a/ext/bigdecimal/bigdecimal.c +++ b/ext/bigdecimal/bigdecimal.c @@ -31,7 +31,6 @@ * */ -#include "ruby.h" #include <ctype.h> #include <stdio.h> #include <stdlib.h> @@ -39,6 +38,8 @@ #include <errno.h> #include <float.h> #include <math.h> +#include "ruby.h" +#include "math.h" #include "version.h" /* #define ENABLE_NUMERIC_STRING */ @@ -720,6 +721,17 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod) if(!b) return DoSomeOne(self,r); SAVE(b); + if(VpIsNaN(a) || VpIsNaN(b)) goto NaN; + if(VpIsInf(a) || VpIsInf(b)) goto NaN; + if(VpIsZero(b)) goto NaN; + if(VpIsZero(a)) { + GUARD_OBJ(c,VpCreateRbObject(1, "0")); + GUARD_OBJ(d,VpCreateRbObject(1, "0")); + *div = d; + *mod = c; + return (VALUE)0; + } + mx = a->Prec; if(mx<b->Prec) mx = b->Prec; mx =(mx + 1) * VpBaseFig(); @@ -728,9 +740,23 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod) VpDivd(c, res, a, b); mx = c->Prec *(VpBaseFig() + 1); GUARD_OBJ(d,VpCreateRbObject(mx, "0")); - VpActiveRound(d,c,VP_ROUND_FLOOR,0); + VpActiveRound(d,c,VP_ROUND_DOWN,0); VpMult(res,d,b); VpAddSub(c,a,res,-1); + if(!VpIsZero(c) && (VpGetSign(a)*VpGetSign(b)<0)) { + VpAddSub(res,d,VpOne(),-1); + VpAddSub(d ,c,b, 1); + *div = res; + *mod = d; + } else { + *div = d; + *mod = c; + } + return (VALUE)0; + +NaN: + GUARD_OBJ(c,VpCreateRbObject(1, "NaN")); + GUARD_OBJ(d,VpCreateRbObject(1, "NaN")); *div = d; *mod = c; return (VALUE)0; @@ -813,22 +839,32 @@ BigDecimal_divmod(VALUE self, VALUE r) } static VALUE -BigDecimal_div2(VALUE self, VALUE b, VALUE n) +BigDecimal_div2(int argc, VALUE *argv, VALUE self) { ENTER(10); VALUE obj; - Real *res=NULL; - Real *av=NULL, *bv=NULL, *cv=NULL; - U_LONG ix = (U_LONG)GetPositiveInt(n); - U_LONG mx = (ix+VpBaseFig()*2); - GUARD_OBJ(cv,VpCreateRbObject(mx,"0")); - GUARD_OBJ(av,GetVpValue(self,1)); - GUARD_OBJ(bv,GetVpValue(b,1)); - mx = cv->MaxPrec+1; - GUARD_OBJ(res,VpCreateRbObject((mx * 2 + 2)*VpBaseFig(), "#0")); - VpDivd(cv,res,av,bv); - VpLeftRound(cv,VpGetRoundMode(),ix); - return ToValue(cv); + VALUE b,n; + int na = rb_scan_args(argc,argv,"11",&b,&n); + if(na==1) { /* div in Float sense */ + Real *div=NULL; + Real *mod; + obj = BigDecimal_DoDivmod(self,b,&div,&mod); + if(obj!=(VALUE)0) return obj; + return ToValue(div); + } else { /* div in BigDecimal sense */ + Real *res=NULL; + Real *av=NULL, *bv=NULL, *cv=NULL; + U_LONG ix = (U_LONG)GetPositiveInt(n); + U_LONG mx = (ix+VpBaseFig()*2); + GUARD_OBJ(cv,VpCreateRbObject(mx,"0")); + GUARD_OBJ(av,GetVpValue(self,1)); + GUARD_OBJ(bv,GetVpValue(b,1)); + mx = cv->MaxPrec+1; + GUARD_OBJ(res,VpCreateRbObject((mx * 2 + 2)*VpBaseFig(), "#0")); + VpDivd(cv,res,av,bv); + VpLeftRound(cv,VpGetRoundMode(),ix); + return ToValue(cv); + } } static VALUE @@ -1318,10 +1354,11 @@ Init_bigdecimal(void) rb_define_method(rb_cBigDecimal, "add", BigDecimal_add2, 2); rb_define_method(rb_cBigDecimal, "sub", BigDecimal_sub2, 2); rb_define_method(rb_cBigDecimal, "mult", BigDecimal_mult2, 2); - rb_define_method(rb_cBigDecimal, "div",BigDecimal_div2, 2); + rb_define_method(rb_cBigDecimal, "div",BigDecimal_div2, -1); rb_define_method(rb_cBigDecimal, "hash", BigDecimal_hash, 0); rb_define_method(rb_cBigDecimal, "to_s", BigDecimal_to_s, -1); rb_define_method(rb_cBigDecimal, "to_i", BigDecimal_to_i, 0); + rb_define_method(rb_cBigDecimal, "to_int", BigDecimal_to_i, 0); rb_define_method(rb_cBigDecimal, "split", BigDecimal_split, 0); rb_define_method(rb_cBigDecimal, "+", BigDecimal_add, 1); rb_define_method(rb_cBigDecimal, "-", BigDecimal_sub, 1); @@ -1329,6 +1366,7 @@ Init_bigdecimal(void) rb_define_method(rb_cBigDecimal, "-@", BigDecimal_neg, 0); rb_define_method(rb_cBigDecimal, "*", BigDecimal_mult, 1); rb_define_method(rb_cBigDecimal, "/", BigDecimal_div, 1); + rb_define_method(rb_cBigDecimal, "quo", BigDecimal_div, 1); rb_define_method(rb_cBigDecimal, "%", BigDecimal_mod, 1); rb_define_method(rb_cBigDecimal, "modulo", BigDecimal_mod, 1); rb_define_method(rb_cBigDecimal, "remainder", BigDecimal_remainder, 1); @@ -1820,6 +1858,12 @@ VpInit(U_LONG BaseVal) return DBLE_FIG; } +VP_EXPORT Real * +VpOne() +{ + return VpConstOne; +} + /* If exponent overflows,then raise exception or returns 0 */ static int AddExponent(Real *a,S_INT n) diff --git a/ext/bigdecimal/bigdecimal.h b/ext/bigdecimal/bigdecimal.h index d8fa35d3c..0af0b1dfc 100644 --- a/ext/bigdecimal/bigdecimal.h +++ b/ext/bigdecimal/bigdecimal.h @@ -150,11 +150,16 @@ VP_EXPORT void VpMidRound(Real *y, int f, int nf); VP_EXPORT void VpLeftRound(Real *y, int f, int nf); VP_EXPORT void VpFrac(Real *y,Real *x); VP_EXPORT int VpPower(Real *y,Real *x,S_INT n); + +/* VP constants */ +VP_EXPORT Real *VpOne(); + +#ifdef ENABLE_TRIAL_METHOD VP_EXPORT void VpPi(Real *y); VP_EXPORT void VpExp1(Real *y); VP_EXPORT void VpExp(Real *y,Real *x); VP_EXPORT void VpSinCos(Real *psin,Real *pcos,Real *x); - +#endif /* ENABLE_TRIAL_METHOD */ /* * ------------------ * MACRO definitions. diff --git a/ext/bigdecimal/bigdecimal_en.html b/ext/bigdecimal/bigdecimal_en.html index 2d86adcc6..a8ced21e0 100644 --- a/ext/bigdecimal/bigdecimal_en.html +++ b/ext/bigdecimal/bigdecimal_en.html @@ -233,40 +233,35 @@ division(c = a / b)<BR> For the resulting number of significant digits of c,see <A HREF="#PREC">Resulting number of significant digits</A>. </BLOCKQUOTE> -<LI><B>add</B></LI><BLOCKQUOTE> +<LI><B>add(b,n)</B></LI><BLOCKQUOTE> c = a.add(b,n)<BR> c = a.add(b,n) performs c = a + b. If n is less than the actual significant digits of a + b, then c is rounded properly according to the BigDecimal.limit. </BLOCKQUOTE> -<LI><B>sub</B></LI><BLOCKQUOTE> +<LI><B>sub(b,n)</B></LI><BLOCKQUOTE> c = a.sub(b,n)<BR> c = a.sub(b,n) performs c = a - b. If n is less than the actual significant digits of a - b, then c is rounded properly according to the BigDecimal.limit. </BLOCKQUOTE> -<LI><B>mult</B></LI><BLOCKQUOTE> +<LI><B>mult(b,n)</B></LI><BLOCKQUOTE> c = a.mult(b,n)<BR> c = a.mult(b,n) performs c = a * b. If n is less than the actual significant digits of a * b, then c is rounded properly according to the BigDecimal.limit. </BLOCKQUOTE> -<LI><B>div</B></LI><BLOCKQUOTE> +<LI><B>div(b[,n])</B></LI><BLOCKQUOTE> c = a.div(b,n)<BR> c = a.div(b,n) performs c = a / b. If n is less than the actual significant digits of a / b, -then c is rounded properly according to the BigDecimal.limit. - +then c is rounded properly according to the BigDecimal.limit.<BR> +If n is not given,then the result will be an integer(BigDecimal) like Float#div. </BLOCKQUOTE> -<LI><B>%</B></LI><BLOCKQUOTE> -r = a%b <BR> -is the same as:<BR> -r = a-((a/b).floor)*b<BR> -</BLOCKQUOTE> <LI><B>fix</B></LI><BLOCKQUOTE> c = a.fix<BR> returns integer part of a.<BR> @@ -350,26 +345,6 @@ If n<0,then the n-th digit counted from the decimal point in integer part is pro c = BigDecimal::new("1.23456").truncate(4) # ==> 1.2345 c = BigDecimal::new("15.23456").truncate(-1) # ==> 10.0 </PRE></CODE> - -</BLOCKQUOTE> -<LI><B>divmod</B></LI><BLOCKQUOTE> -c,r = a.divmod(b) # a = c*b + r<BR> -returns the quotient and remainder of a/b.<BR> -a = c * b + r is always satisfied.<BR> -where c is the integer satisfying -c = (a/b).floor <BR> -and,therefore -r = a - c*b<BR> - -</BLOCKQUOTE> -<LI><B>remainder</B></LI><BLOCKQUOTE> -r=a.remainder(b)<BR> -returns the remainder of a/b.<BR> -where c is the integer satisfying -c = (a/b).fix <BR> -and,therefore: -r = a - c*b<BR> - </BLOCKQUOTE> <LI><B>abs</B></LI><BLOCKQUOTE> c = a.abs<BR> @@ -483,6 +458,11 @@ The same as ** method.<BR> c = a.power(n)<BR> returns the value of a powered by n(c=a**n). n must be an integer.<BR> +</BLOCKQUOTE> + +<LI><B>divmod,quo,modulo,%,remainder</B></LI><BLOCKQUOTE> +See,corresponding methods in Float class. +</BLOCKQUOTE> </BLOCKQUOTE> <LI><B><=></B></LI><BLOCKQUOTE> diff --git a/ext/bigdecimal/bigdecimal_ja.html b/ext/bigdecimal/bigdecimal_ja.html index 31e852bd0..4fc3a4eb8 100644 --- a/ext/bigdecimal/bigdecimal_ja.html +++ b/ext/bigdecimal/bigdecimal_ja.html @@ -247,39 +247,35 @@ c の精度については「<A HREF="#PREC">計算精度について</A>」を参照してください。 </BLOCKQUOTE> -<LI><B>add</B></LI><BLOCKQUOTE> +<LI><B>add(b,n)</B></LI><BLOCKQUOTE> 以下のように使用します。<BR> c = a.add(b,n)<BR> c = a + b を最大で n 桁まで計算します。 a + b の精度が n より大きいときは BigDecimal.mode で指定された方法で丸められます。 </BLOCKQUOTE> -<LI><B>sub</B></LI><BLOCKQUOTE> +<LI><B>sub(b,n)</B></LI><BLOCKQUOTE> 以下のように使用します。<BR> c = a.sub(b,n)<BR> c = a - b を最大で n 桁まで計算します。 a - b の精度が n より大きいときは BigDecimal.mode で指定された方法で丸められます。 </BLOCKQUOTE> -<LI><B>mult</B></LI><BLOCKQUOTE> +<LI><B>mult(b,n)</B></LI><BLOCKQUOTE> 以下のように使用します。<BR> c = a.mult(b,n)<BR> c = a * b を最大で n 桁まで計算します。 a * b の精度が n より大きいときは BigDecimal.mode で指定された方法で丸められます。 </BLOCKQUOTE> -<LI><B>div</B></LI><BLOCKQUOTE> +<LI><B>div(b[,n])</B></LI><BLOCKQUOTE> 以下のように使用します。<BR> c = a.div(b,n)<BR> c = a / b を最大で n 桁まで計算します。 -a / b の精度が n より大きいときは BigDecimal.mode で指定された方法で丸められます。 +a / b の精度が n より大きいときは BigDecimal.mode で指定された方法で丸められます。<BR> +n が省略されたときは Float#div と同様に結果が整数(BigDecimal)になります。 </BLOCKQUOTE> -<LI><B>%</B></LI><BLOCKQUOTE> -r = a%b <BR> -a/b の余りを計算します。以下の計算と同じものです。<BR> -r = a-((a/b).floor)*b<BR> -</BLOCKQUOTE> <LI><B>fix</B></LI><BLOCKQUOTE> a の小数点以下の切り捨て。<BR> c = a.fix @@ -359,23 +355,7 @@ n が負のときは小数点以上 n 桁目をを操作します(小数点位置から左に少なくとも n 個 c = BigDecimal("1.23456").truncate(4) # ==> 1.2345 c = BigDecimal("15.23456").truncate(-1) # ==> 10.0 </PRE></CODE> - -</BLOCKQUOTE> -<LI><B>divmod</B></LI><BLOCKQUOTE> -商と剰余の配列を返します。<BR> -c,r = a.divmod(b) # a = c*b + r<BR> -divmodメソッドは a = c * b + r となる a / b の浮動小数点型の商 c と剰余 r を -計算します。ここで c は整数(少数部分のない実数)になります。<BR> -c = (a/b).floor <BR> -r = a - c*b<BR> -で計算されます。 </BLOCKQUOTE> -<LI><B>remainder</B></LI><BLOCKQUOTE> -r=a.remainder(b)<BR> -a/b の剰余 r を計算します。<BR> -c = (a/b).fix <BR> -r = a - c*b<BR> -で計算されます。 </BLOCKQUOTE> <LI><B>abs</B></LI><BLOCKQUOTE> @@ -482,6 +462,10 @@ aの有効桁 n 桁の平方根(n の平方根ではありません)を c = a.sqrt(n)<BR> </BLOCKQUOTE> +<LI><B>divmod,quo,modulo,%,remainder</B></LI><BLOCKQUOTE> +詳細は対応する Float の各メソッドを参照して下さい。 +</BLOCKQUOTE> + <LI><B><=></B></LI><BLOCKQUOTE> a==b なら 0、a > b なら 1、a < b なら -1 になります。<BR> c = a <=> b |