/*
Copyright (C) 2016-2017 William Hart
Copyright (C) 2017-2020 Daniel Schultz
This file is part of FLINT.
FLINT 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 .
*/
#ifndef MPOLY_H
#define MPOLY_H
#ifdef MPOLY_INLINES_C
#define MPOLY_INLINE FLINT_DLL
#else
#define MPOLY_INLINE static __inline__
#endif
#undef ulong
#define ulong ulongxx /* interferes with system includes */
#include
#undef ulong
#include
#define ulong mp_limb_t
#include "string.h"
#include "flint.h"
#include "fmpz.h"
#include "fmpz_mat.h"
#include "fmpq.h"
#include "ulong_extras.h"
#include "thread_pool.h"
#ifdef __cplusplus
extern "C" {
#endif
#define MPOLY_MIN_BITS (UWORD(8)) /* minimum number of bits to pack into */
/* choose m so that (m + 1)/(n - m) ~= la/lb, i.e. m = (n*la - lb)/(la + lb) */
MPOLY_INLINE slong mpoly_divide_threads(slong n, double la, double lb)
{
double m_double = (n*la - lb)/(la + lb);
slong m = m_double + (2*m_double > n ? -0.5 : 0.5);
/* input must satisfy */
FLINT_ASSERT(n > 0);
if (m <= 0)
m = 0;
if (m >= n - 1)
m = n - 1;
/* output must satisfy */
FLINT_ASSERT(m >= 0);
FLINT_ASSERT(m < n);
return m;
}
typedef enum {
ORD_LEX,
ORD_DEGLEX,
ORD_DEGREVLEX
} ordering_t;
#define MPOLY_NUM_ORDERINGS 3
/* context *******************************************************************/
typedef struct
{
slong nvars; /* number of variables */
slong nfields; /* number of fields in exponent vector */
ordering_t ord; /* monomial ordering */
int deg; /* is ord a degree ordering? */
int rev; /* is ord a reversed ordering? */
slong lut_words_per_exp[FLINT_BITS];
unsigned char lut_fix_bits[FLINT_BITS]; /* FLINT_BITS < 256 */
} mpoly_ctx_struct;
typedef mpoly_ctx_struct mpoly_ctx_t[1];
FLINT_DLL void mpoly_ctx_init(mpoly_ctx_t ctx, slong nvars, const ordering_t ord);
FLINT_DLL void mpoly_ctx_init_rand(mpoly_ctx_t mctx, flint_rand_t state, slong max_nvars);
FLINT_DLL void mpoly_monomial_randbits_fmpz(fmpz * exp, flint_rand_t state, flint_bitcnt_t exp_bits, const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_ctx_clear(mpoly_ctx_t mctx);
/*
number of words used by an exponent vector packed into "bits" bits:
we must have either
(mp) bits > FLINT_BITS and bits % FLINT_BITS == 0, or
(sp) MPOLY_MIN_BITS <= bits <= FLINT_BITS
*/
MPOLY_INLINE
slong mpoly_words_per_exp_sp(flint_bitcnt_t bits, const mpoly_ctx_t mctx)
{
FLINT_ASSERT(0 < bits);
FLINT_ASSERT(bits <= FLINT_BITS);
FLINT_ASSERT(mctx->lut_words_per_exp[bits - 1]
== (mctx->nfields - 1)/(FLINT_BITS/bits) + 1);
return mctx->lut_words_per_exp[bits - 1];
}
MPOLY_INLINE
slong mpoly_words_per_exp_mp(flint_bitcnt_t bits, const mpoly_ctx_t mctx)
{
FLINT_ASSERT(bits % FLINT_BITS == 0);
return bits/FLINT_BITS*mctx->nfields;
}
MPOLY_INLINE
slong mpoly_words_per_exp(flint_bitcnt_t bits, const mpoly_ctx_t mctx)
{
if (bits <= FLINT_BITS)
return mpoly_words_per_exp_sp(bits, mctx);
else
return mpoly_words_per_exp_mp(bits, mctx);
}
/*
If "bits" is simply the number of bits needed to pack an exponent vector,
possibly upgrade it so that it is either
(mp) a multiple of FLINT_BITS in the mp case, or
(sp) as big as possible without increasing words_per_exp in the sp case
The upgrade in (mp) is manditory, while the upgrade in (sp) is simply nice.
*/
MPOLY_INLINE
flint_bitcnt_t mpoly_fix_bits(flint_bitcnt_t bits, const mpoly_ctx_t mctx)
{
FLINT_ASSERT(bits > 0);
if (bits <= FLINT_BITS)
return mctx->lut_fix_bits[bits - 1];
else
return (bits + FLINT_BITS - 1)/FLINT_BITS*FLINT_BITS;
}
/* heaps *********************************************************************/
typedef struct mpoly_heap_t
{
ulong i;
ulong j;
struct mpoly_heap_t * next;
} mpoly_heap_t;
typedef struct mpoly_nheap_t
{
ulong i;
ulong j;
struct mpoly_nheap_t * next;
slong p;
} mpoly_nheap_t;
typedef struct mpoly_heap1_s
{
ulong exp;
void * next;
} mpoly_heap1_s;
typedef struct mpoly_heap_s
{
ulong * exp;
void * next;
} mpoly_heap_s;
/* trees *********************************************************************/
/* red-black with ui keys */
typedef struct {
ulong key;
slong up;
slong left;
slong right;
int color;
} mpoly_rbnode_ui_struct;
typedef struct {
slong length;
mpoly_rbnode_ui_struct * nodes;
slong node_alloc;
char * data;
slong data_alloc;
slong data_size;
} mpoly_rbtree_ui_struct;
typedef mpoly_rbtree_ui_struct mpoly_rbtree_ui_t[1];
FLINT_DLL void mpoly_rbtree_ui_init(mpoly_rbtree_ui_t T, slong data_size);
FLINT_DLL void mpoly_rbtree_ui_clear(mpoly_rbtree_ui_t T);
FLINT_DLL void * mpoly_rbtree_ui_lookup(mpoly_rbtree_ui_t T, int * its_new,
ulong key);
MPOLY_INLINE slong mpoly_rbtree_ui_head(const mpoly_rbtree_ui_t T)
{
FLINT_ASSERT(T->nodes[1].left >= 0 || T->length < 1);
return T->nodes[1].left;
}
/* red-black with fmpz keys */
typedef struct {
fmpz_t key;
slong up;
slong left;
slong right;
int color;
} mpoly_rbnode_fmpz_struct;
typedef struct {
slong length;
mpoly_rbnode_fmpz_struct * nodes;
slong node_alloc;
char * data;
slong data_alloc;
slong data_size;
} mpoly_rbtree_fmpz_struct;
typedef mpoly_rbtree_fmpz_struct mpoly_rbtree_fmpz_t[1];
FLINT_DLL void mpoly_rbtree_fmpz_init(mpoly_rbtree_fmpz_t T, slong data_size);
FLINT_DLL void mpoly_rbtree_fmpz_clear(mpoly_rbtree_fmpz_t T);
FLINT_DLL void * mpoly_rbtree_fmpz_lookup(mpoly_rbtree_fmpz_t T, int * its_new,
const fmpz_t key);
MPOLY_INLINE slong mpoly_rbtree_fmpz_head(const mpoly_rbtree_fmpz_t T)
{
FLINT_ASSERT(T->nodes[1].left >= 0 || T->length < 1);
return T->nodes[1].left;
}
/* Orderings *****************************************************************/
MPOLY_INLINE
ordering_t mpoly_ordering_randtest(flint_rand_t state)
{
return (ordering_t) n_randint(state, MPOLY_NUM_ORDERINGS);
}
MPOLY_INLINE
int mpoly_ordering_isdeg(const mpoly_ctx_t mctx)
{
return mctx->ord == ORD_DEGLEX || mctx->ord == ORD_DEGREVLEX;
}
MPOLY_INLINE
int mpoly_ordering_isrev(const mpoly_ctx_t mctx)
{
return mctx->ord == ORD_DEGREVLEX;
}
MPOLY_INLINE
void mpoly_ordering_print(ordering_t ord)
{
switch (ord)
{
case ORD_LEX:
printf("lex");
break;
case ORD_DEGLEX:
printf("deglex");
break;
case ORD_DEGREVLEX:
printf("degrevlex");
break;
default:
printf("Unknown ordering in mpoly_ordering_print.");
}
}
/* Monomials ****************************************************************/
MPOLY_INLINE
void mpoly_monomial_zero(ulong * exp_ptr, slong N)
{
slong i;
for (i = 0; i < N; i++)
exp_ptr[i] = 0;
}
MPOLY_INLINE
void mpoly_monomial_add(ulong * exp_ptr, const ulong * exp2,
const ulong * exp3, slong N)
{
slong i;
for (i = 0; i < N; i++)
exp_ptr[i] = exp2[i] + exp3[i];
}
MPOLY_INLINE
void mpoly_monomial_add_mp(ulong * exp_ptr, const ulong * exp2,
const ulong * exp3, slong N)
{
mpn_add_n(exp_ptr, exp2, exp3, N);
}
MPOLY_INLINE
void mpoly_monomial_sub(ulong * exp_ptr, const ulong * exp2,
const ulong * exp3, slong N)
{
slong i;
for (i = 0; i < N; i++)
exp_ptr[i] = exp2[i] - exp3[i];
}
MPOLY_INLINE
void mpoly_monomial_sub_mp(ulong * exp_ptr, const ulong * exp2,
const ulong * exp3, slong N)
{
mpn_sub_n(exp_ptr, exp2, exp3, N);
}
MPOLY_INLINE
void mpoly_monomial_madd(ulong * exp1, const ulong * exp2, ulong scalar,
const ulong * exp3, slong N)
{
slong i;
for (i = 0; i < N; i++)
exp1[i] = exp2[i] + scalar*exp3[i];
}
MPOLY_INLINE
void mpoly_monomial_madd_mp(ulong * exp1, const ulong * exp2, ulong scalar,
const ulong * exp3, slong N)
{
slong i;
for (i = 0; i < N; i++)
exp1[i] = exp2[i];
mpn_addmul_1(exp1, exp3, N, scalar);
}
MPOLY_INLINE
void mpoly_monomial_madd_inplace_mp(ulong * exp12, ulong scalar,
const ulong * exp3, slong N)
{
mpn_addmul_1(exp12, exp3, N, scalar);
}
MPOLY_INLINE
void mpoly_monomial_msub(ulong * exp1, const ulong * exp2, ulong scalar,
const ulong * exp3, slong N)
{
slong i;
for (i = 0; i < N; i++)
exp1[i] = exp2[i] - scalar*exp3[i];
}
MPOLY_INLINE
void mpoly_monomial_msub_mp(ulong * exp1, const ulong * exp2, ulong scalar,
const ulong * exp3, slong N)
{
slong i;
for (i = 0; i < N; i++)
exp1[i] = exp2[i];
FLINT_ASSERT(N > 0);
mpn_submul_1(exp1, exp3, N, scalar);
}
MPOLY_INLINE
void mpoly_monomial_msub_ui_array(ulong * exp1, const ulong * exp2,
const ulong * scalar, slong scalar_limbs,
const ulong * exp3, slong N)
{
slong i;
for (i = 0; i < N; i++)
exp1[i] = exp2[i];
FLINT_ASSERT(scalar_limbs <= N);
for (i = 0; i < scalar_limbs; i++)
{
FLINT_ASSERT(N > i);
mpn_submul_1(exp1 + i, exp3, N - i, scalar[i]);
}
}
MPOLY_INLINE
void mpoly_monomial_madd_ui_array(ulong * exp1, const ulong * exp2,
const ulong * scalar, slong scalar_limbs,
const ulong * exp3, slong N)
{
slong i;
for (i = 0; i < N; i++)
exp1[i] = exp2[i];
FLINT_ASSERT(scalar_limbs <= N);
for (i = 0; i < scalar_limbs; i++)
mpn_addmul_1(exp1 + i, exp3, N - i, scalar[i]);
}
MPOLY_INLINE
void mpoly_monomial_madd_fmpz(ulong * exp1, const ulong * exp2,
const fmpz_t scalar, const ulong * exp3, slong N)
{
if (COEFF_IS_MPZ(*scalar))
{
__mpz_struct * mpz = COEFF_TO_PTR(*scalar);
mpoly_monomial_madd_ui_array(exp1, exp2,
mpz->_mp_d, mpz->_mp_size, exp3, N);
}
else
{
mpoly_monomial_madd_mp(exp1, exp2, *scalar, exp3, N);
}
}
MPOLY_INLINE
ulong mpoly_overflow_mask_sp(flint_bitcnt_t bits)
{
slong i;
ulong mask = 0;
FLINT_ASSERT(bits <= FLINT_BITS);
for (i = 0; i < FLINT_BITS/bits; i++)
mask = (mask << bits) + (UWORD(1) << (bits - 1));
return mask;
}
MPOLY_INLINE
ulong mpoly_monomial_max1(ulong exp2, ulong exp3,
flint_bitcnt_t bits, ulong mask)
{
ulong s, m, exp1;
s = mask + exp2 - exp3;
m = mask & s;
m = m - (m >> (bits - 1));
exp1 = exp3 + (s & m);
return exp1;
}
MPOLY_INLINE
void mpoly_monomial_max(ulong * exp1, const ulong * exp2, const ulong * exp3,
flint_bitcnt_t bits, slong N, ulong mask)
{
ulong i, s, m;
for (i = 0; i < N; i++)
{
s = mask + exp2[i] - exp3[i];
m = mask & s;
m = m - (m >> (bits - 1));
exp1[i] = exp3[i] + (s & m);
}
}
MPOLY_INLINE
ulong mpoly_monomial_min1(ulong exp2, ulong exp3,
flint_bitcnt_t bits, ulong mask)
{
ulong s, m, exp1;
s = mask + exp2 - exp3;
m = mask & s;
m = m - (m >> (bits - 1));
exp1 = exp2 - (s & m);
return exp1;
}
MPOLY_INLINE
void mpoly_monomial_min(ulong * exp1, const ulong * exp2, const ulong * exp3,
flint_bitcnt_t bits, slong N, ulong mask)
{
ulong i, s, m;
for (i = 0; i < N; i++)
{
s = mask + exp2[i] - exp3[i];
m = mask & s;
m = m - (m >> (bits - 1));
exp1[i] = exp2[i] - (s & m);
}
}
MPOLY_INLINE
void mpoly_monomial_max_mp(ulong * exp1, const ulong * exp2, const ulong * exp3,
flint_bitcnt_t bits, slong N)
{
slong i, j;
for (i = 0; i < N; i += bits/FLINT_BITS)
{
const ulong * t = exp2;
for (j = bits/FLINT_BITS - 1; j >= 0; j--)
{
if (exp3[i + j] != exp2[i + j])
{
if (exp3[i + j] > exp2[i + j])
t = exp3;
break;
}
}
for (j = 0; j < bits/FLINT_BITS; j++)
{
exp1[i + j] = t[i + j];
}
}
}
MPOLY_INLINE
void mpoly_monomial_min_mp(ulong * exp1, const ulong * exp2, const ulong * exp3,
flint_bitcnt_t bits, slong N)
{
slong i, j;
for (i = 0; i < N; i += bits/FLINT_BITS)
{
const ulong * t = exp2;
for (j = bits/FLINT_BITS - 1; j >= 0; j--)
{
if (exp3[i + j] != exp2[i + j])
{
if (exp3[i + j] < exp2[i + j])
t = exp3;
break;
}
}
for (j = 0; j < bits/FLINT_BITS; j++)
{
exp1[i + j] = t[i + j];
}
}
}
MPOLY_INLINE
int mpoly_monomial_overflows(ulong * exp2, slong N, ulong mask)
{
slong i;
for (i = 0; i < N; i++)
{
if ((exp2[i] & mask) != 0)
return 1;
}
return 0;
}
MPOLY_INLINE
int mpoly_monomial_overflows_mp(ulong * exp_ptr, slong N, flint_bitcnt_t bits)
{
slong i = bits/FLINT_BITS - 1;
do {
if ((slong)(exp_ptr[i]) < 0)
return 1;
i += bits/FLINT_BITS;
} while (i < N);
return 0;
}
MPOLY_INLINE
int mpoly_monomial_overflows1(ulong exp, ulong mask)
{
return (exp & mask) != 0;
}
MPOLY_INLINE
int mpoly_monomial_divides(ulong * exp_ptr, const ulong * exp2,
const ulong * exp3, slong N, ulong mask)
{
slong i;
for (i = 0; i < N; i++)
{
exp_ptr[i] = exp2[i] - exp3[i];
if ((exp_ptr[i] & mask) != 0)
return 0;
}
return 1;
}
MPOLY_INLINE
int mpoly_monomial_halves(ulong * exp_ptr, const ulong * exp2,
slong N, ulong mask)
{
slong i;
ulong bw;
bw = mpn_rshift(exp_ptr, exp2, N, 1);
if (bw != 0)
return 0;
for (i = 0; i < N; i++)
{
if ((exp_ptr[i] & mask) != 0)
return 0;
}
return 1;
}
MPOLY_INLINE
int mpoly_monomial_divides_mp(ulong * exp_ptr, const ulong * exp2,
const ulong * exp3, slong N, flint_bitcnt_t bits)
{
slong i;
mpn_sub_n(exp_ptr, exp2, exp3, N);
i = bits/FLINT_BITS - 1;
do {
if ((slong)(exp_ptr[i]) < 0)
return 0;
i += bits/FLINT_BITS;
} while (i < N);
return 1;
}
MPOLY_INLINE
int mpoly_monomial_halves_mp(ulong * exp_ptr, const ulong * exp2,
slong N, flint_bitcnt_t bits)
{
slong i;
ulong bw;
bw = mpn_rshift(exp_ptr, exp2, N, 1);
if (bw != 0)
return 0;
i = bits/FLINT_BITS - 1;
do {
if ((slong)(exp_ptr[i]) < 0)
return 0;
i += bits/FLINT_BITS;
} while (i < N);
return 1;
}
MPOLY_INLINE
int mpoly_monomial_divides_test(const ulong * exp2,
const ulong * exp3, slong N, ulong mask)
{
slong i;
for (i = 0; i < N; i++)
if (((exp2[i] - exp3[i]) & mask) != 0)
return 0;
return 1;
}
MPOLY_INLINE
int mpoly_monomial_divides_mp_test(const ulong * exp2,
const ulong * exp3, slong N, flint_bitcnt_t bits)
{
slong i, j;
i = 0;
do {
for (j = bits/FLINT_BITS - 1; j >= 0; j--)
{
if (exp2[i + j] > exp3[i + j])
break;
if (exp2[i + j] < exp3[i + j])
return 0;
}
i += bits/FLINT_BITS;
} while (i < N);
return 1;
}
MPOLY_INLINE
int mpoly_monomial_divides1(ulong * exp_ptr, const ulong exp2,
const ulong exp3, ulong mask)
{
(*exp_ptr) = exp2 - exp3;
if (((exp2 - exp3) & mask) != 0)
return 0;
return 1;
}
MPOLY_INLINE
int mpoly_monomial_halves1(ulong * exp_ptr, const ulong exp2, ulong mask)
{
if (exp2 & 1)
return 0;
(*exp_ptr) = exp2 >> 1;
if (((exp2 >> 1) & mask) != 0)
return 0;
return 1;
}
MPOLY_INLINE
void mpoly_monomial_set(ulong * exp2, const ulong * exp3, slong N)
{
slong i;
for (i = 0; i < N; i++)
exp2[i] = exp3[i];
}
MPOLY_INLINE
void mpoly_monomial_set_extra(ulong * exp2, const ulong * exp3,
slong N, slong offset, ulong extra)
{
slong i;
for (i = 0; i < N; i++)
{
exp2[i] = exp3[i] + (i == offset ? extra : 0);
}
}
MPOLY_INLINE
void mpoly_copy_monomials(ulong * exp1, const ulong * exp2, slong len, slong N)
{
memcpy(exp1, exp2, N*len*sizeof(ulong));
}
MPOLY_INLINE
void mpoly_monomial_swap(ulong * exp2, ulong * exp3, slong N)
{
slong i;
ulong t;
for (i = 0; i < N; i++)
{
t = exp2[i];
exp2[i] = exp3[i];
exp3[i] = t;
}
}
MPOLY_INLINE
void mpoly_monomial_mul_ui(ulong * exp2, const ulong * exp3, slong N, ulong c)
{
slong i;
for (i = 0; i < N; i++)
exp2[i] = exp3[i]*c;
}
MPOLY_INLINE
void mpoly_monomial_mul_ui_mp(ulong * exp2, const ulong * exp3, slong N, ulong c)
{
FLINT_ASSERT(N > 0);
mpn_mul_1(exp2, exp3, N, c);
}
FLINT_DLL void mpoly_monomial_mul_fmpz(ulong * exp2, const ulong * exp3,
slong N, const fmpz_t c);
MPOLY_INLINE
int mpoly_monomial_is_zero(const ulong * exp, slong N)
{
slong i;
for (i = 0; i < N; i++)
{
if (exp[i] != 0)
return 0;
}
return 1;
}
MPOLY_INLINE
int mpoly_monomial_equal(const ulong * exp2, const ulong * exp3, slong N)
{
slong i;
for (i = 0; i < N; i++)
{
if (exp2[i] != exp3[i])
return 0;
}
return 1;
}
MPOLY_INLINE
int mpoly_monomial_equal_extra(const ulong * exp2, const ulong * exp3,
slong N, slong offset, ulong extra)
{
slong i;
for (i = 0; i < N; i++)
{
ulong e3 = exp3[i] + ((i == offset) ? extra : 0);
if (exp2[i] != e3)
return 0;
}
return 1;
}
MPOLY_INLINE
int mpoly_monomial_cmp1(ulong a, ulong b, ulong cmpmask)
{
if ((a^cmpmask) != (b^cmpmask))
{
if ((a^cmpmask) > (b^cmpmask))
return 1;
else
return -1;
}
return 0;
}
MPOLY_INLINE
int mpoly_monomial_gt1(ulong a, ulong b, ulong cmpmask)
{
return (a^cmpmask) > (b^cmpmask);
}
MPOLY_INLINE
int mpoly_monomial_ge1(ulong a, ulong b, ulong cmpmask)
{
return (a^cmpmask) >= (b^cmpmask);
}
MPOLY_INLINE
int mpoly_monomial_lt(const ulong * exp3, const ulong * exp2,
slong N, const ulong * cmpmask)
{
slong i = N - 1;
do {
if (exp2[i] != exp3[i])
{
return (exp3[i]^cmpmask[i]) < (exp2[i]^cmpmask[i]);
}
} while (--i >= 0);
return 0;
}
MPOLY_INLINE
int mpoly_monomial_gt(const ulong * exp3, const ulong * exp2,
slong N, const ulong * cmpmask)
{
slong i = N - 1;
do {
if (exp2[i] != exp3[i])
{
return (exp3[i]^cmpmask[i]) > (exp2[i]^cmpmask[i]);
}
} while (--i >= 0);
return 0;
}
MPOLY_INLINE
int mpoly_monomial_lt_nomask(const ulong * exp2, const ulong * exp3, slong N)
{
slong i = N - 1;
do {
if (exp2[i] != exp3[i])
{
return exp2[i] < exp3[i];
}
} while (--i >= 0);
return 0;
}
MPOLY_INLINE
int mpoly_monomial_gt_nomask(const ulong * exp2, const ulong * exp3, slong N)
{
slong i = N - 1;
do {
if (exp2[i] != exp3[i])
{
return exp2[i] > exp3[i];
}
} while (--i >= 0);
return 0;
}
MPOLY_INLINE
int mpoly_monomial_lt_nomask_extra(const ulong * exp2, const ulong * exp3,
slong N, slong offset, ulong extra)
{
slong i = N - 1;
do {
ulong e3 = exp3[i] + ((i == offset) ? extra : 0);
if (exp2[i] != e3)
{
return exp2[i] < e3;
}
} while (--i >= 0);
return 0;
}
MPOLY_INLINE
int mpoly_monomial_gt_nomask_extra(const ulong * exp2, const ulong * exp3,
slong N, slong offset, ulong extra)
{
slong i = N - 1;
do {
ulong e3 = exp3[i] + ((i == offset) ? extra : 0);
if (exp2[i] != e3)
{
return exp2[i] > e3;
}
} while (--i >= 0);
return 0;
}
MPOLY_INLINE
int mpoly_monomial_cmp(const ulong * exp2, const ulong * exp3,
slong N, const ulong * cmpmask)
{
slong i = N - 1;
do {
if (exp2[i] != exp3[i])
{
if ((exp2[i]^cmpmask[i]) > (exp3[i]^cmpmask[i]))
return 1;
else
return -1;
}
} while (--i >= 0);
return 0;
}
MPOLY_INLINE
int mpoly_monomial_cmp_nomask(const ulong * exp2, const ulong * exp3, slong N)
{
slong i = N - 1;
do {
if (exp2[i] != exp3[i])
{
if (exp2[i] > exp3[i])
return 1;
else
return -1;
}
} while (--i >= 0);
return 0;
}
MPOLY_INLINE
int mpoly_monomial_cmp_nomask_extra(const ulong * exp2, const ulong * exp3,
slong N, slong offset, ulong extra)
{
slong i = N - 1;
do {
ulong e3 = exp3[i] + ((i == offset) ? extra : 0);
if (exp2[i] != e3)
{
if (exp2[i] > e3)
return 1;
else
return -1;
}
} while (--i >= 0);
return 0;
}
MPOLY_INLINE
int mpoly_monomial_divides_tight(slong e1, slong e2, slong * prods, slong num)
{
slong j;
for (j = 0; j < num; j++)
{
slong d1 = (e1 % prods[j + 1])/prods[j];
slong d2 = (e2 % prods[j + 1])/prods[j];
if (d1 < d2)
return 0;
}
return 1;
}
MPOLY_INLINE
void mpoly_max_degrees_tight(slong * max_exp,
ulong * exps, slong len, slong * prods, slong num)
{
slong i, j;
for (j = 0; j < num; j++)
max_exp[j] = 0;
for (i = 0; i < len; i++)
{
for (j = 0; j < num; j++)
{
slong d1 = (exps[i] % prods[j + 1])/prods[j];
if (d1 > max_exp[j])
max_exp[j] = d1;
}
}
}
/* ceiling(log_4(x)) - 1 */
MPOLY_INLINE slong mpoly_geobucket_clog4(slong x)
{
if (x <= 4)
return 0;
/*
FLINT_BIT_COUNT returns unsigned int.
Signed division is not defined.
Do the calculation with unsigned ints and then convert to slong.
*/
return (slong)((FLINT_BIT_COUNT(x - 1) - UWORD(1))/(UWORD(2)));
}
/* single-limb packings ******************************************************/
MPOLY_INLINE
ulong pack_exp2(ulong e0, ulong e1)
{
return (e0 << (1*(FLINT_BITS/2))) +
(e1 << (0*(FLINT_BITS/2)));
}
MPOLY_INLINE
ulong pack_exp3(ulong e0, ulong e1, ulong e2)
{
return (e0 << (2*(FLINT_BITS/3))) +
(e1 << (1*(FLINT_BITS/3))) +
(e2 << (0*(FLINT_BITS/3)));
}
MPOLY_INLINE
ulong extract_exp(ulong e, int idx, int nvars)
{
return (e >> (idx*(FLINT_BITS/nvars))) &
((-UWORD(1)) >> (FLINT_BITS - FLINT_BITS/nvars));
}
FLINT_DLL ulong _mpoly_bidegree(const ulong * Aexps, flint_bitcnt_t Abits,
const mpoly_ctx_t mctx);
/* generators ****************************************************************/
FLINT_DLL void mpoly_gen_fields_ui(ulong * exp, slong var,
const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_gen_fields_fmpz(fmpz * exp, slong var,
const mpoly_ctx_t mctx);
FLINT_DLL flint_bitcnt_t mpoly_gen_bits_required(slong var, const mpoly_ctx_t mctx);
/* return the index in the fields where the generator of index v is stored */
MPOLY_INLINE slong mpoly_gen_index(slong v, const mpoly_ctx_t mctx)
{
return mctx->rev ? v : mctx->nvars - 1 - v;
}
FLINT_DLL void mpoly_gen_offset_shift_sp(slong * offset, slong * shift,
slong var, flint_bitcnt_t bits, const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_gen_monomial_offset_shift_sp(ulong * mexp, slong * offset,
slong * shift, slong var, flint_bitcnt_t bits, const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_gen_monomial_sp(ulong * oneexp, slong var,
flint_bitcnt_t bits, const mpoly_ctx_t mctx);
FLINT_DLL slong mpoly_gen_offset_mp(slong var,
flint_bitcnt_t bits, const mpoly_ctx_t mctx);
FLINT_DLL slong mpoly_gen_monomial_offset_mp(ulong * mexp, slong var,
flint_bitcnt_t bits, const mpoly_ctx_t mctx);
FLINT_DLL void fmpz_mat_mul_vec(fmpz * v, const fmpz_mat_t M, fmpz * u);
FLINT_DLL void mpoly_compose_mat_gen(fmpz_mat_t M, const slong * c,
const mpoly_ctx_t mctxB, const mpoly_ctx_t mctxAC);
FLINT_DLL void mpoly_compose_mat_fill_column(fmpz_mat_t M, const ulong * Cexp,
flint_bitcnt_t Cbits, slong Bvar, const mpoly_ctx_t mctxB,
const mpoly_ctx_t mctxAC);
/* Monomial arrays ***********************************************************/
FLINT_DLL void mpoly_get_cmpmask(ulong * cmpmask, slong N, flint_bitcnt_t bits,
const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_get_ovfmask(ulong * ovfmask, slong N, flint_bitcnt_t bits,
const mpoly_ctx_t mctx);
FLINT_DLL int mpoly_monomials_cmp(const ulong * Aexps, flint_bitcnt_t Abits,
const ulong * Bexps, flint_bitcnt_t Bbits,
slong length, const mpoly_ctx_t mctx);
FLINT_DLL flint_bitcnt_t mpoly_exp_bits_required_ui(const ulong * user_exp,
const mpoly_ctx_t mctx);
FLINT_DLL flint_bitcnt_t mpoly_exp_bits_required_ffmpz(const fmpz * user_exp,
const mpoly_ctx_t mctx);
FLINT_DLL flint_bitcnt_t mpoly_exp_bits_required_pfmpz(fmpz * const * user_exp,
const mpoly_ctx_t mctx);
MPOLY_INLINE
flint_bitcnt_t mpoly_gen_pow_exp_bits_required(slong v, ulong e,
const mpoly_ctx_t mctx)
{
return 1 + FLINT_BIT_COUNT(e); /* only lex and deg supported */
}
FLINT_DLL int mpoly_is_poly(const ulong * Aexps, slong Alen,
flint_bitcnt_t Abits, slong var, const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_pack_vec_ui(ulong * exp1, const ulong * exp2,
flint_bitcnt_t bits, slong nfields, slong len);
FLINT_DLL void mpoly_pack_vec_fmpz(ulong * exp1, const fmpz * exp2,
flint_bitcnt_t bits, slong nfields, slong len);
FLINT_DLL void mpoly_unpack_vec_ui(ulong * exp1, const ulong * exp2,
flint_bitcnt_t bits, slong nfields, slong len);
FLINT_DLL void mpoly_unpack_vec_fmpz(fmpz * exp1, const ulong * exp2,
flint_bitcnt_t bits, slong nfields, slong len);
FLINT_DLL void mpoly_get_monomial_ui_unpacked_ffmpz(ulong * user_exps,
const fmpz * poly_exps, const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_get_monomial_ffmpz_unpacked_ffmpz(fmpz * user_exps,
const fmpz * poly_exps, const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_get_monomial_pfmpz_unpacked_ffmpz(fmpz ** user_exps,
const fmpz * poly_exps, const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_get_monomial_ui_unpacked_ui(ulong * user_exps,
const ulong * poly_exps, const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_get_monomial_ui_sp(ulong * user_exps,
const ulong * poly_exps, flint_bitcnt_t bits, const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_get_monomial_ui_mp(ulong * user_exps,
const ulong * poly_exps, flint_bitcnt_t bits, const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_get_monomial_si_mp(slong * user_exps,
const ulong * poly_exps, flint_bitcnt_t bits, const mpoly_ctx_t mctx);
MPOLY_INLINE void mpoly_get_monomial_ui(ulong * user_exps,
const ulong * poly_exps, flint_bitcnt_t bits, const mpoly_ctx_t mctx)
{
if (bits <= FLINT_BITS)
mpoly_get_monomial_ui_sp(user_exps, poly_exps, bits, mctx);
else
mpoly_get_monomial_ui_mp(user_exps, poly_exps, bits, mctx);
}
MPOLY_INLINE void mpoly_get_monomial_si(slong * user_exps,
const ulong * poly_exps, flint_bitcnt_t bits, const mpoly_ctx_t mctx)
{
/* if bits <= FLINT_BITS and poly_exps is canonical, everything should be ok */
if (bits <= FLINT_BITS)
mpoly_get_monomial_ui_sp((ulong *) user_exps, poly_exps, bits, mctx);
else
mpoly_get_monomial_si_mp(user_exps, poly_exps, bits, mctx);
}
FLINT_DLL ulong mpoly_get_monomial_var_exp_ui_sp(const ulong * poly_exps,
slong var, flint_bitcnt_t bits, const mpoly_ctx_t mctx);
FLINT_DLL ulong mpoly_get_monomial_var_exp_ui_mp(const ulong * poly_exps,
slong var, flint_bitcnt_t bits, const mpoly_ctx_t mctx);
FLINT_DLL slong mpoly_get_monomial_var_exp_si_mp(const ulong * poly_exps,
slong var, flint_bitcnt_t bits, const mpoly_ctx_t mctx);
MPOLY_INLINE ulong mpoly_get_monomial_var_exp_ui(const ulong * poly_exps,
slong var, flint_bitcnt_t bits, const mpoly_ctx_t mctx)
{
if (bits <= FLINT_BITS)
return mpoly_get_monomial_var_exp_ui_sp(poly_exps, var, bits, mctx);
else
return mpoly_get_monomial_var_exp_ui_mp(poly_exps, var, bits, mctx);
}
MPOLY_INLINE slong mpoly_get_monomial_var_exp_si(const ulong * poly_exps,
slong var, flint_bitcnt_t bits, const mpoly_ctx_t mctx)
{
if (bits <= FLINT_BITS)
return (slong) mpoly_get_monomial_var_exp_ui_sp(poly_exps, var, bits, mctx);
else
return mpoly_get_monomial_var_exp_si_mp(poly_exps, var, bits, mctx);
}
FLINT_DLL void mpoly_get_monomial_ffmpz(fmpz * exps, const ulong * poly_exps,
flint_bitcnt_t bits, const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_get_monomial_pfmpz(fmpz ** exps, const ulong * poly_exps,
flint_bitcnt_t bits, const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_set_monomial_ui(ulong * exp1, const ulong * exp2,
flint_bitcnt_t bits, const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_set_monomial_ffmpz(ulong * exp1, const fmpz * exp2,
flint_bitcnt_t bits, const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_set_monomial_pfmpz(ulong * exp1, fmpz * const * exp2,
flint_bitcnt_t bits, const mpoly_ctx_t mctx);
FLINT_DLL int mpoly_repack_monomials(ulong * exps1, flint_bitcnt_t bits1,
const ulong * exps2, flint_bitcnt_t bits2, slong len,
const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_pack_monomials_tight(ulong * exp1,
const ulong * exp2, slong len, const slong * mults,
slong num, slong bits);
FLINT_DLL void mpoly_unpack_monomials_tight(ulong * e1, ulong * e2, slong len,
slong * mults, slong num, slong bits);
FLINT_DLL int mpoly_monomial_exists(slong * index, const ulong * poly_exps,
const ulong * exp, slong len, slong N, const ulong * cmpmask);
FLINT_DLL slong mpoly_monomial_index1_nomask(ulong * Aexps, slong Alen, ulong e);
FLINT_DLL slong mpoly_monomial_index_ui(const ulong * Aexp, flint_bitcnt_t Abits,
slong Alength, const ulong * exp, const mpoly_ctx_t mctx);
FLINT_DLL slong mpoly_monomial_index_pfmpz(const ulong * Aexp, flint_bitcnt_t Abits,
slong Alength, fmpz * const * exp, const mpoly_ctx_t mctx);
FLINT_DLL slong mpoly_monomial_index_monomial(const ulong * Aexp,
flint_bitcnt_t Abits, slong Alength, const ulong * Mexp,
flint_bitcnt_t Mbits, const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_min_fields_ui_sp(ulong * min_fields, const ulong * poly_exps,
slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_min_fields_fmpz(fmpz * min_fields, const ulong * poly_exps,
slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_max_fields_ui_sp(ulong * max_fields, const ulong * poly_exps,
slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_max_fields_fmpz(fmpz * max_fields, const ulong * poly_exps,
slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx);
FLINT_DLL int mpoly_degrees_fit_si(const ulong * poly_exps,
slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_degrees_si(slong * user_degs, const ulong * poly_exps,
slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_degrees_si_threaded(slong * user_degs, const ulong * poly_exps,
slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx,
const thread_pool_handle * handles, slong num_handles);
FLINT_DLL void mpoly_degrees_ffmpz(fmpz * user_degs, const ulong * poly_exps,
slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_degrees_pfmpz(fmpz ** user_degs, const ulong * poly_exps,
slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx);
FLINT_DLL slong mpoly_degree_si(const ulong * poly_exps,
slong len, flint_bitcnt_t bits, slong var, const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_degree_fmpz(fmpz_t deg, const ulong * poly_exps,
slong len, flint_bitcnt_t bits, slong var, const mpoly_ctx_t mctx);
FLINT_DLL int mpoly_total_degree_fits_si(const ulong * exps,
slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx);
FLINT_DLL slong mpoly_total_degree_si(const ulong * exps,
slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_total_degree_fmpz(fmpz_t totdeg, const ulong * exps,
slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_total_degree_fmpz_ref(fmpz_t totdeg, const ulong * exps,
slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_used_vars_or(int * used, const ulong * exps,
slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx);
FLINT_DLL int mpoly_monomial_cmp_general(ulong * Aexp, flint_bitcnt_t Abits,
ulong * Bexp, flint_bitcnt_t Bbits, const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_search_monomials(
slong ** e_ind, ulong * e, slong * e_score,
slong * t1, slong * t2, slong *t3,
slong lower, slong upper,
const ulong * a, slong a_len, const ulong * b, slong b_len,
slong N, const ulong * cmpmask);
FLINT_DLL void mpoly_main_variable_split_LEX(slong * ind, ulong * pexp,
const ulong * Aexp, slong l1, slong Alen,
const ulong * mults, slong num, slong Abits);
FLINT_DLL void mpoly_main_variable_split_DEG(slong * ind, ulong * pexp,
const ulong * Aexp, slong l1, slong Alen,
ulong deg, slong num, slong Abits);
FLINT_DLL int mpoly_term_exp_fits_si(ulong * exps, flint_bitcnt_t bits,
slong n, const mpoly_ctx_t mctx);
FLINT_DLL int mpoly_term_exp_fits_ui(ulong * exps, flint_bitcnt_t bits,
slong n, const mpoly_ctx_t mctx);
FLINT_DLL int mpoly_is_gen(ulong * exps, slong var,
flint_bitcnt_t bits, const mpoly_ctx_t mctx);
FLINT_DLL int mpoly_monomials_valid_test(ulong * exps, slong len,
flint_bitcnt_t bits, const mpoly_ctx_t mctx);
FLINT_DLL int mpoly_monomials_overflow_test(ulong * exps, slong len,
flint_bitcnt_t bits, const mpoly_ctx_t mctx);
FLINT_DLL int mpoly_monomials_inorder_test(ulong * exps, slong len,
flint_bitcnt_t bits, const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_reverse(ulong * Aexp, const ulong * Bexp, slong len, slong N);
FLINT_DLL void mpoly_monomials_deflation(fmpz * shift, fmpz * stride,
const ulong * Aexps, flint_bitcnt_t Abits, slong Alength,
const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_monomials_deflate(ulong * Aexps, flint_bitcnt_t Abits,
const ulong * Bexps, flint_bitcnt_t Bbits, slong Blength,
const fmpz * shift, const fmpz * stride, const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_monomials_inflate(ulong * Aexps, flint_bitcnt_t Abits,
const ulong * Bexps, flint_bitcnt_t Bbits, slong Blength,
const fmpz * shift, const fmpz * stride, const mpoly_ctx_t mctx);
FLINT_DLL void _mpoly_gen_shift_right(ulong * Aexp, flint_bitcnt_t Abits,
slong Alength, slong var, ulong amount, const mpoly_ctx_t mctx);
FLINT_DLL void _mpoly_gen_shift_right_fmpz(ulong * Aexp, flint_bitcnt_t Abits,
slong Alength, slong var, const fmpz_t amount, const mpoly_ctx_t mctx);
FLINT_DLL void _mpoly_gen_shift_left(ulong * Aexp, flint_bitcnt_t Abits,
slong Alength, slong var, ulong amount, const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_monomials_shift_right_ui(ulong * Aexps, flint_bitcnt_t Abits,
slong Alength, const ulong * user_exps, const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_monomials_shift_right_ffmpz(ulong * Aexps, flint_bitcnt_t Abits,
slong Alength, const fmpz * user_exps, const mpoly_ctx_t mctx);
FLINT_DLL void mpoly1_fill_marks(ulong ** Dcoeffs, slong * Dlen, slong * Dalloc,
const ulong * Aexps, slong Alen, flint_bitcnt_t Abits,
const mpoly_ctx_t mctx);
FLINT_DLL void mpoly2_fill_marks(ulong ** Dcoeffs, slong * Dlen, slong * Dalloc,
const ulong * Aexps, slong Alen, flint_bitcnt_t Abits,
const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_to_mpolyl_perm_deflate(
ulong * Aexps,
flint_bitcnt_t Abits,
const mpoly_ctx_t Actx,
ulong * Bexps,
flint_bitcnt_t Bbits,
const mpoly_ctx_t Bctx,
slong length,
const slong * perm,
const ulong * shift,
const ulong * stride);
FLINT_DLL void mpoly_from_mpolyl_perm_inflate(
ulong * Bexps,
flint_bitcnt_t Bbits,
const mpoly_ctx_t Bctx,
ulong * Aexps,
flint_bitcnt_t Abits,
const mpoly_ctx_t Actx,
slong length,
const slong * perm,
const ulong * shift,
const ulong * stride);
/* gcd ***********************************************************************/
#define MPOLY_GCD_USE_HENSEL 1
#define MPOLY_GCD_USE_BROWN 2
#define MPOLY_GCD_USE_ZIPPEL 4
#define MPOLY_GCD_USE_ZIPPEL2 8
#define MPOLY_GCD_USE_PRS 16
#define MPOLY_GCD_USE_ALL 31
typedef struct
{
ulong * Amax_exp;
ulong * Amin_exp;
ulong * Astride;
slong * Adeflate_deg;
slong * Alead_count;
slong * Atail_count;
ulong * Bmax_exp;
ulong * Bmin_exp;
ulong * Bstride;
slong * Bdeflate_deg;
slong * Blead_count;
slong * Btail_count;
ulong * Gmin_exp;
ulong * Abarmin_exp;
ulong * Bbarmin_exp;
ulong * Gstride;
slong * Gterm_count_est;
slong * Gdeflate_deg_bound;
flint_bitcnt_t Gbits, Abarbits, Bbarbits;
slong mvars;
slong Adeflate_tdeg;
slong Bdeflate_tdeg;
double Adensity;
double Bdensity;
double hensel_time, brown_time, zippel_time, zippel2_time;
slong * hensel_perm, * brown_perm, * zippel_perm, * zippel2_perm;
unsigned int can_use;
int Gdeflate_deg_bounds_are_nice; /* all of Gdeflate_deg_bound came from real gcd computations */
char * data;
} mpoly_gcd_info_struct;
typedef mpoly_gcd_info_struct mpoly_gcd_info_t[1];
FLINT_DLL void mpoly_gcd_info_init(mpoly_gcd_info_t I, slong nvars);
FLINT_DLL void mpoly_gcd_info_clear(mpoly_gcd_info_t I);
FLINT_DLL void mpoly_gcd_info_limits(ulong * Amax_exp, ulong * Amin_exp,
slong * Amax_exp_count, slong * Amin_exp_count,
const ulong * Aexps, flint_bitcnt_t Abits, slong Alength,
const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_gcd_info_stride(ulong * strides,
const ulong * Aexps, flint_bitcnt_t Abits, slong Alength,
const ulong * Amax_exp, const ulong * Amin_exp,
const ulong * Bexps, flint_bitcnt_t Bbits, slong Blength,
const ulong * Bmax_exp, const ulong * Bmin_exp,
const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_gcd_info_set_perm(mpoly_gcd_info_t I,
slong Alength, slong Blength, const mpoly_ctx_t mctx);
FLINT_DLL slong mpoly_gcd_info_get_brown_upper_limit(const mpoly_gcd_info_t I,
slong var, slong bound);
FLINT_DLL void mpoly_gcd_info_measure_hensel(mpoly_gcd_info_t I,
slong Alength, slong Blength, const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_gcd_info_measure_brown(mpoly_gcd_info_t I,
slong Alength, slong Blength, const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_gcd_info_measure_bma(mpoly_gcd_info_t I,
slong Alength, slong Blength, const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_gcd_info_measure_zippel(mpoly_gcd_info_t I,
slong Alength, slong Blength, const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_gcd_info_measure_zippel2(mpoly_gcd_info_t I,
slong Alength, slong Blength, const mpoly_ctx_t mctx);
FLINT_DLL int mpoly_monomial_cofactors(fmpz * Abarexps, fmpz * Bbarexps,
const ulong * Aexps, flint_bitcnt_t Abits,
const ulong * Bexps, flint_bitcnt_t Bbits,
slong length, const mpoly_ctx_t mctx);
/* factoring ****************************************************************/
#define MPOLY_FACTOR_USE_ZAS 1
#define MPOLY_FACTOR_USE_WANG 2
#define MPOLY_FACTOR_USE_ZIP 4
#define MPOLY_FACTOR_USE_ALL 7
FLINT_DLL int mpoly_is_proved_not_square(const ulong * Aexps,
slong Alen, flint_bitcnt_t Abits, slong N, ulong * t);
FLINT_DLL void mpoly_remove_var_powers(fmpz * var_powers, ulong * Aexps,
flint_bitcnt_t Abits, slong Alen, const mpoly_ctx_t mctx);
FLINT_DLL slong _mpoly_compress_exps(slong * V, slong * D, slong * deg,
slong * S, slong n, slong l);
FLINT_DLL int mpoly_test_irreducible(ulong * Aexps, flint_bitcnt_t Abits,
slong Alen, const mpoly_ctx_t ctx);
FLINT_DLL int _mpoly_test_irreducible(slong * Aexps, slong stride, slong Alen,
slong nvars, flint_rand_t state, slong tries_left);
typedef struct {
slong mvars;
slong nvars;
slong * exps;
slong exps_alloc;
slong * rest;
slong rest_alloc;
slong * umat;
slong * deltas;
slong * degs;
int is_trivial;
int is_perm;
int is_irred;
} mpoly_compression_struct;
typedef mpoly_compression_struct mpoly_compression_t[1];
FLINT_DLL void mpoly_compression_init(mpoly_compression_t M);
FLINT_DLL void mpoly_compression_clear(mpoly_compression_t M);
FLINT_DLL void mpoly_compression_set(mpoly_compression_t M, const ulong * Aexps,
flint_bitcnt_t Abits, slong Alen, const mpoly_ctx_t mctx);
FLINT_DLL void mpoly_bivar_cld_bounds(slong * l, slong n);
MPOLY_INLINE
void _slong_array_fit_length(slong ** array, slong * alloc, slong len)
{
if (len <= *alloc)
return;
len = FLINT_MAX(len, *alloc + *alloc/4 + 1);
*alloc = len;
*array = (slong *) flint_realloc(*array, len*sizeof(slong));
}
/* Heap **********************************************************************/
#define HEAP_LEFT(i) (2*(i))
#define HEAP_RIGHT(i) (2*(i) + 1)
#define HEAP_PARENT(i) ((i)/2)
#define HEAP_ASSIGN(h, c1, c2) \
do { \
(h).exp = (c1); \
(h).next = (c2); \
} while (0)
MPOLY_INLINE
void * _mpoly_heap_pop1(mpoly_heap1_s * heap, slong * heap_len, ulong maskhi)
{
ulong exp;
slong i, j, s = --(*heap_len);
void * x = heap[1].next;
i = 1;
j = 2;
while (j < s)
{
if ((heap[j].exp^maskhi) <= (heap[j + 1].exp^maskhi))
j++;
heap[i] = heap[j];
i = j;
j = HEAP_LEFT(j);
}
/* insert last element into heap[i] */
exp = heap[s].exp;
j = HEAP_PARENT(i);
while (i > 1 && (exp^maskhi) > (heap[j].exp^maskhi))
{
heap[i] = heap[j];
i = j;
j = HEAP_PARENT(j);
}
heap[i] = heap[s];
return x;
}
MPOLY_INLINE
void _mpoly_heap_insert1(mpoly_heap1_s * heap, ulong exp, void * x,
slong * next_loc, slong * heap_len, ulong maskhi)
{
slong i = *heap_len, j, n = *heap_len;
if (i != 1 && exp == heap[1].exp)
{
((mpoly_heap_t *) x)->next = (mpoly_heap_t *) heap[1].next;
heap[1].next = x;
return;
}
if (*next_loc < *heap_len)
{
if (exp == heap[*next_loc].exp)
{
((mpoly_heap_t *) x)->next = (mpoly_heap_t *) heap[*next_loc].next;
heap[*next_loc].next = x;
return;
}
}
while ((j = HEAP_PARENT(i)) >= 1)
{
if (exp == heap[j].exp)
{
((mpoly_heap_t *) x)->next = (mpoly_heap_t *) heap[j].next;
heap[j].next = x;
*next_loc = j;
return;
} else if ((exp^maskhi) > (heap[j].exp^maskhi))
i = j;
else
break;
}
(*heap_len)++;
while (n > i)
{
heap[n] = heap[HEAP_PARENT(n)];
n = HEAP_PARENT(n);
}
HEAP_ASSIGN(heap[i], exp, x);
}
MPOLY_INLINE
void * _mpoly_heap_pop(mpoly_heap_s * heap, slong * heap_len, slong N,
const ulong * cmpmask)
{
ulong * exp;
slong i, j, s = --(*heap_len);
mpoly_heap_t * x = (mpoly_heap_t *) heap[1].next;
i = 1;
j = 2;
while (j < s)
{
if (!mpoly_monomial_gt(heap[j].exp, heap[j + 1].exp, N, cmpmask))
j++;
heap[i] = heap[j];
i = j;
j = HEAP_LEFT(j);
}
/* insert last element into heap[i] */
exp = heap[s].exp;
j = HEAP_PARENT(i);
while (i > 1 && mpoly_monomial_gt(exp, heap[j].exp, N, cmpmask))
{
heap[i] = heap[j];
i = j;
j = HEAP_PARENT(j);
}
heap[i] = heap[s];
return x;
}
MPOLY_INLINE
int _mpoly_heap_insert(mpoly_heap_s * heap, ulong * exp, void * x,
slong * next_loc, slong * heap_len, slong N, const ulong * cmpmask)
{
slong i = *heap_len, j, n = *heap_len;
if (i != 1 && mpoly_monomial_equal(exp, heap[1].exp, N))
{
((mpoly_heap_t *) x)->next = (mpoly_heap_t *) heap[1].next;
heap[1].next = x;
return 0;
}
if (*next_loc < *heap_len)
{
if (mpoly_monomial_equal(exp, heap[*next_loc].exp, N))
{
((mpoly_heap_t *) x)->next = (mpoly_heap_t *) heap[*next_loc].next;
heap[*next_loc].next = x;
return 0;
}
}
while ((j = HEAP_PARENT(i)) >= 1)
{
if (!mpoly_monomial_gt(exp, heap[j].exp, N, cmpmask))
break;
i = j;
}
if (j >= 1 && mpoly_monomial_equal(exp, heap[j].exp, N))
{
((mpoly_heap_t *) x)->next = (mpoly_heap_t *) heap[j].next;
heap[j].next = x;
*next_loc = j;
return 0;
}
(*heap_len)++;
while (n > i)
{
heap[n] = heap[HEAP_PARENT(n)];
n = HEAP_PARENT(n);
}
HEAP_ASSIGN(heap[i], exp, x);
return 1;
}
/* generic parsing ***********************************************************/
typedef struct {
char * coeffs;
fmpz * exps;
slong length;
slong alloc;
} mpoly_univar_struct;
typedef mpoly_univar_struct mpoly_univar_t[1];
typedef struct {
slong elem_size;
const void * ctx;
void (*init)(void *, const void *);
void (*clear)(void *, const void *);
int (*is_zero)(const void *, const void *);
void (*zero)(void *, const void *);
void (*one)(void *, const void *);
void (*set_fmpz)(void *, const fmpz_t, const void *);
void (*set)(void *, const void *, const void *);
void (*swap)(void *, void *, const void *);
void (*neg)(void *, const void *, const void *);
void (*add)(void *, const void *, const void *, const void *);
void (*sub)(void *, const void *, const void *, const void *);
void (*mul_fmpz)(void *, const void *, const fmpz_t, const void *);
void (*mul)(void *, const void *, const void *, const void *);
void (*divexact)(void *, const void *, const void *, const void *);
int (*divides)(void *, const void *, const void *, const void *);
int (*pow_fmpz)(void *, const void *, const fmpz_t, const void *);
slong (*length)(const void *, const void *);
} mpoly_void_ring_t[1];
FLINT_DLL void * mpoly_void_ring_elem_init(mpoly_void_ring_t R);
FLINT_DLL void mpoly_void_ring_elem_clear(void * a, mpoly_void_ring_t R);
FLINT_DLL void mpoly_univar_init(mpoly_univar_t A, mpoly_void_ring_t R);
FLINT_DLL void mpoly_univar_clear(mpoly_univar_t A, mpoly_void_ring_t R);
FLINT_DLL void mpoly_univar_swap(mpoly_univar_t A, mpoly_univar_t B);
FLINT_DLL void mpoly_univar_fit_length(mpoly_univar_t A, slong len,
mpoly_void_ring_t R);
FLINT_DLL void mpoly_univar_init2(mpoly_univar_t A, slong len,
mpoly_void_ring_t R);
FLINT_DLL int mpoly_univar_pseudo_gcd_ducos(mpoly_univar_t G,
mpoly_univar_t B, mpoly_univar_t A, mpoly_void_ring_t R);
FLINT_DLL int mpoly_univar_resultant(void * r, mpoly_univar_t fx,
mpoly_univar_t gx, mpoly_void_ring_t R);
FLINT_DLL int mpoly_univar_discriminant(void * d, mpoly_univar_t fx,
mpoly_void_ring_t R);
typedef struct {
char * str;
slong str_len;
} string_with_length_struct;
typedef struct {
mpoly_void_ring_t R;
slong * stack;
slong stack_len;
slong stack_alloc;
char * estore;
slong estore_len;
slong estore_alloc;
void * tmp;
string_with_length_struct * terminal_strings;
char * terminal_values;
slong terminals_alloc;
slong terminals_len;
} mpoly_parse_struct;
typedef mpoly_parse_struct mpoly_parse_t[1];
FLINT_DLL void mpoly_parse_init(mpoly_parse_t E);
FLINT_DLL void mpoly_parse_clear(mpoly_parse_t E);
FLINT_DLL void mpoly_parse_add_terminal(mpoly_parse_t E,
const char * s, const void * v);
FLINT_DLL int mpoly_parse_parse(mpoly_parse_t E, void * res,
const char * s, slong len);
/* chunking */
/*
Set i1[i] to the index of the i-th "coefficient" in variable k of num
variables, each taking the given number of bits in the exponent. This
assumes there are l1 "coefficients" in a list of len1 exponents.
Note this doesn't currently mask the relevant bits.
*/
MPOLY_INLINE
void mpoly_main_variable_terms1(slong * i1, slong * n1, const ulong * exp1,
slong l1, slong len1, slong k, slong num, slong bits)
{
slong i, j = 0;
slong shift = bits*(k - 1);
i1[0] = 0;
for (i = 0; i < l1 - 1; i++)
{
while (j < len1 && (l1 - i - 1) == (slong) (exp1[j] >> shift))
j++;
i1[i + 1] = j;
n1[i] = j - i1[i];
}
n1[l1 - 1] = len1 - j;
}
#ifdef __cplusplus
}
#endif
#endif