/*=============================================================================
This file is part of Antic.
Antic is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See .
=============================================================================*/
/******************************************************************************
Copyright (C) 2012 William Hart
******************************************************************************/
#include
#include
#include "flint/flint.h"
#include "flint/ulong_extras.h"
#include "flint/fmpz.h"
#include "qfb.h"
void qfb_pow(qfb_t r, qfb_t f, fmpz_t D, fmpz_t e)
{
fmpz_t L, exp;
qfb_t pow;
if (fmpz_is_zero(e))
{
qfb_principal_form(r, D);
return;
}
if (fmpz_is_one(e))
{
qfb_set(r, f);
return;
}
fmpz_init(L);
fmpz_init(exp);
fmpz_set(exp, e);
fmpz_abs(L, D);
fmpz_root(L, L, 4);
qfb_init(pow);
qfb_set(pow, f);
while (fmpz_is_even(exp))
{
qfb_nudupl(pow, pow, D, L);
qfb_reduce(pow, pow, D);
fmpz_fdiv_q_2exp(exp, exp, 1);
}
qfb_set(r, pow);
fmpz_fdiv_q_2exp(exp, exp, 1);
while (!fmpz_is_zero(exp))
{
qfb_nudupl(pow, pow, D, L);
qfb_reduce(pow, pow, D);
if (fmpz_is_odd(exp))
{
qfb_nucomp(r, r, pow, D, L);
qfb_reduce(r, r, D);
}
fmpz_fdiv_q_2exp(exp, exp, 1);
}
qfb_clear(pow);
fmpz_clear(L);
fmpz_clear(exp);
}
void qfb_pow_with_root(qfb_t r, qfb_t f, fmpz_t D, fmpz_t e, fmpz_t L)
{
fmpz_t exp;
qfb_t pow;
if (fmpz_is_zero(e))
{
qfb_principal_form(r, D);
return;
}
if (fmpz_is_one(e))
{
qfb_set(r, f);
return;
}
fmpz_init(exp);
fmpz_set(exp, e);
qfb_init(pow);
qfb_set(pow, f);
while (fmpz_is_even(exp))
{
qfb_nudupl(pow, pow, D, L);
qfb_reduce(pow, pow, D);
fmpz_fdiv_q_2exp(exp, exp, 1);
}
qfb_set(r, pow);
fmpz_fdiv_q_2exp(exp, exp, 1);
while (!fmpz_is_zero(exp))
{
qfb_nudupl(pow, pow, D, L);
qfb_reduce(pow, pow, D);
if (fmpz_is_odd(exp))
{
qfb_nucomp(r, r, pow, D, L);
qfb_reduce(r, r, D);
}
fmpz_fdiv_q_2exp(exp, exp, 1);
}
qfb_clear(pow);
fmpz_clear(exp);
}