1 /*
2     Copyright (C) 2018 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 <http://www.gnu.org/licenses/>.
10 */
11 
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include "fmpz_mpoly.h"
15 
16 int
main(void)17 main(void)
18 {
19     slong i, j, v;
20     FLINT_TEST_INIT(state);
21 
22     flint_printf("compose_fmpz_mpoly....");
23     fflush(stdout);
24 
25     {
26         fmpz_mpoly_t A, A1, A2, B;
27         fmpz_mpoly_struct * Cp[3];
28         fmpz_mpoly_struct C[3];
29         fmpz_mpoly_ctx_t ctxAC, ctxB;
30 
31         fmpz_mpoly_ctx_init(ctxB, 3, ORD_LEX);
32         fmpz_mpoly_ctx_init(ctxAC, 2, ORD_LEX);
33 
34         fmpz_mpoly_init(B, ctxB);
35         fmpz_mpoly_init(A, ctxAC);
36         fmpz_mpoly_init(A1, ctxAC);
37         fmpz_mpoly_init(A2, ctxAC);
38         for (i = 0; i < 3; i++)
39         {
40             Cp[i] = C + i;
41             fmpz_mpoly_init(C + i, ctxAC);
42         }
43 
44         fmpz_mpoly_set_str_pretty(B,
45                 "1 + x1*x2^2 + x2^9999999999999999999999999*x3^9", NULL, ctxB);
46 
47         fmpz_mpoly_set_str_pretty(C + 0, "x1 + x2", NULL, ctxAC);
48         fmpz_mpoly_set_str_pretty(C + 1, "x1 - x2", NULL, ctxAC);
49         fmpz_mpoly_set_str_pretty(C + 2, "1", NULL, ctxAC);
50         if (fmpz_mpoly_compose_fmpz_mpoly(A, B, Cp, ctxB, ctxAC) ||
51             fmpz_mpoly_compose_fmpz_mpoly_horner(A1, B, Cp, ctxB, ctxAC) ||
52             fmpz_mpoly_compose_fmpz_mpoly_geobucket(A2, B, Cp, ctxB, ctxAC))
53         {
54             printf("FAIL\n");
55             flint_printf("Check non-example 1\n", i);
56             flint_abort();
57         }
58 
59         fmpz_mpoly_set_str_pretty(C + 0, "x1", NULL, ctxAC);
60         fmpz_mpoly_set_str_pretty(C + 1, "2*x2", NULL, ctxAC);
61         fmpz_mpoly_set_str_pretty(C + 2, "1", NULL, ctxAC);
62         if (fmpz_mpoly_compose_fmpz_mpoly(A, B, Cp, ctxB, ctxAC) ||
63             fmpz_mpoly_compose_fmpz_mpoly_horner(A1, B, Cp, ctxB, ctxAC) ||
64             fmpz_mpoly_compose_fmpz_mpoly_geobucket(A2, B, Cp, ctxB, ctxAC))
65         {
66             printf("FAIL\n");
67             flint_printf("Check non-example 2\n", i);
68             flint_abort();
69         }
70 
71         fmpz_mpoly_set_str_pretty(C + 0, "2*x1", NULL, ctxAC);
72         fmpz_mpoly_set_str_pretty(C + 1, "x2", NULL, ctxAC);
73         fmpz_mpoly_set_str_pretty(C + 2, "1", NULL, ctxAC);
74         if (!fmpz_mpoly_compose_fmpz_mpoly(A, B, Cp, ctxB, ctxAC) ||
75             !fmpz_mpoly_compose_fmpz_mpoly_horner(A1, B, Cp, ctxB, ctxAC) ||
76             !fmpz_mpoly_compose_fmpz_mpoly_geobucket(A2, B, Cp, ctxB, ctxAC))
77         {
78             printf("FAIL\n");
79             flint_printf("Check example 3\n", i);
80             flint_abort();
81         }
82 
83         fmpz_mpoly_clear(B, ctxB);
84         fmpz_mpoly_clear(A, ctxAC);
85         fmpz_mpoly_clear(A1, ctxAC);
86         fmpz_mpoly_clear(A2, ctxAC);
87         for (i = 0; i < 3; i++)
88             fmpz_mpoly_clear(C + i, ctxAC);
89 
90         fmpz_mpoly_ctx_clear(ctxB);
91         fmpz_mpoly_ctx_clear(ctxAC);
92     }
93 
94     /* check composition with generators */
95     for (i = 0; i < 20*flint_test_multiplier(); i++)
96     {
97         fmpz_mpoly_ctx_t ctxB, ctxAC;
98         fmpz_mpoly_t B, A, A1, A2, A3;
99         fmpz_mpoly_struct ** C;
100         slong * c;
101         slong nvarsB, nvarsAC;
102         slong len;
103         flint_bitcnt_t exp_bits, coeff_bits;
104 
105         fmpz_mpoly_ctx_init_rand(ctxB, state, 20);
106         fmpz_mpoly_ctx_init_rand(ctxAC, state, 20);
107 
108         nvarsB = ctxB->minfo->nvars;
109         nvarsAC = ctxAC->minfo->nvars;
110 
111         fmpz_mpoly_init(B, ctxB);
112         fmpz_mpoly_init(A, ctxAC);
113         fmpz_mpoly_init(A1, ctxAC);
114         fmpz_mpoly_init(A2, ctxAC);
115         fmpz_mpoly_init(A3, ctxAC);
116 
117         c = (slong *) flint_malloc(nvarsB*sizeof(slong));
118         C = (fmpz_mpoly_struct **) flint_malloc(nvarsB * sizeof(fmpz_mpoly_struct *));
119         for (v = 0; v < nvarsB; v++)
120         {
121             C[v] = (fmpz_mpoly_struct *) flint_malloc(sizeof(fmpz_mpoly_struct));
122             fmpz_mpoly_init(C[v], ctxAC);
123         }
124 
125         for (j = 0; j < 4; j++)
126         {
127             len = n_randint(state, 200);
128             exp_bits = n_randint(state, 100) + 1;
129             coeff_bits = n_randint(state, 100) + 1;
130 
131             for (v = 0; v < nvarsB; v++)
132             {
133                 c[v] = n_randint(state, nvarsAC + 2) - 2;
134                 if (c[v] >= 0)
135                     fmpz_mpoly_gen(C[v], c[v], ctxAC);
136                 else
137                     fmpz_mpoly_zero(C[v], ctxAC);
138             }
139 
140             fmpz_mpoly_randtest_bits(B, state, len, coeff_bits, exp_bits, ctxB);
141 
142             fmpz_mpoly_compose_fmpz_mpoly_gen(A, B, c, ctxB, ctxAC);
143 
144             if (!fmpz_mpoly_compose_fmpz_mpoly(A1, B, C, ctxB, ctxAC) ||
145                 !fmpz_mpoly_compose_fmpz_mpoly_horner(A2, B, C, ctxB, ctxAC) ||
146                 !fmpz_mpoly_compose_fmpz_mpoly_geobucket(A3, B, C, ctxB, ctxAC))
147             {
148                 printf("FAIL\n");
149                 flint_printf("Check composition success with generators\n"
150                                                      "i: %wd, j: %wd\n", i, j);
151                 flint_abort();
152             }
153 
154             if (!fmpz_mpoly_equal(A, A1, ctxAC) ||
155                 !fmpz_mpoly_equal(A, A2, ctxAC) ||
156                 !fmpz_mpoly_equal(A, A3, ctxAC))
157             {
158                 printf("FAIL\n");
159                 flint_printf("Check composition with generators\n"
160                                                      "i: %wd, j: %wd\n", i, j);
161                 flint_abort();
162             }
163 
164             fmpz_mpoly_assert_canonical(A, ctxAC);
165             fmpz_mpoly_assert_canonical(A1, ctxAC);
166             fmpz_mpoly_assert_canonical(A2, ctxAC);
167             fmpz_mpoly_assert_canonical(A3, ctxAC);
168         }
169 
170         for (v = 0; v < nvarsB; v++)
171         {
172             fmpz_mpoly_clear(C[v], ctxAC);
173             flint_free(C[v]);
174         }
175         flint_free(C);
176         flint_free(c);
177 
178         fmpz_mpoly_clear(B, ctxB);
179         fmpz_mpoly_clear(A, ctxAC);
180         fmpz_mpoly_clear(A1, ctxAC);
181         fmpz_mpoly_clear(A2, ctxAC);
182         fmpz_mpoly_clear(A3, ctxAC);
183 
184         fmpz_mpoly_ctx_clear(ctxB);
185         fmpz_mpoly_ctx_clear(ctxAC);
186     }
187 
188     /* Check composition with identity */
189     for (i = 0; i < 20*flint_test_multiplier(); i++)
190     {
191         slong len1;
192         flint_bitcnt_t exp_bits, coeff_bits;
193         fmpz_mpoly_struct ** vals1;
194         fmpz_mpoly_t f, g, g1, g2;
195         fmpz_mpoly_ctx_t ctx;
196 
197         fmpz_mpoly_ctx_init_rand(ctx, state, 10);
198 
199         vals1 = (fmpz_mpoly_struct **) flint_malloc(ctx->minfo->nvars*
200                                                   sizeof(fmpz_mpoly_struct *));
201         for (v = 0; v < ctx->minfo->nvars; v++)
202         {
203             vals1[v] = (fmpz_mpoly_struct *) flint_malloc(sizeof(fmpz_mpoly_struct));
204             fmpz_mpoly_init(vals1[v], ctx);
205             fmpz_mpoly_gen(vals1[v], v, ctx);
206         }
207 
208         fmpz_mpoly_init(f, ctx);
209         fmpz_mpoly_init(g, ctx);
210         fmpz_mpoly_init(g1, ctx);
211         fmpz_mpoly_init(g2, ctx);
212 
213         len1 = n_randint(state, 200);
214         exp_bits = n_randint(state, 100) + 1;
215         coeff_bits = n_randint(state, 100) + 1;
216         fmpz_mpoly_randtest_bits(f, state, len1, coeff_bits, exp_bits, ctx);
217 
218         if (!fmpz_mpoly_compose_fmpz_mpoly(g, f, vals1, ctx, ctx) ||
219             !fmpz_mpoly_compose_fmpz_mpoly_horner(g1, f, vals1, ctx, ctx) ||
220             !fmpz_mpoly_compose_fmpz_mpoly_geobucket(g2, f, vals1, ctx, ctx) ||
221             !fmpz_mpoly_equal(g, g1, ctx) ||
222             !fmpz_mpoly_equal(g, g2, ctx))
223         {
224             printf("FAIL\n");
225             flint_printf("Check composition success\ni: %wd\n", i);
226             flint_abort();
227         }
228 
229         fmpz_mpoly_assert_canonical(g, ctx);
230         fmpz_mpoly_assert_canonical(g1, ctx);
231         fmpz_mpoly_assert_canonical(g2, ctx);
232 
233         if (!fmpz_mpoly_equal(f, g, ctx))
234         {
235             printf("FAIL\n");
236             flint_printf("Check composition with identity\ni: %wd\n", i);
237             flint_abort();
238         }
239 
240         fmpz_mpoly_clear(f, ctx);
241         fmpz_mpoly_clear(g, ctx);
242         fmpz_mpoly_clear(g1, ctx);
243         fmpz_mpoly_clear(g2, ctx);
244 
245         for (v = 0; v < ctx->minfo->nvars; v++)
246         {
247             fmpz_mpoly_clear(vals1[v], ctx);
248             flint_free(vals1[v]);
249         }
250         flint_free(vals1);
251 
252         fmpz_mpoly_ctx_clear(ctx);
253     }
254 
255     /* Check composition and evalall commute */
256     for (i = 0; i < 50 * flint_test_multiplier(); i++)
257     {
258         fmpz_mpoly_ctx_t ctx1, ctx2;
259         fmpz_mpoly_t f, g, g1, g2;
260         fmpz_mpoly_struct ** vals1;
261         fmpz_t fe, ge;
262         fmpz ** vals2, ** vals3;
263         slong nvars1, nvars2;
264         slong len1, len2;
265         slong exp_bound1, exp_bound2;
266         slong coeff_bits1, coeff_bits2;
267 
268         fmpz_mpoly_ctx_init_rand(ctx1, state, 6);
269         fmpz_mpoly_ctx_init_rand(ctx2, state, 6);
270 
271         nvars1 = ctx1->minfo->nvars;
272         nvars2 = ctx2->minfo->nvars;
273 
274         fmpz_mpoly_init(f, ctx1);
275         fmpz_mpoly_init(g, ctx2);
276         fmpz_mpoly_init(g1, ctx2);
277         fmpz_mpoly_init(g2, ctx2);
278         fmpz_init(fe);
279         fmpz_init(ge);
280 
281         len1 = n_randint(state, 50/nvars1 + 1) + 1;
282         len2 = n_randint(state, 10/nvars2 + 1) + 1;
283         exp_bound1 = n_randint(state, 15/nvars1 + 2) + 2;
284         exp_bound2 = n_randint(state, 15/nvars2 + 2) + 3;
285         coeff_bits1 = n_randint(state, 200);
286         coeff_bits2 = n_randint(state, 8);
287 
288         vals1 = (fmpz_mpoly_struct **) flint_malloc(nvars1
289                                                 * sizeof(fmpz_mpoly_struct *));
290         for (v = 0; v < nvars1; v++)
291         {
292             vals1[v] = (fmpz_mpoly_struct *) flint_malloc(
293                                                     sizeof(fmpz_mpoly_struct));
294             fmpz_mpoly_init(vals1[v], ctx2);
295             fmpz_mpoly_randtest_bound(vals1[v], state, len2,
296                                                 coeff_bits2, exp_bound2, ctx2);
297         }
298 
299         vals2 = (fmpz **) flint_malloc(nvars2*sizeof(fmpz*));
300         for (v = 0; v < nvars2; v++)
301         {
302             vals2[v] = (fmpz *) flint_malloc(sizeof(fmpz));
303             fmpz_init(vals2[v]);
304             fmpz_randbits(vals2[v], state, 4);
305         }
306 
307         vals3 = (fmpz **) flint_malloc(nvars1*sizeof(fmpz*));
308         for (v = 0; v < nvars1; v++)
309         {
310             vals3[v] = (fmpz *) flint_malloc(sizeof(fmpz));
311             fmpz_init(vals3[v]);
312             if (!fmpz_mpoly_evaluate_all_fmpz(vals3[v], vals1[v], vals2, ctx2))
313             {
314                 printf("FAIL\n");
315                 flint_printf("Check evaluation success\ni: %wd\n", i);
316                 flint_abort();
317             }
318         }
319 
320         fmpz_mpoly_randtest_bound(f, state, len1, coeff_bits1, exp_bound1, ctx1);
321 
322         if (!fmpz_mpoly_compose_fmpz_mpoly(g, f, vals1, ctx1, ctx2) ||
323             !fmpz_mpoly_compose_fmpz_mpoly_horner(g1, f, vals1, ctx1, ctx2) ||
324             !fmpz_mpoly_compose_fmpz_mpoly_geobucket(g2, f, vals1, ctx1, ctx2) ||
325             !fmpz_mpoly_equal(g, g1, ctx2) ||
326             !fmpz_mpoly_equal(g, g2, ctx2))
327         {
328             printf("FAIL\n");
329             flint_printf("Check composition success\ni: %wd\n", i);
330             flint_abort();
331         }
332 
333         fmpz_mpoly_assert_canonical(g, ctx2);
334         fmpz_mpoly_assert_canonical(g1, ctx2);
335         fmpz_mpoly_assert_canonical(g2, ctx2);
336 
337         if (!fmpz_mpoly_evaluate_all_fmpz(fe, f, vals3, ctx1) ||
338             !fmpz_mpoly_evaluate_all_fmpz(ge, g, vals2, ctx2))
339         {
340             printf("FAIL\n");
341             flint_printf("Check evaluation success\ni: %wd\n", i);
342             flint_abort();
343         }
344 
345         if (!fmpz_equal(fe, ge))
346         {
347             printf("FAIL\n");
348             flint_printf("Check composition and evalall commute\ni: %wd\n", i);
349             flint_abort();
350         }
351 
352         for (v = 0; v < nvars1; v++)
353         {
354             fmpz_mpoly_clear(vals1[v], ctx2);
355             flint_free(vals1[v]);
356         }
357         flint_free(vals1);
358 
359         for (v = 0; v < nvars2; v++)
360         {
361             fmpz_clear(vals2[v]);
362             flint_free(vals2[v]);
363         }
364         flint_free(vals2);
365 
366         for (v = 0; v < nvars1; v++)
367         {
368             fmpz_clear(vals3[v]);
369             flint_free(vals3[v]);
370         }
371         flint_free(vals3);
372 
373         fmpz_mpoly_clear(f, ctx1);
374         fmpz_mpoly_clear(g, ctx2);
375         fmpz_mpoly_clear(g1, ctx2);
376         fmpz_mpoly_clear(g2, ctx2);
377 
378         fmpz_clear(fe);
379         fmpz_clear(ge);
380 
381         fmpz_mpoly_ctx_clear(ctx1);
382         fmpz_mpoly_ctx_clear(ctx2);
383     }
384 
385     printf("PASS\n");
386     FLINT_TEST_CLEANUP(state);
387 
388     return 0;
389 }
390 
391