From 06a19bc5dabfde6da5b56b3793cd3f9f13f99f32 Mon Sep 17 00:00:00 2001 From: Marco Bodrato Date: Sun, 24 May 2015 07:56:03 +0200 Subject: mpq/div.c: Reduce memory use. --- mpq/div.c | 50 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 14 deletions(-) (limited to 'mpq') diff --git a/mpq/div.c b/mpq/div.c index 7d91e0998..6c058a250 100644 --- a/mpq/div.c +++ b/mpq/div.c @@ -37,7 +37,6 @@ mpq_div (mpq_ptr quot, mpq_srcptr op1, mpq_srcptr op2) { mpz_t gcd1, gcd2; mpz_t tmp1, tmp2; - mpz_t numtmp; mp_size_t op1_num_size; mp_size_t op1_den_size; mp_size_t op2_num_size; @@ -45,11 +44,40 @@ mpq_div (mpq_ptr quot, mpq_srcptr op1, mpq_srcptr op2) mp_size_t alloc; TMP_DECL; - op2_num_size = ABSIZ(NUM(op2)); + op2_num_size = SIZ(NUM(op2)); if (UNLIKELY (op2_num_size == 0)) DIVIDE_BY_ZERO; + if (op1 == op2) + { + PTR(NUM(quot))[0] = 1; + SIZ(NUM(quot)) = 1; + PTR(DEN(quot))[0] = 1; + SIZ(DEN(quot)) = 1; + return; + } + + if (quot == op2) + { + /* We checked for op1 == op2: we are not in the x=x/x case. + We compute x=y/x by computing x=inv(x)*y */ + MPN_PTR_SWAP (PTR(NUM(quot)), ALLOC(NUM(quot)), + PTR(DEN(quot)), ALLOC(DEN(quot))); + if (op2_num_size > 0) + { + SIZ(NUM(quot)) = SIZ(DEN(quot)); + SIZ(DEN(quot)) = op2_num_size; + } + else + { + SIZ(NUM(quot)) = - SIZ(DEN(quot)); + SIZ(DEN(quot)) = - op2_num_size; + } + mpq_mul (quot, quot, op1); + return; + } + op1_num_size = ABSIZ(NUM(op1)); if (op1_num_size == 0) @@ -62,6 +90,7 @@ mpq_div (mpq_ptr quot, mpq_srcptr op1, mpq_srcptr op2) return; } + op2_num_size = ABS(op2_num_size); op2_den_size = SIZ(DEN(op2)); op1_den_size = SIZ(DEN(op1)); @@ -79,13 +108,10 @@ mpq_div (mpq_ptr quot, mpq_srcptr op1, mpq_srcptr op2) alloc = MAX (op1_den_size, op2_den_size); MPZ_TMP_INIT (tmp2, alloc); - alloc = op1_num_size + op2_den_size; - MPZ_TMP_INIT (numtmp, alloc); - - /* QUOT might be identical to either operand, so don't store the result there - until we are finished with the input operands. We can overwrite the - numerator of QUOT when we are finished with the numerators of OP1 and - OP2. */ + /* QUOT might be identical to OP1, so don't store the result there + until we are finished with the input operand. We can overwrite + the numerator of QUOT when we are finished with the numerator of + OP1. */ mpz_gcd (gcd1, NUM(op1), NUM(op2)); mpz_gcd (gcd2, DEN(op2), DEN(op1)); @@ -93,17 +119,13 @@ mpq_div (mpq_ptr quot, mpq_srcptr op1, mpq_srcptr op2) mpz_divexact_gcd (tmp1, NUM(op1), gcd1); mpz_divexact_gcd (tmp2, DEN(op2), gcd2); - mpz_mul (numtmp, tmp1, tmp2); + mpz_mul (NUM(quot), tmp1, tmp2); mpz_divexact_gcd (tmp1, NUM(op2), gcd1); mpz_divexact_gcd (tmp2, DEN(op1), gcd2); mpz_mul (DEN(quot), tmp1, tmp2); - /* We needed to go via NUMTMP to take care of QUOT being the same as OP2. - Now move NUMTMP to QUOT->_mp_num. */ - mpz_set (NUM(quot), numtmp); - /* Keep the denominator positive. */ if (SIZ(DEN(quot)) < 0) { -- cgit v1.2.1