1 | // Univariate Polynomials. |
2 | |
3 | #ifndef _CL_UNIVPOLY_H |
4 | #define _CL_UNIVPOLY_H |
5 | |
6 | #include "cln/object.h" |
7 | #include "cln/ring.h" |
8 | #include "cln/malloc.h" |
9 | #include "cln/proplist.h" |
10 | #include "cln/symbol.h" |
11 | #include "cln/V.h" |
12 | #include "cln/io.h" |
13 | |
14 | namespace cln { |
15 | |
16 | // To protect against mixing elements of different polynomial rings, every |
17 | // polynomial carries its ring in itself. |
18 | |
19 | class cl_heap_univpoly_ring; |
20 | |
21 | class cl_univpoly_ring : public cl_ring { |
22 | public: |
23 | // Default constructor. |
24 | cl_univpoly_ring (); |
25 | // Constructor. Takes a cl_heap_univpoly_ring*, increments its refcount. |
26 | cl_univpoly_ring (cl_heap_univpoly_ring* r); |
27 | // Private constructor. Doesn't increment the refcount. |
28 | cl_univpoly_ring (cl_private_thing); |
29 | // Copy constructor. |
30 | cl_univpoly_ring (const cl_univpoly_ring&); |
31 | // Assignment operator. |
32 | cl_univpoly_ring& operator= (const cl_univpoly_ring&); |
33 | // Automatic dereferencing. |
34 | cl_heap_univpoly_ring* operator-> () const |
35 | { return (cl_heap_univpoly_ring*)heappointer; } |
36 | }; |
37 | // Copy constructor and assignment operator. |
38 | CL_DEFINE_COPY_CONSTRUCTOR2(cl_univpoly_ring,cl_ring) |
39 | CL_DEFINE_ASSIGNMENT_OPERATOR(cl_univpoly_ring,cl_univpoly_ring) |
40 | |
41 | // Normal constructor for `cl_univpoly_ring'. |
42 | inline cl_univpoly_ring::cl_univpoly_ring (cl_heap_univpoly_ring* r) |
43 | : cl_ring ((cl_private_thing) (cl_inc_pointer_refcount((cl_heap*)r), r)) {} |
44 | // Private constructor for `cl_univpoly_ring'. |
45 | inline cl_univpoly_ring::cl_univpoly_ring (cl_private_thing p) |
46 | : cl_ring (p) {} |
47 | |
48 | // Operations on univariate polynomial rings. |
49 | |
50 | inline bool operator== (const cl_univpoly_ring& R1, const cl_univpoly_ring& R2) |
51 | { return (R1.pointer == R2.pointer); } |
52 | inline bool operator!= (const cl_univpoly_ring& R1, const cl_univpoly_ring& R2) |
53 | { return (R1.pointer != R2.pointer); } |
54 | inline bool operator== (const cl_univpoly_ring& R1, cl_heap_univpoly_ring* R2) |
55 | { return (R1.pointer == R2); } |
56 | inline bool operator!= (const cl_univpoly_ring& R1, cl_heap_univpoly_ring* R2) |
57 | { return (R1.pointer != R2); } |
58 | |
59 | // Representation of a univariate polynomial. |
60 | |
61 | class _cl_UP /* cf. _cl_ring_element */ { |
62 | public: |
63 | cl_gcpointer rep; // vector of coefficients, a cl_V_any |
64 | // Default constructor. |
65 | _cl_UP (); |
66 | public: /* ugh */ |
67 | // Constructor. |
68 | _cl_UP (const cl_heap_univpoly_ring* R, const cl_V_any& r) : rep (as_cl_private_thing(r)) { (void)R; } |
69 | _cl_UP (const cl_univpoly_ring& R, const cl_V_any& r) : rep (as_cl_private_thing(r)) { (void)R; } |
70 | public: |
71 | // Conversion. |
72 | CL_DEFINE_CONVERTER(_cl_ring_element) |
73 | public: // Ability to place an object at a given address. |
74 | void* operator new (size_t size) { return malloc_hook(size); } |
75 | void* operator new (size_t size, void* ptr) { (void)size; return ptr; } |
76 | void operator delete (void* ptr) { free_hook(ptr); } |
77 | }; |
78 | |
79 | class cl_UP /* cf. cl_ring_element */ : public _cl_UP { |
80 | protected: |
81 | cl_univpoly_ring _ring; // polynomial ring (references the base ring) |
82 | public: |
83 | const cl_univpoly_ring& ring () const { return _ring; } |
84 | private: |
85 | // Default constructor. |
86 | cl_UP (); |
87 | public: /* ugh */ |
88 | // Constructor. |
89 | cl_UP (const cl_univpoly_ring& R, const cl_V_any& r) |
90 | : _cl_UP (R,r), _ring (R) {} |
91 | cl_UP (const cl_univpoly_ring& R, const _cl_UP& r) |
92 | : _cl_UP (r), _ring (R) {} |
93 | public: |
94 | // Conversion. |
95 | CL_DEFINE_CONVERTER(cl_ring_element) |
96 | // Destructive modification. |
97 | void set_coeff (uintL index, const cl_ring_element& y); |
98 | void finalize(); |
99 | // Evaluation. |
100 | const cl_ring_element operator() (const cl_ring_element& y) const; |
101 | // Debugging output. |
102 | void debug_print () const; |
103 | public: // Ability to place an object at a given address. |
104 | void* operator new (size_t size) { return malloc_hook(size); } |
105 | void* operator new (size_t size, void* ptr) { (void)size; return ptr; } |
106 | void operator delete (void* ptr) { free_hook(ptr); } |
107 | }; |
108 | |
109 | |
110 | // Ring operations. |
111 | |
112 | struct _cl_univpoly_setops /* cf. _cl_ring_setops */ { |
113 | // print |
114 | void (* fprint) (cl_heap_univpoly_ring* R, std::ostream& stream, const _cl_UP& x); |
115 | // equality |
116 | // (Be careful: This is not well-defined for polynomials with |
117 | // floating-point coefficients.) |
118 | bool (* equal) (cl_heap_univpoly_ring* R, const _cl_UP& x, const _cl_UP& y); |
119 | }; |
120 | struct _cl_univpoly_addops /* cf. _cl_ring_addops */ { |
121 | // 0 |
122 | const _cl_UP (* zero) (cl_heap_univpoly_ring* R); |
123 | bool (* zerop) (cl_heap_univpoly_ring* R, const _cl_UP& x); |
124 | // x+y |
125 | const _cl_UP (* plus) (cl_heap_univpoly_ring* R, const _cl_UP& x, const _cl_UP& y); |
126 | // x-y |
127 | const _cl_UP (* minus) (cl_heap_univpoly_ring* R, const _cl_UP& x, const _cl_UP& y); |
128 | // -x |
129 | const _cl_UP (* uminus) (cl_heap_univpoly_ring* R, const _cl_UP& x); |
130 | }; |
131 | struct _cl_univpoly_mulops /* cf. _cl_ring_mulops */ { |
132 | // 1 |
133 | const _cl_UP (* one) (cl_heap_univpoly_ring* R); |
134 | // canonical homomorphism |
135 | const _cl_UP (* canonhom) (cl_heap_univpoly_ring* R, const cl_I& x); |
136 | // x*y |
137 | const _cl_UP (* mul) (cl_heap_univpoly_ring* R, const _cl_UP& x, const _cl_UP& y); |
138 | // x^2 |
139 | const _cl_UP (* square) (cl_heap_univpoly_ring* R, const _cl_UP& x); |
140 | // x^y, y Integer >0 |
141 | const _cl_UP (* expt_pos) (cl_heap_univpoly_ring* R, const _cl_UP& x, const cl_I& y); |
142 | }; |
143 | struct _cl_univpoly_modulops { |
144 | // scalar multiplication x*y |
145 | const _cl_UP (* scalmul) (cl_heap_univpoly_ring* R, const cl_ring_element& x, const _cl_UP& y); |
146 | }; |
147 | struct _cl_univpoly_polyops { |
148 | // degree |
149 | sintL (* degree) (cl_heap_univpoly_ring* R, const _cl_UP& x); |
150 | // low degree |
151 | sintL (* ldegree) (cl_heap_univpoly_ring* R, const _cl_UP& x); |
152 | // monomial |
153 | const _cl_UP (* monomial) (cl_heap_univpoly_ring* R, const cl_ring_element& x, uintL e); |
154 | // coefficient (0 if index>degree) |
155 | const cl_ring_element (* coeff) (cl_heap_univpoly_ring* R, const _cl_UP& x, uintL index); |
156 | // create new polynomial, bounded degree |
157 | const _cl_UP (* create) (cl_heap_univpoly_ring* R, sintL deg); |
158 | // set coefficient in new polynomial |
159 | void (* set_coeff) (cl_heap_univpoly_ring* R, _cl_UP& x, uintL index, const cl_ring_element& y); |
160 | // finalize polynomial |
161 | void (* finalize) (cl_heap_univpoly_ring* R, _cl_UP& x); |
162 | // evaluate, substitute an element of R |
163 | const cl_ring_element (* eval) (cl_heap_univpoly_ring* R, const _cl_UP& x, const cl_ring_element& y); |
164 | }; |
165 | typedef const _cl_univpoly_setops cl_univpoly_setops; |
166 | typedef const _cl_univpoly_addops cl_univpoly_addops; |
167 | typedef const _cl_univpoly_mulops cl_univpoly_mulops; |
168 | typedef const _cl_univpoly_modulops cl_univpoly_modulops; |
169 | typedef const _cl_univpoly_polyops cl_univpoly_polyops; |
170 | |
171 | // Representation of a univariate polynomial ring. |
172 | |
173 | class cl_heap_univpoly_ring /* cf. cl_heap_ring */ : public cl_heap { |
174 | SUBCLASS_cl_heap_ring() |
175 | private: |
176 | cl_property_list properties; |
177 | protected: |
178 | cl_univpoly_setops* setops; |
179 | cl_univpoly_addops* addops; |
180 | cl_univpoly_mulops* mulops; |
181 | cl_univpoly_modulops* modulops; |
182 | cl_univpoly_polyops* polyops; |
183 | protected: |
184 | cl_ring _basering; // the coefficients are elements of this ring |
185 | public: |
186 | const cl_ring& basering () const { return _basering; } |
187 | public: |
188 | // Low-level operations. |
189 | void _fprint (std::ostream& stream, const _cl_UP& x) |
190 | { setops->fprint(this,stream,x); } |
191 | bool _equal (const _cl_UP& x, const _cl_UP& y) |
192 | { return setops->equal(this,x,y); } |
193 | const _cl_UP _zero () |
194 | { return addops->zero(this); } |
195 | bool _zerop (const _cl_UP& x) |
196 | { return addops->zerop(this,x); } |
197 | const _cl_UP _plus (const _cl_UP& x, const _cl_UP& y) |
198 | { return addops->plus(this,x,y); } |
199 | const _cl_UP _minus (const _cl_UP& x, const _cl_UP& y) |
200 | { return addops->minus(this,x,y); } |
201 | const _cl_UP _uminus (const _cl_UP& x) |
202 | { return addops->uminus(this,x); } |
203 | const _cl_UP _one () |
204 | { return mulops->one(this); } |
205 | const _cl_UP _canonhom (const cl_I& x) |
206 | { return mulops->canonhom(this,x); } |
207 | const _cl_UP _mul (const _cl_UP& x, const _cl_UP& y) |
208 | { return mulops->mul(this,x,y); } |
209 | const _cl_UP _square (const _cl_UP& x) |
210 | { return mulops->square(this,x); } |
211 | const _cl_UP _expt_pos (const _cl_UP& x, const cl_I& y) |
212 | { return mulops->expt_pos(this,x,y); } |
213 | const _cl_UP _scalmul (const cl_ring_element& x, const _cl_UP& y) |
214 | { return modulops->scalmul(this,x,y); } |
215 | sintL _degree (const _cl_UP& x) |
216 | { return polyops->degree(this,x); } |
217 | sintL _ldegree (const _cl_UP& x) |
218 | { return polyops->ldegree(this,x); } |
219 | const _cl_UP _monomial (const cl_ring_element& x, uintL e) |
220 | { return polyops->monomial(this,x,e); } |
221 | const cl_ring_element _coeff (const _cl_UP& x, uintL index) |
222 | { return polyops->coeff(this,x,index); } |
223 | const _cl_UP _create (sintL deg) |
224 | { return polyops->create(this,deg); } |
225 | void _set_coeff (_cl_UP& x, uintL index, const cl_ring_element& y) |
226 | { polyops->set_coeff(this,x,index,y); } |
227 | void _finalize (_cl_UP& x) |
228 | { polyops->finalize(this,x); } |
229 | const cl_ring_element _eval (const _cl_UP& x, const cl_ring_element& y) |
230 | { return polyops->eval(this,x,y); } |
231 | // High-level operations. |
232 | void fprint (std::ostream& stream, const cl_UP& x) |
233 | { |
234 | if (!(x.ring() == this)) throw runtime_exception(); |
235 | _fprint(stream,x); |
236 | } |
237 | bool equal (const cl_UP& x, const cl_UP& y) |
238 | { |
239 | if (!(x.ring() == this)) throw runtime_exception(); |
240 | if (!(y.ring() == this)) throw runtime_exception(); |
241 | return _equal(x,y); |
242 | } |
243 | const cl_UP zero () |
244 | { |
245 | return cl_UP(this,_zero()); |
246 | } |
247 | bool zerop (const cl_UP& x) |
248 | { |
249 | if (!(x.ring() == this)) throw runtime_exception(); |
250 | return _zerop(x); |
251 | } |
252 | const cl_UP plus (const cl_UP& x, const cl_UP& y) |
253 | { |
254 | if (!(x.ring() == this)) throw runtime_exception(); |
255 | if (!(y.ring() == this)) throw runtime_exception(); |
256 | return cl_UP(this,_plus(x,y)); |
257 | } |
258 | const cl_UP minus (const cl_UP& x, const cl_UP& y) |
259 | { |
260 | if (!(x.ring() == this)) throw runtime_exception(); |
261 | if (!(y.ring() == this)) throw runtime_exception(); |
262 | return cl_UP(this,_minus(x,y)); |
263 | } |
264 | const cl_UP uminus (const cl_UP& x) |
265 | { |
266 | if (!(x.ring() == this)) throw runtime_exception(); |
267 | return cl_UP(this,_uminus(x)); |
268 | } |
269 | const cl_UP one () |
270 | { |
271 | return cl_UP(this,_one()); |
272 | } |
273 | const cl_UP canonhom (const cl_I& x) |
274 | { |
275 | return cl_UP(this,_canonhom(x)); |
276 | } |
277 | const cl_UP mul (const cl_UP& x, const cl_UP& y) |
278 | { |
279 | if (!(x.ring() == this)) throw runtime_exception(); |
280 | if (!(y.ring() == this)) throw runtime_exception(); |
281 | return cl_UP(this,_mul(x,y)); |
282 | } |
283 | const cl_UP square (const cl_UP& x) |
284 | { |
285 | if (!(x.ring() == this)) throw runtime_exception(); |
286 | return cl_UP(this,_square(x)); |
287 | } |
288 | const cl_UP expt_pos (const cl_UP& x, const cl_I& y) |
289 | { |
290 | if (!(x.ring() == this)) throw runtime_exception(); |
291 | return cl_UP(this,_expt_pos(x,y)); |
292 | } |
293 | const cl_UP scalmul (const cl_ring_element& x, const cl_UP& y) |
294 | { |
295 | if (!(y.ring() == this)) throw runtime_exception(); |
296 | return cl_UP(this,_scalmul(x,y)); |
297 | } |
298 | sintL degree (const cl_UP& x) |
299 | { |
300 | if (!(x.ring() == this)) throw runtime_exception(); |
301 | return _degree(x); |
302 | } |
303 | sintL ldegree (const cl_UP& x) |
304 | { |
305 | if (!(x.ring() == this)) throw runtime_exception(); |
306 | return _ldegree(x); |
307 | } |
308 | const cl_UP monomial (const cl_ring_element& x, uintL e) |
309 | { |
310 | return cl_UP(this,_monomial(x,e)); |
311 | } |
312 | const cl_ring_element coeff (const cl_UP& x, uintL index) |
313 | { |
314 | if (!(x.ring() == this)) throw runtime_exception(); |
315 | return _coeff(x,index); |
316 | } |
317 | const cl_UP create (sintL deg) |
318 | { |
319 | return cl_UP(this,_create(deg)); |
320 | } |
321 | void set_coeff (cl_UP& x, uintL index, const cl_ring_element& y) |
322 | { |
323 | if (!(x.ring() == this)) throw runtime_exception(); |
324 | _set_coeff(x,index,y); |
325 | } |
326 | void finalize (cl_UP& x) |
327 | { |
328 | if (!(x.ring() == this)) throw runtime_exception(); |
329 | _finalize(x); |
330 | } |
331 | const cl_ring_element eval (const cl_UP& x, const cl_ring_element& y) |
332 | { |
333 | if (!(x.ring() == this)) throw runtime_exception(); |
334 | return _eval(x,y); |
335 | } |
336 | // Property operations. |
337 | cl_property* get_property (const cl_symbol& key) |
338 | { return properties.get_property(key); } |
339 | void add_property (cl_property* new_property) |
340 | { properties.add_property(new_property); } |
341 | // Constructor. |
342 | cl_heap_univpoly_ring (const cl_ring& r, cl_univpoly_setops*, cl_univpoly_addops*, cl_univpoly_mulops*, cl_univpoly_modulops*, cl_univpoly_polyops*); |
343 | ~cl_heap_univpoly_ring () {} |
344 | }; |
345 | #define SUBCLASS_cl_heap_univpoly_ring() \ |
346 | SUBCLASS_cl_heap_ring() |
347 | |
348 | |
349 | // Lookup or create the "standard" univariate polynomial ring over a ring r. |
350 | extern const cl_univpoly_ring find_univpoly_ring (const cl_ring& r); |
351 | |
352 | // Lookup or create a univariate polynomial ring with a named variable over r. |
353 | extern const cl_univpoly_ring find_univpoly_ring (const cl_ring& r, const cl_symbol& varname); |
354 | |
355 | class cl_UP_init_helper |
356 | { |
357 | static int count; |
358 | public: |
359 | cl_UP_init_helper(); |
360 | ~cl_UP_init_helper(); |
361 | }; |
362 | static cl_UP_init_helper cl_UP_init_helper_instance; |
363 | |
364 | |
365 | // Operations on polynomials. |
366 | |
367 | // Output. |
368 | inline void fprint (std::ostream& stream, const cl_UP& x) |
369 | { x.ring()->fprint(stream,x); } |
370 | CL_DEFINE_PRINT_OPERATOR(cl_UP) |
371 | |
372 | // Add. |
373 | inline const cl_UP operator+ (const cl_UP& x, const cl_UP& y) |
374 | { return x.ring()->plus(x,y); } |
375 | |
376 | // Negate. |
377 | inline const cl_UP operator- (const cl_UP& x) |
378 | { return x.ring()->uminus(x); } |
379 | |
380 | // Subtract. |
381 | inline const cl_UP operator- (const cl_UP& x, const cl_UP& y) |
382 | { return x.ring()->minus(x,y); } |
383 | |
384 | // Equality. |
385 | inline bool operator== (const cl_UP& x, const cl_UP& y) |
386 | { return x.ring()->equal(x,y); } |
387 | inline bool operator!= (const cl_UP& x, const cl_UP& y) |
388 | { return !x.ring()->equal(x,y); } |
389 | |
390 | // Compare against 0. |
391 | inline bool zerop (const cl_UP& x) |
392 | { return x.ring()->zerop(x); } |
393 | |
394 | // Multiply. |
395 | inline const cl_UP operator* (const cl_UP& x, const cl_UP& y) |
396 | { return x.ring()->mul(x,y); } |
397 | |
398 | // Squaring. |
399 | inline const cl_UP square (const cl_UP& x) |
400 | { return x.ring()->square(x); } |
401 | |
402 | // Exponentiation x^y, where y > 0. |
403 | inline const cl_UP expt_pos (const cl_UP& x, const cl_I& y) |
404 | { return x.ring()->expt_pos(x,y); } |
405 | |
406 | // Scalar multiplication. |
407 | #if 0 // less efficient |
408 | inline const cl_UP operator* (const cl_I& x, const cl_UP& y) |
409 | { return y.ring()->mul(y.ring()->canonhom(x),y); } |
410 | inline const cl_UP operator* (const cl_UP& x, const cl_I& y) |
411 | { return x.ring()->mul(x.ring()->canonhom(y),x); } |
412 | #endif |
413 | inline const cl_UP operator* (const cl_I& x, const cl_UP& y) |
414 | { return y.ring()->scalmul(y.ring()->basering()->canonhom(x),y); } |
415 | inline const cl_UP operator* (const cl_UP& x, const cl_I& y) |
416 | { return x.ring()->scalmul(x.ring()->basering()->canonhom(y),x); } |
417 | inline const cl_UP operator* (const cl_ring_element& x, const cl_UP& y) |
418 | { return y.ring()->scalmul(x,y); } |
419 | inline const cl_UP operator* (const cl_UP& x, const cl_ring_element& y) |
420 | { return x.ring()->scalmul(y,x); } |
421 | |
422 | // Degree. |
423 | inline sintL degree (const cl_UP& x) |
424 | { return x.ring()->degree(x); } |
425 | |
426 | // Low degree. |
427 | inline sintL ldegree (const cl_UP& x) |
428 | { return x.ring()->ldegree(x); } |
429 | |
430 | // Coefficient. |
431 | inline const cl_ring_element coeff (const cl_UP& x, uintL index) |
432 | { return x.ring()->coeff(x,index); } |
433 | |
434 | // Destructive modification. |
435 | inline void set_coeff (cl_UP& x, uintL index, const cl_ring_element& y) |
436 | { x.ring()->set_coeff(x,index,y); } |
437 | inline void finalize (cl_UP& x) |
438 | { x.ring()->finalize(x); } |
439 | inline void cl_UP::set_coeff (uintL index, const cl_ring_element& y) |
440 | { ring()->set_coeff(*this,index,y); } |
441 | inline void cl_UP::finalize () |
442 | { ring()->finalize(*this); } |
443 | |
444 | // Evaluation. (No extension of the base ring allowed here for now.) |
445 | inline const cl_ring_element cl_UP::operator() (const cl_ring_element& y) const |
446 | { |
447 | return ring()->eval(*this,y); |
448 | } |
449 | |
450 | // Derivative. |
451 | extern const cl_UP deriv (const cl_UP& x); |
452 | |
453 | |
454 | // Ring of uninitialized elements. |
455 | // Any operation results in a run-time error. |
456 | |
457 | extern const cl_univpoly_ring cl_no_univpoly_ring; |
458 | extern cl_class cl_class_no_univpoly_ring; |
459 | |
460 | class cl_UP_no_ring_init_helper |
461 | { |
462 | static int count; |
463 | public: |
464 | cl_UP_no_ring_init_helper(); |
465 | ~cl_UP_no_ring_init_helper(); |
466 | }; |
467 | static cl_UP_no_ring_init_helper cl_UP_no_ring_init_helper_instance; |
468 | |
469 | inline cl_univpoly_ring::cl_univpoly_ring () |
470 | : cl_ring (as_cl_private_thing(cl_no_univpoly_ring)) {} |
471 | inline _cl_UP::_cl_UP () |
472 | : rep ((cl_private_thing) cl_combine(cl_FN_tag,0)) {} |
473 | inline cl_UP::cl_UP () |
474 | : _cl_UP (), _ring () {} |
475 | |
476 | |
477 | // Debugging support. |
478 | #ifdef CL_DEBUG |
479 | extern int cl_UP_debug_module; |
480 | CL_FORCE_LINK(cl_UP_debug_dummy, cl_UP_debug_module) |
481 | #endif |
482 | |
483 | } // namespace cln |
484 | |
485 | #endif /* _CL_UNIVPOLY_H */ |
486 | |
487 | namespace cln { |
488 | |
489 | // Templates for univariate polynomials of complex/real/rational/integers. |
490 | |
491 | #ifdef notyet |
492 | // Unfortunately, this is not usable now, because of gcc-2.7 bugs: |
493 | // - A template inline function is not inline in the first function that |
494 | // uses it. |
495 | // - Argument matching bug: User-defined conversions are not tried (or |
496 | // tried with too low priority) for template functions w.r.t. normal |
497 | // functions. For example, a call expt_pos(cl_UP_specialized<cl_N>,int) |
498 | // is compiled as expt_pos(const cl_UP&, const cl_I&) instead of |
499 | // expt_pos(const cl_UP_specialized<cl_N>&, const cl_I&). |
500 | // It will, however, be usable when gcc-2.8 is released. |
501 | |
502 | #if defined(_CL_UNIVPOLY_COMPLEX_H) || defined(_CL_UNIVPOLY_REAL_H) || defined(_CL_UNIVPOLY_RATIONAL_H) || defined(_CL_UNIVPOLY_INTEGER_H) |
503 | #ifndef _CL_UNIVPOLY_AUX_H |
504 | |
505 | // Normal univariate polynomials with stricter static typing: |
506 | // `class T' instead of `cl_ring_element'. |
507 | |
508 | template <class T> class cl_univpoly_specialized_ring; |
509 | template <class T> class cl_UP_specialized; |
510 | template <class T> class cl_heap_univpoly_specialized_ring; |
511 | |
512 | template <class T> |
513 | class cl_univpoly_specialized_ring : public cl_univpoly_ring { |
514 | public: |
515 | // Default constructor. |
516 | cl_univpoly_specialized_ring () : cl_univpoly_ring () {} |
517 | // Copy constructor. |
518 | cl_univpoly_specialized_ring (const cl_univpoly_specialized_ring&); |
519 | // Assignment operator. |
520 | cl_univpoly_specialized_ring& operator= (const cl_univpoly_specialized_ring&); |
521 | // Automatic dereferencing. |
522 | cl_heap_univpoly_specialized_ring<T>* operator-> () const |
523 | { return (cl_heap_univpoly_specialized_ring<T>*)heappointer; } |
524 | }; |
525 | // Copy constructor and assignment operator. |
526 | template <class T> |
527 | _CL_DEFINE_COPY_CONSTRUCTOR2(cl_univpoly_specialized_ring<T>,cl_univpoly_specialized_ring,cl_univpoly_ring) |
528 | template <class T> |
529 | CL_DEFINE_ASSIGNMENT_OPERATOR(cl_univpoly_specialized_ring<T>,cl_univpoly_specialized_ring<T>) |
530 | |
531 | template <class T> |
532 | class cl_UP_specialized : public cl_UP { |
533 | public: |
534 | const cl_univpoly_specialized_ring<T>& ring () const { return The(cl_univpoly_specialized_ring<T>)(_ring); } |
535 | // Conversion. |
536 | CL_DEFINE_CONVERTER(cl_ring_element) |
537 | // Destructive modification. |
538 | void set_coeff (uintL index, const T& y); |
539 | void finalize(); |
540 | // Evaluation. |
541 | const T operator() (const T& y) const; |
542 | public: // Ability to place an object at a given address. |
543 | void* operator new (size_t size) { return malloc_hook(size); } |
544 | void* operator new (size_t size, void* ptr) { (void)size; return ptr; } |
545 | void operator delete (void* ptr) { free_hook(ptr); } |
546 | }; |
547 | |
548 | template <class T> |
549 | class cl_heap_univpoly_specialized_ring : public cl_heap_univpoly_ring { |
550 | SUBCLASS_cl_heap_univpoly_ring() |
551 | // High-level operations. |
552 | void fprint (std::ostream& stream, const cl_UP_specialized<T>& x) |
553 | { |
554 | cl_heap_univpoly_ring::fprint(stream,x); |
555 | } |
556 | bool equal (const cl_UP_specialized<T>& x, const cl_UP_specialized<T>& y) |
557 | { |
558 | return cl_heap_univpoly_ring::equal(x,y); |
559 | } |
560 | const cl_UP_specialized<T> zero () |
561 | { |
562 | return The2(cl_UP_specialized<T>)(cl_heap_univpoly_ring::zero()); |
563 | } |
564 | bool zerop (const cl_UP_specialized<T>& x) |
565 | { |
566 | return cl_heap_univpoly_ring::zerop(x); |
567 | } |
568 | const cl_UP_specialized<T> plus (const cl_UP_specialized<T>& x, const cl_UP_specialized<T>& y) |
569 | { |
570 | return The2(cl_UP_specialized<T>)(cl_heap_univpoly_ring::plus(x,y)); |
571 | } |
572 | const cl_UP_specialized<T> minus (const cl_UP_specialized<T>& x, const cl_UP_specialized<T>& y) |
573 | { |
574 | return The2(cl_UP_specialized<T>)(cl_heap_univpoly_ring::minus(x,y)); |
575 | } |
576 | const cl_UP_specialized<T> uminus (const cl_UP_specialized<T>& x) |
577 | { |
578 | return The2(cl_UP_specialized<T>)(cl_heap_univpoly_ring::uminus(x)); |
579 | } |
580 | const cl_UP_specialized<T> one () |
581 | { |
582 | return The2(cl_UP_specialized<T>)(cl_heap_univpoly_ring::one()); |
583 | } |
584 | const cl_UP_specialized<T> canonhom (const cl_I& x) |
585 | { |
586 | return The2(cl_UP_specialized<T>)(cl_heap_univpoly_ring::canonhom(x)); |
587 | } |
588 | const cl_UP_specialized<T> mul (const cl_UP_specialized<T>& x, const cl_UP_specialized<T>& y) |
589 | { |
590 | return The2(cl_UP_specialized<T>)(cl_heap_univpoly_ring::mul(x,y)); |
591 | } |
592 | const cl_UP_specialized<T> square (const cl_UP_specialized<T>& x) |
593 | { |
594 | return The2(cl_UP_specialized<T>)(cl_heap_univpoly_ring::square(x)); |
595 | } |
596 | const cl_UP_specialized<T> expt_pos (const cl_UP_specialized<T>& x, const cl_I& y) |
597 | { |
598 | return The2(cl_UP_specialized<T>)(cl_heap_univpoly_ring::expt_pos(x,y)); |
599 | } |
600 | const cl_UP_specialized<T> scalmul (const T& x, const cl_UP_specialized<T>& y) |
601 | { |
602 | return The2(cl_UP_specialized<T>)(cl_heap_univpoly_ring::scalmul(x,y)); |
603 | } |
604 | sintL degree (const cl_UP_specialized<T>& x) |
605 | { |
606 | return cl_heap_univpoly_ring::degree(x); |
607 | } |
608 | sintL ldegree (const cl_UP_specialized<T>& x) |
609 | { |
610 | return cl_heap_univpoly_ring::ldegree(x); |
611 | } |
612 | const cl_UP_specialized<T> monomial (const T& x, uintL e) |
613 | { |
614 | return The2(cl_UP_specialized<T>)(cl_heap_univpoly_ring::monomial(cl_ring_element(cl_C_ring??,x),e)); |
615 | } |
616 | const T coeff (const cl_UP_specialized<T>& x, uintL index) |
617 | { |
618 | return The(T)(cl_heap_univpoly_ring::coeff(x,index)); |
619 | } |
620 | const cl_UP_specialized<T> create (sintL deg) |
621 | { |
622 | return The2(cl_UP_specialized<T>)(cl_heap_univpoly_ring::create(deg)); |
623 | } |
624 | void set_coeff (cl_UP_specialized<T>& x, uintL index, const T& y) |
625 | { |
626 | cl_heap_univpoly_ring::set_coeff(x,index,cl_ring_element(cl_C_ring??,y)); |
627 | } |
628 | void finalize (cl_UP_specialized<T>& x) |
629 | { |
630 | cl_heap_univpoly_ring::finalize(x); |
631 | } |
632 | const T eval (const cl_UP_specialized<T>& x, const T& y) |
633 | { |
634 | return The(T)(cl_heap_univpoly_ring::eval(x,cl_ring_element(cl_C_ring??,y))); |
635 | } |
636 | private: |
637 | // No need for any constructors. |
638 | cl_heap_univpoly_specialized_ring (); |
639 | }; |
640 | |
641 | // Lookup of polynomial rings. |
642 | template <class T> |
643 | inline const cl_univpoly_specialized_ring<T> find_univpoly_ring (const cl_specialized_number_ring<T>& r) |
644 | { return The(cl_univpoly_specialized_ring<T>) (find_univpoly_ring((const cl_ring&)r)); } |
645 | template <class T> |
646 | inline const cl_univpoly_specialized_ring<T> find_univpoly_ring (const cl_specialized_number_ring<T>& r, const cl_symbol& varname) |
647 | { return The(cl_univpoly_specialized_ring<T>) (find_univpoly_ring((const cl_ring&)r,varname)); } |
648 | |
649 | // Operations on polynomials. |
650 | |
651 | // Add. |
652 | template <class T> |
653 | inline const cl_UP_specialized<T> operator+ (const cl_UP_specialized<T>& x, const cl_UP_specialized<T>& y) |
654 | { return x.ring()->plus(x,y); } |
655 | |
656 | // Negate. |
657 | template <class T> |
658 | inline const cl_UP_specialized<T> operator- (const cl_UP_specialized<T>& x) |
659 | { return x.ring()->uminus(x); } |
660 | |
661 | // Subtract. |
662 | template <class T> |
663 | inline const cl_UP_specialized<T> operator- (const cl_UP_specialized<T>& x, const cl_UP_specialized<T>& y) |
664 | { return x.ring()->minus(x,y); } |
665 | |
666 | // Multiply. |
667 | template <class T> |
668 | inline const cl_UP_specialized<T> operator* (const cl_UP_specialized<T>& x, const cl_UP_specialized<T>& y) |
669 | { return x.ring()->mul(x,y); } |
670 | |
671 | // Squaring. |
672 | template <class T> |
673 | inline const cl_UP_specialized<T> square (const cl_UP_specialized<T>& x) |
674 | { return x.ring()->square(x); } |
675 | |
676 | // Exponentiation x^y, where y > 0. |
677 | template <class T> |
678 | inline const cl_UP_specialized<T> expt_pos (const cl_UP_specialized<T>& x, const cl_I& y) |
679 | { return x.ring()->expt_pos(x,y); } |
680 | |
681 | // Scalar multiplication. |
682 | // Need more discrimination on T ?? |
683 | template <class T> |
684 | inline const cl_UP_specialized<T> operator* (const cl_I& x, const cl_UP_specialized<T>& y) |
685 | { return y.ring()->mul(y.ring()->canonhom(x),y); } |
686 | template <class T> |
687 | inline const cl_UP_specialized<T> operator* (const cl_UP_specialized<T>& x, const cl_I& y) |
688 | { return x.ring()->mul(x.ring()->canonhom(y),x); } |
689 | template <class T> |
690 | inline const cl_UP_specialized<T> operator* (const T& x, const cl_UP_specialized<T>& y) |
691 | { return y.ring()->scalmul(x,y); } |
692 | template <class T> |
693 | inline const cl_UP_specialized<T> operator* (const cl_UP_specialized<T>& x, const T& y) |
694 | { return x.ring()->scalmul(y,x); } |
695 | |
696 | // Coefficient. |
697 | template <class T> |
698 | inline const T coeff (const cl_UP_specialized<T>& x, uintL index) |
699 | { return x.ring()->coeff(x,index); } |
700 | |
701 | // Destructive modification. |
702 | template <class T> |
703 | inline void set_coeff (cl_UP_specialized<T>& x, uintL index, const T& y) |
704 | { x.ring()->set_coeff(x,index,y); } |
705 | template <class T> |
706 | inline void finalize (cl_UP_specialized<T>& x) |
707 | { x.ring()->finalize(x); } |
708 | template <class T> |
709 | inline void cl_UP_specialized<T>::set_coeff (uintL index, const T& y) |
710 | { ring()->set_coeff(*this,index,y); } |
711 | template <class T> |
712 | inline void cl_UP_specialized<T>::finalize () |
713 | { ring()->finalize(*this); } |
714 | |
715 | // Evaluation. (No extension of the base ring allowed here for now.) |
716 | template <class T> |
717 | inline const T cl_UP_specialized<T>::operator() (const T& y) const |
718 | { |
719 | return ring()->eval(*this,y); |
720 | } |
721 | |
722 | // Derivative. |
723 | template <class T> |
724 | inline const cl_UP_specialized<T> deriv (const cl_UP_specialized<T>& x) |
725 | { return The(cl_UP_specialized<T>)(deriv((const cl_UP&)x)); } |
726 | |
727 | |
728 | #endif /* _CL_UNIVPOLY_AUX_H */ |
729 | #endif |
730 | |
731 | #endif /* notyet */ |
732 | |
733 | } // namespace cln |
734 | |