@@ -1823,7 +1823,7 @@ BigDecimal_mult(VALUE self, VALUE r)
1823
1823
return VpCheckGetValue (c );
1824
1824
}
1825
1825
1826
- static VALUE BigDecimal_DoDivmod (VALUE self , VALUE r , Real * * div , Real * * mod );
1826
+ static VALUE BigDecimal_DoDivmod (VALUE self , VALUE r , Real * * div , Real * * mod , bool truncate );
1827
1827
1828
1828
/* call-seq:
1829
1829
* a / b -> bigdecimal
@@ -1893,9 +1893,10 @@ BigDecimal_quo(int argc, VALUE *argv, VALUE self)
1893
1893
/*
1894
1894
* %: mod = a%b = a - (a.to_f/b).floor * b
1895
1895
* div = (a.to_f/b).floor
1896
+ * In truncate mode, use truncate instead of floor.
1896
1897
*/
1897
1898
static VALUE
1898
- BigDecimal_DoDivmod (VALUE self , VALUE r , Real * * div , Real * * mod )
1899
+ BigDecimal_DoDivmod (VALUE self , VALUE r , Real * * div , Real * * mod , bool truncate )
1899
1900
{
1900
1901
ENTER (8 );
1901
1902
Real * c = NULL , * d = NULL , * res = NULL ;
@@ -1978,7 +1979,7 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod)
1978
1979
VpMult (res , d , b );
1979
1980
VpAddSub (c , a , res , -1 );
1980
1981
1981
- if (!VpIsZero (c ) && (VpGetSign (a ) * VpGetSign (b ) < 0 )) {
1982
+ if (!truncate && ! VpIsZero (c ) && (VpGetSign (a ) * VpGetSign (b ) < 0 )) {
1982
1983
/* result adjustment for negative case */
1983
1984
res = rbd_reallocate_struct (res , d -> MaxPrec );
1984
1985
res -> MaxPrec = d -> MaxPrec ;
@@ -2017,66 +2018,13 @@ BigDecimal_mod(VALUE self, VALUE r) /* %: a%b = a - (a.to_f/b).floor * b */
2017
2018
ENTER (3 );
2018
2019
Real * div = NULL , * mod = NULL ;
2019
2020
2020
- if (BigDecimal_DoDivmod (self , r , & div , & mod )) {
2021
- SAVE (div ); SAVE (mod );
2021
+ if (BigDecimal_DoDivmod (self , r , & div , & mod , false )) {
2022
+ SAVE (div ); SAVE (mod );
2022
2023
return VpCheckGetValue (mod );
2023
2024
}
2024
2025
return DoSomeOne (self , r , '%' );
2025
2026
}
2026
2027
2027
- static VALUE
2028
- BigDecimal_divremain (VALUE self , VALUE r , Real * * dv , Real * * rv )
2029
- {
2030
- ENTER (10 );
2031
- size_t mx ;
2032
- Real * a = NULL , * b = NULL , * c = NULL , * res = NULL , * d = NULL , * rr = NULL , * ff = NULL ;
2033
- Real * f = NULL ;
2034
-
2035
- GUARD_OBJ (a , GetVpValue (self , 1 ));
2036
- if (RB_TYPE_P (r , T_FLOAT )) {
2037
- b = GetVpValueWithPrec (r , 0 , 1 );
2038
- }
2039
- else if (RB_TYPE_P (r , T_RATIONAL )) {
2040
- b = GetVpValueWithPrec (r , a -> Prec * VpBaseFig (), 1 );
2041
- }
2042
- else {
2043
- b = GetVpValue (r , 0 );
2044
- }
2045
-
2046
- if (!b ) return Qfalse ;
2047
- SAVE (b );
2048
-
2049
- if (VpIsPosInf (b ) || VpIsNegInf (b )) {
2050
- GUARD_OBJ (* dv , NewZeroWrapLimited (1 , 1 ));
2051
- VpSetZero (* dv , 1 );
2052
- * rv = a ;
2053
- return Qtrue ;
2054
- }
2055
-
2056
- mx = (a -> MaxPrec + b -> MaxPrec ) * VpBaseFig ();
2057
- GUARD_OBJ (c , NewZeroWrapLimited (1 , mx ));
2058
- GUARD_OBJ (res , NewZeroWrapNolimit (1 , (mx + 1 ) * 2 + (VpBaseFig () + 1 )));
2059
- GUARD_OBJ (rr , NewZeroWrapNolimit (1 , (mx + 1 ) * 2 + (VpBaseFig () + 1 )));
2060
- GUARD_OBJ (ff , NewZeroWrapNolimit (1 , (mx + 1 ) * 2 + (VpBaseFig () + 1 )));
2061
-
2062
- VpDivd (c , res , a , b );
2063
-
2064
- mx = c -> Prec * (VpBaseFig () + 1 );
2065
-
2066
- GUARD_OBJ (d , NewZeroWrapLimited (1 , mx ));
2067
- GUARD_OBJ (f , NewZeroWrapLimited (1 , mx ));
2068
-
2069
- VpActiveRound (d , c , VP_ROUND_DOWN , 0 ); /* 0: round off */
2070
-
2071
- VpFrac (f , c );
2072
- VpMult (rr , f , b );
2073
- VpAddSub (ff , res , rr , 1 );
2074
-
2075
- * dv = d ;
2076
- * rv = ff ;
2077
- return Qtrue ;
2078
- }
2079
-
2080
2028
/* call-seq:
2081
2029
* remainder(value)
2082
2030
*
@@ -2087,9 +2035,12 @@ BigDecimal_divremain(VALUE self, VALUE r, Real **dv, Real **rv)
2087
2035
static VALUE
2088
2036
BigDecimal_remainder (VALUE self , VALUE r ) /* remainder */
2089
2037
{
2090
- Real * d , * rv = 0 ;
2091
- if (BigDecimal_divremain (self , r , & d , & rv )) {
2092
- return VpCheckGetValue (rv );
2038
+ ENTER (3 );
2039
+ Real * div = NULL , * mod = NULL ;
2040
+
2041
+ if (BigDecimal_DoDivmod (self , r , & div , & mod , true)) {
2042
+ SAVE (div ); SAVE (mod );
2043
+ return VpCheckGetValue (mod );
2093
2044
}
2094
2045
return DoSomeOne (self , r , rb_intern ("remainder" ));
2095
2046
}
@@ -2122,7 +2073,7 @@ BigDecimal_divmod(VALUE self, VALUE r)
2122
2073
ENTER (5 );
2123
2074
Real * div = NULL , * mod = NULL ;
2124
2075
2125
- if (BigDecimal_DoDivmod (self , r , & div , & mod )) {
2076
+ if (BigDecimal_DoDivmod (self , r , & div , & mod , false )) {
2126
2077
SAVE (div ); SAVE (mod );
2127
2078
return rb_assoc_new (VpCheckGetValue (div ), VpCheckGetValue (mod ));
2128
2079
}
@@ -2145,7 +2096,7 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
2145
2096
if (NIL_P (n )) { /* div in Float sense */
2146
2097
Real * div = NULL ;
2147
2098
Real * mod ;
2148
- if (BigDecimal_DoDivmod (self , b , & div , & mod )) {
2099
+ if (BigDecimal_DoDivmod (self , b , & div , & mod , false )) {
2149
2100
return BigDecimal_to_i (VpCheckGetValue (div ));
2150
2101
}
2151
2102
return DoSomeOne (self , b , rb_intern ("div" ));
0 commit comments