#include "fmpq.h"
void _fmpq_gcd_cofactors(
fmpz_t ng_, fmpz_t dg_,
fmpz_t abar,
fmpz_t bbar,
const fmpz_t na, const fmpz_t da,
const fmpz_t nb, const fmpz_t db)
{
fmpz_t ng, dg, nabar, dabar, nbbar, dbbar;
#if FLINT_WANT_ASSERT
fmpq_t cqt_g;
int input_is_canonical = _fmpq_is_canonical(na, da) &&
_fmpq_is_canonical(nb, db);
#endif
fmpz_init(ng);
fmpz_gcd(ng, na, nb);
if (fmpz_is_zero(ng))
{
fmpz_zero(ng_);
fmpz_one(dg_);
fmpz_zero(abar);
fmpz_zero(bbar);
fmpz_clear(ng);
return;
}
#if FLINT_WANT_ASSERT
fmpq_init(cqt_g);
_fmpq_gcd(fmpq_numref(cqt_g), fmpq_denref(cqt_g), na, da, nb, db);
#endif
fmpz_init(dg);
fmpz_init(nabar);
fmpz_init(dabar);
fmpz_init(nbbar);
fmpz_init(dbbar);
fmpz_divexact(nabar, na, ng);
fmpz_divexact(nbbar, nb, ng);
fmpz_gcd(dg, da, db);
fmpz_divexact(dabar, da, dg);
fmpz_divexact(dbbar, db, dg);
fmpz_mul(abar, nabar, dbbar);
fmpz_mul(bbar, dabar, nbbar);
fmpz_mul(dg_, da, dbbar);
fmpz_swap(ng_, ng);
#if FLINT_WANT_ASSERT
if (input_is_canonical)
{
FLINT_ASSERT(fmpz_equal(fmpq_numref(cqt_g), ng_));
FLINT_ASSERT(fmpz_equal(fmpq_denref(cqt_g), dg_));
fmpz_gcd(ng, abar, bbar);
FLINT_ASSERT(fmpz_is_one(ng));
}
fmpq_clear(cqt_g);
#endif
fmpz_clear(ng);
fmpz_clear(dg);
fmpz_clear(nabar);
fmpz_clear(dabar);
fmpz_clear(nbbar);
fmpz_clear(dbbar);
}
void
fmpq_gcd_cofactors(fmpq_t g, fmpz_t A, fmpz_t B, const fmpq_t a, const fmpq_t b)
{
_fmpq_gcd_cofactors(fmpq_numref(g), fmpq_denref(g), A, B,
fmpq_numref(a), fmpq_denref(a), fmpq_numref(b), fmpq_denref(b));
}