1 /*
2     Copyright (C) 2020 Daniel Schultz
3 
4     This file is part of FLINT.
5 
6     FLINT is free software: you can redistribute it and/or modify it under
7     the terms of the GNU Lesser General Public License (LGPL) as published
8     by the Free Software Foundation; either version 2.1 of the License, or
9     (at your option) any later version.  See <https://www.gnu.org/licenses/>.
10 */
11 
12 #include "fmpz_mpoly_factor.h"
13 
check_omega(slong lower,slong upper,const fmpz_mpoly_t p,const fmpz_mpoly_ctx_t ctx)14 void check_omega(slong lower, slong upper, const fmpz_mpoly_t p, const fmpz_mpoly_ctx_t ctx)
15 {
16     slong i;
17     fmpz_mpoly_t q;
18     fmpz_mpoly_factor_t g, h;
19     fmpz_t omega;
20 
21     fmpz_init(omega);
22     fmpz_mpoly_factor_init(g, ctx);
23     fmpz_mpoly_factor_init(h, ctx);
24     fmpz_mpoly_init(q, ctx);
25 
26     if (!fmpz_mpoly_factor_wang(g, p, ctx))
27     {
28         flint_printf("check factorization 1 could be computed\n");
29         flint_abort();
30     }
31 
32     if (!fmpz_mpoly_factor(h, p, ctx))
33     {
34         flint_printf("check factorization 2 could be computed\n");
35         flint_abort();
36     }
37 
38     for (i = 0; i < g->num; i++)
39     {
40         if (g->poly[i].length < 1 || fmpz_sgn(g->poly[i].coeffs + 0) <= 0)
41         {
42             flint_printf("factorization is not unit normal\n");
43             flint_abort();
44         }
45     }
46 
47     fmpz_zero(omega);
48     for (i = 0; i < g->num; i++)
49         fmpz_add(omega, omega, g->exp + i);
50 
51     if (fmpz_cmp_si(omega, lower) < 0 || fmpz_cmp_si(omega, upper) > 0)
52     {
53         flint_printf("factorization has wrong number of factors\n");
54         flint_abort();
55     }
56 
57     fmpz_mpoly_factor_expand(q, g, ctx);
58 
59     if (!fmpz_mpoly_equal(q, p, ctx))
60     {
61         flint_printf("factorization does not match original polynomial\n");
62         flint_abort();
63     }
64 
65     fmpz_mpoly_factor_sort(g, ctx);
66     fmpz_mpoly_factor_sort(h, ctx);
67     if (fmpz_mpoly_factor_cmp(g, h, ctx) != 0)
68     {
69         flint_printf("factorizations do not match\n");
70         flint_abort();
71     }
72 
73     for (i = 0; i < g->num; i++)
74     {
75         fmpz_mpoly_factor(h, g->poly + i, ctx);
76         if (h->num != 1 || !fmpz_is_one(h->exp + 0))
77         {
78             flint_printf("FAIL:\nfactor is reducible\n");
79             flint_abort();
80         }
81     }
82 
83     fmpz_mpoly_clear(q, ctx);
84     fmpz_mpoly_factor_clear(g, ctx);
85     fmpz_mpoly_factor_clear(h, ctx);
86     fmpz_clear(omega);
87     return;
88 }
89 
90 
91 int
main(void)92 main(void)
93 {
94     slong i, j, tmul = 20;
95 
96     FLINT_TEST_INIT(state);
97 
98     flint_printf("factor_wang....");
99     fflush(stdout);
100 
101     for (i = 0; i < tmul * flint_test_multiplier(); i++)
102     {
103         slong lower;
104         fmpz_mpoly_ctx_t ctx;
105         fmpz_mpoly_t a, at, t;
106         flint_bitcnt_t coeff_bits;
107         slong nfacs, len;
108         ulong expbound, powbound, pow;
109 
110         fmpz_mpoly_ctx_init_rand(ctx, state, 6);
111 
112         fmpz_mpoly_init(a, ctx);
113         fmpz_mpoly_init(at, ctx);
114         fmpz_mpoly_init(t, ctx);
115 
116         nfacs = 1 + (4 + n_randint(state, 5))/ctx->minfo->nvars;
117         expbound = 2 + 25/nfacs/ctx->minfo->nvars;
118         powbound = 1 + n_randint(state, 3);
119 
120         lower = 0;
121         fmpz_mpoly_one(a, ctx);
122         for (j = 0; j < nfacs; j++)
123         {
124             do {
125                 len = 2 + n_randint(state, 10);
126                 coeff_bits = 100 + n_randint(state, 300)/nfacs;
127                 fmpz_mpoly_randtest_bound(t, state, len, coeff_bits, expbound, ctx);
128             } while (t->length == 0);
129             pow = 1 + n_randint(state, powbound);
130 
131             fmpz_mpoly_pow_ui(t, t, pow, ctx);
132             fmpz_mpoly_mul(at, a, t, ctx);
133 
134             if (t->length < 200)
135             {
136                 fmpz_mpoly_swap(a, at, ctx);
137                 if (!fmpz_mpoly_is_fmpz(t, ctx))
138                     lower += pow;
139             }
140         }
141 
142         check_omega(lower, WORD_MAX, a, ctx);
143 
144         fmpz_mpoly_clear(t, ctx);
145         fmpz_mpoly_clear(at, ctx);
146         fmpz_mpoly_clear(a, ctx);
147         fmpz_mpoly_ctx_clear(ctx);
148     }
149 
150     FLINT_TEST_CLEANUP(state);
151 
152     flint_printf("PASS\n");
153     return 0;
154 }
155