diff --git a/ChangeLog b/ChangeLog index 41db5cfffc..51fb6a9ae0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +Thu Sep 5 06:22:42 2013 Tanaka Akira + + * bignum.c (bary_divmod_normal): Reduce temporary array allocations. + Thu Sep 5 02:17:06 2013 Tanaka Akira * bignum.c (rb_big_divrem_normal): Add GC guards. diff --git a/bignum.c b/bignum.c index b09080d4ee..308af6b2f3 100644 --- a/bignum.c +++ b/bignum.c @@ -2641,8 +2641,7 @@ bary_divmod_normal(BDIGIT *qds, size_t qn, BDIGIT *rds, size_t rn, const BDIGIT int shift; BDIGIT *zds, *yyds; size_t zn; - VALUE tmpz = 0; - VALUE tmpyy = 0; + VALUE tmpyz = 0; assert(yn < xn || (xn == yn && yds[yn - 1] <= xds[xn - 1])); assert(qds ? (xn - yn + 1) <= qn : 1); @@ -2652,14 +2651,16 @@ bary_divmod_normal(BDIGIT *qds, size_t qn, BDIGIT *rds, size_t rn, const BDIGIT shift = nlz(yds[yn-1]); if (shift) { - if (qds && zn <= qn) - zds = qds; - else - zds = ALLOCV_N(BDIGIT, tmpz, zn); - if (rds) - yyds = rds; - else - yyds = ALLOCV_N(BDIGIT, tmpyy, yn); + int alloc_y = !rds; + int alloc_z = !qds || qn < zn; + if (alloc_y && alloc_z) { + yyds = ALLOCV_N(BDIGIT, tmpyz, yn+zn); + zds = yyds + yn; + } + else { + yyds = alloc_y ? ALLOCV_N(BDIGIT, tmpyz, yn) : rds; + zds = alloc_z ? ALLOCV_N(BDIGIT, tmpyz, zn) : qds; + } zds[xn] = bary_small_lshift(zds, xds, xn, shift); bary_small_lshift(yyds, yds, yn, shift); } @@ -2667,7 +2668,7 @@ bary_divmod_normal(BDIGIT *qds, size_t qn, BDIGIT *rds, size_t rn, const BDIGIT if (qds && zn <= qn) zds = qds; else - zds = ALLOCV_N(BDIGIT, tmpz, zn); + zds = ALLOCV_N(BDIGIT, tmpyz, zn); MEMCPY(zds, xds, BDIGIT, xn); zds[xn] = 0; /* bigdivrem_restoring will not modify y. @@ -2691,10 +2692,8 @@ bary_divmod_normal(BDIGIT *qds, size_t qn, BDIGIT *rds, size_t rn, const BDIGIT BDIGITS_ZERO(qds+j, qn-j); } - if (tmpyy) - ALLOCV_END(tmpyy); - if (tmpz) - ALLOCV_END(tmpz); + if (tmpyz) + ALLOCV_END(tmpyz); } VALUE