summaryrefslogtreecommitdiff
path: root/mpq
diff options
context:
space:
mode:
authorMarco Bodrato <bodrato@mail.dm.unipi.it>2015-05-24 07:56:03 +0200
committerMarco Bodrato <bodrato@mail.dm.unipi.it>2015-05-24 07:56:03 +0200
commit06a19bc5dabfde6da5b56b3793cd3f9f13f99f32 (patch)
tree4e5f551a756421198504003f918b73f055f402f1 /mpq
parent41b28532283a7c4433a96de71bf87d00723d89ba (diff)
downloadgmp-06a19bc5dabfde6da5b56b3793cd3f9f13f99f32.tar.gz
mpq/div.c: Reduce memory use.
Diffstat (limited to 'mpq')
-rw-r--r--mpq/div.c50
1 files changed, 36 insertions, 14 deletions
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)
{