@@ -145,6 +145,9 @@ bdvalue_nullable(BDVALUE v)
145145#define BIGDECIMAL_POSITIVE_P (bd ) ((bd)->sign > 0)
146146#define BIGDECIMAL_NEGATIVE_P (bd ) ((bd)->sign < 0)
147147
148+ #define MULT_BY_RB_INTEGER_THRESHOLD 150
149+ #define DIV_BY_RB_INTEGER_THRESHOLD 300
150+
148151/*
149152 * ================== Memory allocation ============================
150153 */
@@ -5873,6 +5876,31 @@ VpSetPTR(Real *a, Real *b, Real *c, size_t *a_pos, size_t *b_pos, size_t *c_pos,
58735876 return word_shift ;
58745877}
58755878
5879+ static int
5880+ VpMultWithRubyInteger (Real * c , Real * a , Real * b )
5881+ {
5882+ Real * ap , * bp , * cp ;
5883+ VALUE a2 , b2 , ab , c2 ;
5884+ ap = VpCopy (NULL , a );
5885+ bp = VpCopy (NULL , b );
5886+ ap -> exponent = a -> Prec ;
5887+ bp -> exponent = b -> Prec ;
5888+ a2 = TypedData_Wrap_Struct (rb_cBigDecimal , & BigDecimal_data_type , 0 );
5889+ b2 = TypedData_Wrap_Struct (rb_cBigDecimal , & BigDecimal_data_type , 0 );
5890+ BigDecimal_wrap_struct (a2 , ap );
5891+ BigDecimal_wrap_struct (b2 , bp );
5892+ ab = rb_big_mul (BigDecimal_to_i (a2 ), BigDecimal_to_i (b2 ));
5893+ c2 = rb_inum_convert_to_BigDecimal (ab , 0 , true);
5894+ cp = DATA_PTR (c2 );
5895+ VpAsgn (c , cp , 1 );
5896+ if (!AddExponent (c , a -> exponent )) return 0 ;
5897+ if (!AddExponent (c , b -> exponent )) return 0 ;
5898+ if (!AddExponent (c , - a -> Prec )) return 0 ;
5899+ if (!AddExponent (c , - b -> Prec )) return 0 ;
5900+ RB_GC_GUARD (c2 );
5901+ return 1 ;
5902+ }
5903+
58765904/*
58775905 * Return number of significant digits
58785906 * c = a * b , Where a = a0a1a2 ... an
@@ -5926,6 +5954,11 @@ VpMult(Real *c, Real *a, Real *b)
59265954 MxIndC = c -> MaxPrec - 1 ;
59275955 MxIndAB = a -> Prec + b -> Prec - 1 ;
59285956
5957+ if (a -> Prec >= MULT_BY_RB_INTEGER_THRESHOLD && b -> Prec >= MULT_BY_RB_INTEGER_THRESHOLD ) {
5958+ if (!VpMultWithRubyInteger (c , a , b )) return 0 ;
5959+ goto Exit ;
5960+ }
5961+
59295962 if (MxIndC < MxIndAB ) { /* The Max. prec. of c < Prec(a)+Prec(b) */
59305963w = c ;
59315964 c = NewZeroNolimit (1 , (size_t )((MxIndAB + 1 ) * BASE_FIG ));
@@ -6000,6 +6033,42 @@ VpMult(Real *c, Real *a, Real *b)
60006033 return c -> Prec * BASE_FIG ;
60016034}
60026035
6036+ static void
6037+ VpDivdWithRubyInteger (Real * c , Real * r , Real * a , Real * b )
6038+ {
6039+ Real * ap , * bp ;
6040+ BDVALUE c2 , r2 ;
6041+ VALUE a2 , b2 , divmod , div , mod ;
6042+ size_t div_prec = c -> MaxPrec - 1 ;
6043+ size_t base_prec = b -> Prec ;
6044+
6045+ ap = VpCopy (NULL , a );
6046+ bp = VpCopy (NULL , b );
6047+ VpSetSign (ap , 1 );
6048+ VpSetSign (bp , 1 );
6049+ ap -> exponent = base_prec + div_prec ;
6050+ bp -> exponent = base_prec ;
6051+ a2 = TypedData_Wrap_Struct (rb_cBigDecimal , & BigDecimal_data_type , 0 );
6052+ b2 = TypedData_Wrap_Struct (rb_cBigDecimal , & BigDecimal_data_type , 0 );
6053+ BigDecimal_wrap_struct (a2 , ap );
6054+ BigDecimal_wrap_struct (b2 , bp );
6055+ divmod = rb_big_divmod (BigDecimal_to_i (a2 ), BigDecimal_to_i (b2 ));
6056+ div = RARRAY_AREF (divmod , 0 );
6057+ mod = RARRAY_AREF (divmod , 1 );
6058+
6059+ c2 = GetBDValueMust (div );
6060+ r2 = GetBDValueMust (mod );
6061+ VpAsgn (c , c2 .real , VpGetSign (a ) * VpGetSign (b ));
6062+ VpAsgn (r , r2 .real , VpGetSign (a ));
6063+ RB_GC_GUARD (c2 .bigdecimal );
6064+ RB_GC_GUARD (r2 .bigdecimal );
6065+ AddExponent (c , a -> exponent );
6066+ AddExponent (c , - b -> exponent );
6067+ AddExponent (c , - div_prec );
6068+ AddExponent (r , a -> exponent );
6069+ AddExponent (r , - base_prec - div_prec );
6070+ }
6071+
60036072/*
60046073 * c = a / b, remainder = r
60056074 * XXXX_YYYY_ZZZZ / 0001 = XXXX_YYYY_ZZZZ
@@ -6041,6 +6110,11 @@ VpDivd(Real *c, Real *r, Real *a, Real *b)
60416110
60426111 if (word_a > word_r || word_b + word_c - 2 >= word_r ) goto space_error ;
60436112
6113+ if (word_c >= DIV_BY_RB_INTEGER_THRESHOLD && word_b >= DIV_BY_RB_INTEGER_THRESHOLD ) {
6114+ VpDivdWithRubyInteger (c , r , a , b );
6115+ goto Exit ;
6116+ }
6117+
60446118 for (i = 0 ; i < word_a ; ++ i ) r -> frac [i ] = a -> frac [i ];
60456119 for (i = word_a ; i < word_r ; ++ i ) r -> frac [i ] = 0 ;
60466120 for (i = 0 ; i < word_c ; ++ i ) c -> frac [i ] = 0 ;
0 commit comments