/*=============================================================================
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) 2010 Sebastian Pancratz
Copyright (C) 2014 William Hart
******************************************************************************/
#include "nf_elem.h"
#include
#include
#include "flint/flint.h"
#include "flint/fmpz.h"
#include "flint/fmpz_vec.h"
#include "flint/fmpz_poly.h"
void
_nf_elem_pow(nf_elem_t res, const nf_elem_t a, ulong e, const nf_t nf)
{
ulong bit = ~((~UWORD(0)) >> 1);
nf_elem_t v;
nf_elem_struct * R, * S, * T;
nf_elem_init(v, nf);
/*
Set bits to the bitmask with a 1 one place lower than the msb of e
*/
while ((bit & e) == UWORD(0))
bit >>= 1;
bit >>= 1;
/*
Trial run without any polynomial arithmetic to determine the parity
of the number of swaps; then set R and S accordingly
*/
{
unsigned int swaps = 0U;
ulong bit2 = bit;
if ((bit2 & e))
swaps = ~swaps;
while (bit2 >>= 1)
if ((bit2 & e) == UWORD(0))
swaps = ~swaps;
if (swaps == 0U)
{
R = res;
S = v;
}
else
{
R = v;
S = res;
}
}
/*
We unroll the first step of the loop, referring to {poly, len}
*/
nf_elem_mul(R, a, a, nf);
if ((bit & e))
{
nf_elem_mul(S, R, a, nf);
T = R;
R = S;
S = T;
}
while ((bit >>= 1))
{
if ((bit & e))
{
nf_elem_mul(S, R, R, nf);
nf_elem_mul(R, S, a, nf);
}
else
{
nf_elem_mul(S, R, R, nf);
T = R;
R = S;
S = T;
}
}
nf_elem_clear(v, nf);
}
void
nf_elem_pow(nf_elem_t res, const nf_elem_t a, ulong e, const nf_t nf)
{
nf_elem_t t;
if (e == UWORD(0))
{
nf_elem_one(res, nf);
return;
}
if (nf_elem_is_zero(a, nf))
{
nf_elem_zero(res, nf);
return;
}
if (nf->flag & NF_LINEAR)
_fmpq_pow_si(LNF_ELEM_NUMREF(res), LNF_ELEM_DENREF(res),
LNF_ELEM_NUMREF(a), LNF_ELEM_DENREF(a), e);
else
{
if (e < UWORD(3))
{
if (e == UWORD(1))
nf_elem_set(res, a, nf);
else /* e == UWORD(2) */
nf_elem_mul(res, a, a, nf);
return;
}
if (res == a)
{
nf_elem_init(t, nf);
_nf_elem_pow(t, a, e, nf);
nf_elem_swap(t, res, nf);
nf_elem_clear(t, nf);
}
else
_nf_elem_pow(res, a, e, nf);
}
}