1 // Copyright (c) 1997-2006 John Abbott
2
3 // This file is part of the source of CoCoALib, the CoCoA Library.
4
5 // CoCoALib is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9
10 // CoCoALib is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14
15 // You should have received a copy of the GNU General Public License
16 // along with CoCoALib. If not, see <http://www.gnu.org/licenses/>.
17
18
19 #include <stddef.h>
20 #include <stdio.h>
21 #include "DUPZfactor_liftq.h"
22 #include "jalloc.h"
23 #include "jaaerror.h"
24 #include "DUPZ_DUPFF.h"
25 #include "DUPZfactor_info.h"
26
27
28 /***************************************************************************/
29
30
DUPZfactor_lifter_ctor(DUPFF g,DUPFF h,DUPZfactor_lifter g_lifter,DUPZfactor_lifter h_lifter)31 DUPZfactor_lifter DUPZfactor_lifter_ctor(DUPFF g, DUPFF h, DUPZfactor_lifter g_lifter, DUPZfactor_lifter h_lifter)
32 {
33 DUPZfactor_lifter ans;
34 DUPFF corr_factor, junk, tmp;
35 int df;
36
37 if (DUPFFdeg(g) > DUPFFdeg(h)) return DUPZfactor_lifter_ctor(h, g, h_lifter, g_lifter);
38 ans = (DUPZfactor_lifter)MALLOC(sizeof(struct DUPZfactor_lift_struct));
39 ans->g = DUPFF_to_DUPZ(g);
40 ans->h = DUPFF_to_DUPZ(h);
41 df = DUPFFdeg(g) + DUPFFdeg(h);
42 tmp = DUPFFexgcd(&junk, &corr_factor, g, h);
43 if (DUPFFdeg(tmp) != 0) { JERROR(JERROR_HENSEL); exit(1); }
44 /* since the gcd is not monic we have to do this... */
45 DUPFFdiv2ff(corr_factor, DUPFFlc(tmp));
46 ans->corr_factor = DUPZnew(df-1); /* need spare space for revise_lift_tree */
47 DUPFF_to_DUPZ2(ans->corr_factor, corr_factor);
48 ans->g_lifter = g_lifter;
49 ans->h_lifter = h_lifter;
50 DUPFFfree(tmp);
51 DUPFFfree(corr_factor);
52 DUPFFfree(junk);
53
54 return ans;
55 }
56
57
DUPZfactor_lift_dtor(DUPZfactor_lifter THIS)58 void DUPZfactor_lift_dtor(DUPZfactor_lifter THIS)
59 {
60 if (THIS == NULL) return;
61 if (THIS->g_lifter) DUPZfactor_lift_dtor(THIS->g_lifter);
62 if (THIS->h_lifter) DUPZfactor_lift_dtor(THIS->h_lifter);
63 DUPZfree(THIS->g);
64 DUPZfree(THIS->h);
65 DUPZfree(THIS->corr_factor);
66 FREE(THIS);
67 }
68
69 /***************************************************************************/
70
DUPZfactor_lift_step(DUPZfactor_lifter THIS,DUPZ f,mpz_t Q)71 void DUPZfactor_lift_step(DUPZfactor_lifter THIS, DUPZ f, mpz_t Q)
72 {
73 /* local workspace -- maybe put these in lifter struct??? */
74 DUPZ Delta, delta_g, tmp;
75 /* just aliases to make the code easier to read (!?!) */
76 DUPZ g = THIS->g;
77 DUPZ h = THIS->h;
78 DUPZ alpha = THIS->corr_factor;
79
80 Delta = DUPZmul(g, h);
81 DUPZsub3(Delta, f, Delta);
82 DUPZdiv2z(Delta, Q);
83 DUPZmod2z(Delta, Q);
84
85 tmp = DUPZnew(DUPZdeg(f));
86 DUPZmul3(tmp, alpha, h);
87 mpz_sub_ui(tmp->coeffs[0], tmp->coeffs[0], 2);
88 DUPZmod2(tmp, g, Q);
89 DUPZmul3(tmp, alpha, tmp);
90 DUPZneg1(tmp);
91 DUPZmod2(tmp, g, Q);
92 DUPZcopy2(alpha, tmp);
93
94 delta_g = DUPZnew(DUPZdeg(f));
95 DUPZcopy2(delta_g, Delta);
96 DUPZmod2(delta_g, g, Q);
97 DUPZmul3(delta_g, alpha, delta_g);
98 DUPZmod2(delta_g, g, Q);
99 DUPZmul3(tmp, h, delta_g);
100 DUPZsub3(tmp, Delta, tmp);
101 DUPZmdiv2(tmp, g, Q);
102 DUPZmul2z(delta_g, Q);
103 DUPZmul2z(tmp, Q);
104 DUPZadd3(g, g, delta_g);
105 DUPZadd3(h, h, tmp);
106 DUPZfree(Delta);DUPZfree(delta_g);DUPZfree(tmp);
107
108 if (THIS->g_lifter) DUPZfactor_lift_step(THIS->g_lifter, g, Q);
109 if (THIS->h_lifter) DUPZfactor_lift_step(THIS->h_lifter, h, Q);
110 }
111
112
113 /***************************************************************************/
114
DUPZfactor_lift_init_stupid(const DUPFFlist pfactors)115 static DUPZfactor_lifter DUPZfactor_lift_init_stupid(const DUPFFlist pfactors)
116 {
117 DUPZfactor_lifter ans;
118 DUPFFlist iter;
119 DUPFF tmp;
120 int df;
121
122 df = 0;
123 for (iter = pfactors; iter; iter = iter->next)
124 df += DUPFFdeg(iter->poly);
125 ans = NULL;
126 tmp = DUPFFnew(df);
127 DUPFFcopy2(tmp, pfactors->poly);
128 for (iter = pfactors->next; iter; iter = iter->next)
129 {
130 ans = DUPZfactor_lifter_ctor(iter->poly, tmp, NULL, ans);
131 DUPFFmul3(tmp, tmp, iter->poly);
132 }
133 DUPFFfree(tmp);
134
135 return ans;
136 }
137
138
DUPZfactor_lift_init(DUPZfactor_info THIS)139 void DUPZfactor_lift_init(DUPZfactor_info THIS)
140 {
141 THIS->lifter = DUPZfactor_lift_init_stupid(THIS->pfactors);
142 }
143
144
145 #if 0
146 /****************************************************************************/
147 /* This function is called after a speculative early search which has found */
148 /* at least one factor but further lifting is still required. */
149 /* It creates a new lifting tree for the remaining factors. */
150
151 static DUPZfactor_lifter revise_lifter(DUPZfactor_lifter old_tree, mpz_t Q)
152 {
153 ?????????????????????????????????????????????????????????????????????????????
154 if (old_tree->g_lifter != NULL) g1 = revise_lifter(old_tree->g_lifter, Q);
155 if (old_tree->h_lifter != NULL) h1 = revise_lifter(old_tree->h_lifter, Q);
156 ans->g = DUPZmul(g1->g, h1->g);
157 ans->h = DUPZmul(g1->h, h1->h);
158 ans->g_lifter = NULL;
159
160 if (DUPZdeg(g1->g) == 0 || DUPZdeg(h1->g) == 0) goto tidy_up;
161 if (DUPZdeg(g1->g) > DUPZdeg(h1->g))
162 {
163 new_tree->g = g1->g; g1->g = NULL;
164 new_tree->h = h1->g; h1->g = NULL;
165 new_tree->g_lifter = g1->g_lifter;
166 new_tree->h_lifter = h1->g_lifter;
167 new_tree->corr_factor = DUPZnew(DUPZdeg(ans->g));
168 DUPZmul3(new_tree->corr_factor, old_tree->corr_factor, h1->h);
169 DUPZmod3(new_tree->corr_factor, new_tree->g, Q);
170 }
171 else
172 {
173 new_tree->g = h1->g; h1->g = NULL;
174 new_tree->h = g1->g; g1->g = NULL;
175 new_tree->g_lifter = h1->g_lifter;
176 new_tree->h_lifter = g1->g_lifter;
177 new_tree->corr_factor = DUPZnew(df-1);
178 DUPZmul3(new_tree->corr_factor, old_tree->corr_factor, g1->h);
179 DUPZmod3(new_tree->corr_factor, new_tree->h, Q);
180 DUPZmul3(new_tree->corr_factor, new_tree->corr_factor, new_tree->g);
181 DUPZmod3(new_tree->corr_factor, new_tree->h, Q);
182 DUPZneg(new_tree->corr_factor);
183 DUPZadd3(new_tree->corr_factor, new_tree->corr_factor, 1);
184 DUPZdivmodQ(new_tree->corr_factor, new_tree->h);
185 }
186 tidy_up:
187 DUPZfactor_lift_dtor(g1);
188 DUPZfactor_lift_dtor(h1);
189 return ans;
190 }
191 #endif
192
revise_lift_tree(DUPZfactor_lifter * tree,mpz_t Q)193 static DUPZ revise_lift_tree(DUPZfactor_lifter *tree, mpz_t Q)
194 {
195 DUPZ G, H, ans;
196 int g_prune, h_prune;
197 DUPZfactor_lifter THIS = *tree; /* alias */
198 DUPZ g = THIS->g; /* alias */
199 DUPZ h = THIS->h; /* alias */
200 DUPZ alpha = THIS->corr_factor; /* alias */
201
202 if (THIS->g_lifter != NULL)
203 G = revise_lift_tree(&THIS->g_lifter, Q);
204 else
205 {
206 if (DUPZdeg(g) > 0) G = int_to_DUPZ(1);
207 else
208 {
209 g->deg = - g->deg;
210 G = DUPZcopy(g); /* wasteful */
211 }
212 }
213 g_prune = (DUPZdeg(G) == DUPZdeg(g));
214
215 if (THIS->h_lifter != NULL)
216 H = revise_lift_tree(&THIS->h_lifter, Q);
217 else
218 {
219 if (DUPZdeg(h) > 0) H = int_to_DUPZ(1);
220 else
221 {
222 h->deg = - h->deg;
223 H = DUPZcopy(h); /* wasteful */
224 }
225 }
226 h_prune = (DUPZdeg(H) == DUPZdeg(h));
227
228 if (g_prune && h_prune)
229 {
230 DUPZfactor_lift_dtor(THIS);
231 *tree = NULL;
232 goto end;
233 }
234 if (g_prune)
235 {
236 *tree = THIS->h_lifter;
237 THIS->h_lifter = NULL;
238 DUPZfactor_lift_dtor(THIS);
239 goto end;
240 }
241 if (h_prune)
242 {
243 *tree = THIS->g_lifter;
244 THIS->g_lifter = NULL;
245 DUPZfactor_lift_dtor(THIS);
246 goto end;
247 }
248 DUPZmdiv2(g, G, Q);
249 DUPZmdiv2(h, H, Q);
250 DUPZmod2(alpha, g, Q);
251 DUPZmul3(alpha, alpha, H);
252 DUPZmod2(alpha, g, Q);
253
254 end:
255 ans = DUPZmul(G, H);
256 DUPZfree(G); DUPZfree(H);
257 return ans;
258 }
259
260
DUPZfactor_lift_revise(DUPZfactor_info info)261 void DUPZfactor_lift_revise(DUPZfactor_info info)
262 {
263 DUPZfree(revise_lift_tree(&info->lifter, info->Q));
264 }
265
266
267 /***************************************************************************/
268 /* Make the lifted factors available to outsiders. */
269 /* We actually return pointers to our own copies so that outsiders can */
270 /* modify them: they should negate the degree if the factor was used to */
271 /* form a true factor (see DUPZfactor_lift_revise above). */
272
DUPZfactor_lift_output(DUPZ ** factors,const DUPZfactor_lifter THIS,int i)273 int DUPZfactor_lift_output(DUPZ **factors, const DUPZfactor_lifter THIS, int i)
274 {
275 if (THIS->g_lifter) i = DUPZfactor_lift_output(factors, THIS->g_lifter, i);
276 else factors[i++] = &THIS->g;
277 if (THIS->h_lifter) i = DUPZfactor_lift_output(factors, THIS->h_lifter, i);
278 else factors[i++] = &THIS->h;
279 return i;
280 }
281
282 /***************************************************************************/
283