34#ifndef CONFIG_H_INCLUDED
35#define CONFIG_H_INCLUDED
53static_assert(
sizeof(WORD) ==
sizeof(int32_t),
"flint interface expects 32bit WORD");
54static_assert(
sizeof(UWORD) ==
sizeof(uint32_t),
"flint interface expects 32bit WORD");
55static_assert(BITSINWORD == 32,
"flint interface expects 32bit WORD");
56static_assert(
sizeof(ulong) ==
sizeof(uint64_t),
"flint interface expects ulong is uint64_t");
57static_assert(
sizeof(slong) ==
sizeof(int64_t),
"flint interface expects slong is int64_t");
71#define UNIVARIATE_DENSITY_THR 0.02f
76void flint::cleanup(
void) {
83void flint::cleanup_master(
void) {
84 flint_cleanup_master();
91WORD* flint::divmod_mpoly(PHEAD
const WORD *a,
const WORD *b,
const bool return_rem,
92 const WORD must_fit_term,
const var_map_t &var_map,
const bool sort_vars) {
95 flint::mpoly pa(ctx.d), pb(ctx.d), denpa(ctx.d), denpb(ctx.d);
97 flint::from_argument_mpoly(pa.d, denpa.d, a,
false, var_map, ctx.d);
98 flint::from_argument_mpoly(pb.d, denpb.d, b,
false, var_map, ctx.d);
102 if ( fmpz_mpoly_is_fmpz(denpa.d, ctx.d) != 1 ) {
104 MLOCK(ErrorMessageLock);
105 MesPrint(
"!>flint::divmod_mpoly: error: denpa is non-constant");
106 MUNLOCK(ErrorMessageLock);
110 if ( fmpz_mpoly_is_fmpz(denpb.d, ctx.d) != 1 ) {
112 MLOCK(ErrorMessageLock);
113 MesPrint(
"!>flint::divmod_mpoly: error: denpb is non-constant");
114 MUNLOCK(ErrorMessageLock);
123 fmpz_mpoly_quasidivrem(scale.d, div.d, rem.d, pa.d, pb.d, ctx.d);
126 fmpz_mpoly_mul(div.d, div.d, denpb.d, ctx.d);
131 fmpz_mul(scale.d, scale.d, fmpz_mpoly_term_coeff_ref(denpa.d, 0, ctx.d));
135 const bool with_arghead =
false;
137 const uint64_t prev_size = 0;
138 const uint64_t out_size = return_rem ?
139 (uint64_t)flint::to_argument_mpoly(BHEAD NULL, with_arghead, must_fit_term, write, prev_size,
140 rem.d, var_map, ctx.d, sort_vars, scale.d)
142 (uint64_t)flint::to_argument_mpoly(BHEAD NULL, with_arghead, must_fit_term, write, prev_size,
143 div.d, var_map, ctx.d, sort_vars, scale.d)
145 WORD* res = (WORD *)Malloc1(
sizeof(WORD)*out_size,
"flint::divrem_mpoly");
151 flint::to_argument_mpoly(BHEAD res, with_arghead, must_fit_term, write, prev_size,
152 rem.d, var_map, ctx.d, sort_vars, scale.d);
155 flint::to_argument_mpoly(BHEAD res, with_arghead, must_fit_term, write, prev_size,
156 div.d, var_map, ctx.d, sort_vars, scale.d);
165WORD* flint::divmod_poly(PHEAD
const WORD *a,
const WORD *b,
const bool return_rem,
166 const WORD must_fit_term,
const var_map_t &var_map) {
170 flint::from_argument_poly(pa.d, denpa.d, a,
false);
171 flint::from_argument_poly(pb.d, denpb.d, b,
false);
175 if ( fmpz_poly_length(denpa.d) != 1 ) {
177 MLOCK(ErrorMessageLock);
178 MesPrint(
"!>flint::divmod_poly: error: denpa is non-constant");
179 MUNLOCK(ErrorMessageLock);
183 if ( fmpz_poly_length(denpb.d) != 1 ) {
185 MLOCK(ErrorMessageLock);
186 MesPrint(
"!>flint::divmod_poly: error: denpb is non-constant");
187 MUNLOCK(ErrorMessageLock);
193 uint64_t scale_power = 0;
197 fmpz_poly_get_coeff_fmpz(scale.d, pb.d, fmpz_poly_degree(pb.d));
199 fmpz_poly_pseudo_divrem(div.d, rem.d, (ulong*)&scale_power, pa.d, pb.d);
202 fmpz_poly_mul(div.d, div.d, denpb.d);
207 fmpz_pow_ui(scale.d, scale.d, scale_power);
208 fmpz_mul(scale.d, scale.d, fmpz_poly_get_coeff_ptr(denpa.d, 0));
212 const bool with_arghead =
false;
214 const uint64_t prev_size = 0;
215 const uint64_t out_size = return_rem ?
216 (uint64_t)flint::to_argument_poly(BHEAD NULL, with_arghead, must_fit_term, write, prev_size,
217 rem.d, var_map, scale.d)
219 (uint64_t)flint::to_argument_poly(BHEAD NULL, with_arghead, must_fit_term, write, prev_size,
220 div.d, var_map, scale.d)
222 WORD* res = (WORD *)Malloc1(
sizeof(WORD)*out_size,
"flint::divrem_poly");
228 flint::to_argument_poly(BHEAD res, with_arghead, must_fit_term, write, prev_size,
229 rem.d, var_map, scale.d);
232 flint::to_argument_poly(BHEAD res, with_arghead, must_fit_term, write, prev_size,
233 div.d, var_map, scale.d);
243WORD* flint::factorize_mpoly(PHEAD
const WORD *argin, WORD *argout,
const bool with_arghead,
244 const bool is_fun_arg,
const var_map_t &var_map,
const bool sort_vars) {
249 flint::from_argument_mpoly(arg.d, den.d, argin, with_arghead, var_map, ctx.d);
251 if ( fmpz_mpoly_is_one(den.d, ctx.d) != 1 ) {
253 MLOCK(ErrorMessageLock);
254 MesPrint(
"!>flint::factorize_mpoly error: den != 1");
255 MUNLOCK(ErrorMessageLock);
263 fmpz_mpoly_factor(arg_fac.d, arg.d, ctx.d);
264 const int64_t num_factors = fmpz_mpoly_factor_length(arg_fac.d, ctx.d);
267 fmpz_mpoly_factor_get_constant_fmpz(overall_constant.d, arg_fac.d, ctx.d);
270 if ( ! ( fmpz_equal_si(overall_constant.d, 1) || fmpz_equal_si(overall_constant.d, -1) ) ) {
272 MLOCK(ErrorMessageLock);
273 MesPrint(
"!>flint::factorize_mpoly error: overall constant factor != +-1");
274 MUNLOCK(ErrorMessageLock);
288 uint64_t output_size = 1;
291 vector<uint32_t> var_map_inv;
292 var_map_inv.resize(var_map.size());
293 for (
auto x : var_map ) {
294 var_map_inv[x.second] = x.first;
298 vector<int32_t> base_sign(num_factors, 0);
300 for ( int64_t i = 0; i < num_factors; i++ ) {
301 fmpz_mpoly_factor_get_base(base.d, arg_fac.d, i, ctx.d);
302 const int64_t exponent = fmpz_mpoly_factor_get_exp_si(arg_fac.d, i, ctx.d);
309 uint32_t max_var = 0;
310 int32_t max_pow = -1;
311 vector<int64_t> base_term_exponents(var_map.size(), 0);
313 for ( int64_t j = 0; j < fmpz_mpoly_length(base.d, ctx.d); j++ ) {
314 fmpz_mpoly_get_term_exp_si((slong*)base_term_exponents.data(), base.d, (slong)j, ctx.d);
316 for (
size_t k = 0; k < var_map.size(); k++ ) {
317 if ( base_term_exponents[k] > 0 && ( var_map_inv[k] > max_var ||
318 ( var_map_inv[k] == max_var && base_term_exponents[k] > max_pow ) ) ) {
320 max_var = var_map_inv[k];
321 max_pow = base_term_exponents[k];
322 base_sign[i] = fmpz_sgn(fmpz_mpoly_term_coeff_ref(base.d, j, ctx.d));
328 if ( ( base_sign[i] == -1 ) && ( exponent % 2 == 1 ) ) {
329 fmpz_neg(overall_constant.d, overall_constant.d);
333 if ( argout == NULL ) {
334 const bool write =
false;
335 for ( int64_t j = 0; j < exponent; j++ ) {
336 output_size += (uint64_t)flint::to_argument_mpoly(BHEAD NULL, with_arghead,
337 is_fun_arg, write, 0, base.d, var_map, ctx.d, sort_vars);
341 if ( fmpz_sgn(overall_constant.d) == -1 && argout == NULL ) {
343 output_size += with_arghead ? 2 : 4+1;
347 if ( argout == NULL ) {
348 argout = (WORD*)Malloc1(
sizeof(WORD)*output_size,
"flint::factorize_mpoly");
353 WORD* old_argout = argout;
357 if ( fmpz_sgn(overall_constant.d) == -1 ) {
358 if ( with_arghead ) {
361 *argout++ = -SNUMBER;
373 for ( int64_t i = 0; i < num_factors; i++ ) {
374 fmpz_mpoly_factor_get_base(base.d, arg_fac.d, i, ctx.d);
375 const int64_t exponent = fmpz_mpoly_factor_get_exp_si(arg_fac.d, i, ctx.d);
377 if ( base_sign[i] == -1 ) {
378 fmpz_mpoly_neg(base.d, base.d, ctx.d);
381 const bool write =
true;
382 for ( int64_t j = 0; j < exponent; j++ ) {
383 argout += flint::to_argument_mpoly(BHEAD argout, with_arghead, is_fun_arg, write,
384 argout-old_argout, base.d, var_map, ctx.d, sort_vars);
396WORD* flint::factorize_poly(PHEAD
const WORD *argin, WORD *argout,
const bool with_arghead,
397 const bool is_fun_arg,
const var_map_t &var_map) {
401 flint::from_argument_poly(arg.d, den.d, argin, with_arghead);
403 if ( fmpz_poly_is_one(den.d) != 1 ) {
405 MLOCK(ErrorMessageLock);
406 MesPrint(
"!>flint::factorize_poly error: den != 1");
407 MUNLOCK(ErrorMessageLock);
415 fmpz_poly_factor(arg_fac.d, arg.d);
418 const long num_factors = (arg_fac.d)->num;
425 if ( argout == NULL ) {
429 uint64_t output_size = 1;
434 if ( ! fmpz_is_one(&(arg_fac.d)->c) ) {
436 fmpz_poly_set_fmpz(overall_factor.d, &(arg_fac.d)->c);
437 const bool write =
false;
438 output_size += (uint64_t)flint::to_argument_poly(BHEAD NULL, with_arghead, is_fun_arg,
439 write, 0, overall_factor.d, var_map);
442 for (
long i = 0; i < num_factors; i++ ) {
443 fmpz_poly_struct* base = (arg_fac.d)->p + i;
445 const long exponent = (arg_fac.d)->exp[i];
447 const bool write =
false;
448 for (
long j = 0; j < exponent; j++ ) {
449 output_size += (uint64_t)flint::to_argument_poly(BHEAD NULL, with_arghead,
450 is_fun_arg, write, 0, base, var_map);
454 argout = (WORD*)Malloc1(
sizeof(WORD)*output_size,
"flint::factorize_poly");
457 WORD* old_argout = argout;
462 if ( ! fmpz_is_one(&(arg_fac.d)->c) ) {
464 fmpz_poly_set_fmpz(overall_factor.d, &(arg_fac.d)->c);
465 const bool write =
true;
466 argout += (uint64_t)flint::to_argument_poly(BHEAD argout, with_arghead, is_fun_arg, write,
467 argout-old_argout, overall_factor.d, var_map);
470 for (
long i = 0; i < num_factors; i++ ) {
471 fmpz_poly_struct* base = (arg_fac.d)->p + i;
473 const long exponent = (arg_fac.d)->exp[i];
475 const bool write =
true;
476 for (
long j = 0; j < exponent; j++ ) {
477 argout += flint::to_argument_poly(BHEAD argout, with_arghead, is_fun_arg, write,
478 argout-old_argout, base, var_map);
493void flint::form_sort(PHEAD WORD *terms) {
495 if ( terms[0] < 0 ) {
500 const WORD oldsorttype = AR.SortType;
501 AR.SortType = SORTHIGHFIRST;
503 const WORD in_size = terms[0] - ARGHEAD;
512 for ( WORD i = ARGHEAD; i < terms[0]; i += terms[i] ) {
514 AR.SortType = oldsorttype;
515 AR.CompareRoutine = (COMPAREDUMMY)(&
Compare1);
521 if ( ( out_size =
EndSort(BHEAD terms+ARGHEAD, 1) ) < 0 ) {
522 AR.SortType = oldsorttype;
523 AR.CompareRoutine = (COMPAREDUMMY)(&
Compare1);
528 if ( in_size != out_size ) {
530 MLOCK(ErrorMessageLock);
531 MesPrint(
"!>flint::form_sort: error: unexpected sorted arg length change %d->%d", in_size,
533 MUNLOCK(ErrorMessageLock);
538 AR.SortType = oldsorttype;
539 AR.CompareRoutine = (COMPAREDUMMY)(&
Compare1);
550uint64_t flint::from_argument_mpoly(fmpz_mpoly_t
poly, fmpz_mpoly_t denpoly,
const WORD *args,
551 const bool with_arghead,
const var_map_t &var_map,
const fmpz_mpoly_ctx_t ctx) {
555 fmpz_mpoly_set_si(
poly, 0, ctx);
556 fmpz_mpoly_set_si(denpoly, 0, ctx);
559 if ( *args == -SNUMBER ) {
560 fmpz_mpoly_set_si(
poly, *(args+1), ctx);
561 fmpz_mpoly_set_si(denpoly, 1, ctx);
565 if ( *args == -SYMBOL ) {
567 vector<uint64_t> exponents(var_map.size(), 0);
568 exponents[var_map.at(*(args+1))] = 1;
570 fmpz_mpoly_set_coeff_ui_ui(
poly, (ulong)1, (ulong*)exponents.data(), ctx);
571 fmpz_mpoly_set_ui(denpoly, (ulong)1, ctx);
579 const WORD* arg_stop = with_arghead ? args+args[0] : (WORD*)UINT64_MAX;
580 uint64_t arg_size = 0;
581 if ( with_arghead ) {
589 fmpz_set_si(den_coeff.d, 1);
590 vector<uint64_t> exponents(var_map.size(), 0);
591 vector<uint64_t> neg_exponents(var_map.size(), 0);
593 for (
const WORD* term = args; term < arg_stop; term += term[0] ) {
594 const WORD* term_stop = term+term[0];
595 const WORD coeff_size = (term_stop)[-1];
596 const WORD* symbol_stop = term_stop - ABS(coeff_size);
597 const WORD* t = term;
600 if ( t == symbol_stop ) {
607 for (
const WORD* s = t; s < symbol_stop; s += 2 ) {
609 neg_exponents[var_map.at(*s)] =
610 MaX(neg_exponents[var_map.at(*s)], (uint64_t)(-(*(s+1))) );
616 if ( *(symbol_stop+ABS(coeff_size/2)) != 1 ) {
617 flint::fmpz_set_form(tmp.d, (UWORD*)(symbol_stop+ABS(coeff_size/2)), ABS(coeff_size/2));
619 fmpz_lcm(den_coeff.d, den_coeff.d, tmp.d);
622 if ( !with_arghead && *term_stop == 0 ) {
624 arg_size = term_stop - args + 1;
630 fmpz_mpoly_set_coeff_fmpz_ui(denpoly, den_coeff.d, (ulong*)neg_exponents.data(), ctx);
636 for (
const WORD* term = args; term < arg_stop; term += term[0] ) {
637 const WORD* term_stop = term+term[0];
638 const WORD coeff_size = (term_stop)[-1];
639 const WORD* symbol_stop = term_stop - ABS(coeff_size);
640 const WORD* t = term;
642 fill(exponents.begin(), exponents.end(), 0);
645 if ( t == symbol_stop ) {
651 for (
const WORD* s = t; s < symbol_stop; s += 2 ) {
652 exponents[var_map.at(*s)] = *(s+1);
656 flint::fmpz_set_form(coeff.d, (UWORD*)symbol_stop, coeff_size/2);
659 fmpz_mul(coeff.d, coeff.d, den_coeff.d);
662 for (
size_t i = 0; i < var_map.size(); i++ ) {
663 exponents[i] += neg_exponents[i];
667 if ( *(symbol_stop+ABS(coeff_size/2)) != 1 ) {
668 flint::fmpz_set_form(tmp.d, (UWORD*)(symbol_stop+ABS(coeff_size/2)), ABS(coeff_size/2));
670 fmpz_divexact(coeff.d, coeff.d, tmp.d);
675 fmpz_mpoly_push_term_fmpz_ui(
poly, coeff.d, (ulong*)exponents.data(), ctx);
677 if ( !with_arghead && *term_stop == 0 ) {
683 if ( ! fmpz_mpoly_is_canonical(
poly, ctx) ) {
684 fmpz_mpoly_sort_terms(
poly, ctx);
696uint64_t flint::from_argument_poly(fmpz_poly_t
poly, fmpz_poly_t denpoly,
const WORD *args,
697 const bool with_arghead) {
701 fmpz_poly_set_si(
poly, 0);
702 fmpz_poly_set_si(denpoly, 0);
705 if ( *args == -SNUMBER ) {
706 fmpz_poly_set_si(
poly, *(args+1));
707 fmpz_poly_set_si(denpoly, 1);
711 if ( *args == -SYMBOL ) {
713 fmpz_poly_set_coeff_si(
poly, 1, 1);
714 fmpz_poly_set_si(denpoly, 1);
721 const WORD* arg_stop = with_arghead ? args+args[0] : (WORD*)UINT64_MAX;
722 uint64_t arg_size = 0;
723 if ( with_arghead ) {
730 fmpz_set_si(den_coeff.d, 1);
731 uint64_t neg_exponent = 0;
733 for (
const WORD* term = args; term < arg_stop; term += term[0] ) {
735 const WORD* term_stop = term+term[0];
736 const WORD coeff_size = (term_stop)[-1];
737 const WORD* symbol_stop = term_stop - ABS(coeff_size);
738 const WORD* t = term;
741 if ( t == symbol_stop ) {
749 neg_exponent = MaX(neg_exponent, (uint64_t)(-(*t)) );
754 if ( *(symbol_stop+ABS(coeff_size/2)) != 1 ) {
755 flint::fmpz_set_form(tmp.d, (UWORD*)(symbol_stop+ABS(coeff_size/2)), ABS(coeff_size/2));
757 fmpz_lcm(den_coeff.d, den_coeff.d, tmp.d);
760 if ( *term_stop == 0 ) {
762 arg_size = term_stop - args + 1;
767 fmpz_poly_set_coeff_fmpz(denpoly, neg_exponent, den_coeff.d);
773 for (
const WORD* term = args; term < arg_stop; term += term[0] ) {
775 const WORD* term_stop = term+term[0];
776 const WORD coeff_size = (term_stop)[-1];
777 const WORD* symbol_stop = term_stop - ABS(coeff_size);
778 const WORD* t = term;
780 uint64_t exponent = 0;
783 if ( t == symbol_stop ) {
794 flint::fmpz_set_form(coeff.d, (UWORD*)symbol_stop, coeff_size/2);
797 fmpz_mul(coeff.d, coeff.d, den_coeff.d);
800 exponent += neg_exponent;
803 if ( *(symbol_stop+ABS(coeff_size/2)) != 1 ) {
804 flint::fmpz_set_form(tmp.d, (UWORD*)(symbol_stop+ABS(coeff_size/2)), ABS(coeff_size/2));
806 fmpz_divexact(coeff.d, coeff.d, tmp.d);
810 fmpz_poly_set_coeff_fmpz(
poly, exponent, coeff.d);
812 if ( *term_stop == 0 ) {
826WORD flint::fmpz_get_form(fmpz_t z, WORD *a) {
829 const int32_t sgn = fmpz_sgn(z);
833 const int64_t nlimbs = fmpz_size(z);
841 const uint64_t limb = fmpz_get_ui(z);
842 a[0] = (WORD)(limb & 0xFFFFFFFF);
844 a[1] = (WORD)(limb >> BITSINWORD);
849 else if ( nlimbs == 2 ) {
850 uint64_t limb_hi = 0, limb_lo = 0;
851 fmpz_get_uiui((ulong*)&limb_hi, (ulong*)&limb_lo, z);
852 a[0] = (WORD)(limb_lo & 0xFFFFFFFF);
854 a[1] = (WORD)(limb_lo >> BITSINWORD);
856 a[2] = (WORD)(limb_hi & 0xFFFFFFFF);
858 a[3] = (WORD)(limb_hi >> BITSINWORD);
864 vector<uint64_t> limb_data(nlimbs, 0);
865 fmpz_get_ui_array((ulong*)limb_data.data(), (slong)nlimbs, z);
866 for (
long i = 0; i < nlimbs; i++ ) {
867 a[2*i] = (WORD)(limb_data[i] & 0xFFFFFFFF);
869 a[2*i+1] = (WORD)(limb_data[i] >> BITSINWORD);
870 if ( a[2*i+1] != 0 || i < (nlimbs-1) ) {
891void flint::fmpz_set_form(fmpz_t z, UWORD *a, WORD na) {
909 while ( a[na-1] == 0 ) {
916 fmpz_set_ui(z, (uint64_t)a[0]);
918 else if ( na == 2 ) {
919 fmpz_set_ui(z, (((uint64_t)a[1])<<BITSINWORD) + (uint64_t)a[0]);
921 else if ( na == 3 ) {
922 fmpz_set_uiui(z, (uint64_t)a[2], (((uint64_t)a[1])<<BITSINWORD) + (uint64_t)a[0]);
924 else if ( na == 4 ) {
925 fmpz_set_uiui(z, (((uint64_t)a[3])<<BITSINWORD) + (uint64_t)a[2],
926 (((uint64_t)a[1])<<BITSINWORD) + (uint64_t)a[0]);
929 const int32_t nlimbs = (na+1)/2;
930 vector<uint64_t> limb_data(nlimbs, 0);
931 for ( int32_t i = 0; i < nlimbs; i++ ) {
932 if ( 2*i+1 <= na-1 ) {
933 limb_data[i] = (uint64_t)a[2*i] + (((uint64_t)a[2*i+1])<<BITSINWORD);
936 limb_data[i] = (uint64_t)a[2*i];
939 fmpz_set_ui_array(z, (ulong*)limb_data.data(), nlimbs);
957WORD* flint::gcd_mpoly(PHEAD
const WORD *a,
const WORD *b,
const WORD must_fit_term,
958 const var_map_t &var_map,
const bool sort_vars) {
961 flint::mpoly pa(ctx.d), pb(ctx.d), denpa(ctx.d), denpb(ctx.d), gcd(ctx.d);
963 flint::from_argument_mpoly(pa.d, denpa.d, a,
false, var_map, ctx.d);
964 flint::from_argument_mpoly(pb.d, denpb.d, b,
false, var_map, ctx.d);
967 if ( fmpz_mpoly_is_one(denpa.d, ctx.d) != 1 ) {
969 MLOCK(ErrorMessageLock);
970 MesPrint(
"!>flint::gcd_mpoly: error: denpa != 1");
971 MUNLOCK(ErrorMessageLock);
975 if ( fmpz_mpoly_is_one(denpb.d, ctx.d) != 1 ) {
977 MLOCK(ErrorMessageLock);
978 MesPrint(
"!>flint::gcd_mpoly: error: denpb != 1");
979 MUNLOCK(ErrorMessageLock);
985 if ( fmpz_mpoly_equal(pa.d, pb.d, ctx.d) ) {
986 fmpz_mpoly_set(gcd.d, pa.d, ctx.d);
994 fmpz_mpoly_term_content(tmp.d, pa.d, ctx.d);
995 if ( fmpz_mpoly_is_one(tmp.d, ctx.d) != 1 ) {
997 MLOCK(ErrorMessageLock);
998 MesPrint(
"!>flint::gcd_mpoly: error: content of 1st arg != 1");
999 MUNLOCK(ErrorMessageLock);
1003 fmpz_mpoly_term_content(tmp.d, pb.d, ctx.d);
1004 if ( fmpz_mpoly_is_one(tmp.d, ctx.d) != 1 ) {
1006 MLOCK(ErrorMessageLock);
1007 MesPrint(
"!>flint::gcd_mpoly: error: content of 2nd arg != 1");
1008 MUNLOCK(ErrorMessageLock);
1019 if ( ( fmpz_sgn(fmpz_mpoly_term_coeff_ref(pa.d, 0, ctx.d)) == -1 ) &&
1020 ( fmpz_sgn(fmpz_mpoly_term_coeff_ref(pb.d, 0, ctx.d)) == -1 ) ) {
1024 fmpz_mpoly_gcd(gcd.d, pa.d, pb.d, ctx.d);
1026 fmpz_mpoly_neg(gcd.d, gcd.d, ctx.d);
1032 if ( must_fit_term ) {
1033 res = TermMalloc(
"flint::gcd_mpoly");
1037 const bool with_arghead =
false;
1038 const bool write =
false;
1039 const uint64_t prev_size = 0;
1040 const uint64_t gcd_size = (uint64_t)flint::to_argument_mpoly(BHEAD NULL,
1041 with_arghead, must_fit_term, write, prev_size, gcd.d, var_map, ctx.d, sort_vars);
1043 res = (WORD *)Malloc1(
sizeof(WORD)*gcd_size,
"flint::gcd_mpoly");
1046 const bool with_arghead =
false;
1047 const bool write =
true;
1048 const uint64_t prev_size = 0;
1049 flint::to_argument_mpoly(BHEAD res, with_arghead, must_fit_term, write, prev_size, gcd.d,
1050 var_map, ctx.d, sort_vars);
1061WORD* flint::gcd_poly(PHEAD
const WORD *a,
const WORD *b,
const WORD must_fit_term,
1062 const var_map_t &var_map) {
1066 flint::from_argument_poly(pa.d, denpa.d, a,
false);
1067 flint::from_argument_poly(pb.d, denpb.d, b,
false);
1070 if ( fmpz_poly_is_one(denpa.d) != 1 ) {
1072 MLOCK(ErrorMessageLock);
1073 MesPrint(
"!>flint::gcd_poly: error: denpa != 1");
1074 MUNLOCK(ErrorMessageLock);
1078 if ( fmpz_poly_is_one(denpb.d) != 1 ) {
1080 MLOCK(ErrorMessageLock);
1081 MesPrint(
"!>flint::gcd_poly: error: denpb != 1");
1082 MUNLOCK(ErrorMessageLock);
1088 if ( fmpz_poly_equal(pa.d, pb.d) ) {
1089 fmpz_poly_set(gcd.d, pa.d);
1096 fmpz_poly_content(tmp.d, pa.d);
1097 if ( fmpz_is_one(tmp.d) != 1 ) {
1099 MLOCK(ErrorMessageLock);
1100 MesPrint(
"!>flint::gcd_poly: error: content of 1st arg != 1");
1101 MUNLOCK(ErrorMessageLock);
1105 fmpz_poly_content(tmp.d, pb.d);
1106 if ( fmpz_is_one(tmp.d) != 1 ) {
1108 MLOCK(ErrorMessageLock);
1109 MesPrint(
"!>flint::gcd_poly: error: content of 2nd arg != 1");
1110 MUNLOCK(ErrorMessageLock);
1115 fmpz_poly_gcd(gcd.d, pa.d, pb.d);
1120 if ( must_fit_term ) {
1121 res = TermMalloc(
"flint::gcd_poly");
1125 const bool with_arghead =
false;
1126 const bool write =
false;
1127 const uint64_t prev_size = 0;
1128 const uint64_t gcd_size = (uint64_t)flint::to_argument_poly(BHEAD NULL,
1129 with_arghead, must_fit_term, write, prev_size, gcd.d, var_map);
1131 res = (WORD *)Malloc1(
sizeof(WORD)*gcd_size,
"flint::gcd_poly");
1134 const bool with_arghead =
false;
1135 const uint64_t prev_size = 0;
1136 const bool write =
true;
1137 flint::to_argument_poly(BHEAD res, with_arghead, must_fit_term, write, prev_size, gcd.d,
1151flint::var_map_t flint::get_variables(
const vector <WORD *> &es,
const bool with_arghead,
1152 const bool sort_vars) {
1154 int32_t num_vars = 0;
1156 uint32_t num_terms = 0;
1158 vector<int32_t> degrees;
1162 for (
size_t ei = 0; ei < es.size(); ei++ ) {
1166 if ( *e == -SNUMBER ) {
1169 else if ( *e == -SYMBOL ) {
1171 if ( !var_map.count(e[1]) ) {
1172 var_map[e[1]] = num_vars++;
1173 degrees.push_back(1);
1177 else if ( *e < 0 ) {
1178 MLOCK(ErrorMessageLock);
1179 MesPrint(
"ERROR: polynomials and polyratfuns must contain symbols only");
1180 MUNLOCK(ErrorMessageLock);
1184 for ( WORD i = with_arghead ? ARGHEAD:0; with_arghead ? i < e[0]:e[i] != 0; i += e[i] ) {
1186 const WORD coeff_size = e[i+e[i]-1];
1187 const WORD symbols_size = e[i] - ABS(coeff_size);
1188 if ( e[i+1] != SYMBOL && 1 < symbols_size ) {
1189 MLOCK(ErrorMessageLock);
1190 MesPrint(
"ERROR: polynomials and polyratfuns must contain symbols only");
1191 MUNLOCK(ErrorMessageLock);
1195 for ( WORD j = i+3; j < i+symbols_size; j += 2 ) {
1196 const WORD symbol = e[j];
1197 const WORD degree = e[j+1];
1198 auto it = var_map.find(symbol);
1199 if ( it == var_map.end() ) {
1200 var_map[symbol] = num_vars++;
1201 degrees.push_back(degree);
1204 degrees[it->second] = MaX(degrees[it->second], degree);
1214 for (
size_t i = 0; i < var_map.size(); i++ ) {
1215 for (
size_t j = 0; j+1 < var_map.size(); j++ ) {
1216 if ( degrees[j] < degrees[j+1] ) {
1217 swap(degrees[j], degrees[j+1]);
1222 for (
auto x: var_map ) {
1223 if ( x.second == j ) {
1226 else if ( x.second == j+1 ) {
1230 swap(var_map.at(j0), var_map.at(j1));
1237 for (
size_t i = 0; i < var_map.size(); i++ ) {
1238 for (
size_t j = 0; j+1 < var_map.size(); j++ ) {
1241 for (
auto x: var_map ) {
1242 if ( x.second == j ) {
1245 else if ( x.second == j+1 ) {
1250 swap(var_map.at(j0), var_map.at(j1));
1256 if ( var_map.size() == 1 ) {
1259 if ( (
float)num_terms <= UNIVARIATE_DENSITY_THR * (
float)degrees[0] ) {
1262 var_map[-1] = num_vars;
1273WORD* flint::inverse_poly(PHEAD
const WORD *a,
const WORD *b,
const var_map_t &var_map) {
1277 flint::from_argument_poly(pa.d, denpa.d, a,
false);
1278 flint::from_argument_poly(pb.d, denpb.d, b,
false);
1286 fmpz_poly_content(content_a.d, pa.d);
1287 if ( fmpz_sgn(fmpz_poly_lead(pa.d)) == -1 ) {
1288 fmpz_neg(content_a.d, content_a.d);
1290 fmpz_poly_primitive_part(pa.d, pa.d);
1291 fmpz_poly_primitive_part(pb.d, pb.d);
1295 if ( fmpz_poly_is_one(pa.d) && fmpz_poly_is_one(pb.d) ) {
1296 fmpz_poly_one(inverse.d);
1297 fmpz_one(resultant.d);
1299 else if ( fmpz_poly_is_one(pb.d) ) {
1300 fmpz_poly_zero(inverse.d);
1301 fmpz_one(resultant.d);
1307 fmpz_poly_xgcd(resultant.d, inverse.d, tmp.d, pa.d, pb.d);
1310 if ( fmpz_is_zero(resultant.d) ) {
1311 MLOCK(ErrorMessageLock);
1312 MesPrint(
"flint::inverse_poly error: inverse does not exist");
1313 MUNLOCK(ErrorMessageLock);
1321 fmpz_poly_mul(inverse.d, inverse.d, denpa.d);
1322 fmpz_mul(resultant.d, resultant.d, content_a.d);
1328 const bool with_arghead =
false;
1330 const bool must_fit_term =
false;
1331 const uint64_t prev_size = 0;
1332 const uint64_t res_size = (uint64_t)flint::to_argument_poly(BHEAD NULL,
1333 with_arghead, must_fit_term, write, prev_size, inverse.d, var_map, resultant.d);
1334 res = (WORD*)Malloc1(
sizeof(WORD)*res_size,
"flint::inverse_poly");
1337 flint::to_argument_poly(BHEAD res, with_arghead, must_fit_term, write, prev_size, inverse.d,
1338 var_map, resultant.d);
1349WORD* flint::mul_mpoly(PHEAD
const WORD *a,
const WORD *b,
const var_map_t &var_map,
1350 const bool sort_vars) {
1353 flint::mpoly pa(ctx.d), pb(ctx.d), denpa(ctx.d), denpb(ctx.d);
1355 flint::from_argument_mpoly(pa.d, denpa.d, a,
false, var_map, ctx.d);
1356 flint::from_argument_mpoly(pb.d, denpb.d, b,
false, var_map, ctx.d);
1359 if ( fmpz_mpoly_is_fmpz(denpa.d, ctx.d) != 1 ) {
1361 MLOCK(ErrorMessageLock);
1362 MesPrint(
"!>flint::mul_mpoly: error: denpa is non-constant");
1363 MUNLOCK(ErrorMessageLock);
1367 if ( fmpz_mpoly_is_fmpz(denpb.d, ctx.d) != 1 ) {
1369 MLOCK(ErrorMessageLock);
1370 MesPrint(
"!>flint::mul_mpoly: error: denpb is non-constant");
1371 MUNLOCK(ErrorMessageLock);
1377 fmpz_mpoly_mul(pa.d, pa.d, pb.d, ctx.d);
1379 fmpz_mpoly_mul(denpa.d, denpa.d, denpb.d, ctx.d);
1381 fmpz_mpoly_get_fmpz(den.d, denpa.d, ctx.d);
1386 const bool with_arghead =
false;
1388 const bool must_fit_term =
false;
1389 const uint64_t prev_size = 0;
1390 const uint64_t mul_size = (uint64_t)flint::to_argument_mpoly(BHEAD NULL,
1391 with_arghead, must_fit_term, write, prev_size, pa.d, var_map, ctx.d, sort_vars, den.d);
1392 res = (WORD*)Malloc1(
sizeof(WORD)*mul_size,
"flint::mul_mpoly");
1395 flint::to_argument_mpoly(BHEAD res, with_arghead, must_fit_term, write, prev_size, pa.d,
1396 var_map, ctx.d, sort_vars, den.d);
1406WORD* flint::mul_poly(PHEAD
const WORD *a,
const WORD *b,
const var_map_t &var_map) {
1410 flint::from_argument_poly(pa.d, denpa.d, a,
false);
1411 flint::from_argument_poly(pb.d, denpb.d, b,
false);
1414 if ( fmpz_poly_degree(denpa.d) != 0 ) {
1416 MLOCK(ErrorMessageLock);
1417 MesPrint(
"!>flint::mul_poly: error: denpa is non-constant");
1418 MUNLOCK(ErrorMessageLock);
1422 if ( fmpz_poly_degree(denpb.d) != 0 ) {
1424 MLOCK(ErrorMessageLock);
1425 MesPrint(
"!>flint::mul_poly: error: denpb is non-constant");
1426 MUNLOCK(ErrorMessageLock);
1432 fmpz_poly_mul(pa.d, pa.d, pb.d);
1434 fmpz_poly_mul(denpa.d, denpa.d, denpb.d);
1436 fmpz_poly_get_coeff_fmpz(den.d, denpa.d, 0);
1441 const bool with_arghead =
false;
1443 const bool must_fit_term =
false;
1444 const uint64_t prev_size = 0;
1445 const uint64_t mul_size = (uint64_t)flint::to_argument_poly(BHEAD NULL,
1446 with_arghead, must_fit_term, write, prev_size, pa.d, var_map, den.d);
1447 res = (WORD*)Malloc1(
sizeof(WORD)*mul_size,
"flint::mul_poly");
1450 flint::to_argument_poly(BHEAD res, with_arghead, must_fit_term, write, prev_size, pa.d,
1461void flint::ratfun_add_mpoly(PHEAD
const WORD *t1,
const WORD *t2, WORD *out,
1462 const var_map_t &var_map,
const bool sort_vars) {
1465 flint::mpoly gcd(ctx.d), num1(ctx.d), den1(ctx.d), num2(ctx.d), den2(ctx.d);
1467 flint::ratfun_read_mpoly(t1, num1.d, den1.d, var_map, ctx.d);
1468 flint::ratfun_read_mpoly(t2, num2.d, den2.d, var_map, ctx.d);
1470 if ( fmpz_mpoly_cmp(den1.d, den2.d, ctx.d) != 0 ) {
1471 fmpz_mpoly_gcd_cofactors(gcd.d, den1.d, den2.d, den1.d, den2.d, ctx.d);
1473 fmpz_mpoly_mul(num1.d, num1.d, den2.d, ctx.d);
1474 fmpz_mpoly_mul(num2.d, num2.d, den1.d, ctx.d);
1476 fmpz_mpoly_add(num1.d, num1.d, num2.d, ctx.d);
1477 fmpz_mpoly_mul(den1.d, den1.d, den2.d, ctx.d);
1478 fmpz_mpoly_mul(den1.d, den1.d, gcd.d, ctx.d);
1481 fmpz_mpoly_add(num1.d, num1.d, num2.d, ctx.d);
1485 fmpz_mpoly_gcd_cofactors(gcd.d, num1.d, den1.d, num1.d, den1.d, ctx.d);
1487 flint::util::fix_sign_fmpz_mpoly_ratfun(num1.d, den1.d, ctx.d);
1490 *out++ = AR.PolyFun;
1491 WORD* args_size = out++;
1492 WORD* args_flag = out++;
1496 const bool with_arghead =
true;
1497 const bool must_fit_term =
true;
1498 const bool write =
true;
1500 out += flint::to_argument_mpoly(BHEAD out, with_arghead, must_fit_term, write, out-args_size+4,
1501 num1.d, var_map, ctx.d, sort_vars);
1502 out += flint::to_argument_mpoly(BHEAD out, with_arghead, must_fit_term, write, out-args_size+4,
1503 den1.d, var_map, ctx.d, sort_vars);
1505 *args_size = out - args_size + 1;
1506 AT.WorkPointer = out;
1513void flint::ratfun_add_poly(PHEAD
const WORD *t1,
const WORD *t2, WORD *out,
1514 const var_map_t &var_map) {
1518 flint::ratfun_read_poly(t1, num1.d, den1.d);
1519 flint::ratfun_read_poly(t2, num2.d, den2.d);
1521 if ( fmpz_poly_equal(den1.d, den2.d) == 0 ) {
1522 flint::util::simplify_fmpz_poly(den1.d, den2.d, gcd.d);
1524 fmpz_poly_mul(num1.d, num1.d, den2.d);
1525 fmpz_poly_mul(num2.d, num2.d, den1.d);
1527 fmpz_poly_add(num1.d, num1.d, num2.d);
1528 fmpz_poly_mul(den1.d, den1.d, den2.d);
1529 fmpz_poly_mul(den1.d, den1.d, gcd.d);
1532 fmpz_poly_add(num1.d, num1.d, num2.d);
1536 flint::util::simplify_fmpz_poly(num1.d, den1.d, gcd.d);
1538 flint::util::fix_sign_fmpz_poly_ratfun(num1.d, den1.d);
1541 *out++ = AR.PolyFun;
1542 WORD* args_size = out++;
1543 WORD* args_flag = out++;
1547 const bool with_arghead =
true;
1548 const bool must_fit_term =
true;
1549 const bool write =
true;
1551 out += flint::to_argument_poly(BHEAD out, with_arghead, must_fit_term, write, out-args_size+4,
1553 out += flint::to_argument_poly(BHEAD out, with_arghead, must_fit_term, write, out-args_size+4,
1556 *args_size = out - args_size + 1;
1557 AT.WorkPointer = out;
1566void flint::ratfun_normalize_mpoly(PHEAD WORD *term,
const var_map_t &var_map,
1567 const bool sort_vars) {
1570 const WORD ncoeff = (term + *term)[-1];
1572 const WORD *tstop = term + *term - ABS(ncoeff);
1575 flint::mpoly num1(ctx.d), den1(ctx.d), num2(ctx.d), den2(ctx.d), gcd(ctx.d);
1579 flint::fmpz_set_form(tmpNum.d, (UWORD*)tstop, ncoeff/2);
1580 flint::fmpz_set_form(tmpDen.d, (UWORD*)tstop+ABS(ncoeff/2), ABS(ncoeff/2));
1581 fmpz_mpoly_set_fmpz(num1.d, tmpNum.d, ctx.d);
1582 fmpz_mpoly_set_fmpz(den1.d, tmpDen.d, ctx.d);
1587 WORD* term_size = term;
1589 for ( WORD *t = term + 1; t < tstop; ) {
1590 if ( *t == AR.PolyFun ) {
1591 flint::ratfun_read_mpoly(t, num2.d, den2.d, var_map, ctx.d);
1594 fmpz_mpoly_gcd_cofactors(gcd.d, num1.d, den2.d, num1.d, den2.d, ctx.d);
1595 fmpz_mpoly_gcd_cofactors(gcd.d, num2.d, den1.d, num2.d, den1.d, ctx.d);
1597 fmpz_mpoly_mul(num1.d, num1.d, num2.d, ctx.d);
1598 fmpz_mpoly_mul(den1.d, den1.d, den2.d, ctx.d);
1606 if ( s != t ) { NCOPY(s,t,i); }
1607 else { t += i; s += i; }
1611 flint::util::fix_sign_fmpz_mpoly_ratfun(num1.d, den1.d, ctx.d);
1615 *out++ = AR.PolyFun;
1616 WORD* args_size = out++;
1617 WORD* args_flag = out++;
1618 *args_flag &= ~MUSTCLEANPRF;
1620 const bool with_arghead =
true;
1621 const bool must_fit_term =
true;
1622 const bool write =
true;
1623 out += flint::to_argument_mpoly(BHEAD out, with_arghead, must_fit_term, write, out-term_size,
1624 num1.d, var_map, ctx.d, sort_vars);
1625 out += flint::to_argument_mpoly(BHEAD out, with_arghead, must_fit_term, write, out-term_size,
1626 den1.d, var_map, ctx.d, sort_vars);
1628 *args_size = out - args_size + 1;
1631 if (
sizeof(WORD)*(out-term_size+3) > (
size_t)AM.MaxTer ) {
1632 MLOCK(ErrorMessageLock);
1633 MesPrint(
"flint::ratfun_normalize: output exceeds MaxTermSize");
1634 MUNLOCK(ErrorMessageLock);
1642 *term_size = out - term_size;
1650void flint::ratfun_normalize_poly(PHEAD WORD *term,
const var_map_t &var_map) {
1653 const WORD ncoeff = (term + *term)[-1];
1655 const WORD *tstop = term + *term - ABS(ncoeff);
1661 flint::fmpz_set_form(tmpNum.d, (UWORD*)tstop, ncoeff/2);
1662 flint::fmpz_set_form(tmpDen.d, (UWORD*)tstop+ABS(ncoeff/2), ABS(ncoeff/2));
1663 fmpz_poly_set_fmpz(num1.d, tmpNum.d);
1664 fmpz_poly_set_fmpz(den1.d, tmpDen.d);
1669 WORD* term_size = term;
1671 for ( WORD *t = term + 1; t < tstop; ) {
1672 if ( *t == AR.PolyFun ) {
1673 flint::ratfun_read_poly(t, num2.d, den2.d);
1676 flint::util::simplify_fmpz_poly(num1.d, den2.d, gcd.d);
1677 flint::util::simplify_fmpz_poly(num2.d, den1.d, gcd.d);
1679 fmpz_poly_mul(num1.d, num1.d, num2.d);
1680 fmpz_poly_mul(den1.d, den1.d, den2.d);
1688 if ( s != t ) { NCOPY(s,t,i); }
1689 else { t += i; s += i; }
1693 flint::util::fix_sign_fmpz_poly_ratfun(num1.d, den1.d);
1697 *out++ = AR.PolyFun;
1698 WORD* args_size = out++;
1699 WORD* args_flag = out++;
1700 *args_flag &= ~MUSTCLEANPRF;
1702 const bool with_arghead =
true;
1703 const bool must_fit_term =
true;
1704 const bool write =
true;
1705 out += flint::to_argument_poly(BHEAD out, with_arghead, must_fit_term, write, out-term_size,
1707 out += flint::to_argument_poly(BHEAD out, with_arghead, must_fit_term, write, out-term_size,
1710 *args_size = out - args_size + 1;
1713 if (
sizeof(WORD)*(out-term_size+3) > (
size_t)AM.MaxTer ) {
1714 MLOCK(ErrorMessageLock);
1715 MesPrint(
"flint::ratfun_normalize: output exceeds MaxTermSize");
1716 MUNLOCK(ErrorMessageLock);
1724 *term_size = out - term_size;
1733void flint::ratfun_read_mpoly(
const WORD *a, fmpz_mpoly_t num, fmpz_mpoly_t den,
1734 const var_map_t &var_map, fmpz_mpoly_ctx_t ctx) {
1737 const WORD* arg_stop = a+a[1];
1739 const bool must_normalize = (a[2] & MUSTCLEANPRF) != 0;
1742 if ( a >= arg_stop ) {
1743 MLOCK(ErrorMessageLock);
1744 MesPrint(
"ERROR: PolyRatFun cannot have zero arguments");
1745 MUNLOCK(ErrorMessageLock);
1754 flint::from_argument_mpoly(num, den_num.d, a,
true, var_map, ctx);
1757 if ( a < arg_stop ) {
1759 flint::from_argument_mpoly(den, den_den.d, a,
true, var_map, ctx);
1764 MLOCK(ErrorMessageLock);
1765 MesPrint(
"implement this");
1766 MUNLOCK(ErrorMessageLock);
1769 if ( a < arg_stop ) {
1770 MLOCK(ErrorMessageLock);
1771 MesPrint(
"ERROR: PolyRatFun cannot have more than two arguments");
1772 MUNLOCK(ErrorMessageLock);
1777 fmpz_mpoly_mul(num, num, den_den.d, ctx);
1778 fmpz_mpoly_mul(den, den, den_num.d, ctx);
1780 if ( must_normalize ) {
1782 fmpz_mpoly_gcd_cofactors(gcd.d, num, den, num, den, ctx);
1791void flint::ratfun_read_poly(
const WORD *a, fmpz_poly_t num, fmpz_poly_t den) {
1794 const WORD* arg_stop = a+a[1];
1796 const bool must_normalize = (a[2] & MUSTCLEANPRF) != 0;
1799 if ( a >= arg_stop ) {
1800 MLOCK(ErrorMessageLock);
1801 MesPrint(
"ERROR: PolyRatFun cannot have zero arguments");
1802 MUNLOCK(ErrorMessageLock);
1811 flint::from_argument_poly(num, den_num.d, a,
true);
1814 if ( a < arg_stop ) {
1816 flint::from_argument_poly(den, den_den.d, a,
true);
1821 MLOCK(ErrorMessageLock);
1822 MesPrint(
"implement this");
1823 MUNLOCK(ErrorMessageLock);
1826 if ( a < arg_stop ) {
1827 MLOCK(ErrorMessageLock);
1828 MesPrint(
"ERROR: PolyRatFun cannot have more than two arguments");
1829 MUNLOCK(ErrorMessageLock);
1834 fmpz_poly_mul(num, num, den_den.d);
1835 fmpz_poly_mul(den, den, den_num.d);
1837 if ( must_normalize ) {
1839 flint::util::simplify_fmpz_poly(num, den, gcd.d);
1852#define IFW(x) { if ( write ) {x;} }
1853uint64_t flint::to_argument_mpoly(PHEAD WORD *out,
const bool with_arghead,
1854 const bool must_fit_term,
const bool write,
const uint64_t prev_size,
const fmpz_mpoly_t
poly,
1855 const var_map_t &var_map,
const fmpz_mpoly_ctx_t ctx,
const bool sort_vars,
1856 const fmpz_t denscale) {
1859 const WORD* out_entry = out;
1866 if ( write && must_fit_term && (
sizeof(WORD)*(prev_size + ARGHEAD) > (
size_t)AM.MaxTer) ) {
1867 MLOCK(ErrorMessageLock);
1868 MesPrint(
"flint::to_argument_mpoly: output exceeds MaxTermSize");
1869 MUNLOCK(ErrorMessageLock);
1874 vector<uint32_t> var_map_inv;
1875 var_map_inv.resize(var_map.size());
1876 for (
auto x : var_map ) {
1877 var_map_inv[x.second] = x.first;
1880 vector<int64_t> exponents(var_map.size());
1881 const int64_t n_terms = fmpz_mpoly_length(
poly, ctx);
1883 if ( n_terms == 0 ) {
1884 if ( with_arghead ) {
1885 IFW(*out++ = -SNUMBER); ws++;
1886 IFW(*out++ = 0); ws++;
1890 IFW(*out++ = 0); ws++;
1899 if ( with_arghead && n_terms == 1 ) {
1901 if ( fmpz_mpoly_is_fmpz(
poly, ctx) ) {
1904 fmpz_mpoly_get_term_coeff_fmpz(coeff.d,
poly, 0, ctx);
1905 fmpz_set(den.d, denscale);
1906 flint::util::simplify_fmpz(coeff.d, den.d, gcd.d);
1908 if ( fmpz_is_one(den.d) && fmpz_fits_si(coeff.d) ) {
1909 const int64_t fast_coeff = fmpz_get_si(coeff.d);
1911 if ( fast_coeff > INT32_MIN && fast_coeff <= INT32_MAX ) {
1912 IFW(*out++ = -SNUMBER); ws++;
1913 IFW(*out++ = (WORD)fast_coeff); ws++;
1920 fmpz_mpoly_get_term_coeff_fmpz(coeff.d,
poly, 0, ctx);
1921 fmpz_set(den.d, denscale);
1922 flint::util::simplify_fmpz(coeff.d, den.d, gcd.d);
1924 if ( fmpz_is_one(coeff.d) && fmpz_is_one(den.d) ) {
1927 fmpz_mpoly_get_term_exp_si((slong*)exponents.data(),
poly, 0, ctx);
1928 int64_t use_fast = 0;
1929 uint32_t fast_symbol = 0;
1931 for (
size_t i = 0; i < var_map.size(); i++ ) {
1932 if ( exponents[i] == 1 ) fast_symbol = var_map_inv[i];
1933 use_fast += exponents[i];
1937 if ( use_fast == 1 ) {
1938 IFW(*out++ = -SYMBOL); ws++;
1939 IFW(*out++ = fast_symbol); ws++;
1947 WORD *tmp_coeff = (WORD *)NumberMalloc(
"flint::to_argument_mpoly");
1948 WORD *tmp_den = (WORD *)NumberMalloc(
"flint::to_argument_mpoly");
1952 if ( with_arghead ) {
1953 IFW(arg_size = out++); ws++;
1954 IFW(arg_flag = out++); ws++;
1958 for ( int64_t i = 0; i < n_terms; i++ ) {
1960 fmpz_mpoly_get_term_exp_si((slong*)exponents.data(),
poly, i, ctx);
1962 fmpz_mpoly_get_term_coeff_fmpz(coeff.d,
poly, i, ctx);
1963 fmpz_set(den.d, denscale);
1964 flint::util::simplify_fmpz(coeff.d, den.d, gcd.d);
1966 uint32_t num_symbols = 0;
1967 for (
size_t j = 0; j < var_map.size(); j++ ) {
1968 if ( exponents[j] != 0 ) { num_symbols += 1; }
1972 const WORD num_size = flint::fmpz_get_form(coeff.d, tmp_coeff);
1973 const WORD den_size = flint::fmpz_get_form(den.d, tmp_den);
1974 const WORD coeff_size = [num_size, den_size] () -> WORD {
1975 WORD size = ABS(num_size) > ABS(den_size) ? ABS(num_size) : ABS(den_size);
1976 return size * SGN(num_size) * SGN(den_size);
1981 uint64_t current_size = prev_size + ws + 1 + 2*ABS(coeff_size) + 1;
1982 if ( num_symbols ) {
1984 current_size += 2 + 2*num_symbols;
1986 if ( write && must_fit_term && (
sizeof(WORD)*current_size > (
size_t)AM.MaxTer) ) {
1987 MLOCK(ErrorMessageLock);
1988 MesPrint(
"flint::to_argument_mpoly: output exceeds MaxTermSize");
1989 MUNLOCK(ErrorMessageLock);
1993 WORD* term_size = 0;
1994 IFW(term_size = out++); ws++;
1995 if ( num_symbols ) {
1996 IFW(*out++ = SYMBOL); ws++;
1997 WORD* symbol_size = 0;
1998 IFW(symbol_size = out++); ws++;
1999 IFW(*symbol_size = 2);
2001 for (
size_t j = 0; j < var_map.size(); j++ ) {
2002 if ( exponents[j] != 0 ) {
2003 IFW(*out++ = var_map_inv[j]); ws++;
2004 IFW(*out++ = exponents[j]); ws++;
2005 IFW(*symbol_size += 2);
2011 for ( WORD j = 0; j < ABS(num_size); j++ ) {
2012 IFW(*out++ = tmp_coeff[j]); ws++;
2014 for ( WORD j = ABS(num_size); j < ABS(coeff_size); j++ ) {
2015 IFW(*out++ = 0); ws++;
2018 for ( WORD j = 0; j < ABS(den_size); j++ ) {
2019 IFW(*out++ = tmp_den[j]); ws++;
2021 for ( WORD j = ABS(den_size); j < ABS(coeff_size); j++ ) {
2022 IFW(*out++ = 0); ws++;
2025 IFW(*out = 2*ABS(coeff_size) + 1);
2026 IFW(
if ( coeff_size < 0 ) { *out = -(*out); });
2029 IFW(*term_size = out - term_size);
2032 if ( with_arghead ) {
2033 IFW(*arg_size = out - arg_size);
2034 if ( write && sort_vars ) {
2038 flint::form_sort(BHEAD (WORD*)(out_entry));
2043 IFW(*out++ = 0); ws++;
2046 NumberFree(tmp_coeff,
"flint::to_argument_mpoly");
2047 NumberFree(tmp_den,
"flint::to_argument_mpoly");
2053uint64_t flint::to_argument_mpoly(PHEAD WORD *out,
const bool with_arghead,
2054 const bool must_fit_term,
const bool write,
const uint64_t prev_size,
const fmpz_mpoly_t
poly,
2055 const var_map_t &var_map,
const fmpz_mpoly_ctx_t ctx,
const bool sort_vars) {
2058 fmpz_set_ui(tmp.d, 1);
2060 uint64_t ret = flint::to_argument_mpoly(BHEAD out, with_arghead, must_fit_term, write,
2061 prev_size,
poly, var_map, ctx, sort_vars, tmp.d);
2075uint64_t flint::to_argument_poly(PHEAD WORD *out,
const bool with_arghead,
2076 const bool must_fit_term,
const bool write,
const uint64_t prev_size,
const fmpz_poly_t
poly,
2077 const var_map_t &var_map,
const fmpz_t denscale) {
2084 if ( write && must_fit_term && (
sizeof(WORD)*(prev_size + ARGHEAD) > (
size_t)AM.MaxTer) ) {
2085 MLOCK(ErrorMessageLock);
2086 MesPrint(
"flint::to_argument_poly: output exceeds MaxTermSize");
2087 MUNLOCK(ErrorMessageLock);
2092 vector<uint32_t> var_map_inv;
2093 var_map_inv.resize(var_map.size());
2094 for (
auto x : var_map ) {
2095 var_map_inv[x.second] = x.first;
2098 const int64_t n_terms = fmpz_poly_length(
poly);
2101 if ( n_terms == 0 ) {
2102 if ( with_arghead ) {
2103 IFW(*out++ = -SNUMBER); ws++;
2104 IFW(*out++ = 0); ws++;
2108 IFW(*out++ = 0); ws++;
2117 if ( with_arghead && n_terms == 1 ) {
2119 fmpz_poly_get_coeff_fmpz(coeff.d,
poly, 0);
2120 fmpz_set(den.d, denscale);
2121 flint::util::simplify_fmpz(coeff.d, den.d, gcd.d);
2123 if ( fmpz_is_one(den.d) && fmpz_fits_si(coeff.d) ) {
2124 const long fast_coeff = fmpz_get_si(coeff.d);
2126 if ( fast_coeff > INT_MIN && fast_coeff <= INT_MAX ) {
2127 IFW(*out++ = -SNUMBER); ws++;
2128 IFW(*out++ = (WORD)fast_coeff); ws++;
2135 if ( with_arghead && n_terms == 2 ) {
2136 if ( fmpz_is_zero(fmpz_poly_get_coeff_ptr(
poly, 0)) ) {
2139 fmpz_poly_get_coeff_fmpz(coeff.d,
poly, 1);
2140 fmpz_set(den.d, denscale);
2141 flint::util::simplify_fmpz(coeff.d, den.d, gcd.d);
2143 if ( fmpz_is_one(coeff.d) && fmpz_is_one(den.d) ) {
2145 IFW(*out++ = -SYMBOL); ws++;
2146 IFW(*out++ = var_map_inv[0]); ws++;
2152 WORD *tmp_coeff = (WORD *)NumberMalloc(
"flint::to_argument_poly");
2153 WORD *tmp_den = (WORD *)NumberMalloc(
"flint::to_argument_mpoly");
2157 if ( with_arghead ) {
2158 IFW(arg_size = out++); ws++;
2159 IFW(arg_flag = out++); ws++;
2164 for ( int64_t i = n_terms-1; i >= 0; i-- ) {
2167 if ( !fmpz_is_zero(fmpz_poly_get_coeff_ptr(
poly, i)) ) {
2169 fmpz_poly_get_coeff_fmpz(coeff.d,
poly, i);
2170 fmpz_set(den.d, denscale);
2171 flint::util::simplify_fmpz(coeff.d, den.d, gcd.d);
2174 const WORD num_size = flint::fmpz_get_form(coeff.d, tmp_coeff);
2175 const WORD den_size = flint::fmpz_get_form(den.d, tmp_den);
2176 const WORD coeff_size = [num_size, den_size] () -> WORD {
2177 WORD size = ABS(num_size) > ABS(den_size) ? ABS(num_size) : ABS(den_size);
2178 return size * SGN(num_size) * SGN(den_size);
2184 uint64_t current_size = prev_size + ws + 1 + 2*ABS(coeff_size) + 1;
2189 if ( write && must_fit_term && (
sizeof(WORD)*current_size > (
size_t)AM.MaxTer) ) {
2190 MLOCK(ErrorMessageLock);
2191 MesPrint(
"flint::to_argument_poly: output exceeds MaxTermSize");
2192 MUNLOCK(ErrorMessageLock);
2196 WORD* term_size = 0;
2197 IFW(term_size = out++); ws++;
2200 IFW(*out++ = SYMBOL); ws++;
2201 IFW(*out++ = 4); ws++;
2202 IFW(*out++ = var_map_inv[0]); ws++;
2203 IFW(*out++ = i); ws++;
2207 for ( WORD j = 0; j < ABS(num_size); j++ ) {
2208 IFW(*out++ = tmp_coeff[j]); ws++;
2210 for ( WORD j = ABS(num_size); j < ABS(coeff_size); j++ ) {
2211 IFW(*out++ = 0); ws++;
2214 for ( WORD j = 0; j < ABS(den_size); j++ ) {
2215 IFW(*out++ = tmp_den[j]); ws++;
2217 for ( WORD j = ABS(den_size); j < ABS(coeff_size); j++ ) {
2218 IFW(*out++ = 0); ws++;
2221 IFW(*out = 2*ABS(coeff_size) + 1);
2222 IFW(
if ( coeff_size < 0 ) { *out = -(*out); });
2225 IFW(*term_size = out - term_size);
2230 if ( with_arghead ) {
2231 IFW(*arg_size = out - arg_size);
2235 IFW(*out++ = 0); ws++;
2238 NumberFree(tmp_coeff,
"flint::to_argument_poly");
2239 NumberFree(tmp_den,
"flint::to_argument_poly");
2245uint64_t flint::to_argument_poly(PHEAD WORD *out,
const bool with_arghead,
2246 const bool must_fit_term,
const bool write,
const uint64_t prev_size,
const fmpz_poly_t
poly,
2247 const var_map_t &var_map) {
2250 fmpz_set_ui(tmp.d, 1);
2252 uint64_t ret = flint::to_argument_poly(BHEAD out, with_arghead, must_fit_term, write, prev_size,
2253 poly, var_map, tmp.d);
2266inline void flint::util::simplify_fmpz(fmpz_t num, fmpz_t den, fmpz_t gcd) {
2267 fmpz_gcd(gcd, num, den);
2268 if ( !fmpz_is_one(gcd) ) {
2269 fmpz_divexact(num, num, gcd);
2270 fmpz_divexact(den, den, gcd);
2278inline void flint::util::simplify_fmpz_poly(fmpz_poly_t num, fmpz_poly_t den, fmpz_poly_t gcd) {
2279 fmpz_poly_gcd(gcd, num, den);
2280 if ( !fmpz_poly_is_one(gcd) ) {
2281#if __FLINT_RELEASE >= 30100
2283 fmpz_poly_divexact(num, num, gcd);
2284 fmpz_poly_divexact(den, den, gcd);
2286 fmpz_poly_div(num, num, gcd);
2287 fmpz_poly_div(den, den, gcd);
2295inline void flint::util::fix_sign_fmpz_mpoly_ratfun(fmpz_mpoly_t num, fmpz_mpoly_t den,
2296 const fmpz_mpoly_ctx_t ctx) {
2298 if ( fmpz_sgn(fmpz_mpoly_term_coeff_ref(den, 0, ctx)) == -1 ) {
2299 fmpz_mpoly_neg(num, num, ctx);
2300 fmpz_mpoly_neg(den, den, ctx);
2307inline void flint::util::fix_sign_fmpz_poly_ratfun(fmpz_poly_t num, fmpz_poly_t den) {
2309 if ( fmpz_sgn(fmpz_poly_get_coeff_ptr(den, fmpz_poly_degree(den))) == -1 ) {
2310 fmpz_poly_neg(num, num);
2311 fmpz_poly_neg(den, den);
LONG EndSort(PHEAD WORD *, int)
void LowerSortLevel(void)
int StoreTerm(PHEAD WORD *)
WORD Compare1(PHEAD WORD *, WORD *, WORD)
WORD CompareSymbols(PHEAD WORD *, WORD *, WORD)
int SymbolNormalize(WORD *)