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) {
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 ) {
103 MLOCK(ErrorMessageLock);
104 MesPrint(
"flint::divmod_mpoly: error: denpa is non-constant");
105 MUNLOCK(ErrorMessageLock);
108 if ( fmpz_mpoly_is_fmpz(denpb.d, ctx.d) != 1 ) {
109 MLOCK(ErrorMessageLock);
110 MesPrint(
"flint::divmod_mpoly: error: denpb is non-constant");
111 MUNLOCK(ErrorMessageLock);
119 fmpz_mpoly_quasidivrem(scale.d, div.d, rem.d, pa.d, pb.d, ctx.d);
122 fmpz_mpoly_mul(div.d, div.d, denpb.d, ctx.d);
127 fmpz_mul(scale.d, scale.d, fmpz_mpoly_term_coeff_ref(denpa.d, 0, ctx.d));
131 const bool with_arghead =
false;
133 const uint64_t prev_size = 0;
134 const uint64_t out_size = return_rem ?
135 (uint64_t)flint::to_argument_mpoly(BHEAD NULL, with_arghead, must_fit_term, write, prev_size,
136 rem.d, var_map, ctx.d, scale.d)
138 (uint64_t)flint::to_argument_mpoly(BHEAD NULL, with_arghead, must_fit_term, write, prev_size,
139 div.d, var_map, ctx.d, scale.d)
141 WORD* res = (WORD *)Malloc1(
sizeof(WORD)*out_size,
"flint::divrem_mpoly");
147 (uint64_t)flint::to_argument_mpoly(BHEAD res, with_arghead, must_fit_term, write, prev_size,
148 rem.d, var_map, ctx.d, scale.d);
151 (uint64_t)flint::to_argument_mpoly(BHEAD res, with_arghead, must_fit_term, write, prev_size,
152 div.d, var_map, ctx.d, scale.d);
161WORD* flint::divmod_poly(PHEAD
const WORD *a,
const WORD *b,
const bool return_rem,
162 const WORD must_fit_term,
const var_map_t &var_map) {
166 flint::from_argument_poly(pa.d, denpa.d, a,
false);
167 flint::from_argument_poly(pb.d, denpb.d, b,
false);
171 if ( fmpz_poly_length(denpa.d) != 1 ) {
172 MLOCK(ErrorMessageLock);
173 MesPrint(
"flint::divmod_poly: error: denpa is non-constant");
174 MUNLOCK(ErrorMessageLock);
177 if ( fmpz_poly_length(denpb.d) != 1 ) {
178 MLOCK(ErrorMessageLock);
179 MesPrint(
"flint::divmod_poly: error: denpb is non-constant");
180 MUNLOCK(ErrorMessageLock);
185 uint64_t scale_power = 0;
189 fmpz_poly_get_coeff_fmpz(scale.d, pb.d, fmpz_poly_degree(pb.d));
191 fmpz_poly_pseudo_divrem(div.d, rem.d, (ulong*)&scale_power, pa.d, pb.d);
194 fmpz_poly_mul(div.d, div.d, denpb.d);
199 fmpz_pow_ui(scale.d, scale.d, scale_power);
200 fmpz_mul(scale.d, scale.d, fmpz_poly_get_coeff_ptr(denpa.d, 0));
204 const bool with_arghead =
false;
206 const uint64_t prev_size = 0;
207 const uint64_t out_size = return_rem ?
208 (uint64_t)flint::to_argument_poly(BHEAD NULL, with_arghead, must_fit_term, write, prev_size,
209 rem.d, var_map, scale.d)
211 (uint64_t)flint::to_argument_poly(BHEAD NULL, with_arghead, must_fit_term, write, prev_size,
212 div.d, var_map, scale.d)
214 WORD* res = (WORD *)Malloc1(
sizeof(WORD)*out_size,
"flint::divrem_poly");
220 (uint64_t)flint::to_argument_poly(BHEAD res, with_arghead, must_fit_term, write, prev_size,
221 rem.d, var_map, scale.d);
224 (uint64_t)flint::to_argument_poly(BHEAD res, with_arghead, must_fit_term, write, prev_size,
225 div.d, var_map, scale.d);
235WORD* flint::factorize_mpoly(PHEAD
const WORD *argin, WORD *argout,
const bool with_arghead,
236 const bool is_fun_arg,
const var_map_t &var_map) {
241 flint::from_argument_mpoly(arg.d, den.d, argin, with_arghead, var_map, ctx.d);
243 if ( fmpz_mpoly_is_one(den.d, ctx.d) != 1 ) {
244 MLOCK(ErrorMessageLock);
245 MesPrint(
"flint::factorize_mpoly error: den != 1");
246 MUNLOCK(ErrorMessageLock);
253 fmpz_mpoly_factor(arg_fac.d, arg.d, ctx.d);
254 const int64_t num_factors = fmpz_mpoly_factor_length(arg_fac.d, ctx.d);
257 fmpz_mpoly_factor_get_constant_fmpz(overall_constant.d, arg_fac.d, ctx.d);
260 if ( ! ( fmpz_equal_si(overall_constant.d, 1) || fmpz_equal_si(overall_constant.d, -1) ) ) {
261 MLOCK(ErrorMessageLock);
262 MesPrint(
"flint::factorize_mpoly error: overall constant factor != +-1");
263 MUNLOCK(ErrorMessageLock);
276 uint64_t output_size = 1;
279 var_map_t var_map_inv;
280 for (
auto x: var_map ) {
281 var_map_inv[x.second] = x.first;
285 vector<int32_t> base_sign(num_factors, 0);
287 for ( int64_t i = 0; i < num_factors; i++ ) {
288 fmpz_mpoly_factor_get_base(base.d, arg_fac.d, i, ctx.d);
289 const int64_t exponent = fmpz_mpoly_factor_get_exp_si(arg_fac.d, i, ctx.d);
296 uint32_t max_var = 0;
297 int32_t max_pow = -1;
298 vector<int64_t> base_term_exponents(var_map.size(), 0);
300 for ( int64_t j = 0; j < fmpz_mpoly_length(base.d, ctx.d); j++ ) {
301 fmpz_mpoly_get_term_exp_si((slong*)base_term_exponents.data(), base.d, (slong)j, ctx.d);
303 for (
size_t k = 0; k < var_map.size(); k++ ) {
304 if ( base_term_exponents[k] > 0 && ( var_map_inv.at(k) > max_var ||
305 ( var_map_inv.at(k) == max_var && base_term_exponents[k] > max_pow ) ) ) {
307 max_var = var_map_inv.at(k);
308 max_pow = base_term_exponents[k];
309 base_sign[i] = fmpz_sgn(fmpz_mpoly_term_coeff_ref(base.d, j, ctx.d));
315 if ( ( base_sign[i] == -1 ) && ( exponent % 2 == 1 ) ) {
316 fmpz_neg(overall_constant.d, overall_constant.d);
320 if ( argout == NULL ) {
321 const bool write =
false;
322 for ( int64_t j = 0; j < exponent; j++ ) {
323 output_size += (uint64_t)flint::to_argument_mpoly(BHEAD NULL, with_arghead,
324 is_fun_arg, write, 0, base.d, var_map, ctx.d);
328 if ( fmpz_sgn(overall_constant.d) == -1 && argout == NULL ) {
330 output_size += with_arghead ? 2 : 4+1;
334 if ( argout == NULL ) {
335 argout = (WORD*)Malloc1(
sizeof(WORD)*output_size,
"flint::factorize_mpoly");
340 WORD* old_argout = argout;
344 if ( fmpz_sgn(overall_constant.d) == -1 ) {
345 if ( with_arghead ) {
348 *argout++ = -SNUMBER;
360 for ( int64_t i = 0; i < num_factors; i++ ) {
361 fmpz_mpoly_factor_get_base(base.d, arg_fac.d, i, ctx.d);
362 const int64_t exponent = fmpz_mpoly_factor_get_exp_si(arg_fac.d, i, ctx.d);
364 if ( base_sign[i] == -1 ) {
365 fmpz_mpoly_neg(base.d, base.d, ctx.d);
368 const bool write =
true;
369 for ( int64_t j = 0; j < exponent; j++ ) {
370 argout += flint::to_argument_mpoly(BHEAD argout, with_arghead, is_fun_arg, write,
371 argout-old_argout, base.d, var_map, ctx.d);
383WORD* flint::factorize_poly(PHEAD
const WORD *argin, WORD *argout,
const bool with_arghead,
384 const bool is_fun_arg,
const var_map_t &var_map) {
388 flint::from_argument_poly(arg.d, den.d, argin, with_arghead);
390 if ( fmpz_poly_is_one(den.d) != 1 ) {
391 MLOCK(ErrorMessageLock);
392 MesPrint(
"flint::factorize_poly error: den != 1");
393 MUNLOCK(ErrorMessageLock);
400 fmpz_poly_factor(arg_fac.d, arg.d);
403 const long num_factors = (arg_fac.d)->num;
410 if ( argout == NULL ) {
414 uint64_t output_size = 1;
416 for (
long i = 0; i < num_factors; i++ ) {
417 fmpz_poly_struct* base = (arg_fac.d)->p + i;
419 const long exponent = (arg_fac.d)->exp[i];
421 const bool write =
false;
422 for (
long j = 0; j < exponent; j++ ) {
423 output_size += (uint64_t)flint::to_argument_poly(BHEAD NULL, with_arghead,
424 is_fun_arg, write, 0, base, var_map);
428 argout = (WORD*)Malloc1(
sizeof(WORD)*output_size,
"flint::factorize_poly");
431 WORD* old_argout = argout;
433 for (
long i = 0; i < num_factors; i++ ) {
434 fmpz_poly_struct* base = (arg_fac.d)->p + i;
436 const long exponent = (arg_fac.d)->exp[i];
438 const bool write =
true;
439 for (
long j = 0; j < exponent; j++ ) {
440 argout += flint::to_argument_poly(BHEAD argout, with_arghead, is_fun_arg, write,
441 argout-old_argout, base, var_map);
456void flint::form_sort(PHEAD WORD *terms) {
458 if ( terms[0] < 0 ) {
463 const WORD oldsorttype = AR.SortType;
464 AR.SortType = SORTHIGHFIRST;
466 const WORD in_size = terms[0] - ARGHEAD;
475 for ( WORD i = ARGHEAD; i < terms[0]; i += terms[i] ) {
477 AR.SortType = oldsorttype;
478 AR.CompareRoutine = (COMPAREDUMMY)(&
Compare1);
484 if ( ( out_size =
EndSort(BHEAD terms+ARGHEAD, 1) ) < 0 ) {
485 AR.SortType = oldsorttype;
486 AR.CompareRoutine = (COMPAREDUMMY)(&
Compare1);
491 if ( in_size != out_size ) {
492 MLOCK(ErrorMessageLock);
493 MesPrint(
"flint::form_sort: error: unexpected sorted arg length change %d->%d", in_size,
495 MUNLOCK(ErrorMessageLock);
499 AR.SortType = oldsorttype;
500 AR.CompareRoutine = (COMPAREDUMMY)(&
Compare1);
511uint64_t flint::from_argument_mpoly(fmpz_mpoly_t
poly, fmpz_mpoly_t denpoly,
const WORD *args,
512 const bool with_arghead,
const var_map_t &var_map,
const fmpz_mpoly_ctx_t ctx) {
516 fmpz_mpoly_set_si(
poly, 0, ctx);
517 fmpz_mpoly_set_si(denpoly, 0, ctx);
520 if ( *args == -SNUMBER ) {
521 fmpz_mpoly_set_si(
poly, *(args+1), ctx);
522 fmpz_mpoly_set_si(denpoly, 1, ctx);
526 if ( *args == -SYMBOL ) {
528 vector<uint64_t> exponents(var_map.size(), 0);
529 exponents[var_map.at(*(args+1))] = 1;
531 fmpz_mpoly_set_coeff_ui_ui(
poly, (ulong)1, (ulong*)exponents.data(), ctx);
532 fmpz_mpoly_set_ui(denpoly, (ulong)1, ctx);
540 const WORD* arg_stop = with_arghead ? args+args[0] : (WORD*)UINT64_MAX;
541 uint64_t arg_size = 0;
542 if ( with_arghead ) {
550 fmpz_set_si(den_coeff.d, 1);
551 vector<uint64_t> neg_exponents(var_map.size(), 0);
553 for (
const WORD* term = args; term < arg_stop; term += term[0] ) {
554 const WORD* term_stop = term+term[0];
555 const WORD coeff_size = (term_stop)[-1];
556 const WORD* symbol_stop = term_stop - ABS(coeff_size);
557 const WORD* t = term;
560 if ( t == symbol_stop ) {
567 for (
const WORD* s = t; s < symbol_stop; s += 2 ) {
569 neg_exponents[var_map.at(*s)] =
570 MaX(neg_exponents[var_map.at(*s)], (uint64_t)(-(*(s+1))) );
576 if ( *(symbol_stop+ABS(coeff_size/2)) != 1 ) {
577 flint::fmpz_set_form(tmp.d, (UWORD*)(symbol_stop+ABS(coeff_size/2)), ABS(coeff_size/2));
579 fmpz_lcm(den_coeff.d, den_coeff.d, tmp.d);
582 if ( !with_arghead && *term_stop == 0 ) {
584 arg_size = term_stop - args + 1;
590 fmpz_mpoly_set_coeff_fmpz_ui(denpoly, den_coeff.d, (ulong*)neg_exponents.data(), ctx);
596 for (
const WORD* term = args; term < arg_stop; term += term[0] ) {
597 const WORD* term_stop = term+term[0];
598 const WORD coeff_size = (term_stop)[-1];
599 const WORD* symbol_stop = term_stop - ABS(coeff_size);
600 const WORD* t = term;
602 vector<uint64_t> exponents(var_map.size(), 0);
605 if ( t == symbol_stop ) {
611 for (
const WORD* s = t; s < symbol_stop; s += 2 ) {
612 exponents[var_map.at(*s)] = *(s+1);
616 flint::fmpz_set_form(coeff.d, (UWORD*)symbol_stop, coeff_size/2);
619 fmpz_mul(coeff.d, coeff.d, den_coeff.d);
622 for (
size_t i = 0; i < var_map.size(); i++ ) {
623 exponents[i] += neg_exponents[i];
627 if ( *(symbol_stop+ABS(coeff_size/2)) != 1 ) {
628 flint::fmpz_set_form(tmp.d, (UWORD*)(symbol_stop+ABS(coeff_size/2)), ABS(coeff_size/2));
630 fmpz_divexact(coeff.d, coeff.d, tmp.d);
635 fmpz_mpoly_push_term_fmpz_ui(
poly, coeff.d, (ulong*)exponents.data(), ctx);
637 if ( !with_arghead && *term_stop == 0 ) {
643 fmpz_mpoly_sort_terms(
poly, ctx);
654uint64_t flint::from_argument_poly(fmpz_poly_t
poly, fmpz_poly_t denpoly,
const WORD *args,
655 const bool with_arghead) {
659 fmpz_poly_set_si(
poly, 0);
660 fmpz_poly_set_si(denpoly, 0);
663 if ( *args == -SNUMBER ) {
664 fmpz_poly_set_si(
poly, *(args+1));
665 fmpz_poly_set_si(denpoly, 1);
669 if ( *args == -SYMBOL ) {
671 fmpz_poly_set_coeff_si(
poly, 1, 1);
672 fmpz_poly_set_si(denpoly, 1);
679 const WORD* arg_stop = with_arghead ? args+args[0] : (WORD*)UINT64_MAX;
680 uint64_t arg_size = 0;
681 if ( with_arghead ) {
688 fmpz_set_si(den_coeff.d, 1);
689 uint64_t neg_exponent = 0;
691 for (
const WORD* term = args; term < arg_stop; term += term[0] ) {
693 const WORD* term_stop = term+term[0];
694 const WORD coeff_size = (term_stop)[-1];
695 const WORD* symbol_stop = term_stop - ABS(coeff_size);
696 const WORD* t = term;
699 if ( t == symbol_stop ) {
707 neg_exponent = MaX(neg_exponent, (uint64_t)(-(*t)) );
712 if ( *(symbol_stop+ABS(coeff_size/2)) != 1 ) {
713 flint::fmpz_set_form(tmp.d, (UWORD*)(symbol_stop+ABS(coeff_size/2)), ABS(coeff_size/2));
715 fmpz_lcm(den_coeff.d, den_coeff.d, tmp.d);
718 if ( *term_stop == 0 ) {
720 arg_size = term_stop - args + 1;
725 fmpz_poly_set_coeff_fmpz(denpoly, neg_exponent, den_coeff.d);
731 for (
const WORD* term = args; term < arg_stop; term += term[0] ) {
733 const WORD* term_stop = term+term[0];
734 const WORD coeff_size = (term_stop)[-1];
735 const WORD* symbol_stop = term_stop - ABS(coeff_size);
736 const WORD* t = term;
738 uint64_t exponent = 0;
741 if ( t == symbol_stop ) {
752 flint::fmpz_set_form(coeff.d, (UWORD*)symbol_stop, coeff_size/2);
755 fmpz_mul(coeff.d, coeff.d, den_coeff.d);
758 exponent += neg_exponent;
761 if ( *(symbol_stop+ABS(coeff_size/2)) != 1 ) {
762 flint::fmpz_set_form(tmp.d, (UWORD*)(symbol_stop+ABS(coeff_size/2)), ABS(coeff_size/2));
764 fmpz_divexact(coeff.d, coeff.d, tmp.d);
768 fmpz_poly_set_coeff_fmpz(
poly, exponent, coeff.d);
770 if ( *term_stop == 0 ) {
784WORD flint::fmpz_get_form(fmpz_t z, WORD *a) {
787 const int32_t sgn = fmpz_sgn(z);
791 const int64_t nlimbs = fmpz_size(z);
799 const uint64_t limb = fmpz_get_ui(z);
800 a[0] = (WORD)(limb & 0xFFFFFFFF);
802 a[1] = (WORD)(limb >> BITSINWORD);
807 else if ( nlimbs == 2 ) {
808 uint64_t limb_hi = 0, limb_lo = 0;
809 fmpz_get_uiui((ulong*)&limb_hi, (ulong*)&limb_lo, z);
810 a[0] = (WORD)(limb_lo & 0xFFFFFFFF);
812 a[1] = (WORD)(limb_lo >> BITSINWORD);
814 a[2] = (WORD)(limb_hi & 0xFFFFFFFF);
816 a[3] = (WORD)(limb_hi >> BITSINWORD);
822 vector<uint64_t> limb_data(nlimbs, 0);
823 fmpz_get_ui_array((ulong*)limb_data.data(), (slong)nlimbs, z);
824 for (
long i = 0; i < nlimbs; i++ ) {
825 a[2*i] = (WORD)(limb_data[i] & 0xFFFFFFFF);
827 a[2*i+1] = (WORD)(limb_data[i] >> BITSINWORD);
828 if ( a[2*i+1] != 0 || i < (nlimbs-1) ) {
849void flint::fmpz_set_form(fmpz_t z, UWORD *a, WORD na) {
867 while ( a[na-1] == 0 ) {
874 fmpz_set_ui(z, (uint64_t)a[0]);
876 else if ( na == 2 ) {
877 fmpz_set_ui(z, (((uint64_t)a[1])<<BITSINWORD) + (uint64_t)a[0]);
879 else if ( na == 3 ) {
880 fmpz_set_uiui(z, (uint64_t)a[2], (((uint64_t)a[1])<<BITSINWORD) + (uint64_t)a[0]);
882 else if ( na == 4 ) {
883 fmpz_set_uiui(z, (((uint64_t)a[3])<<BITSINWORD) + (uint64_t)a[2],
884 (((uint64_t)a[1])<<BITSINWORD) + (uint64_t)a[0]);
887 const int32_t nlimbs = (na+1)/2;
888 vector<uint64_t> limb_data(nlimbs, 0);
889 for ( int32_t i = 0; i < nlimbs; i++ ) {
890 if ( 2*i+1 <= na-1 ) {
891 limb_data[i] = (uint64_t)a[2*i] + (((uint64_t)a[2*i+1])<<BITSINWORD);
894 limb_data[i] = (uint64_t)a[2*i];
897 fmpz_set_ui_array(z, (ulong*)limb_data.data(), nlimbs);
915WORD* flint::gcd_mpoly(PHEAD
const WORD *a,
const WORD *b,
const WORD must_fit_term,
916 const var_map_t &var_map) {
919 flint::mpoly pa(ctx.d), pb(ctx.d), denpa(ctx.d), denpb(ctx.d), gcd(ctx.d);
921 flint::from_argument_mpoly(pa.d, denpa.d, a,
false, var_map, ctx.d);
922 flint::from_argument_mpoly(pb.d, denpb.d, b,
false, var_map, ctx.d);
925 if ( fmpz_mpoly_is_one(denpa.d, ctx.d) != 1 ) {
926 MLOCK(ErrorMessageLock);
927 MesPrint(
"flint::gcd_mpoly: error: denpa != 1");
928 MUNLOCK(ErrorMessageLock);
931 if ( fmpz_mpoly_is_one(denpb.d, ctx.d) != 1 ) {
932 MLOCK(ErrorMessageLock);
933 MesPrint(
"flint::gcd_mpoly: error: denpb != 1");
934 MUNLOCK(ErrorMessageLock);
939 if ( fmpz_mpoly_equal(pa.d, pb.d, ctx.d) ) {
940 fmpz_mpoly_set(gcd.d, pa.d, ctx.d);
948 fmpz_mpoly_term_content(tmp.d, pa.d, ctx.d);
949 if ( fmpz_mpoly_is_one(tmp.d, ctx.d) != 1 ) {
950 MLOCK(ErrorMessageLock);
951 MesPrint(
"flint::gcd_mpoly: error: content of 1st arg != 1");
952 MUNLOCK(ErrorMessageLock);
955 fmpz_mpoly_term_content(tmp.d, pb.d, ctx.d);
956 if ( fmpz_mpoly_is_one(tmp.d, ctx.d) != 1 ) {
957 MLOCK(ErrorMessageLock);
958 MesPrint(
"flint::gcd_mpoly: error: content of 2nd arg != 1");
959 MUNLOCK(ErrorMessageLock);
969 if ( ( fmpz_sgn(fmpz_mpoly_term_coeff_ref(pa.d, 0, ctx.d)) == -1 ) &&
970 ( fmpz_sgn(fmpz_mpoly_term_coeff_ref(pb.d, 0, ctx.d)) == -1 ) ) {
974 fmpz_mpoly_gcd(gcd.d, pa.d, pb.d, ctx.d);
976 fmpz_mpoly_neg(gcd.d, gcd.d, ctx.d);
982 if ( must_fit_term ) {
983 res = TermMalloc(
"flint::gcd_mpoly");
987 const bool with_arghead =
false;
988 const bool write =
false;
989 const uint64_t prev_size = 0;
990 const uint64_t gcd_size = (uint64_t)flint::to_argument_mpoly(BHEAD NULL,
991 with_arghead, must_fit_term, write, prev_size, gcd.d, var_map, ctx.d);
993 res = (WORD *)Malloc1(
sizeof(WORD)*gcd_size,
"flint::gcd_mpoly");
996 const bool with_arghead =
false;
997 const bool write =
true;
998 const uint64_t prev_size = 0;
999 flint::to_argument_mpoly(BHEAD res, with_arghead, must_fit_term, write, prev_size, gcd.d,
1011WORD* flint::gcd_poly(PHEAD
const WORD *a,
const WORD *b,
const WORD must_fit_term,
1012 const var_map_t &var_map) {
1016 flint::from_argument_poly(pa.d, denpa.d, a,
false);
1017 flint::from_argument_poly(pb.d, denpb.d, b,
false);
1020 if ( fmpz_poly_is_one(denpa.d) != 1 ) {
1021 MLOCK(ErrorMessageLock);
1022 MesPrint(
"flint::gcd_poly: error: denpa != 1");
1023 MUNLOCK(ErrorMessageLock);
1026 if ( fmpz_poly_is_one(denpb.d) != 1 ) {
1027 MLOCK(ErrorMessageLock);
1028 MesPrint(
"flint::gcd_poly: error: denpb != 1");
1029 MUNLOCK(ErrorMessageLock);
1034 if ( fmpz_poly_equal(pa.d, pb.d) ) {
1035 fmpz_poly_set(gcd.d, pa.d);
1042 fmpz_poly_content(tmp.d, pa.d);
1043 if ( fmpz_is_one(tmp.d) != 1 ) {
1044 MLOCK(ErrorMessageLock);
1045 MesPrint(
"flint::gcd_poly: error: content of 1st arg != 1");
1046 MUNLOCK(ErrorMessageLock);
1049 fmpz_poly_content(tmp.d, pb.d);
1050 if ( fmpz_is_one(tmp.d) != 1 ) {
1051 MLOCK(ErrorMessageLock);
1052 MesPrint(
"flint::gcd_poly: error: content of 2nd arg != 1");
1053 MUNLOCK(ErrorMessageLock);
1057 fmpz_poly_gcd(gcd.d, pa.d, pb.d);
1062 if ( must_fit_term ) {
1063 res = TermMalloc(
"flint::gcd_poly");
1067 const bool with_arghead =
false;
1068 const bool write =
false;
1069 const uint64_t prev_size = 0;
1070 const uint64_t gcd_size = (uint64_t)flint::to_argument_poly(BHEAD NULL,
1071 with_arghead, must_fit_term, write, prev_size, gcd.d, var_map);
1073 res = (WORD *)Malloc1(
sizeof(WORD)*gcd_size,
"flint::gcd_poly");
1076 const bool with_arghead =
false;
1077 const uint64_t prev_size = 0;
1078 const bool write =
true;
1079 flint::to_argument_poly(BHEAD res, with_arghead, must_fit_term, write, prev_size, gcd.d,
1093flint::var_map_t flint::get_variables(
const vector <WORD *> &es,
const bool with_arghead,
1094 const bool sort_vars) {
1096 int32_t num_vars = 0;
1098 uint32_t num_terms = 0;
1100 vector<int32_t> degrees;
1104 for (
size_t ei = 0; ei < es.size(); ei++ ) {
1108 if ( *e == -SNUMBER ) {
1111 else if ( *e == -SYMBOL ) {
1113 if ( !var_map.count(e[1]) ) {
1114 var_map[e[1]] = num_vars++;
1115 degrees.push_back(1);
1119 else if ( *e < 0 ) {
1120 MLOCK(ErrorMessageLock);
1121 MesPrint(
"ERROR: polynomials and polyratfuns must contain symbols only");
1122 MUNLOCK(ErrorMessageLock);
1126 for ( WORD i = with_arghead ? ARGHEAD:0; with_arghead ? i < e[0]:e[i] != 0; i += e[i] ) {
1128 if ( i+1 < i+e[i]-ABS(e[i+e[i]-1]) && e[i+1] != SYMBOL ) {
1129 MLOCK(ErrorMessageLock);
1130 MesPrint(
"ERROR: polynomials and polyratfuns must contain symbols only");
1131 MUNLOCK(ErrorMessageLock);
1135 for ( WORD j = i+3; j<i+e[i]-ABS(e[i+e[i]-1]); j += 2 ) {
1136 if ( !var_map.count(e[j]) ) {
1137 var_map[e[j]] = num_vars++;
1138 degrees.push_back(e[j+1]);
1141 degrees[var_map[e[j]]] = MaX(degrees[var_map[e[j]]], e[j+1]);
1151 for (
size_t i = 0; i < var_map.size(); i++ ) {
1152 for (
size_t j = 0; j+1 < var_map.size(); j++ ) {
1153 if ( degrees[j] < degrees[j+1] ) {
1154 swap(degrees[j], degrees[j+1]);
1159 for (
auto x: var_map ) {
1160 if ( x.second == j ) {
1163 else if ( x.second == j+1 ) {
1167 swap(var_map.at(j0), var_map.at(j1));
1174 for (
size_t i = 0; i < var_map.size(); i++ ) {
1175 for (
size_t j = 0; j+1 < var_map.size(); j++ ) {
1178 for (
auto x: var_map ) {
1179 if ( x.second == j ) {
1182 else if ( x.second == j+1 ) {
1187 swap(var_map.at(j0), var_map.at(j1));
1193 if ( var_map.size() == 1 ) {
1196 if ( (
float)num_terms <= UNIVARIATE_DENSITY_THR * (
float)degrees[0] ) {
1199 var_map[-1] = num_vars;
1210WORD* flint::inverse_poly(PHEAD
const WORD *a,
const WORD *b,
const var_map_t &var_map) {
1214 flint::from_argument_poly(pa.d, denpa.d, a,
false);
1215 flint::from_argument_poly(pb.d, denpb.d, b,
false);
1223 fmpz_poly_content(content_a.d, pa.d);
1224 if ( fmpz_sgn(fmpz_poly_lead(pa.d)) == -1 ) {
1225 fmpz_neg(content_a.d, content_a.d);
1227 fmpz_poly_primitive_part(pa.d, pa.d);
1228 fmpz_poly_primitive_part(pb.d, pb.d);
1232 if ( fmpz_poly_is_one(pa.d) && fmpz_poly_is_one(pb.d) ) {
1233 fmpz_poly_one(inverse.d);
1234 fmpz_one(resultant.d);
1236 else if ( fmpz_poly_is_one(pb.d) ) {
1237 fmpz_poly_zero(inverse.d);
1238 fmpz_one(resultant.d);
1244 fmpz_poly_xgcd(resultant.d, inverse.d, tmp.d, pa.d, pb.d);
1247 if ( fmpz_is_zero(resultant.d) ) {
1248 MLOCK(ErrorMessageLock);
1249 MesPrint(
"flint::inverse_poly error: inverse does not exist");
1250 MUNLOCK(ErrorMessageLock);
1258 fmpz_poly_mul(inverse.d, inverse.d, denpa.d);
1259 fmpz_mul(resultant.d, resultant.d, content_a.d);
1265 const bool with_arghead =
false;
1267 const bool must_fit_term =
false;
1268 const uint64_t prev_size = 0;
1269 const uint64_t res_size = (uint64_t)flint::to_argument_poly(BHEAD NULL,
1270 with_arghead, must_fit_term, write, prev_size, inverse.d, var_map, resultant.d);
1271 res = (WORD*)Malloc1(
sizeof(WORD)*res_size,
"flint::inverse_poly");
1274 flint::to_argument_poly(BHEAD res, with_arghead, must_fit_term, write, prev_size, inverse.d,
1275 var_map, resultant.d);
1286WORD* flint::mul_mpoly(PHEAD
const WORD *a,
const WORD *b,
const var_map_t &var_map) {
1289 flint::mpoly pa(ctx.d), pb(ctx.d), denpa(ctx.d), denpb(ctx.d);
1291 flint::from_argument_mpoly(pa.d, denpa.d, a,
false, var_map, ctx.d);
1292 flint::from_argument_mpoly(pb.d, denpb.d, b,
false, var_map, ctx.d);
1295 if ( fmpz_mpoly_is_fmpz(denpa.d, ctx.d) != 1 ) {
1296 MLOCK(ErrorMessageLock);
1297 MesPrint(
"flint::mul_mpoly: error: denpa is non-constant");
1298 MUNLOCK(ErrorMessageLock);
1301 if ( fmpz_mpoly_is_fmpz(denpb.d, ctx.d) != 1 ) {
1302 MLOCK(ErrorMessageLock);
1303 MesPrint(
"flint::mul_mpoly: error: denpb is non-constant");
1304 MUNLOCK(ErrorMessageLock);
1309 fmpz_mpoly_mul(pa.d, pa.d, pb.d, ctx.d);
1311 fmpz_mpoly_mul(denpa.d, denpa.d, denpb.d, ctx.d);
1313 fmpz_mpoly_get_fmpz(den.d, denpa.d, ctx.d);
1318 const bool with_arghead =
false;
1320 const bool must_fit_term =
false;
1321 const uint64_t prev_size = 0;
1322 const uint64_t mul_size = (uint64_t)flint::to_argument_mpoly(BHEAD NULL,
1323 with_arghead, must_fit_term, write, prev_size, pa.d, var_map, ctx.d, den.d);
1324 res = (WORD*)Malloc1(
sizeof(WORD)*mul_size,
"flint::mul_mpoly");
1327 flint::to_argument_mpoly(BHEAD res, with_arghead, must_fit_term, write, prev_size, pa.d,
1328 var_map, ctx.d, den.d);
1338WORD* flint::mul_poly(PHEAD
const WORD *a,
const WORD *b,
const var_map_t &var_map) {
1342 flint::from_argument_poly(pa.d, denpa.d, a,
false);
1343 flint::from_argument_poly(pb.d, denpb.d, b,
false);
1346 if ( fmpz_poly_degree(denpa.d) != 0 ) {
1347 MLOCK(ErrorMessageLock);
1348 MesPrint(
"flint::mul_poly: error: denpa is non-constant");
1349 MUNLOCK(ErrorMessageLock);
1352 if ( fmpz_poly_degree(denpb.d) != 0 ) {
1353 MLOCK(ErrorMessageLock);
1354 MesPrint(
"flint::mul_poly: error: denpb is non-constant");
1355 MUNLOCK(ErrorMessageLock);
1360 fmpz_poly_mul(pa.d, pa.d, pb.d);
1362 fmpz_poly_mul(denpa.d, denpa.d, denpb.d);
1364 fmpz_poly_get_coeff_fmpz(den.d, denpa.d, 0);
1369 const bool with_arghead =
false;
1371 const bool must_fit_term =
false;
1372 const uint64_t prev_size = 0;
1373 const uint64_t mul_size = (uint64_t)flint::to_argument_poly(BHEAD NULL,
1374 with_arghead, must_fit_term, write, prev_size, pa.d, var_map, den.d);
1375 res = (WORD*)Malloc1(
sizeof(WORD)*mul_size,
"flint::mul_poly");
1378 flint::to_argument_poly(BHEAD res, with_arghead, must_fit_term, write, prev_size, pa.d,
1389void flint::ratfun_add_mpoly(PHEAD
const WORD *t1,
const WORD *t2, WORD *out,
1390 const var_map_t &var_map) {
1393 flint::mpoly gcd(ctx.d), num1(ctx.d), den1(ctx.d), num2(ctx.d), den2(ctx.d);
1395 flint::ratfun_read_mpoly(t1, num1.d, den1.d, var_map, ctx.d);
1396 flint::ratfun_read_mpoly(t2, num2.d, den2.d, var_map, ctx.d);
1398 if ( fmpz_mpoly_cmp(den1.d, den2.d, ctx.d) != 0 ) {
1399 fmpz_mpoly_gcd_cofactors(gcd.d, den1.d, den2.d, den1.d, den2.d, ctx.d);
1401 fmpz_mpoly_mul(num1.d, num1.d, den2.d, ctx.d);
1402 fmpz_mpoly_mul(num2.d, num2.d, den1.d, ctx.d);
1404 fmpz_mpoly_add(num1.d, num1.d, num2.d, ctx.d);
1405 fmpz_mpoly_mul(den1.d, den1.d, den2.d, ctx.d);
1406 fmpz_mpoly_mul(den1.d, den1.d, gcd.d, ctx.d);
1409 fmpz_mpoly_add(num1.d, num1.d, num2.d, ctx.d);
1413 fmpz_mpoly_gcd_cofactors(gcd.d, num1.d, den1.d, num1.d, den1.d, ctx.d);
1415 flint::util::fix_sign_fmpz_mpoly_ratfun(num1.d, den1.d, ctx.d);
1418 *out++ = AR.PolyFun;
1419 WORD* args_size = out++;
1420 WORD* args_flag = out++;
1424 const bool with_arghead =
true;
1425 const bool must_fit_term =
true;
1426 const bool write =
true;
1428 out += flint::to_argument_mpoly(BHEAD out, with_arghead, must_fit_term, write, out-args_size+4,
1429 num1.d, var_map, ctx.d);
1430 out += flint::to_argument_mpoly(BHEAD out, with_arghead, must_fit_term, write, out-args_size+4,
1431 den1.d, var_map, ctx.d);
1433 *args_size = out - args_size + 1;
1434 AT.WorkPointer = out;
1441void flint::ratfun_add_poly(PHEAD
const WORD *t1,
const WORD *t2, WORD *out,
1442 const var_map_t &var_map) {
1446 flint::ratfun_read_poly(t1, num1.d, den1.d);
1447 flint::ratfun_read_poly(t2, num2.d, den2.d);
1449 if ( fmpz_poly_equal(den1.d, den2.d) == 0 ) {
1450 flint::util::simplify_fmpz_poly(den1.d, den2.d, gcd.d);
1452 fmpz_poly_mul(num1.d, num1.d, den2.d);
1453 fmpz_poly_mul(num2.d, num2.d, den1.d);
1455 fmpz_poly_add(num1.d, num1.d, num2.d);
1456 fmpz_poly_mul(den1.d, den1.d, den2.d);
1457 fmpz_poly_mul(den1.d, den1.d, gcd.d);
1460 fmpz_poly_add(num1.d, num1.d, num2.d);
1464 flint::util::simplify_fmpz_poly(num1.d, den1.d, gcd.d);
1466 flint::util::fix_sign_fmpz_poly_ratfun(num1.d, den1.d);
1469 *out++ = AR.PolyFun;
1470 WORD* args_size = out++;
1471 WORD* args_flag = out++;
1475 const bool with_arghead =
true;
1476 const bool must_fit_term =
true;
1477 const bool write =
true;
1479 out += flint::to_argument_poly(BHEAD out, with_arghead, must_fit_term, write, out-args_size+4,
1481 out += flint::to_argument_poly(BHEAD out, with_arghead, must_fit_term, write, out-args_size+4,
1484 *args_size = out - args_size + 1;
1485 AT.WorkPointer = out;
1494void flint::ratfun_normalize_mpoly(PHEAD WORD *term,
const var_map_t &var_map) {
1497 const WORD ncoeff = (term + *term)[-1];
1499 const WORD *tstop = term + *term - ABS(ncoeff);
1502 flint::mpoly num1(ctx.d), den1(ctx.d), num2(ctx.d), den2(ctx.d), gcd(ctx.d);
1506 flint::fmpz_set_form(tmpNum.d, (UWORD*)tstop, ncoeff/2);
1507 flint::fmpz_set_form(tmpDen.d, (UWORD*)tstop+ABS(ncoeff/2), ABS(ncoeff/2));
1508 fmpz_mpoly_set_fmpz(num1.d, tmpNum.d, ctx.d);
1509 fmpz_mpoly_set_fmpz(den1.d, tmpDen.d, ctx.d);
1514 WORD* term_size = term;
1516 for ( WORD *t = term + 1; t < tstop; ) {
1517 if ( *t == AR.PolyFun ) {
1518 flint::ratfun_read_mpoly(t, num2.d, den2.d, var_map, ctx.d);
1521 fmpz_mpoly_gcd_cofactors(gcd.d, num1.d, den2.d, num1.d, den2.d, ctx.d);
1522 fmpz_mpoly_gcd_cofactors(gcd.d, num2.d, den1.d, num2.d, den1.d, ctx.d);
1524 fmpz_mpoly_mul(num1.d, num1.d, num2.d, ctx.d);
1525 fmpz_mpoly_mul(den1.d, den1.d, den2.d, ctx.d);
1533 if ( s != t ) { NCOPY(s,t,i); }
1534 else { t += i; s += i; }
1538 flint::util::fix_sign_fmpz_mpoly_ratfun(num1.d, den1.d, ctx.d);
1542 *out++ = AR.PolyFun;
1543 WORD* args_size = out++;
1544 WORD* args_flag = out++;
1545 *args_flag &= ~MUSTCLEANPRF;
1547 const bool with_arghead =
true;
1548 const bool must_fit_term =
true;
1549 const bool write =
true;
1550 out += flint::to_argument_mpoly(BHEAD out, with_arghead, must_fit_term, write, out-term_size,
1551 num1.d, var_map, ctx.d);
1552 out += flint::to_argument_mpoly(BHEAD out, with_arghead, must_fit_term, write, out-term_size,
1553 den1.d, var_map, ctx.d);
1555 *args_size = out - args_size + 1;
1558 if (
sizeof(WORD)*(out-term_size+3) > (
size_t)AM.MaxTer ) {
1559 MLOCK(ErrorMessageLock);
1560 MesPrint(
"flint::ratfun_normalize: output exceeds MaxTermSize");
1561 MUNLOCK(ErrorMessageLock);
1569 *term_size = out - term_size;
1577void flint::ratfun_normalize_poly(PHEAD WORD *term,
const var_map_t &var_map) {
1580 const WORD ncoeff = (term + *term)[-1];
1582 const WORD *tstop = term + *term - ABS(ncoeff);
1588 flint::fmpz_set_form(tmpNum.d, (UWORD*)tstop, ncoeff/2);
1589 flint::fmpz_set_form(tmpDen.d, (UWORD*)tstop+ABS(ncoeff/2), ABS(ncoeff/2));
1590 fmpz_poly_set_fmpz(num1.d, tmpNum.d);
1591 fmpz_poly_set_fmpz(den1.d, tmpDen.d);
1596 WORD* term_size = term;
1598 for ( WORD *t = term + 1; t < tstop; ) {
1599 if ( *t == AR.PolyFun ) {
1600 flint::ratfun_read_poly(t, num2.d, den2.d);
1603 flint::util::simplify_fmpz_poly(num1.d, den2.d, gcd.d);
1604 flint::util::simplify_fmpz_poly(num2.d, den1.d, gcd.d);
1606 fmpz_poly_mul(num1.d, num1.d, num2.d);
1607 fmpz_poly_mul(den1.d, den1.d, den2.d);
1615 if ( s != t ) { NCOPY(s,t,i); }
1616 else { t += i; s += i; }
1620 flint::util::fix_sign_fmpz_poly_ratfun(num1.d, den1.d);
1624 *out++ = AR.PolyFun;
1625 WORD* args_size = out++;
1626 WORD* args_flag = out++;
1627 *args_flag &= ~MUSTCLEANPRF;
1629 const bool with_arghead =
true;
1630 const bool must_fit_term =
true;
1631 const bool write =
true;
1632 out += flint::to_argument_poly(BHEAD out, with_arghead, must_fit_term, write, out-term_size,
1634 out += flint::to_argument_poly(BHEAD out, with_arghead, must_fit_term, write, out-term_size,
1637 *args_size = out - args_size + 1;
1640 if (
sizeof(WORD)*(out-term_size+3) > (
size_t)AM.MaxTer ) {
1641 MLOCK(ErrorMessageLock);
1642 MesPrint(
"flint::ratfun_normalize: output exceeds MaxTermSize");
1643 MUNLOCK(ErrorMessageLock);
1651 *term_size = out - term_size;
1660void flint::ratfun_read_mpoly(
const WORD *a, fmpz_mpoly_t num, fmpz_mpoly_t den,
1661 const var_map_t &var_map, fmpz_mpoly_ctx_t ctx) {
1664 const WORD* arg_stop = a+a[1];
1666 const bool must_normalize = (a[2] & MUSTCLEANPRF) != 0;
1669 if ( a >= arg_stop ) {
1670 MLOCK(ErrorMessageLock);
1671 MesPrint(
"ERROR: PolyRatFun cannot have zero arguments");
1672 MUNLOCK(ErrorMessageLock);
1681 flint::from_argument_mpoly(num, den_num.d, a,
true, var_map, ctx);
1684 if ( a < arg_stop ) {
1686 flint::from_argument_mpoly(den, den_den.d, a,
true, var_map, ctx);
1691 MLOCK(ErrorMessageLock);
1692 MesPrint(
"implement this");
1693 MUNLOCK(ErrorMessageLock);
1696 if ( a < arg_stop ) {
1697 MLOCK(ErrorMessageLock);
1698 MesPrint(
"ERROR: PolyRatFun cannot have more than two arguments");
1699 MUNLOCK(ErrorMessageLock);
1704 fmpz_mpoly_mul(num, num, den_den.d, ctx);
1705 fmpz_mpoly_mul(den, den, den_num.d, ctx);
1707 if ( must_normalize ) {
1709 fmpz_mpoly_gcd_cofactors(gcd.d, num, den, num, den, ctx);
1718void flint::ratfun_read_poly(
const WORD *a, fmpz_poly_t num, fmpz_poly_t den) {
1721 const WORD* arg_stop = a+a[1];
1723 const bool must_normalize = (a[2] & MUSTCLEANPRF) != 0;
1726 if ( a >= arg_stop ) {
1727 MLOCK(ErrorMessageLock);
1728 MesPrint(
"ERROR: PolyRatFun cannot have zero arguments");
1729 MUNLOCK(ErrorMessageLock);
1738 flint::from_argument_poly(num, den_num.d, a,
true);
1741 if ( a < arg_stop ) {
1743 flint::from_argument_poly(den, den_den.d, a,
true);
1748 MLOCK(ErrorMessageLock);
1749 MesPrint(
"implement this");
1750 MUNLOCK(ErrorMessageLock);
1753 if ( a < arg_stop ) {
1754 MLOCK(ErrorMessageLock);
1755 MesPrint(
"ERROR: PolyRatFun cannot have more than two arguments");
1756 MUNLOCK(ErrorMessageLock);
1761 fmpz_poly_mul(num, num, den_den.d);
1762 fmpz_poly_mul(den, den, den_num.d);
1764 if ( must_normalize ) {
1766 flint::util::simplify_fmpz_poly(num, den, gcd.d);
1779#define IFW(x) { if ( write ) {x;} }
1780uint64_t flint::to_argument_mpoly(PHEAD WORD *out,
const bool with_arghead,
1781 const bool must_fit_term,
const bool write,
const uint64_t prev_size,
const fmpz_mpoly_t
poly,
1782 const var_map_t &var_map,
const fmpz_mpoly_ctx_t ctx,
const fmpz_t denscale) {
1785 const WORD* out_entry = out;
1792 if ( write && must_fit_term && (
sizeof(WORD)*(prev_size + ARGHEAD) > (
size_t)AM.MaxTer) ) {
1793 MLOCK(ErrorMessageLock);
1794 MesPrint(
"flint::to_argument_mpoly: output exceeds MaxTermSize");
1795 MUNLOCK(ErrorMessageLock);
1800 var_map_t var_map_inv;
1801 for (
auto x: var_map ) {
1802 var_map_inv[x.second] = x.first;
1805 vector<int64_t> exponents(var_map.size());
1806 const int64_t n_terms = fmpz_mpoly_length(
poly, ctx);
1808 if ( n_terms == 0 ) {
1809 if ( with_arghead ) {
1810 IFW(*out++ = -SNUMBER); ws++;
1811 IFW(*out++ = 0); ws++;
1815 IFW(*out++ = 0); ws++;
1824 if ( with_arghead && n_terms == 1 ) {
1826 if ( fmpz_mpoly_is_fmpz(
poly, ctx) ) {
1829 fmpz_mpoly_get_term_coeff_fmpz(coeff.d,
poly, 0, ctx);
1830 fmpz_set(den.d, denscale);
1831 flint::util::simplify_fmpz(coeff.d, den.d, gcd.d);
1833 if ( fmpz_is_one(den.d) && fmpz_fits_si(coeff.d) ) {
1834 const int64_t fast_coeff = fmpz_get_si(coeff.d);
1836 if ( fast_coeff > INT32_MIN && fast_coeff <= INT32_MAX ) {
1837 IFW(*out++ = -SNUMBER); ws++;
1838 IFW(*out++ = (WORD)fast_coeff); ws++;
1845 fmpz_mpoly_get_term_coeff_fmpz(coeff.d,
poly, 0, ctx);
1846 fmpz_set(den.d, denscale);
1847 flint::util::simplify_fmpz(coeff.d, den.d, gcd.d);
1849 if ( fmpz_is_one(coeff.d) && fmpz_is_one(den.d) ) {
1852 fmpz_mpoly_get_term_exp_si((slong*)exponents.data(),
poly, 0, ctx);
1853 int64_t use_fast = 0;
1854 uint32_t fast_symbol = 0;
1856 for (
size_t i = 0; i < var_map.size(); i++ ) {
1857 if ( exponents[i] == 1 ) fast_symbol = var_map_inv[i];
1858 use_fast += exponents[i];
1862 if ( use_fast == 1 ) {
1863 IFW(*out++ = -SYMBOL); ws++;
1864 IFW(*out++ = fast_symbol); ws++;
1872 WORD *tmp_coeff = (WORD *)NumberMalloc(
"flint::to_argument_mpoly");
1873 WORD *tmp_den = (WORD *)NumberMalloc(
"flint::to_argument_mpoly");
1877 if ( with_arghead ) {
1878 IFW(arg_size = out++); ws++;
1879 IFW(arg_flag = out++); ws++;
1883 for ( int64_t i = 0; i < n_terms; i++ ) {
1885 fmpz_mpoly_get_term_exp_si((slong*)exponents.data(),
poly, i, ctx);
1887 fmpz_mpoly_get_term_coeff_fmpz(coeff.d,
poly, i, ctx);
1888 fmpz_set(den.d, denscale);
1889 flint::util::simplify_fmpz(coeff.d, den.d, gcd.d);
1891 uint32_t num_symbols = 0;
1892 for (
size_t j = 0; j < var_map.size(); j++ ) {
1893 if ( exponents[j] != 0 ) { num_symbols += 1; }
1897 const WORD num_size = flint::fmpz_get_form(coeff.d, tmp_coeff);
1898 const WORD den_size = flint::fmpz_get_form(den.d, tmp_den);
1899 const WORD coeff_size = [num_size, den_size] () -> WORD {
1900 WORD size = ABS(num_size) > ABS(den_size) ? ABS(num_size) : ABS(den_size);
1901 return size * SGN(num_size) * SGN(den_size);
1906 uint64_t current_size = prev_size + ws + 1 + 2*ABS(coeff_size) + 1;
1907 if ( num_symbols ) {
1909 current_size += 2 + 2*num_symbols;
1911 if ( write && must_fit_term && (
sizeof(WORD)*current_size > (
size_t)AM.MaxTer) ) {
1912 MLOCK(ErrorMessageLock);
1913 MesPrint(
"flint::to_argument_mpoly: output exceeds MaxTermSize");
1914 MUNLOCK(ErrorMessageLock);
1918 WORD* term_size = 0;
1919 IFW(term_size = out++); ws++;
1920 if ( num_symbols ) {
1921 IFW(*out++ = SYMBOL); ws++;
1922 WORD* symbol_size = 0;
1923 IFW(symbol_size = out++); ws++;
1924 IFW(*symbol_size = 2);
1926 for (
size_t j = 0; j < var_map.size(); j++ ) {
1927 if ( exponents[j] != 0 ) {
1928 IFW(*out++ = var_map_inv[j]); ws++;
1929 IFW(*out++ = exponents[j]); ws++;
1930 IFW(*symbol_size += 2);
1936 for ( WORD j = 0; j < ABS(num_size); j++ ) {
1937 IFW(*out++ = tmp_coeff[j]); ws++;
1939 for ( WORD j = ABS(num_size); j < ABS(coeff_size); j++ ) {
1940 IFW(*out++ = 0); ws++;
1943 for ( WORD j = 0; j < ABS(den_size); j++ ) {
1944 IFW(*out++ = tmp_den[j]); ws++;
1946 for ( WORD j = ABS(den_size); j < ABS(coeff_size); j++ ) {
1947 IFW(*out++ = 0); ws++;
1950 IFW(*out = 2*ABS(coeff_size) + 1);
1951 IFW(
if ( coeff_size < 0 ) { *out = -(*out); });
1954 IFW(*term_size = out - term_size);
1957 if ( with_arghead ) {
1958 IFW(*arg_size = out - arg_size);
1961 flint::form_sort(BHEAD (WORD*)(out_entry));
1966 IFW(*out++ = 0); ws++;
1969 NumberFree(tmp_coeff,
"flint::to_argument_mpoly");
1970 NumberFree(tmp_den,
"flint::to_argument_mpoly");
1976uint64_t flint::to_argument_mpoly(PHEAD WORD *out,
const bool with_arghead,
1977 const bool must_fit_term,
const bool write,
const uint64_t prev_size,
const fmpz_mpoly_t
poly,
1978 const var_map_t &var_map,
const fmpz_mpoly_ctx_t ctx) {
1981 fmpz_set_ui(tmp.d, 1);
1983 uint64_t ret = flint::to_argument_mpoly(BHEAD out, with_arghead, must_fit_term, write,
1984 prev_size,
poly, var_map, ctx, tmp.d);
1998uint64_t flint::to_argument_poly(PHEAD WORD *out,
const bool with_arghead,
1999 const bool must_fit_term,
const bool write,
const uint64_t prev_size,
const fmpz_poly_t
poly,
2000 const var_map_t &var_map,
const fmpz_t denscale) {
2007 if ( write && must_fit_term && (
sizeof(WORD)*(prev_size + ARGHEAD) > (
size_t)AM.MaxTer) ) {
2008 MLOCK(ErrorMessageLock);
2009 MesPrint(
"flint::to_argument_poly: output exceeds MaxTermSize");
2010 MUNLOCK(ErrorMessageLock);
2015 var_map_t var_map_inv;
2016 for (
auto x: var_map ) {
2017 var_map_inv[x.second] = x.first;
2020 const int64_t n_terms = fmpz_poly_length(
poly);
2023 if ( n_terms == 0 ) {
2024 if ( with_arghead ) {
2025 IFW(*out++ = -SNUMBER); ws++;
2026 IFW(*out++ = 0); ws++;
2030 IFW(*out++ = 0); ws++;
2039 if ( with_arghead && n_terms == 1 ) {
2041 fmpz_poly_get_coeff_fmpz(coeff.d,
poly, 0);
2042 fmpz_set(den.d, denscale);
2043 flint::util::simplify_fmpz(coeff.d, den.d, gcd.d);
2045 if ( fmpz_is_one(den.d) && fmpz_fits_si(coeff.d) ) {
2046 const long fast_coeff = fmpz_get_si(coeff.d);
2048 if ( fast_coeff > INT_MIN && fast_coeff <= INT_MAX ) {
2049 IFW(*out++ = -SNUMBER); ws++;
2050 IFW(*out++ = (WORD)fast_coeff); ws++;
2057 if ( with_arghead && n_terms == 2 ) {
2058 if ( fmpz_is_zero(fmpz_poly_get_coeff_ptr(
poly, 0)) ) {
2061 fmpz_poly_get_coeff_fmpz(coeff.d,
poly, 1);
2062 fmpz_set(den.d, denscale);
2063 flint::util::simplify_fmpz(coeff.d, den.d, gcd.d);
2065 if ( fmpz_is_one(coeff.d) && fmpz_is_one(den.d) ) {
2067 IFW(*out++ = -SYMBOL); ws++;
2068 IFW(*out++ = var_map_inv[0]); ws++;
2074 WORD *tmp_coeff = (WORD *)NumberMalloc(
"flint::to_argument_poly");
2075 WORD *tmp_den = (WORD *)NumberMalloc(
"flint::to_argument_mpoly");
2079 if ( with_arghead ) {
2080 IFW(arg_size = out++); ws++;
2081 IFW(arg_flag = out++); ws++;
2086 for ( int64_t i = n_terms-1; i >= 0; i-- ) {
2089 if ( !fmpz_is_zero(fmpz_poly_get_coeff_ptr(
poly, i)) ) {
2091 fmpz_poly_get_coeff_fmpz(coeff.d,
poly, i);
2092 fmpz_set(den.d, denscale);
2093 flint::util::simplify_fmpz(coeff.d, den.d, gcd.d);
2096 const WORD num_size = flint::fmpz_get_form(coeff.d, tmp_coeff);
2097 const WORD den_size = flint::fmpz_get_form(den.d, tmp_den);
2098 const WORD coeff_size = [num_size, den_size] () -> WORD {
2099 WORD size = ABS(num_size) > ABS(den_size) ? ABS(num_size) : ABS(den_size);
2100 return size * SGN(num_size) * SGN(den_size);
2106 uint64_t current_size = prev_size + ws + 1 + 2*ABS(coeff_size) + 1;
2111 if ( write && must_fit_term && (
sizeof(WORD)*current_size > (
size_t)AM.MaxTer) ) {
2112 MLOCK(ErrorMessageLock);
2113 MesPrint(
"flint::to_argument_poly: output exceeds MaxTermSize");
2114 MUNLOCK(ErrorMessageLock);
2118 WORD* term_size = 0;
2119 IFW(term_size = out++); ws++;
2122 IFW(*out++ = SYMBOL); ws++;
2123 IFW(*out++ = 4); ws++;
2124 IFW(*out++ = var_map_inv[0]); ws++;
2125 IFW(*out++ = i); ws++;
2129 for ( WORD j = 0; j < ABS(num_size); j++ ) {
2130 IFW(*out++ = tmp_coeff[j]); ws++;
2132 for ( WORD j = ABS(num_size); j < ABS(coeff_size); j++ ) {
2133 IFW(*out++ = 0); ws++;
2136 for ( WORD j = 0; j < ABS(den_size); j++ ) {
2137 IFW(*out++ = tmp_den[j]); ws++;
2139 for ( WORD j = ABS(den_size); j < ABS(coeff_size); j++ ) {
2140 IFW(*out++ = 0); ws++;
2143 IFW(*out = 2*ABS(coeff_size) + 1);
2144 IFW(
if ( coeff_size < 0 ) { *out = -(*out); });
2147 IFW(*term_size = out - term_size);
2152 if ( with_arghead ) {
2153 IFW(*arg_size = out - arg_size);
2157 IFW(*out++ = 0); ws++;
2160 NumberFree(tmp_coeff,
"flint::to_argument_poly");
2161 NumberFree(tmp_den,
"flint::to_argument_poly");
2167uint64_t flint::to_argument_poly(PHEAD WORD *out,
const bool with_arghead,
2168 const bool must_fit_term,
const bool write,
const uint64_t prev_size,
const fmpz_poly_t
poly,
2169 const var_map_t &var_map) {
2172 fmpz_set_ui(tmp.d, 1);
2174 uint64_t ret = flint::to_argument_poly(BHEAD out, with_arghead, must_fit_term, write, prev_size,
2175 poly, var_map, tmp.d);
2188inline void flint::util::simplify_fmpz(fmpz_t num, fmpz_t den, fmpz_t gcd) {
2189 fmpz_gcd(gcd, num, den);
2190 if ( !fmpz_is_one(gcd) ) {
2191 fmpz_divexact(num, num, gcd);
2192 fmpz_divexact(den, den, gcd);
2200inline void flint::util::simplify_fmpz_poly(fmpz_poly_t num, fmpz_poly_t den, fmpz_poly_t gcd) {
2201 fmpz_poly_gcd(gcd, num, den);
2202 if ( !fmpz_poly_is_one(gcd) ) {
2203#if __FLINT_RELEASE >= 30100
2205 fmpz_poly_divexact(num, num, gcd);
2206 fmpz_poly_divexact(den, den, gcd);
2208 fmpz_poly_div(num, num, gcd);
2209 fmpz_poly_div(den, den, gcd);
2217inline void flint::util::fix_sign_fmpz_mpoly_ratfun(fmpz_mpoly_t num, fmpz_mpoly_t den,
2218 const fmpz_mpoly_ctx_t ctx) {
2220 if ( fmpz_sgn(fmpz_mpoly_term_coeff_ref(den, 0, ctx)) == -1 ) {
2221 fmpz_mpoly_neg(num, num, ctx);
2222 fmpz_mpoly_neg(den, den, ctx);
2229inline void flint::util::fix_sign_fmpz_poly_ratfun(fmpz_poly_t num, fmpz_poly_t den) {
2231 if ( fmpz_sgn(fmpz_poly_get_coeff_ptr(den, fmpz_poly_degree(den))) == -1 ) {
2232 fmpz_poly_neg(num, num);
2233 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 *)