1 // Univariate Polynomials over a general ring.
3 #include "cl_SV_ringelt.h"
4 #include "cl_integer.h"
7 // Assume a ring is a ring.
8 inline cl_heap_ring* TheRing (const cl_ring& R)
9 { return (cl_heap_ring*) R.heappointer; }
11 // Normalize a vector: remove leading zero coefficients.
12 // The result vector is known to have length len > 0.
13 static inline void gen_normalize (cl_heap_ring* R, cl_SV_ringelt& result, uintL len)
15 if (R->_zerop(result[len-1])) {
18 if (!R->_zerop(result[len-1]))
22 var cl_SV_ringelt newresult = cl_SV_ringelt(cl_make_heap_SV_ringelt_uninit(len));
23 for (var sintL i = len-1; i >= 0; i--)
24 init1(_cl_ring_element, newresult[i]) (result[i]);
29 static void gen_fprint (cl_heap_univpoly_ring* UPR, cl_ostream stream, const _cl_UP& x)
31 DeclarePoly(cl_SV_ringelt,x);
32 var cl_heap_ring* R = TheRing(UPR->basering());
33 var sintL xlen = x.length();
37 var cl_string varname = get_varname(UPR);
38 for (var sintL i = xlen-1; i >= 0; i--)
39 if (!R->_zerop(x[i])) {
41 fprint(stream, " + ");
43 R->_fprint(stream, x[i]);
47 fprint(stream, varname);
50 fprintdecimal(stream, i);
57 static cl_boolean gen_equal (cl_heap_univpoly_ring* UPR, const _cl_UP& x, const _cl_UP& y)
59 DeclarePoly(cl_SV_ringelt,x);
60 DeclarePoly(cl_SV_ringelt,y);
61 var cl_heap_ring* R = TheRing(UPR->basering());
62 var sintL xlen = x.length();
63 var sintL ylen = y.length();
66 for (var sintL i = xlen-1; i >= 0; i--)
67 if (!R->_equal(x[i],y[i]))
72 static const _cl_UP gen_zero (cl_heap_univpoly_ring* UPR)
74 return _cl_UP(UPR, cl_null_SV_ringelt);
77 static cl_boolean gen_zerop (cl_heap_univpoly_ring* UPR, const _cl_UP& x)
80 { DeclarePoly(cl_SV_ringelt,x);
81 var sintL xlen = x.length();
88 static const _cl_UP gen_plus (cl_heap_univpoly_ring* UPR, const _cl_UP& x, const _cl_UP& y)
90 DeclarePoly(cl_SV_ringelt,x);
91 DeclarePoly(cl_SV_ringelt,y);
92 var cl_heap_ring* R = TheRing(UPR->basering());
93 var sintL xlen = x.length();
94 var sintL ylen = y.length();
96 return _cl_UP(UPR, y);
98 return _cl_UP(UPR, x);
99 // Now xlen > 0, ylen > 0.
101 var cl_SV_ringelt result = cl_SV_ringelt(cl_make_heap_SV_ringelt_uninit(xlen));
103 for (i = xlen-1; i >= ylen; i--)
104 init1(_cl_ring_element, result[i]) (x[i]);
105 for (i = ylen-1; i >= 0; i--)
106 init1(_cl_ring_element, result[i]) (R->_plus(x[i],y[i]));
107 return _cl_UP(UPR, result);
110 var cl_SV_ringelt result = cl_SV_ringelt(cl_make_heap_SV_ringelt_uninit(ylen));
112 for (i = ylen-1; i >= xlen; i--)
113 init1(_cl_ring_element, result[i]) (y[i]);
114 for (i = xlen-1; i >= 0; i--)
115 init1(_cl_ring_element, result[i]) (R->_plus(x[i],y[i]));
116 return _cl_UP(UPR, result);
118 // Now xlen = ylen > 0. Add and normalize simultaneously.
119 for (var sintL i = xlen-1; i >= 0; i--) {
120 var _cl_ring_element hicoeff = R->_plus(x[i],y[i]);
121 if (!R->_zerop(hicoeff)) {
122 var cl_SV_ringelt result = cl_SV_ringelt(cl_make_heap_SV_ringelt_uninit(i+1));
123 init1(_cl_ring_element, result[i]) (hicoeff);
124 for (i-- ; i >= 0; i--)
125 init1(_cl_ring_element, result[i]) (R->_plus(x[i],y[i]));
126 return _cl_UP(UPR, result);
129 return _cl_UP(UPR, cl_null_SV_ringelt);
132 static const _cl_UP gen_minus (cl_heap_univpoly_ring* UPR, const _cl_UP& x, const _cl_UP& y)
134 DeclarePoly(cl_SV_ringelt,x);
135 DeclarePoly(cl_SV_ringelt,y);
136 var cl_heap_ring* R = TheRing(UPR->basering());
137 var sintL xlen = x.length();
138 var sintL ylen = y.length();
140 return _cl_UP(UPR, y);
142 return _cl_UP(UPR, x);
143 // Now xlen > 0, ylen > 0.
145 var cl_SV_ringelt result = cl_SV_ringelt(cl_make_heap_SV_ringelt_uninit(xlen));
147 for (i = xlen-1; i >= ylen; i--)
148 init1(_cl_ring_element, result[i]) (x[i]);
149 for (i = ylen-1; i >= 0; i--)
150 init1(_cl_ring_element, result[i]) (R->_minus(x[i],y[i]));
151 return _cl_UP(UPR, result);
154 var cl_SV_ringelt result = cl_SV_ringelt(cl_make_heap_SV_ringelt_uninit(ylen));
156 for (i = ylen-1; i >= xlen; i--)
157 init1(_cl_ring_element, result[i]) (R->_uminus(y[i]));
158 for (i = xlen-1; i >= 0; i--)
159 init1(_cl_ring_element, result[i]) (R->_minus(x[i],y[i]));
160 return _cl_UP(UPR, result);
162 // Now xlen = ylen > 0. Add and normalize simultaneously.
163 for (var sintL i = xlen-1; i >= 0; i--) {
164 var _cl_ring_element hicoeff = R->_minus(x[i],y[i]);
165 if (!R->_zerop(hicoeff)) {
166 var cl_SV_ringelt result = cl_SV_ringelt(cl_make_heap_SV_ringelt_uninit(i+1));
167 init1(_cl_ring_element, result[i]) (hicoeff);
168 for (i-- ; i >= 0; i--)
169 init1(_cl_ring_element, result[i]) (R->_minus(x[i],y[i]));
170 return _cl_UP(UPR, result);
173 return _cl_UP(UPR, cl_null_SV_ringelt);
176 static const _cl_UP gen_uminus (cl_heap_univpoly_ring* UPR, const _cl_UP& x)
178 DeclarePoly(cl_SV_ringelt,x);
179 var cl_heap_ring* R = TheRing(UPR->basering());
180 var sintL xlen = x.length();
182 return _cl_UP(UPR, x);
184 // Negate. No normalization necessary, since the degree doesn't change.
185 var sintL i = xlen-1;
186 var _cl_ring_element hicoeff = R->_uminus(x[i]);
187 if (R->_zerop(hicoeff)) cl_abort();
188 var cl_SV_ringelt result = cl_SV_ringelt(cl_make_heap_SV_ringelt_uninit(xlen));
189 init1(_cl_ring_element, result[i]) (hicoeff);
190 for (i-- ; i >= 0; i--)
191 init1(_cl_ring_element, result[i]) (R->_uminus(x[i]));
192 return _cl_UP(UPR, result);
195 static const _cl_UP gen_one (cl_heap_univpoly_ring* UPR)
197 var cl_heap_ring* R = TheRing(UPR->basering());
198 var cl_SV_ringelt result = cl_SV_ringelt(cl_make_heap_SV_ringelt_uninit(1));
199 init1(_cl_ring_element, result[0]) (R->_one());
200 return _cl_UP(UPR, result);
203 static const _cl_UP gen_canonhom (cl_heap_univpoly_ring* UPR, const cl_I& x)
205 var cl_heap_ring* R = TheRing(UPR->basering());
206 var cl_SV_ringelt result = cl_SV_ringelt(cl_make_heap_SV_ringelt_uninit(1));
207 init1(_cl_ring_element, result[0]) (R->_canonhom(x));
208 return _cl_UP(UPR, result);
211 static const _cl_UP gen_mul (cl_heap_univpoly_ring* UPR, const _cl_UP& x, const _cl_UP& y)
213 DeclarePoly(cl_SV_ringelt,x);
214 DeclarePoly(cl_SV_ringelt,y);
215 var cl_heap_ring* R = TheRing(UPR->basering());
216 var sintL xlen = x.length();
217 var sintL ylen = y.length();
219 return _cl_UP(UPR, x);
221 return _cl_UP(UPR, y);
223 var sintL len = xlen + ylen - 1;
224 var cl_SV_ringelt result = cl_SV_ringelt(cl_make_heap_SV_ringelt_uninit(len));
227 var sintL i = xlen-1;
228 var _cl_ring_element xi = x[i];
229 for (sintL j = ylen-1; j >= 0; j--)
230 init1(_cl_ring_element, result[i+j]) (R->_mul(xi,y[j]));
232 for (sintL i = xlen-2; i >= 0; i--) {
233 var _cl_ring_element xi = x[i];
234 for (sintL j = ylen-1; j > 0; j--)
235 result[i+j] = R->_plus(result[i+j],R->_mul(xi,y[j]));
236 /* j=0 */ init1(_cl_ring_element, result[i]) (R->_mul(xi,y[0]));
240 var sintL j = ylen-1;
241 var _cl_ring_element yj = y[j];
242 for (sintL i = xlen-1; i >= 0; i--)
243 init1(_cl_ring_element, result[i+j]) (R->_mul(x[i],yj));
245 for (sintL j = ylen-2; j >= 0; j--) {
246 var _cl_ring_element yj = y[j];
247 for (sintL i = xlen-1; i > 0; i--)
248 result[i+j] = R->_plus(result[i+j],R->_mul(x[i],yj));
249 /* i=0 */ init1(_cl_ring_element, result[j]) (R->_mul(x[0],yj));
252 // Normalize (not necessary in integral domains).
253 //gen_normalize(R,result,len);
254 if (R->_zerop(result[len-1])) cl_abort();
255 return _cl_UP(UPR, result);
258 static const _cl_UP gen_square (cl_heap_univpoly_ring* UPR, const _cl_UP& x)
260 DeclarePoly(cl_SV_ringelt,x);
261 var cl_heap_ring* R = TheRing(UPR->basering());
262 var sintL xlen = x.length();
264 return cl_UP(UPR, x);
265 var sintL len = 2*xlen-1;
266 var cl_SV_ringelt result = cl_SV_ringelt(cl_make_heap_SV_ringelt_uninit(len));
268 // Loop through all 0 <= j < i <= xlen-1.
270 var sintL i = xlen-1;
271 var _cl_ring_element xi = x[i];
272 for (sintL j = i-1; j >= 0; j--)
273 init1(_cl_ring_element, result[i+j]) (R->_mul(xi,x[j]));
275 {for (sintL i = xlen-2; i >= 1; i--) {
276 var _cl_ring_element xi = x[i];
277 for (sintL j = i-1; j >= 1; j--)
278 result[i+j] = R->_plus(result[i+j],R->_mul(xi,x[j]));
279 /* j=0 */ init1(_cl_ring_element, result[i]) (R->_mul(xi,x[0]));
282 {for (sintL i = len-2; i >= 1; i--)
283 result[i] = R->_plus(result[i],result[i]);
286 init1(_cl_ring_element, result[2*(xlen-1)]) (R->_square(x[xlen-1]));
287 for (sintL i = xlen-2; i >= 1; i--)
288 result[2*i] = R->_plus(result[2*i],R->_square(x[i]));
290 init1(_cl_ring_element, result[0]) (R->_square(x[0]));
291 // Normalize (not necessary in integral domains).
292 //gen_normalize(R,result,len);
293 if (R->_zerop(result[len-1])) cl_abort();
294 return _cl_UP(UPR, result);
297 static const _cl_UP gen_exptpos (cl_heap_univpoly_ring* UPR, const _cl_UP& x, const cl_I& y)
301 while (!oddp(b)) { a = UPR->_square(a); b = b >> 1; }
306 if (oddp(b)) { c = UPR->_mul(a,c); }
311 static const _cl_UP gen_scalmul (cl_heap_univpoly_ring* UPR, const cl_ring_element& x, const _cl_UP& y)
313 if (!(UPR->basering() == x.ring())) cl_abort();
315 DeclarePoly(cl_SV_ringelt,y);
316 var cl_heap_ring* R = TheRing(UPR->basering());
317 var sintL ylen = y.length();
319 return _cl_UP(UPR, y);
321 return _cl_UP(UPR, cl_null_SV_ringelt);
322 var cl_SV_ringelt result = cl_SV_ringelt(cl_make_heap_SV_ringelt_uninit(ylen));
323 for (sintL i = ylen-1; i >= 0; i--)
324 init1(_cl_ring_element, result[i]) (R->_mul(x,y[i]));
325 // Normalize (not necessary in integral domains).
326 //gen_normalize(R,result,ylen);
327 if (R->_zerop(result[ylen-1])) cl_abort();
328 return _cl_UP(UPR, result);
331 static sintL gen_degree (cl_heap_univpoly_ring* UPR, const _cl_UP& x)
334 { DeclarePoly(cl_SV_ringelt,x);
335 return (sintL) x.length() - 1;
338 static const _cl_UP gen_monomial (cl_heap_univpoly_ring* UPR, const cl_ring_element& x, uintL e)
340 if (!(UPR->basering() == x.ring())) cl_abort();
341 var cl_heap_ring* R = TheRing(UPR->basering());
343 return _cl_UP(UPR, cl_null_SV_ringelt);
346 var cl_SV_ringelt result = cl_SV_ringelt(len);
348 return _cl_UP(UPR, result);
352 static const cl_ring_element gen_coeff (cl_heap_univpoly_ring* UPR, const _cl_UP& x, uintL index)
354 DeclarePoly(cl_SV_ringelt,x);
355 var cl_heap_ring* R = TheRing(UPR->basering());
356 if (index < x.length())
357 return cl_ring_element(R, x[index]);
362 static const _cl_UP gen_create (cl_heap_univpoly_ring* UPR, sintL deg)
365 return _cl_UP(UPR, cl_null_SV_ringelt);
367 var sintL len = deg+1;
368 return _cl_UP(UPR, cl_SV_ringelt(len));
372 static void gen_set_coeff (cl_heap_univpoly_ring* UPR, _cl_UP& x, uintL index, const cl_ring_element& y)
374 DeclareMutablePoly(cl_SV_ringelt,x);
375 if (!(UPR->basering() == y.ring())) cl_abort();
376 if (!(index < x.length())) cl_abort();
380 static void gen_finalize (cl_heap_univpoly_ring* UPR, _cl_UP& x)
382 DeclareMutablePoly(cl_SV_ringelt,x); // NB: x is modified by reference!
383 var cl_heap_ring* R = TheRing(UPR->basering());
384 var uintL len = x.length();
386 gen_normalize(R,x,len);
389 static const cl_ring_element gen_eval (cl_heap_univpoly_ring* UPR, const _cl_UP& x, const cl_ring_element& y)
392 // If x = 0, return 0.
393 // If y = 0, return x[0].
394 // Else compute (...(x[len-1]*y+x[len-2])*y ...)*y + x[0].
395 DeclarePoly(cl_SV_ringelt,x);
396 var cl_heap_ring* R = TheRing(UPR->basering());
397 if (!(y.ring() == R)) cl_abort();
398 var uintL len = x.length();
402 return cl_ring_element(R, x[0]);
404 var _cl_ring_element z = x[i];
406 z = R->_plus(R->_mul(z,y),x[i]);
407 return cl_ring_element(R, z);
410 static cl_univpoly_setops gen_setops = {
415 static cl_univpoly_addops gen_addops = {
423 static cl_univpoly_mulops gen_mulops = {
431 static cl_univpoly_modulops gen_modulops = {
435 static cl_univpoly_polyops gen_polyops = {
445 class cl_heap_gen_univpoly_ring : public cl_heap_univpoly_ring {
446 SUBCLASS_cl_heap_univpoly_ring()
449 cl_heap_gen_univpoly_ring (const cl_ring& r)
450 : cl_heap_univpoly_ring (r, &gen_setops, &gen_addops, &gen_mulops, &gen_modulops, &gen_polyops) {}