#include "longlong.h"
#include "fmpz_mod_mpoly.h"
FLINT_FORCE_INLINE
slong clog4(slong x)
{
return (x <= 4) ? 0 : (slong) ((FLINT_BIT_COUNT(x - 1) - UWORD(1)) / UWORD(2));
}
void fmpz_mod_mpoly_geobucket_init(
fmpz_mod_mpoly_geobucket_t B,
const fmpz_mod_mpoly_ctx_t ctx)
{
slong i;
for (i = 0; i < FLINT_BITS/2; i++)
{
fmpz_mod_mpoly_init(B->polys + i, ctx);
fmpz_mod_mpoly_init(B->temps + i, ctx);
}
B->length = 0;
}
void fmpz_mod_mpoly_geobucket_clear(
fmpz_mod_mpoly_geobucket_t B,
const fmpz_mod_mpoly_ctx_t ctx)
{
slong i;
for (i = 0; i < FLINT_BITS/2; i++)
{
fmpz_mod_mpoly_clear(B->polys + i, ctx);
fmpz_mod_mpoly_clear(B->temps + i, ctx);
}
}
void fmpz_mod_mpoly_geobucket_empty(
fmpz_mod_mpoly_t p,
fmpz_mod_mpoly_geobucket_t B,
const fmpz_mod_mpoly_ctx_t ctx)
{
slong i;
if (B->length < 2)
{
if (B->length < 1)
fmpz_mod_mpoly_zero(p, ctx);
else
fmpz_mod_mpoly_set(p, B->polys + 0, ctx);
}
else if (B->length == 2)
{
fmpz_mod_mpoly_add(p, B->polys + 1, B->polys + 0, ctx);
}
else
{
fmpz_mod_mpoly_add(B->temps + 1, B->polys + 1, B->polys + 0, ctx);
for (i = 2; i < B->length - 1; i++)
fmpz_mod_mpoly_add(B->temps + i, B->polys + i, B->temps + i - 1, ctx);
fmpz_mod_mpoly_add(p, B->polys + i, B->temps + i - 1, ctx);
}
B->length = 0;
}
void fmpz_mod_mpoly_geobucket_fit_length(
fmpz_mod_mpoly_geobucket_t B, slong len,
const fmpz_mod_mpoly_ctx_t ctx)
{
slong j;
for (j = B->length; j < len; j++)
fmpz_mod_mpoly_zero(B->polys + j, ctx);
B->length = j;
}
void fmpz_mod_mpoly_geobucket_set(
fmpz_mod_mpoly_geobucket_t B,
fmpz_mod_mpoly_t p,
const fmpz_mod_mpoly_ctx_t ctx)
{
slong i = clog4(p->length);
B->length = 0;
fmpz_mod_mpoly_geobucket_fit_length(B, i + 1, ctx);
fmpz_mod_mpoly_swap(B->polys + i, p, ctx);
B->length = i + 1;
}
static void _fmpz_mod_mpoly_geobucket_fix(
fmpz_mod_mpoly_geobucket_t B,
slong i,
const fmpz_mod_mpoly_ctx_t ctx)
{
while (clog4(B->polys[i].length) > i)
{
FLINT_ASSERT(i + 1 <= B->length);
if (i + 1 == B->length)
{
B->length = i + 2;
fmpz_mod_mpoly_set(B->polys + i + 1, B->polys + i, ctx);
}
else
{
fmpz_mod_mpoly_add(B->temps + i + 1, B->polys + i + 1, B->polys + i, ctx);
fmpz_mod_mpoly_swap(B->polys + i + 1, B->temps + i + 1, ctx);
}
fmpz_mod_mpoly_zero(B->polys + i, ctx);
i++;
}
}
void fmpz_mod_mpoly_geobucket_add(
fmpz_mod_mpoly_geobucket_t B,
fmpz_mod_mpoly_t p,
const fmpz_mod_mpoly_ctx_t ctx)
{
slong i;
if (fmpz_mod_mpoly_is_zero(p, ctx))
return;
i = clog4(p->length);
fmpz_mod_mpoly_geobucket_fit_length(B, i + 1, ctx);
fmpz_mod_mpoly_add(B->temps + i, B->polys + i, p, ctx);
fmpz_mod_mpoly_swap(B->polys + i, B->temps + i, ctx);
_fmpz_mod_mpoly_geobucket_fix(B, i, ctx);
}
void fmpz_mod_mpoly_geobucket_sub(
fmpz_mod_mpoly_geobucket_t B,
fmpz_mod_mpoly_t p,
const fmpz_mod_mpoly_ctx_t ctx)
{
slong i;
if (fmpz_mod_mpoly_is_zero(p, ctx))
return;
i = clog4(p->length);
fmpz_mod_mpoly_geobucket_fit_length(B, i + 1, ctx);
fmpz_mod_mpoly_sub(B->temps + i, B->polys + i, p, ctx);
fmpz_mod_mpoly_swap(B->polys + i, B->temps + i, ctx);
_fmpz_mod_mpoly_geobucket_fix(B, i, ctx);
}