1 | /**************************************** |
---|
2 | * Computer Algebra System SINGULAR * |
---|
3 | ****************************************/ |
---|
4 | /*************************************************************** |
---|
5 | * File: p_Procs.cc |
---|
6 | * Purpose: implementation of primitive procs for polys |
---|
7 | * Author: obachman (Olaf Bachmann) |
---|
8 | * Created: 8/00 |
---|
9 | * Version: $Id: p_Procs.cc,v 1.1 2000-08-24 14:42:43 obachman Exp $ |
---|
10 | *******************************************************************/ |
---|
11 | #include "mod2.h" |
---|
12 | |
---|
13 | |
---|
14 | /*************************************************************** |
---|
15 | * |
---|
16 | * Configurations |
---|
17 | * |
---|
18 | *******************************************************************/ |
---|
19 | |
---|
20 | /*************************************************************** |
---|
21 | Here is how it works: |
---|
22 | At run-time, SetProcs is used to choose the appropriate PolyProcs |
---|
23 | based on the ring properies. |
---|
24 | At generate-time, SetProcs is used to generate all |
---|
25 | possible PolyProcs. |
---|
26 | Which PolyProcs are generated/used can be controled by values of |
---|
27 | HAVE_FAST_P_PROCS, HAVE_FAST_LENGTH, HAVE_FAST_ORD, and FAST_FIELD |
---|
28 | |
---|
29 | At generate-time, the file p_Procs.inc is generated, |
---|
30 | which provides implementations of the p_Procs, based on |
---|
31 | the p_*_Templates.cc and header files which provide the respective |
---|
32 | macros. |
---|
33 | |
---|
34 | At run-time, a fast proc is set/choosen if found/generated, else |
---|
35 | a general proc is set/choosen. |
---|
36 | *******************************************************************/ |
---|
37 | |
---|
38 | // Set HAVE_FAST_P_PROCS to: |
---|
39 | // 0 -- only FieldGeneral_LengthGeneral_OrdGeneral |
---|
40 | // 1 -- plus FieldZp_Length*_OrdGeneral procs |
---|
41 | // 2 -- plus FiedZp_Length*_Ord* procs |
---|
42 | // 3 -- plus Field*_Length*_OrdGeneral procs |
---|
43 | // 4 -- all Field*_Length*_Ord* procs |
---|
44 | const int HAVE_FAST_P_PROCS = 4; |
---|
45 | |
---|
46 | // Set HAVE_FAST_FIELD to: |
---|
47 | // 0 -- only FieldGeneral |
---|
48 | // 1 -- special cases for FieldZp |
---|
49 | // nothing else is implemented, yet |
---|
50 | const int HAVE_FAST_FIELD = 1; |
---|
51 | |
---|
52 | // Set HAVE_FAST_LENGTH to: |
---|
53 | // 0 -- only LengthGeneral |
---|
54 | // 1 -- special cases for length <= 1 |
---|
55 | // 2 -- special cases for length <= 2 |
---|
56 | // 3 -- special cases for length <= 4 |
---|
57 | // 4 -- special cases for length <= 8 |
---|
58 | const int HAVE_FAST_LENGTH = 4; |
---|
59 | |
---|
60 | // Set HAVE_FAST_ORD to: |
---|
61 | // 0 -- only OrdGeneral |
---|
62 | // 1 -- special for ords with n_min <= 1 |
---|
63 | // 2 -- special for ords with n_min <= 2 |
---|
64 | // 3 -- special ords for with n_min <= 3 |
---|
65 | // 4 -- special for all ords |
---|
66 | const int HAVE_FAST_ORD = 4; |
---|
67 | |
---|
68 | // undefine this, if ExpLSize always equals CompLSize |
---|
69 | #define HAVE_LENGTH_DIFF |
---|
70 | // Set HAVE_FAST_ZERO_ORD to: |
---|
71 | // 0 -- no zero ords are considered |
---|
72 | // 1 -- only ZeroOrds for OrdPosNomogPosZero, OrdNomogPosZero, OrdPomogNegZero |
---|
73 | // 2 -- ZeroOrds for all |
---|
74 | const int HAVE_FAST_ZERO_ORD = 2; |
---|
75 | |
---|
76 | // Predicate which returns true if alloc/copy/free of numbers is |
---|
77 | // like that of Zp |
---|
78 | #define ZP_COPY_FIELD(field) \ |
---|
79 | (field == FieldZp || field == FieldGF || field == FieldR) |
---|
80 | |
---|
81 | /*************************************************************** |
---|
82 | * |
---|
83 | * Definitions of our fields, lengths, ords, procs we work with |
---|
84 | * |
---|
85 | *******************************************************************/ |
---|
86 | |
---|
87 | // Here are the different parameters for setting the PolyProcs: |
---|
88 | |
---|
89 | // If you add/remove things from here, also remeber to adjust the |
---|
90 | // respective *_2_String |
---|
91 | typedef enum p_Field |
---|
92 | { |
---|
93 | FieldGeneral = 0, |
---|
94 | FieldZp, |
---|
95 | FieldR, |
---|
96 | FieldGF, |
---|
97 | #if HAVE_MORE_FIELDS_IMPLEMENTED |
---|
98 | FieldQ, |
---|
99 | FieldLong_R, |
---|
100 | FieldLong_C, |
---|
101 | FieldZp_a, |
---|
102 | FieldQ_a, |
---|
103 | #endif |
---|
104 | FieldUnknown |
---|
105 | }; |
---|
106 | typedef enum p_Length // Length of exponent vector in words |
---|
107 | { |
---|
108 | LengthGeneral = 0, // n >= 1 |
---|
109 | LengthEight, // n == 8 |
---|
110 | LengthSeven, |
---|
111 | LengthSix, |
---|
112 | LengthFive, |
---|
113 | LengthFour, |
---|
114 | LengthThree, |
---|
115 | LengthTwo, |
---|
116 | LengthOne, |
---|
117 | LengthUnknown |
---|
118 | }; |
---|
119 | typedef enum p_Ord |
---|
120 | { |
---|
121 | OrdGeneral = 0, |
---|
122 | // ordsgn |
---|
123 | // 0 1 i n-1 n n_min Example |
---|
124 | OrdPomog, // + + + + + 1 (lp,C) |
---|
125 | OrdNomog, // - - - - - 1 (ls, c), (ds, c) |
---|
126 | #define ORD_MAX_N_1 OrdNomog |
---|
127 | |
---|
128 | #ifdef HAVE_LENGTH_DIFF |
---|
129 | OrdPomogZero, // + + + + 0 2 (Dp, C), Even vars |
---|
130 | OrdNomogZero, // - - - - 0 2 (ds, c), Even vars |
---|
131 | #endif |
---|
132 | |
---|
133 | OrdNegPomog, // - + + + + 2 (c, lp), (Ds, c) |
---|
134 | OrdPomogNeg, // + + + + - 2 (lp, c) |
---|
135 | #define ORD_MAX_N_2 OrdPomogNeg |
---|
136 | |
---|
137 | OrdPosNomog, // + - - - + 3 (dp, c) (for n == 2, use PomogNeg) |
---|
138 | OrdNomogPos, // - - - - + 3 (ls, C) (for n == 2, use NegPomog) |
---|
139 | |
---|
140 | #ifdef HAVE_LENGTH_DIFF |
---|
141 | OrdNegPomogZero, // - + + + 0 3 (c, lp), (Ds, c) |
---|
142 | OrdPomogNegZero, // + + + - 0 3 (lp, c) |
---|
143 | #endif |
---|
144 | |
---|
145 | OrdPosPosNomog, // + + - - - 3 (C, dp) |
---|
146 | OrdPosNomogPos, // + - - - + 3 (dp, C) |
---|
147 | OrdNegPosNomog, // - + - - - 3 (c, dp) |
---|
148 | #define ORD_MAX_N_3 OrdNegPosNomog |
---|
149 | |
---|
150 | #ifdef HAVE_LENGTH_DIFF |
---|
151 | OrdNomogPosZero, // - - - + 0 4 (ls, C) (for n == 3, use NegPomogZero) |
---|
152 | OrdPosNomogZero, // + - - - 0 4 (dp, c) (for n == 3, use PomogNegZero) |
---|
153 | |
---|
154 | OrdPosPosNomogZero,// + + - - 0 4 (C, dp) |
---|
155 | OrdPosNomogPosZero,// + - - + 0 4 (dp, C) |
---|
156 | OrdNegPosNomogZero,// - + - - 0 4 (c, dp) |
---|
157 | #endif |
---|
158 | |
---|
159 | OrdUnknown |
---|
160 | }; |
---|
161 | |
---|
162 | typedef enum p_Proc |
---|
163 | { |
---|
164 | p_Copy_Proc = 0, |
---|
165 | p_Delete_Proc, |
---|
166 | p_ShallowCopyDelete_Proc, |
---|
167 | p_Mult_n_Proc, |
---|
168 | p_Mult_m_Proc, |
---|
169 | p_Add_q_Proc, |
---|
170 | p_Minus_m_Mult_q_Proc, |
---|
171 | p_Unknown_Proc |
---|
172 | }; |
---|
173 | |
---|
174 | // *_2_String conversions of these enums |
---|
175 | // they are only needed at for GENERATE_P_PROCS or RDEBUG |
---|
176 | #if defined(GENERATE_P_PROCS) || defined(RDEBUG) |
---|
177 | char* p_FieldEnum_2_String(p_Field field) |
---|
178 | { |
---|
179 | switch(field) |
---|
180 | { |
---|
181 | case FieldGeneral: return "FieldGeneral"; |
---|
182 | case FieldZp: return "FieldZp"; |
---|
183 | case FieldR: return "FieldR"; |
---|
184 | case FieldGF: return "FieldGF"; |
---|
185 | #if HAVE_MORE_FIELDS_IMPLEMENTED |
---|
186 | case FieldQ: return "FieldQ"; |
---|
187 | case FieldLong_R: return "FieldLong_R"; |
---|
188 | case FieldLong_C: return "FieldLong_C"; |
---|
189 | case FieldZp_a: return "FieldZp_a"; |
---|
190 | case FieldQ_a: return "FieldQ_a"; |
---|
191 | #endif |
---|
192 | case FieldUnknown: return "FieldUnknown"; |
---|
193 | } |
---|
194 | return "NoField_2_String"; |
---|
195 | } |
---|
196 | |
---|
197 | char* p_LengthEnum_2_String(p_Length length) |
---|
198 | { |
---|
199 | switch(length) |
---|
200 | { |
---|
201 | case LengthGeneral: return "LengthGeneral"; |
---|
202 | case LengthEight: return "LengthEight"; |
---|
203 | case LengthSeven: return "LengthSeven"; |
---|
204 | case LengthSix: return "LengthSix"; |
---|
205 | case LengthFive: return "LengthFive"; |
---|
206 | case LengthFour: return "LengthFour"; |
---|
207 | case LengthThree: return "LengthThree"; |
---|
208 | case LengthTwo: return "LengthTwo"; |
---|
209 | case LengthOne: return "LengthOne"; |
---|
210 | case LengthUnknown: return "LengthUnknown"; |
---|
211 | } |
---|
212 | return "NoLength_2_String"; |
---|
213 | } |
---|
214 | |
---|
215 | char* p_OrdEnum_2_String(p_Ord ord) |
---|
216 | { |
---|
217 | switch(ord) |
---|
218 | { |
---|
219 | case OrdGeneral: return "OrdGeneral"; |
---|
220 | case OrdPomog: return "OrdPomog"; |
---|
221 | case OrdNomog: return "OrdNomog"; |
---|
222 | case OrdNegPomog: return "OrdNegPomog"; |
---|
223 | case OrdPomogNeg: return "OrdPomogNeg"; |
---|
224 | case OrdPosNomog: return "OrdPosNomog"; |
---|
225 | case OrdNomogPos: return "OrdNomogPos"; |
---|
226 | case OrdPosPosNomog: return "OrdPosPosNomog"; |
---|
227 | case OrdPosNomogPos: return "OrdPosNomogPos"; |
---|
228 | case OrdNegPosNomog: return "OrdNegPosNomog"; |
---|
229 | #ifdef HAVE_LENGTH_DIFF |
---|
230 | case OrdNegPomogZero: return "OrdNegPomogZero"; |
---|
231 | case OrdPomogNegZero: return "OrdPomogNegZero"; |
---|
232 | case OrdPomogZero: return "OrdPomogZero"; |
---|
233 | case OrdNomogZero: return "OrdNomogZero"; |
---|
234 | case OrdNomogPosZero: return "OrdNomogPosZero"; |
---|
235 | case OrdPosNomogZero: return "OrdPosNomogZero"; |
---|
236 | case OrdPosPosNomogZero: return "OrdPosPosNomogZero"; |
---|
237 | case OrdPosNomogPosZero: return "OrdPosNomogPosZero"; |
---|
238 | case OrdNegPosNomogZero: return "OrdNegPosNomogZero"; |
---|
239 | #endif |
---|
240 | case OrdUnknown: return "OrdUnknown"; |
---|
241 | } |
---|
242 | return "NoOrd_2_String"; |
---|
243 | } |
---|
244 | |
---|
245 | char* p_ProcEnum_2_String(p_Proc proc) |
---|
246 | { |
---|
247 | switch(proc) |
---|
248 | { |
---|
249 | case p_Copy_Proc: return "p_Copy_Proc"; |
---|
250 | case p_Delete_Proc: return "p_Delete_Proc"; |
---|
251 | case p_ShallowCopyDelete_Proc: return "p_ShallowCopyDelete_Proc"; |
---|
252 | case p_Mult_n_Proc: return "p_Mult_n_Proc"; |
---|
253 | case p_Mult_m_Proc: return "p_Mult_m_Proc"; |
---|
254 | case p_Add_q_Proc: return "p_Add_q_Proc"; |
---|
255 | case p_Minus_m_Mult_q_Proc: return "p_Minus_m_Mult_q_Proc"; |
---|
256 | case p_Unknown_Proc: return "p_Unknown_Proc"; |
---|
257 | } |
---|
258 | return "NoProc_2_String"; |
---|
259 | } |
---|
260 | #endif // defined(GENERATE_P_PROCS) || defined(RDEBUG) |
---|
261 | |
---|
262 | |
---|
263 | #ifdef GENERATE_P_PROCS |
---|
264 | #include <stdio.h> |
---|
265 | #define assume_violation(f, l) do{fprintf(stderr, "assume violation: %s:%d\n", f, l);exit(1);}while(0) |
---|
266 | #endif |
---|
267 | |
---|
268 | /*************************************************************** |
---|
269 | * |
---|
270 | * |
---|
271 | * Deal with OrdZero |
---|
272 | * |
---|
273 | *******************************************************************/ |
---|
274 | #ifdef HAVE_LENGTH_DIFF |
---|
275 | static inline int IsZeroOrd(p_Ord ord) |
---|
276 | { |
---|
277 | return (ord == OrdPomogZero || ord == OrdNomogZero || |
---|
278 | ord == OrdNegPomogZero || ord == OrdPosNomogZero || |
---|
279 | ord == OrdPomogNegZero || ord == OrdNomogPosZero || |
---|
280 | ord == OrdPosNomogPosZero || ord == OrdPosPosNomogZero || |
---|
281 | ord == OrdNegPosNomogZero); |
---|
282 | } |
---|
283 | |
---|
284 | static inline p_Ord ZeroOrd_2_NonZeroOrd(p_Ord ord, int strict) |
---|
285 | { |
---|
286 | if (IsZeroOrd(ord)) |
---|
287 | { |
---|
288 | switch (ord) |
---|
289 | { |
---|
290 | case OrdPomogZero: return OrdPomog; |
---|
291 | case OrdNomogZero: return OrdNomog; |
---|
292 | case OrdNegPomogZero: return OrdNegPomog; |
---|
293 | case OrdPosNomogZero: return OrdPosNomog; |
---|
294 | case OrdPosPosNomogZero: return OrdPosPosNomog; |
---|
295 | case OrdNegPosNomogZero: return OrdNegPosNomog; |
---|
296 | default: |
---|
297 | if (strict) return OrdGeneral; |
---|
298 | else if (ord == OrdPomogNegZero) return OrdPomogNeg; |
---|
299 | else if (ord == OrdNomogPosZero) return OrdNomogPos; |
---|
300 | else if (ord == OrdPosNomogPosZero) return OrdPosNomogPos; |
---|
301 | else return OrdGeneral; |
---|
302 | } |
---|
303 | } |
---|
304 | else |
---|
305 | { |
---|
306 | return ord; |
---|
307 | } |
---|
308 | } |
---|
309 | #else |
---|
310 | #define IsZeroOrd(ord) 0 |
---|
311 | #define ZeroOrd_2_NonZeroOrd(ord) (ord) |
---|
312 | #endif |
---|
313 | |
---|
314 | /*************************************************************** |
---|
315 | * |
---|
316 | * Filters which are applied to field/length/ord, before a proc is |
---|
317 | * choosen |
---|
318 | * |
---|
319 | *******************************************************************/ |
---|
320 | static inline void FastP_ProcsFilter(p_Field &field, p_Length &length, p_Ord &ord) |
---|
321 | { |
---|
322 | if (HAVE_FAST_P_PROCS >= 4) return; |
---|
323 | |
---|
324 | if ((HAVE_FAST_P_PROCS == 0) || |
---|
325 | (HAVE_FAST_P_PROCS <= 3 && field != FieldZp)) |
---|
326 | { |
---|
327 | field = FieldGeneral; |
---|
328 | length = LengthGeneral; |
---|
329 | ord = OrdGeneral; |
---|
330 | return; |
---|
331 | } |
---|
332 | if (HAVE_FAST_P_PROCS == 1 || (HAVE_FAST_P_PROCS == 3 && field != FieldZp)) |
---|
333 | ord = OrdGeneral; |
---|
334 | } |
---|
335 | |
---|
336 | static inline void FastFieldFilter(p_Field &field) |
---|
337 | { |
---|
338 | if (HAVE_FAST_FIELD == 0 || field != FieldZp) |
---|
339 | field = FieldGeneral; |
---|
340 | } |
---|
341 | |
---|
342 | static inline void FastLengthFilter(p_Length &length) |
---|
343 | { |
---|
344 | if ((HAVE_FAST_LENGTH == 3 && length <= LengthFive) || |
---|
345 | (HAVE_FAST_LENGTH == 2 && length <= LengthFour) || |
---|
346 | (HAVE_FAST_LENGTH == 1 && length <= LengthTwo) || |
---|
347 | (HAVE_FAST_LENGTH <= 0)) |
---|
348 | { |
---|
349 | length = LengthGeneral; |
---|
350 | } |
---|
351 | } |
---|
352 | |
---|
353 | static inline void FastOrdFilter(p_Ord &ord) |
---|
354 | { |
---|
355 | if ((HAVE_FAST_ORD == 3 && ord >= OrdNomogPosZero) || |
---|
356 | (HAVE_FAST_ORD == 2 && ord >= OrdPosNomog) || |
---|
357 | (HAVE_FAST_ORD == 1 && ord >= OrdPomogZero) || |
---|
358 | (HAVE_FAST_ORD <= 0)) |
---|
359 | ord = OrdGeneral; |
---|
360 | } |
---|
361 | |
---|
362 | static inline void FastOrdZeroFilter(p_Ord &ord) |
---|
363 | { |
---|
364 | if (IsZeroOrd(ord)) |
---|
365 | { |
---|
366 | if ((HAVE_FAST_ZERO_ORD == 1 && (ord != OrdPosNomogPosZero && |
---|
367 | ord != OrdNomogPosZero && |
---|
368 | ord != OrdPomogNegZero)) || |
---|
369 | (HAVE_FAST_ZERO_ORD <= 0)) |
---|
370 | ord = ZeroOrd_2_NonZeroOrd(ord, 1); |
---|
371 | } |
---|
372 | } |
---|
373 | |
---|
374 | static inline void NCopy__Filter(p_Field &field) |
---|
375 | { |
---|
376 | if (ZP_COPY_FIELD(field)) field = FieldZp; |
---|
377 | } |
---|
378 | |
---|
379 | // in p_Add_q, p_MemCmp works with CompLSize, |
---|
380 | // hence, we do not need to consider ZeroOrds |
---|
381 | static inline void p_Add_q__Filter(p_Length &length, p_Ord &ord) |
---|
382 | { |
---|
383 | if (IsZeroOrd(ord)) |
---|
384 | { |
---|
385 | ord = ZeroOrd_2_NonZeroOrd(ord, 0); |
---|
386 | if (length > LengthGeneral) |
---|
387 | { |
---|
388 | length = (p_Length) ((int)length + 1); |
---|
389 | } |
---|
390 | } |
---|
391 | } |
---|
392 | |
---|
393 | static inline void FastProcFilter(p_Proc proc, p_Field &field, p_Length &length, |
---|
394 | p_Ord &ord) |
---|
395 | { |
---|
396 | switch(proc) |
---|
397 | { |
---|
398 | case p_Add_q_Proc: |
---|
399 | p_Add_q__Filter(length, ord); |
---|
400 | break; |
---|
401 | |
---|
402 | case p_Copy_Proc: |
---|
403 | case p_Delete_Proc: |
---|
404 | NCopy__Filter(field); |
---|
405 | break; |
---|
406 | |
---|
407 | default: break; |
---|
408 | } |
---|
409 | |
---|
410 | FastOrdFilter(ord); |
---|
411 | FastLengthFilter(length); |
---|
412 | FastFieldFilter(field); |
---|
413 | FastP_ProcsFilter(field, length, ord); |
---|
414 | } |
---|
415 | |
---|
416 | // returns 1 if combination of field/length/ord is invalid |
---|
417 | static inline int IsValidSpec(p_Field field, p_Length length, p_Ord ord) |
---|
418 | { |
---|
419 | if (field == FieldUnknown || length == LengthUnknown || ord == OrdUnknown) |
---|
420 | return 0; |
---|
421 | |
---|
422 | if (length >= LengthThree && // i.e. 1, 2, or 3 |
---|
423 | ord > ORD_MAX_N_3) // i.e. OrdNomogPosZero and below |
---|
424 | return 0; |
---|
425 | |
---|
426 | if (length >= LengthTwo && // i.e. 1 or 2 |
---|
427 | ord > ORD_MAX_N_2) // i.e. PosNomog and below |
---|
428 | return 0; |
---|
429 | |
---|
430 | if (length == LengthOne && |
---|
431 | ord > ORD_MAX_N_1) // i.e. PosPomogZero and below |
---|
432 | return 0; |
---|
433 | |
---|
434 | // we cover everything for length <= two |
---|
435 | if (ord == OrdGeneral && length >= LengthTwo) |
---|
436 | return 0; |
---|
437 | return 1; |
---|
438 | } |
---|
439 | |
---|
440 | |
---|
441 | static inline int index(p_Field field, p_Length length) |
---|
442 | { |
---|
443 | return field*LengthUnknown + length; |
---|
444 | } |
---|
445 | |
---|
446 | static inline int index(p_Field field, p_Length length, p_Ord ord) |
---|
447 | { |
---|
448 | return field*LengthUnknown*OrdUnknown + length*OrdUnknown + ord; |
---|
449 | } |
---|
450 | |
---|
451 | static inline int index(p_Proc proc, p_Field field, p_Length length, p_Ord ord) |
---|
452 | { |
---|
453 | switch(proc) |
---|
454 | { |
---|
455 | case p_Delete_Proc: |
---|
456 | case p_Mult_n_Proc: |
---|
457 | return field; |
---|
458 | |
---|
459 | case p_ShallowCopyDelete_Proc: |
---|
460 | return length; |
---|
461 | |
---|
462 | case p_Copy_Proc: |
---|
463 | case p_Mult_m_Proc: |
---|
464 | return index(field, length); |
---|
465 | |
---|
466 | case p_Add_q_Proc: |
---|
467 | case p_Minus_m_Mult_q_Proc: |
---|
468 | return index(field, length, ord); |
---|
469 | |
---|
470 | default: |
---|
471 | assume(0); |
---|
472 | return -1; |
---|
473 | } |
---|
474 | } |
---|
475 | |
---|
476 | // The procedure which does the work of choosing/generating a |
---|
477 | // set of poly procs |
---|
478 | static void SetProcs(p_Field field, p_Length length, p_Ord ord); |
---|
479 | |
---|
480 | |
---|
481 | #ifndef GENERATE_P_PROCS |
---|
482 | |
---|
483 | /*************************************************************** |
---|
484 | * |
---|
485 | * Runtime stuff |
---|
486 | * |
---|
487 | ***************************************************************/ |
---|
488 | #include "structs.h" |
---|
489 | #include "ring.h" |
---|
490 | #include "polys.h" |
---|
491 | #include "polys-impl.h" |
---|
492 | #include "p_Procs.h" |
---|
493 | #include "p_Numbers.h" |
---|
494 | #include "p_MemCmp.h" |
---|
495 | #include "p_MemAdd.h" |
---|
496 | #include "p_MemCopy.h" |
---|
497 | #define FreeAndAdvance(p) \ |
---|
498 | do \ |
---|
499 | { \ |
---|
500 | poly _pn = pNext(p); \ |
---|
501 | omFreeBinAddr(p); \ |
---|
502 | p = _pn; \ |
---|
503 | } \ |
---|
504 | while (0) |
---|
505 | |
---|
506 | // now include the generated pprocs |
---|
507 | extern int rComp0_Func(poly p1,poly p2); |
---|
508 | #undef rComp0 |
---|
509 | #define rComp0 rComp0_Func |
---|
510 | #include "p_Procs.inc" |
---|
511 | |
---|
512 | // the rest is related to getting the procs |
---|
513 | static inline p_Field p_FieldIs(ring r) |
---|
514 | { |
---|
515 | if (rField_is_Zp(r)) return FieldZp; |
---|
516 | if (rField_is_R(r)) return FieldR; |
---|
517 | if (rField_is_GF(r)) return FieldGF; |
---|
518 | #ifdef HAVE_MORE_FIELDS_IMPLEMENTED |
---|
519 | if (rField_is_Q(r)) return FieldQ; |
---|
520 | if (rField_is_long_R(r)) return FieldLong_R; |
---|
521 | if (rField_is_long_C(r)) return FieldLong_C; |
---|
522 | if (rField_is_Zp_a(r)) return FieldZp_a; |
---|
523 | if (rField_is_Q_a(r)) return FieldQ_a; |
---|
524 | #endif |
---|
525 | return FieldGeneral; |
---|
526 | } |
---|
527 | |
---|
528 | static inline p_Length p_LengthIs(ring r) |
---|
529 | { |
---|
530 | assume(r->ExpLSize > 0); |
---|
531 | if (r->ExpLSize == 1) return LengthOne; |
---|
532 | if (r->ExpLSize == 2) return LengthTwo; |
---|
533 | if (r->ExpLSize == 3) return LengthThree; |
---|
534 | if (r->ExpLSize == 4) return LengthFour; |
---|
535 | if (r->ExpLSize == 5) return LengthFive; |
---|
536 | if (r->ExpLSize == 6) return LengthSix; |
---|
537 | if (r->ExpLSize == 7) return LengthSeven; |
---|
538 | if (r->ExpLSize == 8) return LengthEight; |
---|
539 | return LengthGeneral; |
---|
540 | } |
---|
541 | |
---|
542 | static inline int p_IsNomog(long* sgn, int l) |
---|
543 | { |
---|
544 | int i; |
---|
545 | for (i=0;i<l;i++) |
---|
546 | if (sgn[i] > 0) return 0; |
---|
547 | |
---|
548 | return 1; |
---|
549 | } |
---|
550 | |
---|
551 | static inline int p_IsPomog(long* sgn, int l) |
---|
552 | { |
---|
553 | int i; |
---|
554 | for (i=0;i<l;i++) |
---|
555 | if (sgn[i] < 0) return 0; |
---|
556 | return 1; |
---|
557 | } |
---|
558 | |
---|
559 | static inline p_Ord p_OrdIs(ring r) |
---|
560 | { |
---|
561 | long* sgn = r->ordsgn; |
---|
562 | long l = r->ExpLSize; |
---|
563 | int zero = 0; |
---|
564 | |
---|
565 | if (sgn[l-1] == 0) |
---|
566 | { |
---|
567 | l--; |
---|
568 | zero = 1; |
---|
569 | } |
---|
570 | |
---|
571 | // we always favour the pomog cases |
---|
572 | if (p_IsPomog(sgn,l)) return (zero ? OrdPomogZero : OrdPomog); |
---|
573 | if (p_IsNomog(sgn,l)) return (zero ? OrdNomogZero : OrdNomog); |
---|
574 | |
---|
575 | assume(l > 1); |
---|
576 | |
---|
577 | if (sgn[0] == -1 && p_IsPomog(&sgn[1], l-1)) |
---|
578 | return (zero ? OrdNegPomogZero : OrdNegPomog); |
---|
579 | if (sgn[l-1] == -1 && p_IsPomog(sgn, l-1)) |
---|
580 | return (zero ? OrdPomogNegZero : OrdPomogNeg); |
---|
581 | |
---|
582 | if (sgn[0] == 1 && p_IsNomog(&sgn[1], l-1)) |
---|
583 | return (zero ? OrdPosNomogZero : OrdPosNomog); |
---|
584 | if (sgn[l-1] == 1 && p_IsNomog(sgn, l-1)) |
---|
585 | return (zero ? OrdNomogPosZero : OrdNomogPos); |
---|
586 | |
---|
587 | assume(l > 2); |
---|
588 | |
---|
589 | if (sgn[0] == 1 && sgn[1] == 1 && p_IsNomog(&sgn[2], l-2)) |
---|
590 | return (zero ? OrdPosPosNomogZero : OrdPosPosNomog); |
---|
591 | |
---|
592 | if (sgn[0] == 1 && sgn[l-1] == 1 && p_IsNomog(&sgn[1], l-2)) |
---|
593 | return (zero ? OrdPosNomogPosZero : OrdPosNomogPos); |
---|
594 | |
---|
595 | if (sgn[0] == -1 && sgn[1] == 0 && p_IsNomog(&sgn[2], l-2)) |
---|
596 | return (zero ? OrdNegPosNomogZero : OrdNegPosNomog); |
---|
597 | |
---|
598 | return OrdGeneral; |
---|
599 | } |
---|
600 | |
---|
601 | static p_Procs_s *_p_procs; |
---|
602 | // Choose a set of p_Procs |
---|
603 | void p_SetProcs(ring r, p_Procs_s* p_Procs) |
---|
604 | { |
---|
605 | p_Field field = p_FieldIs(r); |
---|
606 | p_Length length = p_LengthIs(r); |
---|
607 | p_Ord ord = p_OrdIs(r); |
---|
608 | |
---|
609 | assume(p_Procs != NULL); |
---|
610 | #ifdef RDEBUG |
---|
611 | memset(p_Procs, 0, sizeof(p_Procs_s)); |
---|
612 | #endif |
---|
613 | _p_procs = p_Procs; |
---|
614 | assume(IsValidSpec(field, length, ord)); |
---|
615 | |
---|
616 | SetProcs(field, length, ord); |
---|
617 | assume( |
---|
618 | (p_Procs->p_Delete != NULL) && |
---|
619 | (p_Procs->p_ShallowCopyDelete != NULL) && |
---|
620 | (p_Procs->p_Mult_n != NULL) && |
---|
621 | (p_Procs->p_Copy != NULL) && |
---|
622 | (p_Procs->p_Mult_m != NULL) && |
---|
623 | (p_Procs->p_Add_q != NULL) && |
---|
624 | (p_Procs->p_Minus_m_Mult_q != NULL)); |
---|
625 | } |
---|
626 | |
---|
627 | #ifdef RDEBUG |
---|
628 | void p_Debug_GetSpecNames(const ring r, char* &field, char* &length, char* &ord) |
---|
629 | { |
---|
630 | p_Field e_field = p_FieldIs(r); |
---|
631 | p_Length e_length = p_LengthIs(r); |
---|
632 | p_Ord e_ord = p_OrdIs(r); |
---|
633 | |
---|
634 | field = p_FieldEnum_2_String(p_FieldIs(r)); |
---|
635 | length = p_LengthEnum_2_String(p_LengthIs(r)); |
---|
636 | ord = p_OrdEnum_2_String(p_OrdIs(r)); |
---|
637 | } |
---|
638 | // like SetProcs, only that names are set |
---|
639 | static int set_names = 0; |
---|
640 | void p_Debug_GetProcNames(const ring r, p_Procs_s* p_Procs) |
---|
641 | { |
---|
642 | set_names = 1; |
---|
643 | p_SetProcs(r, p_Procs); |
---|
644 | set_names = 0; |
---|
645 | } |
---|
646 | #endif // RDEBUG |
---|
647 | |
---|
648 | #define __SetProc(what, type, field, length, ord) \ |
---|
649 | _p_procs->what = (what##_Proc_Ptr) what##_Proc_##type [index(what##_Proc, field, length, ord)] |
---|
650 | |
---|
651 | #define ___SetProc(what, field, length, ord) __SetProc(what, funcs, field, length, ord) |
---|
652 | |
---|
653 | #ifdef RDEBUG |
---|
654 | #define _SetProc(what, field, length, ord) \ |
---|
655 | do \ |
---|
656 | { \ |
---|
657 | if (set_names) \ |
---|
658 | __SetProc(what, names, field, length, ord); \ |
---|
659 | else \ |
---|
660 | ___SetProc(what, field, length, ord); \ |
---|
661 | } \ |
---|
662 | while(0) |
---|
663 | #else |
---|
664 | #define _SetProc ___SetProc |
---|
665 | #endif |
---|
666 | |
---|
667 | #else /* GENERATE_P_PROCS */ |
---|
668 | /*************************************************************** |
---|
669 | * |
---|
670 | * generate time stuff |
---|
671 | * |
---|
672 | ***************************************************************/ |
---|
673 | #include <stdio.h> |
---|
674 | #include <stdlib.h> |
---|
675 | #include <string.h> |
---|
676 | |
---|
677 | char*** generated_p_procs; |
---|
678 | |
---|
679 | inline int AlreadyHaveProc(p_Proc proc, p_Field field, p_Length length, p_Ord ord) |
---|
680 | { |
---|
681 | return (generated_p_procs[proc])[index(proc, field, length, ord)] != 0; |
---|
682 | } |
---|
683 | |
---|
684 | const char* macros_field[] = {"p_nCopy","p_nDelete", "p_nMult", "p_nAdd", "p_nSub", "p_nIsZero", "p_nEqual" , "p_nNeg", NULL}; |
---|
685 | |
---|
686 | const char* macros_length[] = |
---|
687 | {"p_MemCopy", "p_MemAdd", NULL}; |
---|
688 | |
---|
689 | const char* macros_length_ord[] = {"p_MemCmp", NULL}; |
---|
690 | int DummyProcs = 0; |
---|
691 | |
---|
692 | void AddProc(const char* s_what, p_Proc proc, p_Field field, p_Length length, p_Ord ord) |
---|
693 | { |
---|
694 | int i; |
---|
695 | const char* s_length = p_LengthEnum_2_String(length); |
---|
696 | const char* s_ord = p_OrdEnum_2_String(ord); |
---|
697 | const char* s_field = p_FieldEnum_2_String(field); |
---|
698 | char* s_full_proc_name = (char*) malloc(200); |
---|
699 | |
---|
700 | sprintf(s_full_proc_name, "%s__%s_%s_%s", s_what, s_field, s_length, s_ord); |
---|
701 | |
---|
702 | (generated_p_procs[proc])[index(proc, field, length, ord)] = s_full_proc_name; |
---|
703 | |
---|
704 | // define all macros |
---|
705 | printf("\n// definition of %s\n", s_full_proc_name); |
---|
706 | i = 0; |
---|
707 | while (macros_field[i] != NULL) |
---|
708 | { |
---|
709 | printf("#undef %s\n#define %s\t%s_%s\n", |
---|
710 | macros_field[i], macros_field[i], macros_field[i], s_field); |
---|
711 | i++; |
---|
712 | } |
---|
713 | i = 0; |
---|
714 | while (macros_length[i] != NULL) |
---|
715 | { |
---|
716 | printf("#undef %s\n#define %s\t%s_%s\n", |
---|
717 | macros_length[i], macros_length[i], macros_length[i], s_length); |
---|
718 | i++; |
---|
719 | } |
---|
720 | i = 0; |
---|
721 | while (macros_length_ord[i] != NULL) |
---|
722 | { |
---|
723 | printf("#undef %s\n#define %s\t%s_%s_%s\n", |
---|
724 | macros_length_ord[i], macros_length_ord[i], macros_length_ord[i], s_length, s_ord); |
---|
725 | i++; |
---|
726 | } |
---|
727 | |
---|
728 | // define DECLARE_LENGTH |
---|
729 | printf("#undef DECLARE_LENGTH\n"); |
---|
730 | if (length != LengthGeneral) |
---|
731 | printf("#define DECLARE_LENGTH(what) ((void)0)\n"); |
---|
732 | else |
---|
733 | printf("#define DECLARE_LENGTH(what) what\n"); |
---|
734 | |
---|
735 | // define DECLARE_ORDSGN |
---|
736 | printf("#undef DECLARE_ORDSGN\n"); |
---|
737 | if (ord != OrdGeneral) |
---|
738 | printf("#define DECLARE_ORDSGN(what) ((void)0)\n"); |
---|
739 | else |
---|
740 | printf("#define DECLARE_ORDSGN(what) what\n"); |
---|
741 | |
---|
742 | // define p_Mult_m, for p_Minus_m_Mult_q |
---|
743 | if (strcmp(s_what, "p_Minus_m_Mult_q") == 0) |
---|
744 | { |
---|
745 | printf("#undef p_Mult_m\n"); |
---|
746 | printf("#define p_Mult_m p_Mult_m__%s_%s_OrdGeneral\n", s_field, s_length); |
---|
747 | } |
---|
748 | printf("#undef %s\n#define %s %s\n", s_what, s_what, s_full_proc_name); |
---|
749 | printf("#include \"%s__Template.cc\"\n", s_what); |
---|
750 | printf("#undef %s\n#undef p_Mult_m\n", s_what); |
---|
751 | } |
---|
752 | |
---|
753 | void GenerateProc(const char* s_what, p_Proc proc, p_Field field, p_Length length, p_Ord ord) |
---|
754 | { |
---|
755 | if (! AlreadyHaveProc(proc, field, length, ord)) |
---|
756 | AddProc(s_what, proc, field, length, ord); |
---|
757 | } |
---|
758 | |
---|
759 | int main() |
---|
760 | { |
---|
761 | int field; |
---|
762 | int length; |
---|
763 | int ord; |
---|
764 | int i, j; |
---|
765 | int NumberOfHaveProcs = 0; |
---|
766 | |
---|
767 | |
---|
768 | printf("/* -*-c++-*- */\n"); |
---|
769 | printf("/***************************************************************\n"); |
---|
770 | printf(" This file was generated automatically by p_Procs.cc: DO NOT EDIT\n\n"); |
---|
771 | printf(" This file provides the needed implementation of p_Procs\n"); |
---|
772 | printf(" See the end for a summary. \n"); |
---|
773 | printf("*******************************************************************/\n"); |
---|
774 | |
---|
775 | generated_p_procs = (char***) malloc(p_Unknown_Proc*sizeof(char**)); |
---|
776 | for (i=0; i<p_Unknown_Proc; i++) |
---|
777 | { |
---|
778 | generated_p_procs[i] = |
---|
779 | (char**) calloc(index((p_Proc)i, FieldUnknown, LengthUnknown, OrdUnknown), sizeof(char*)); |
---|
780 | } |
---|
781 | |
---|
782 | // set default procs |
---|
783 | for (field = 0; field < (int) FieldUnknown; field++) |
---|
784 | { |
---|
785 | for (length=0; length < (int) LengthUnknown; length++) |
---|
786 | { |
---|
787 | for (ord=0; ord < (int)OrdUnknown; ord++) |
---|
788 | { |
---|
789 | if (IsValidSpec((p_Field) field, (p_Length) length, (p_Ord) ord)) |
---|
790 | SetProcs((p_Field) field, (p_Length) length, (p_Ord) ord); |
---|
791 | } |
---|
792 | } |
---|
793 | } |
---|
794 | |
---|
795 | printf(" |
---|
796 | /*************************************************************** |
---|
797 | Names of procs for RDEBUG */ |
---|
798 | #ifdef RDEBUG\n"); |
---|
799 | |
---|
800 | for (i=0; i<p_Unknown_Proc; i++) |
---|
801 | { |
---|
802 | printf("static const char* %s_names[] = {", p_ProcEnum_2_String((p_Proc)i)); |
---|
803 | for (j=0;j<index((p_Proc)i, FieldUnknown, LengthUnknown, OrdUnknown); j++) |
---|
804 | { |
---|
805 | char* s = (generated_p_procs[i])[j]; |
---|
806 | if (s != 0) |
---|
807 | { |
---|
808 | printf("\n\"%s\",", s); |
---|
809 | } |
---|
810 | else |
---|
811 | printf("0,"); |
---|
812 | |
---|
813 | } |
---|
814 | printf("\n};\n"); |
---|
815 | } |
---|
816 | printf(" |
---|
817 | #endif // RDEBUG |
---|
818 | |
---|
819 | |
---|
820 | /***************************************************************/ |
---|
821 | /* Tables for lookup of procedures: */\n"); |
---|
822 | |
---|
823 | for (i=0; i<p_Unknown_Proc; i++) |
---|
824 | { |
---|
825 | printf("static const %s_Ptr %s_funcs[] = {", p_ProcEnum_2_String((p_Proc)i), p_ProcEnum_2_String((p_Proc)i)); |
---|
826 | for (j=0;j<index((p_Proc)i, FieldUnknown, LengthUnknown, OrdUnknown); j++) |
---|
827 | { |
---|
828 | char* s = (generated_p_procs[i])[j]; |
---|
829 | if (s != 0) |
---|
830 | { |
---|
831 | NumberOfHaveProcs++; |
---|
832 | printf("\n%s,", s); |
---|
833 | } |
---|
834 | else |
---|
835 | printf("0,"); |
---|
836 | |
---|
837 | } |
---|
838 | printf("\n};\n"); |
---|
839 | } |
---|
840 | printf(" |
---|
841 | /*************************************************************** |
---|
842 | * Summary: |
---|
843 | * HAVE_FAST_P_PROCS = %d, |
---|
844 | * HAVE_FAST_FIELD = %d, |
---|
845 | * HAVE_FAST_LENGTH = %d, |
---|
846 | * HAVE_FAST_ORD = %d, |
---|
847 | * HAVE_FAST_ZERO_ORD = %d |
---|
848 | * |
---|
849 | * Generated PolyProcs= %d |
---|
850 | * |
---|
851 | *******************************************************************/\n", |
---|
852 | HAVE_FAST_P_PROCS, HAVE_FAST_FIELD, HAVE_FAST_LENGTH, HAVE_FAST_ORD, HAVE_FAST_ZERO_ORD, |
---|
853 | NumberOfHaveProcs); |
---|
854 | } |
---|
855 | |
---|
856 | #define _SetProc(what, field, length, ord) \ |
---|
857 | GenerateProc(#what, what##_Proc, field, length, ord) |
---|
858 | #endif // GENERATE_P_PROCS |
---|
859 | |
---|
860 | /*************************************************************** |
---|
861 | * |
---|
862 | * Setting the procedures |
---|
863 | * |
---|
864 | ***************************************************************/ |
---|
865 | |
---|
866 | #define SetProc(what, field, length, ord) \ |
---|
867 | do \ |
---|
868 | { \ |
---|
869 | p_Field t_field = field; \ |
---|
870 | p_Ord t_ord = ord; \ |
---|
871 | p_Length t_length = length; \ |
---|
872 | FastProcFilter(what##_Proc, t_field, t_length, t_ord); \ |
---|
873 | _SetProc(what, t_field, t_length, t_ord); \ |
---|
874 | } \ |
---|
875 | while (0) \ |
---|
876 | |
---|
877 | static void SetProcs(p_Field field, p_Length length, p_Ord ord) |
---|
878 | { |
---|
879 | SetProc(p_Delete, field, LengthGeneral, OrdGeneral); |
---|
880 | SetProc(p_Mult_n, field, LengthGeneral, OrdGeneral); |
---|
881 | SetProc(p_ShallowCopyDelete, FieldGeneral, length, OrdGeneral); |
---|
882 | SetProc(p_Copy, field, length, OrdGeneral); |
---|
883 | SetProc(p_Mult_m, field, length, OrdGeneral); |
---|
884 | SetProc(p_Add_q, field, length, ord); |
---|
885 | SetProc(p_Minus_m_Mult_q, field, length, ord); |
---|
886 | } |
---|
887 | |
---|
888 | |
---|
889 | |
---|