source: git/kernel/linear_algebra/interpolation.cc @ 8abd84

fieker-DuValspielwiese
Last change on this file since 8abd84 was 9f7665, checked in by Oleksandr Motsak <motsak@…>, 10 years ago
Removed HAVE_CONFIG guards fix: fixed the inclusion of configure-generated *config.h's
  • Property mode set to 100644
File size: 49.0 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4
5
6
7
8#include <kernel/mod2.h>
9
10#include <factory/factory.h>
11
12#include <misc/options.h>
13#include <misc/intvec.h>
14
15#include <coeffs/longrat.h>
16
17#include <polys/monomials/ring.h>
18
19#include <kernel/polys.h>
20#include <kernel/febase.h>
21#include <kernel/ideals.h>
22
23#include "interpolation.h"
24
25// parameters to debug
26//#define shmat
27//#define checksize
28//#define writemsg
29
30// possible strategies
31#define unsortedmatrix
32//#define integerstrategy
33
34#define modp_number int
35#define exponent int
36
37static modp_number myp;  // all modp computation done mod myp
38static int myp_index; // index of small prime in Singular table of primes
39
40static inline modp_number modp_mul (modp_number x,modp_number y)
41{
42//    return (x*y)%myp;
43   return (modp_number)(((unsigned long)x)*((unsigned long)y)%((unsigned long)myp));
44}
45static inline modp_number modp_sub (modp_number x,modp_number y)
46{
47//   if (x>=y) return x-y; else return x+myp-y;
48     return (x+myp-y)%myp;
49}
50
51typedef exponent *mono_type;
52typedef struct {mono_type mon; unsigned int point_ref;} condition_type;
53typedef modp_number *coordinate_products;
54typedef coordinate_products *coordinates;
55
56struct mon_list_entry_struct {mono_type mon;
57                              struct mon_list_entry_struct *next;};
58typedef struct mon_list_entry_struct mon_list_entry;
59
60struct row_list_entry_struct {modp_number *row_matrix;
61                              modp_number *row_solve;
62                              int first_col;
63                              struct row_list_entry_struct *next;};
64
65typedef struct row_list_entry_struct row_list_entry;
66
67struct generator_struct {modp_number *coef;
68                         mono_type lt;
69                         modp_number ltcoef;
70                         struct generator_struct *next;};
71
72typedef struct generator_struct generator_entry;
73
74struct modp_result_struct {modp_number p;
75                           generator_entry *generator;
76                           int n_generators;
77                           struct modp_result_struct *next;
78                           struct modp_result_struct *prev;};
79
80typedef struct modp_result_struct modp_result_entry;
81
82typedef modp_number *modp_coordinates;
83typedef mpq_t *q_coordinates;
84typedef mpz_t *int_coordinates;
85typedef bool *coord_exist_table;
86
87static int final_base_dim;    // dimension of the quotient space, known from the beginning
88static int last_solve_column;  // last non-zero column in "solve" part of matrix, used for speed up
89static int n_points;  // modp_number of ideals (points)
90static int *multiplicity;  // multiplicities of points
91static int variables;  // modp_number of variables
92static int max_coord;  // maximal possible coordinate product used during Evaluation
93static bool only_modp;  // perform only one modp computations
94
95static modp_coordinates *modp_points; // coordinates of points for modp problem - used by Evaluate (this is also initial data for only modp)
96static q_coordinates *q_points; // coordinates of points for rational data (not used for modp)
97static int_coordinates *int_points; // coordinates of points for integer data - used to check generators (not used for modp)
98static coord_exist_table *coord_exist; // checks whether all coordinates has been initialized
99static mon_list_entry *check_list; // monomials to be checked in next stages
100static coordinates *points; // power products of coordinates of points used in modp cycles
101static condition_type *condition_list; // conditions stored in an array
102static mon_list_entry *lt_list; // leading terms found so far
103static mon_list_entry *base_list; // standard monomials found so far
104static row_list_entry *row_list; // rows of the matrix (both parts)
105static modp_number *my_row; // one special row to perform operations
106static modp_number *my_solve_row; // one special row to find the linear dependence ("solve" part)
107static mono_type *column_name; // monomials assigned to columns in solve_row
108
109static int n_results;  // modp_number of performed modp computations (not discarded)
110static modp_number modp_denom; // denominator of mod p computations
111static modp_result_entry *modp_result; // list of results for various mod p calculations (used for modp - first result is the desired one)
112static modp_result_entry *cur_result; // pointer to current result (as before)
113static modp_number *congr; // primes used in computations (chinese remainder theorem) (not used for modp)
114static modp_number *in_gamma; // inverts used in chinese remainder theorem (not used for modp)
115static mpz_t bigcongr; // result, in fact, is given in mod bigcongr (not used for modp)
116
117static mpz_t *polycoef; // polynomial integercoefficients (not used for modp)
118static mono_type *polyexp; // polynomial exponents
119
120struct gen_list_struct {mpz_t *polycoef;
121                        mono_type *polyexp;
122                        struct gen_list_struct *next;};
123typedef struct gen_list_struct gen_list_entry;
124
125static gen_list_entry *gen_list=NULL; // list of resulting generators - output data (integer version)
126
127static int generic_n_generators; // modp_number of generators - should be the same for all modp comp (not used for modp)
128static mono_type *generic_column_name; // monomials assigned to columns in solve_row - should be the same for all modp comp (!!! used for modp)
129static mon_list_entry *generic_lt=NULL; // leading terms for ordered generators - should be the same for all modp comp (not used for modp)
130static int good_primes; // modp_number of good primes so far;
131static int bad_primes; // modp_number of bad primes so far;
132static mpz_t common_denom; // common denominator used to force points coordinates to Z (not used for modp)
133static bool denom_divisible; // common denominator is divisible by p (not used for modp)
134
135static poly comparizon_p1;  //polynomials used to do comparizons by Singular
136static poly comparizon_p2;
137
138static modp_number *modp_Reverse; // reverses in mod p
139
140static bool protocol; // true to show the protocol
141
142#ifdef checksize
143static int maximal_size=0;
144#endif
145
146#if 0  /* only for debuggig*/
147void WriteMono (mono_type m) // Writes a monomial on the screen - only for debug
148{
149     int i;
150     for (i=0;i<variables;i++) Print("_%d", m[i]);
151     PrintS(" ");
152}
153
154void WriteMonoList (mon_list_entry *list)
155{
156     mon_list_entry *ptr;
157     ptr=list;
158     while (ptr!=NULL)
159     {
160           WriteMono(ptr->mon);
161           ptr=ptr->next;
162     }
163}
164
165void Info ()
166{
167     int i;
168     row_list_entry *curptr;
169     modp_number *row;
170     modp_number *solve;
171     char ch;
172     cout << endl << "quotient basis: ";
173     WriteMonoList (base_list);
174     cout << endl << "leading terms: ";
175     WriteMonoList (lt_list);
176     cout << endl << "to be checked: ";
177     WriteMonoList (check_list);
178#ifdef shmat
179     cout << endl << "Matrix:" << endl;
180     cout << "                                      ";
181     for (i=0;i<final_base_dim;i++)
182     {
183         WriteMono (column_name[i]);
184     }
185     cout << endl;
186     curptr=row_list;
187     while (curptr!=NULL)
188     {
189           row=curptr->row_matrix;
190           solve=curptr->row_solve;
191           for (i=0;i<final_base_dim;i++)
192           {
193               cout << *row << " , ";
194               row++;
195           }
196           cout << "        ";
197           for (i=0;i<final_base_dim;i++)
198           {
199               cout << *solve << " , ";
200               solve++;
201           }
202           curptr=curptr->next;
203           cout << endl;}
204     cout << "Special row:                           Solve row:" << endl;
205     row=my_row;
206     for (i=0;i<final_base_dim;i++)
207     {
208         cout << *row << " , ";
209         row++;
210     }
211     cout << "          ";
212     row=my_solve_row;
213     for (i=0;i<final_base_dim;i++)
214     {
215         cout << *row << " , ";
216         row++;
217     }
218#endif
219     cout << endl;
220     cin >> ch;
221     cout << endl << endl;
222}
223#endif
224
225static modp_number OneInverse(modp_number a,modp_number p) // computes inverse of d mod p without using tables
226{
227   long  u, v, u0, u1, u2, q, r;
228   u1=1; u2=0;
229   u = a; v = p;
230   while (v != 0)
231   {
232      q = u / v;
233      r = u % v;
234      u = v;
235      v = r;
236      u0 = u2;
237      u2 = u1 - q*u2;
238      u1 = u0;
239   }
240   if (u1 < 0) u1=u1+p;
241// now it should be ok, but for any case...
242   if ((u1<0)||((u1*a)%p!=1))
243   {
244     PrintS("?");
245     modp_number i;
246     for (i=1;i<p;i++)
247     {
248       if ((a*i)%p==1) return i;
249     }
250   }
251   return (modp_number)u1;
252}
253
254static int CalcBaseDim () // returns the maximal (expected) dimension of quotient space
255{
256    int c;
257    int i,j;
258    int s=0;
259    max_coord=1;
260    for (i=0;i<n_points;i++) max_coord=max_coord+multiplicity[i];
261    for (j=0;j<n_points;j++)
262    {
263        c=1;
264        for (i=1;i<=variables;i++)
265        {
266            c=(c*(multiplicity[j]+i-1))/i;
267        }
268        s=s+c;
269    }
270    return s;
271}
272
273static bool EqualMon (mono_type m1, mono_type m2)  // compares two monomials, true if equal, false otherwise
274{
275     int i;
276     for (i=0;i<variables;i++)
277         if (m1[i]!=m2[i]) return false;;
278     return true;
279}
280
281static exponent MonDegree (mono_type mon)  // computes the degree of a monomial
282{
283     exponent v=0;
284     int i;
285     for (i=0;i<variables;i++) v=v+mon[i];
286     return v;
287}
288
289static bool Greater (mono_type m1, mono_type m2) // true if m1 > m2, false otherwise. uses Singular comparing function
290{
291     for (int j = variables; j; j--)
292     {
293       pSetExp(comparizon_p1, j, m1[j-1]);
294       pSetExp(comparizon_p2, j, m2[j-1]);
295     }
296     pSetm(comparizon_p1);
297     pSetm(comparizon_p2);
298     bool res=(pLmCmp(comparizon_p1,comparizon_p2)>0);
299     return res;
300}
301
302static mon_list_entry* MonListAdd (mon_list_entry *list, mono_type mon)  // adds one entry to the list of monomials structure
303{
304     mon_list_entry *curptr=list;
305     mon_list_entry *prevptr=NULL;
306     mon_list_entry *temp;
307
308     while (curptr!=NULL)
309     {
310           if (EqualMon (mon,(*curptr).mon)) return list;
311           if (Greater ((*curptr).mon,mon)) break;
312           prevptr=curptr;
313           curptr=curptr->next;
314     }
315     temp=(mon_list_entry*)omAlloc0(sizeof(mon_list_entry));
316     (*temp).next=curptr;
317     (*temp).mon=(exponent*)omAlloc(sizeof(exponent)*variables);
318     memcpy(temp->mon,mon,sizeof(exponent)*variables);
319     if (prevptr==NULL) return temp;
320     else
321     {
322          prevptr->next=temp;
323          return list;
324     }
325}
326
327static mono_type MonListElement (mon_list_entry *list, int n)  // returns ith element from list of monomials - no error checking!
328{
329     mon_list_entry *cur=list;
330     int i;
331     for (i=0;i<n;i++) cur=cur->next;
332     return cur->mon;
333}
334
335static mono_type ZeroMonomial ()  // allocates memory for new monomial with all enries equal 0
336{
337     mono_type m;
338     m=(exponent*)omAlloc0(sizeof(exponent)*variables);
339     return m;
340}
341
342static void GeneralInit ()  // general initialization
343{
344     int i,j;
345     points=(coordinates*)omAlloc(sizeof(coordinates)*n_points);
346     for (i=0;i<n_points;i++)
347     {
348         points[i]=(coordinate_products*)omAlloc(sizeof(coordinate_products)*variables);
349         for (j=0;j<variables;j++) points[i][j]=(modp_number*)omAlloc0(sizeof(modp_number)*(max_coord));
350     }
351     condition_list=(condition_type*)omAlloc0(sizeof(condition_type)*final_base_dim);
352     for (i=0;i<final_base_dim;i++) condition_list[i].mon=(exponent*)omAlloc0(sizeof(exponent)*variables);
353     modp_points=(modp_coordinates*)omAlloc(sizeof(modp_coordinates)*n_points);
354     for (i=0;i<n_points;i++) modp_points[i]=(modp_number*)omAlloc0(sizeof(modp_number)*variables);
355     if (!only_modp)
356     {
357        q_points=(q_coordinates*)omAlloc0(sizeof(q_coordinates)*n_points);
358        for (i=0;i<n_points;i++)
359        {
360            q_points[i]=(mpq_t*)omAlloc(sizeof(mpq_t)*variables);
361            for (j=0;j<variables;j++) mpq_init(q_points[i][j]);
362        }
363        int_points=(int_coordinates*)omAlloc0(sizeof(int_coordinates)*n_points);
364        for (i=0;i<n_points;i++)
365        {
366            int_points[i]=(mpz_t*)omAlloc(sizeof(mpz_t)*variables);
367            for (j=0;j<variables;j++) mpz_init(int_points[i][j]);
368        }
369     }
370     coord_exist=(coord_exist_table*)omAlloc(sizeof(coord_exist_table)*n_points);
371     for (i=0;i<n_points;i++)
372     {
373         coord_exist[i]=(bool*)omAlloc0(sizeof(bool)*variables);
374     }
375     generic_column_name=(mono_type*)omAlloc(sizeof(mono_type)*final_base_dim);
376     for (i=0;i<final_base_dim;i++) generic_column_name[i]=ZeroMonomial ();
377     good_primes=0;
378     bad_primes=1;
379     generic_n_generators=0;
380     if (!only_modp)
381     {
382        polycoef=(mpz_t*)omAlloc(sizeof(mpz_t)*(final_base_dim+1));
383        polyexp=(mono_type*)omAlloc(sizeof(mono_type)*(final_base_dim+1));
384        for (i=0;i<=final_base_dim;i++)
385        {
386             mpz_init(polycoef[i]);
387             polyexp[i]=ZeroMonomial ();
388        }
389        mpz_init(common_denom);
390     }
391
392// set all globally used lists to be initially empty
393     modp_result=NULL;
394     cur_result=NULL;
395     gen_list=NULL;
396     n_results=0;
397
398// creates polynomials to compare by Singular
399     comparizon_p1=pOne();
400     comparizon_p2=pOne();
401}
402
403static void InitProcData ()  // initialization for procedures which do computations mod p
404{
405     int i;
406     check_list=MonListAdd (check_list,ZeroMonomial ());
407     my_row=(modp_number*)omAlloc0(sizeof(modp_number)*final_base_dim);
408     my_solve_row=(modp_number*)omAlloc0(sizeof(modp_number)*final_base_dim);
409     column_name=(mono_type*)omAlloc(sizeof(mono_type)*final_base_dim);
410     for (i=0;i<final_base_dim;i++) column_name[i]=ZeroMonomial ();
411     last_solve_column=0;
412     modp_number *gen_table;
413     modp_number pos_gen;
414     bool gen_ok;
415     modp_Reverse=(modp_number*)omAlloc0(sizeof(modp_number)*myp);
416
417// produces table of modp inverts by finding a generator of (Z_myp*,*)
418     gen_table=(modp_number*)omAlloc(sizeof(modp_number)*myp);
419     gen_table[1]=1;
420     for (pos_gen=2;pos_gen<myp;pos_gen++)
421     {
422         gen_ok=true;
423         for (i=2;i<myp;i++)
424         {
425             gen_table[i]=modp_mul(gen_table[i-1],pos_gen);
426             if (gen_table[i]==1)
427             {
428                gen_ok=false;
429                break;
430             }
431         }
432         if (gen_ok) break;
433     }
434     for (i=2;i<myp;i++) modp_Reverse[gen_table[i]]=gen_table[myp-i+1];
435     modp_Reverse[1]=1;
436     omFree(gen_table);
437}
438
439static mon_list_entry* FreeMonList (mon_list_entry *list)  // destroys a list of monomials, returns NULL pointer
440{
441     mon_list_entry *ptr;
442     mon_list_entry *pptr;
443     ptr=list;
444     while (ptr!=NULL)
445     {
446           pptr=ptr->next;
447           omFree(ptr->mon);
448           omFree(ptr);
449           ptr=pptr;}
450     return NULL;
451}
452
453static void GeneralDone ()  // to be called before exit to free memory
454{
455     int i,j;
456     for (i=0;i<n_points;i++)
457     {
458         for (j=0;j<variables;j++)
459         {
460             omFree(points[i][j]);
461         }
462         omFree(points[i]);
463     }
464     omFree(points);
465     for (i=0;i<final_base_dim;i++) omFree(condition_list[i].mon);
466     omFree(condition_list);
467     for (i=0;i<n_points;i++) omFree(modp_points[i]);
468     omFree(modp_points);
469     if (!only_modp)
470     {
471        for (i=0;i<n_points;i++)
472        {
473            for (j=0;j<variables;j++) mpq_clear(q_points[i][j]);
474            omFree(q_points[i]);
475        }
476        omFree(q_points);
477        for (i=0;i<n_points;i++)
478        {
479            for (j=0;j<variables;j++) mpz_clear(int_points[i][j]);
480            omFree(int_points[i]);
481        }
482        omFree(int_points);
483        generic_lt=FreeMonList (generic_lt);
484        for (i=0;i<=final_base_dim;i++)
485        {
486            mpz_clear(polycoef[i]);
487            omFree(polyexp[i]);
488        }
489        omFree(polycoef);
490        omFree(polyexp);
491        if (!only_modp) mpz_clear(common_denom);
492     }
493     for (i=0;i<final_base_dim;i++)
494     {
495         omFree(generic_column_name[i]);
496     }
497     omFree(generic_column_name);
498     for (i=0;i<n_points;i++) omFree(coord_exist[i]);
499     omFree(coord_exist);
500     pDelete(&comparizon_p1);
501     pDelete(&comparizon_p2);
502}
503
504static void FreeProcData ()  // to be called after one modp computation to free memory
505{
506     int i;
507     row_list_entry *ptr;
508     row_list_entry *pptr;
509     check_list=FreeMonList (check_list);
510     lt_list=FreeMonList (lt_list);
511     base_list=FreeMonList (base_list);
512     omFree(my_row);
513     my_row=NULL;
514     omFree(my_solve_row);
515     my_solve_row=NULL;
516     ptr=row_list;
517     while (ptr!=NULL)
518     {
519           pptr=ptr->next;
520           omFree(ptr->row_matrix);
521           omFree(ptr->row_solve);
522           omFree(ptr);
523           ptr=pptr;
524     }
525     row_list=NULL;
526     for (i=0;i<final_base_dim;i++) omFree(column_name[i]);
527     omFree(column_name);
528     omFree(modp_Reverse);
529}
530
531static void modp_Evaluate(modp_number *ev, mono_type mon, condition_type con)  // evaluates monomial on condition (modp)
532{
533    int i;
534    *ev=0;
535    for (i=0;i<variables;i++)
536        if (con.mon[i] > mon[i]) return ;;
537    *ev=1;
538    int j,k;
539    mono_type mn;
540    mn=(exponent*)omAlloc(sizeof(exponent)*variables);
541    memcpy(mn,mon,sizeof(exponent)*variables);
542    for (k=0;k<variables;k++)
543    {
544        for (j=1;j<=con.mon[k];j++) // this loop computes the coefficient from derivation
545        {
546            *ev=modp_mul(*ev,mn[k]);
547            mn[k]--;
548        }
549        *ev=modp_mul(*ev,points[con.point_ref][k][mn[k]]);
550    }
551    omFree(mn);
552}
553
554static void int_Evaluate(mpz_t ev, mono_type mon, condition_type con) // (***) evaluates monomial on condition for integer numbers
555{
556    int i;
557    mpz_set_si(ev,0);
558    for (i=0;i<variables;i++)
559        if (con.mon[i] > mon[i]) return ;;
560    mpz_set_si(ev,1);
561    mpz_t mon_conv;
562    mpz_init(mon_conv);
563    int j,k;
564    mono_type mn;
565    mn=(exponent*)omAlloc(sizeof(exponent)*variables);
566    memcpy(mn,mon,sizeof(exponent)*variables);
567    for (k=0;k<variables;k++)
568    {
569        for (j=1;j<=con.mon[k];j++) // this loop computes the coefficient from derivation
570        {
571            mpz_set_si(mon_conv,mn[k]); // (***)
572            mpz_mul(ev,ev,mon_conv);
573            mn[k]--;
574        }
575        for (j=1;j<=mn[k];j++) mpz_mul(ev,ev,int_points[con.point_ref][k]);  // this loop computes the product of coordinate
576    }
577    omFree(mn);
578    mpz_clear(mon_conv);
579}
580
581static void ProduceRow(mono_type mon)  // produces a row for monomial - first part is an evaluated part, second 0 to obtain the coefs of dependence
582{
583     modp_number *row;
584     condition_type *con;
585     int i;
586     row=my_row;
587     con=condition_list;
588     for (i=0;i<final_base_dim;i++)
589     {
590         modp_Evaluate (row, mon, *con);
591         row++;
592         con++;
593     }
594     row=my_solve_row;
595     for (i=0;i<final_base_dim;i++)
596     {
597         *row=0;
598         row++;
599     }
600}
601
602static void IntegerPoints ()  // produces integer points from rationals by scaling the coordinate system
603{
604     int i,j;
605     mpz_set_si(common_denom,1); // this is common scaling factor
606     for (i=0;i<n_points;i++)
607     {
608         for (j=0;j<variables;j++)
609         {
610             mpz_lcm(common_denom,common_denom,mpq_denref(q_points[i][j]));
611         }
612     }
613     mpq_t temp;
614     mpq_init(temp);
615     mpq_t denom_q;
616     mpq_init(denom_q);
617     mpq_set_z(denom_q,common_denom);
618     for (i=0;i<n_points;i++)
619     {
620         for (j=0;j<variables;j++)
621         {
622             mpq_mul(temp,q_points[i][j],denom_q);  // multiplies by common denominator
623             mpz_set(int_points[i][j],mpq_numref(temp));  // and changes into integer
624         }
625     }
626     mpq_clear(temp);
627     mpq_clear(denom_q);
628}
629
630static void int_PrepareProducts ()  // prepares coordinates of points and products for modp case (from integer coefs)
631{
632     int i,j,k;
633     mpz_t big_myp;
634     mpz_init(big_myp);
635     mpz_set_si(big_myp,myp);
636     mpz_t temp;
637     mpz_init(temp);
638     for (i=0;i<n_points;i++)
639     {
640         for (j=0;j<variables;j++)
641         {
642             mpz_mod(temp,int_points[i][j],big_myp);  // coordinate is now modulo myp
643             points[i][j][1]=mpz_get_ui(temp);
644             points[i][j][0]=1;
645             for (k=2;k<max_coord;k++) points[i][j][k]=modp_mul(points[i][j][k-1],points[i][j][1]);
646         }
647     }
648     mpz_mod(temp,common_denom,big_myp);  // computes the common denominator (from rational data) modulo myp
649     denom_divisible=(mpz_sgn(temp)==0);  // checks whether it is divisible by modp
650     mpz_clear(temp);
651     mpz_clear(big_myp);
652}
653
654static void modp_PrepareProducts () // prepares products for modp computation from modp data
655{
656     int i,j,k;
657     for (i=0;i<n_points;i++)
658     {
659         for (j=0;j<variables;j++)
660         {
661             points[i][j][1]=modp_points[i][j];
662             points[i][j][0]=1;
663             for (k=2;k<max_coord;k++) points[i][j][k]=modp_mul(points[i][j][k-1],points[i][j][1]);
664         }
665     }
666}
667
668static void MakeConditions ()  // prepares a list of conditions from list of multiplicities
669{
670     condition_type *con;
671     int n,i,k;
672     mono_type mon;
673     mon=ZeroMonomial ();
674     con=condition_list;
675     for (n=0;n<n_points;n++)
676     {
677         for (i=0;i<variables;i++) mon[i]=0;
678         while (mon[0]<multiplicity[n])
679         {
680             if (MonDegree (mon) < multiplicity[n])
681             {
682                memcpy(con->mon,mon,sizeof(exponent)*variables);
683                con->point_ref=n;
684                con++;
685             }
686             k=variables-1;
687             mon[k]++;
688             while ((k>0)&&(mon[k]>=multiplicity[n]))
689             {
690                 mon[k]=0;
691                 k--;
692                 mon[k]++;
693             }
694         }
695     }
696     omFree(mon);
697}
698
699static void ReduceRow ()  // reduces my_row by previous rows, does the same for solve row
700{
701     if (row_list==NULL) return ;
702     row_list_entry *row_ptr;
703     modp_number *cur_row_ptr;
704     modp_number *solve_row_ptr;
705     modp_number *my_row_ptr;
706     modp_number *my_solve_row_ptr;
707     int first_col;
708     int i;
709     modp_number red_val;
710     modp_number mul_val;
711#ifdef integerstrategy
712     modp_number *m_row_ptr;
713     modp_number prep_val;
714#endif
715     row_ptr=row_list;
716     while (row_ptr!=NULL)
717     {
718           cur_row_ptr=row_ptr->row_matrix;
719           solve_row_ptr=row_ptr->row_solve;
720           my_row_ptr=my_row;
721           my_solve_row_ptr=my_solve_row;
722           first_col=row_ptr->first_col;
723           cur_row_ptr=cur_row_ptr+first_col;  // reduction begins at first_col position
724           my_row_ptr=my_row_ptr+first_col;
725           red_val=*my_row_ptr;
726           if (red_val!=0)
727           {
728#ifdef integerstrategy
729              prep_val=*cur_row_ptr;
730              if (prep_val!=1)
731              {
732                 m_row_ptr=my_row;
733                 for (i=0;i<final_base_dim;i++)
734                 {
735                     if (*m_row_ptr!=0) *m_row_ptr=modp_mul(*m_row_ptr,prep_val);
736                     m_row_ptr++;
737                 }
738                 m_row_ptr=my_solve_row;
739                 for (i=0;i<last_solve_column;i++)
740                 {
741                     if (*m_row_ptr!=0) *m_row_ptr=modp_mul(*m_row_ptr,prep_val);
742                     m_row_ptr++;
743                 }
744              }
745#endif
746              for (i=first_col;i<final_base_dim;i++)
747              {
748                  if (*cur_row_ptr!=0)
749                  {
750                    mul_val=modp_mul(*cur_row_ptr,red_val);
751                    *my_row_ptr=modp_sub(*my_row_ptr,mul_val);
752                  }
753                  my_row_ptr++;
754                  cur_row_ptr++;
755              }
756              for (i=0;i<=last_solve_column;i++)  // last_solve_column stores the last non-enmpty entry in solve matrix
757              {
758                  if (*solve_row_ptr!=0)
759                  {
760                     mul_val=modp_mul(*solve_row_ptr,red_val);
761                     *my_solve_row_ptr=modp_sub(*my_solve_row_ptr,mul_val);
762                  }
763                  solve_row_ptr++;
764                  my_solve_row_ptr++;
765              }
766           }
767           row_ptr=row_ptr->next;
768#if 0 /* only debugging */
769           PrintS("reduction by row ");
770           Info ();
771#endif
772     }
773}
774
775static bool RowIsZero () // check whether a row is zero
776{
777     bool zero=1;
778     int i;
779     modp_number *row;
780     row=my_row;
781     for (i=0;i<final_base_dim;i++)
782     {
783         if (*row!=0) {zero=0; break;}
784         row++;
785     }
786     return zero;
787}
788
789static bool DivisibleMon (mono_type m1, mono_type m2) // checks whether m1 is divisible by m2
790{
791     int i;
792     for (i=0;i<variables;i++)
793         if (m1[i]>m2[i]) return false;;
794     return true;
795}
796
797static void ReduceCheckListByMon (mono_type m)  // from check_list monomials divisible by m are thrown out
798{
799     mon_list_entry *c_ptr;
800     mon_list_entry *p_ptr;
801     mon_list_entry *n_ptr;
802     c_ptr=check_list;
803     p_ptr=NULL;
804     while (c_ptr!=NULL)
805     {
806          if (DivisibleMon (m,c_ptr->mon))
807          {
808             if (p_ptr==NULL)
809                check_list=c_ptr->next;
810             else
811                p_ptr->next=c_ptr->next;
812             n_ptr=c_ptr->next;
813             omFree(c_ptr->mon);
814             omFree(c_ptr);
815             c_ptr=n_ptr;
816          }
817          else
818          {
819              p_ptr=c_ptr;
820              c_ptr=c_ptr->next;
821          }
822     }
823}
824
825static void TakeNextMonomial (mono_type mon)  // reads first monomial from check_list, then it is deleted
826{
827     mon_list_entry *n_check_list;
828     if (check_list!=NULL)
829     {
830        memcpy(mon,check_list->mon,sizeof(exponent)*variables);
831        n_check_list=check_list->next;
832        omFree(check_list->mon);
833        omFree(check_list);
834        check_list=n_check_list;
835     }
836}
837
838static void UpdateCheckList (mono_type m) // adds all monomials which are "next" to m (divisible by m and degree +1)
839{
840     int i;
841     for (i=0;i<variables;i++)
842     {
843         m[i]++;
844         check_list=MonListAdd (check_list,m);
845         m[i]--;
846     }
847}
848
849static void ReduceCheckListByLTs ()  // deletes all monomials from check_list which are divisible by one of the leading terms
850{
851     mon_list_entry *ptr;
852     ptr=lt_list;
853     while (ptr!=NULL)
854     {
855           ReduceCheckListByMon (ptr->mon);
856           ptr=ptr->next;
857     }
858}
859
860static void RowListAdd (int first_col, mono_type mon) // puts a row into matrix
861{
862     row_list_entry *ptr;
863     row_list_entry *pptr;
864     row_list_entry *temp;
865     ptr=row_list;
866     pptr=NULL;
867     while (ptr!=NULL)
868     {
869#ifndef unsortedmatrix
870         if (  first_col <= ptr->first_col ) break;
871#endif
872         pptr=ptr;
873         ptr=ptr->next;
874     }
875     temp=(row_list_entry*)omAlloc0(sizeof(row_list_entry));
876     (*temp).row_matrix=(modp_number*)omAlloc0(sizeof(modp_number)*final_base_dim);
877     memcpy((*temp).row_matrix,my_row,sizeof(modp_number)*(final_base_dim));
878     (*temp).row_solve=(modp_number*)omAlloc0(sizeof(modp_number)*final_base_dim);
879     memcpy((*temp).row_solve,my_solve_row,sizeof(modp_number)*(final_base_dim));
880     (*temp).first_col=first_col;
881     temp->next=ptr;
882     if (pptr==NULL) row_list=temp; else pptr->next=temp;
883     memcpy(column_name[first_col],mon,sizeof(exponent)*variables);
884}
885
886
887static void PrepareRow (mono_type mon) // prepares a row and puts it into matrix
888{
889     modp_number *row;
890     int first_col=-1;
891     int col;
892     modp_number red_val=1;
893     row=my_row;
894#ifdef integerstrategy
895     for (col=0;col<final_base_dim;col++)
896     {
897         if (*row!=0)
898         {
899            first_col=col;
900            break;
901         }
902         row++;
903     }
904     my_solve_row[first_col]=1;
905     if (first_col > last_solve_column) last_solve_column=first_col;
906#else
907     for (col=0;col<final_base_dim;col++)
908     {
909         if (*row!=0)
910         {
911            first_col=col;
912            red_val=modp_Reverse[*row]; // first non-zero entry, should multiply all row by inverse to obtain 1
913            modp_denom=modp_mul(modp_denom,*row);  // remembers the divisor
914            *row=1;
915            break;
916         }
917         row++;
918     }
919     my_solve_row[first_col]=1;
920     if (first_col > last_solve_column) last_solve_column=first_col;
921     if (red_val!=1)
922     {
923        row++;
924        for (col=first_col+1;col<final_base_dim;col++)
925        {
926            if (*row!=0) *row=modp_mul(*row,red_val);
927            row++;
928        }
929        row=my_solve_row;
930        for (col=0;col<=last_solve_column;col++)
931        {
932            if (*row!=0) *row=modp_mul(*row,red_val);
933            row++;
934        }
935     }
936#endif
937     RowListAdd (first_col, mon);
938}
939
940static void NewResultEntry ()  // creates an entry for new modp result
941{
942    modp_result_entry *temp;
943    temp=(modp_result_entry*)omAlloc0(sizeof(modp_result_entry));
944    if (cur_result==NULL)
945    {
946       modp_result=temp;
947       temp->prev=NULL;
948    }
949    else
950    {
951       temp->prev=cur_result;
952       cur_result->next=temp;
953    }
954    cur_result=temp;
955    cur_result->next=NULL;
956    cur_result->p=myp;
957    cur_result->generator=NULL;
958    cur_result->n_generators=0;
959    n_results++;
960}
961
962static void FreeResultEntry (modp_result_entry *e) // destroys the result entry, without worrying about where it is
963{
964     generator_entry *cur_gen;
965     generator_entry *next_gen;
966     cur_gen=e->generator;
967     while (cur_gen!=NULL)
968     {
969         next_gen=cur_gen->next;
970         omFree(cur_gen->coef);
971         omFree(cur_gen->lt);
972         omFree(cur_gen);
973         cur_gen=next_gen;
974     }
975     omFree(e);
976}
977
978
979static void NewGenerator (mono_type mon)  // new generator in modp comp found, shoul be stored on the list
980{
981     generator_entry *cur_ptr;
982     generator_entry *prev_ptr;
983     generator_entry *temp;
984     cur_ptr=cur_result->generator;
985     prev_ptr=NULL;
986     while (cur_ptr!=NULL)
987     {
988         prev_ptr=cur_ptr;
989         cur_ptr=cur_ptr->next;
990     }
991     temp=(generator_entry*)omAlloc0(sizeof(generator_entry));
992     if (prev_ptr==NULL) cur_result->generator=temp;
993     else prev_ptr->next=temp;
994     temp->next=NULL;
995     temp->coef=(modp_number*)omAlloc0(sizeof(modp_number)*final_base_dim);
996     memcpy(temp->coef,my_solve_row,sizeof(modp_number)*final_base_dim);
997     temp->lt=ZeroMonomial ();
998     memcpy(temp->lt,mon,sizeof(exponent)*variables);
999     temp->ltcoef=1;
1000     cur_result->n_generators++;
1001}
1002
1003static void MultGenerators () // before reconstructing, all denominators must be cancelled
1004{
1005#ifndef integerstrategy
1006     int i;
1007     generator_entry *cur_ptr;
1008     cur_ptr=cur_result->generator;
1009     while (cur_ptr!=NULL)
1010     {
1011         for (i=0;i<final_base_dim;i++)
1012             cur_ptr->coef[i]=modp_mul(cur_ptr->coef[i],modp_denom);
1013         cur_ptr->ltcoef=modp_denom;
1014         cur_ptr=cur_ptr->next;
1015     }
1016#endif
1017}
1018#if 0 /* only debbuging */
1019void PresentGenerator (int i)  // only for debuging, writes a generator in its form in program
1020{
1021     int j;
1022     modp_result_entry *cur_ptr;
1023     generator_entry *cur_gen;
1024     cur_ptr=modp_result;
1025     while (cur_ptr!=NULL)
1026     {
1027        cur_gen=cur_ptr->generator;
1028        for (j=0;j<i;j++) cur_gen=cur_gen->next;
1029        for (j=0;j<final_base_dim;j++)
1030        {
1031            Print("%d;", cur_gen->coef[j]);
1032        }
1033        PrintS(" and LT = ");
1034        WriteMono (cur_gen->lt);
1035        Print(" ( %d )  prime = %d\n", cur_gen->ltcoef, cur_ptr->p);
1036        cur_ptr=cur_ptr->next;
1037     }
1038}
1039#endif
1040
1041static modp_number TakePrime (modp_number /*p*/)  // takes "previous" (smaller) prime
1042{
1043    myp_index--;
1044    return cf_getSmallPrime(myp_index);
1045}
1046
1047static void PrepareChinese (int n) // initialization for CRA
1048{
1049     int i,k;
1050     modp_result_entry *cur_ptr;
1051     cur_ptr=modp_result;
1052     modp_number *congr_ptr;
1053     modp_number prod;
1054     in_gamma=(modp_number*)omAlloc0(sizeof(modp_number)*n);
1055     congr=(modp_number*)omAlloc0(sizeof(modp_number)*n);
1056     congr_ptr=congr;
1057     while (cur_ptr!=NULL)
1058     {
1059        *congr_ptr=cur_ptr->p;
1060        cur_ptr=cur_ptr->next;
1061        congr_ptr++;
1062     }
1063     for (k=1;k<n;k++)
1064     {
1065         prod=congr[0]%congr[k];
1066         for (i=1;i<=k-1;i++) prod=(prod*congr[i])%congr[k];
1067         in_gamma[i]=OneInverse(prod,congr[k]);
1068     }
1069     mpz_init(bigcongr);
1070     mpz_set_ui(bigcongr,congr[0]);
1071     for (k=1;k<n;k++) mpz_mul_ui(bigcongr,bigcongr,congr[k]);
1072}
1073
1074static void CloseChinese () // after CRA
1075{
1076     omFree(in_gamma);
1077     omFree(congr);
1078     mpz_clear(bigcongr);
1079}
1080
1081static void ClearGCD () // divides polynomials in basis by gcd of coefficients
1082{
1083     bool first_gcd=true;
1084     int i;
1085     mpz_t g;
1086     mpz_init(g);
1087     for (i=0;i<=final_base_dim;i++)
1088     {
1089         if (mpz_sgn(polycoef[i])!=0)
1090         {
1091            if (first_gcd)
1092            {
1093               first_gcd=false;
1094               mpz_set(g,polycoef[i]);
1095            }
1096            else
1097               mpz_gcd(g,g,polycoef[i]);
1098         }
1099     }
1100     for (i=0;i<=final_base_dim;i++) mpz_divexact(polycoef[i],polycoef[i],g);
1101     mpz_clear(g);
1102}
1103
1104static void ReconstructGenerator (int ngen,int n) // recostruction of generator from various modp comp
1105{
1106     int i,j,k;
1107     int coef;
1108     char *str=NULL;
1109     str=(char*)omAlloc0(sizeof(char)*1000);
1110     modp_result_entry *cur_ptr;
1111     generator_entry *cur_gen;
1112     modp_number *u;
1113     modp_number *v;
1114     modp_number temp;
1115     mpz_t sol;
1116     mpz_t nsol;
1117     mpz_init(sol);
1118     mpz_init(nsol);
1119     u=(modp_number*)omAlloc0(sizeof(modp_number)*n);
1120     v=(modp_number*)omAlloc0(sizeof(modp_number)*n);
1121     for (coef=0;coef<=final_base_dim;coef++)
1122     {
1123         i=0;
1124         cur_ptr=modp_result;
1125         while (cur_ptr!=NULL)
1126         {
1127            cur_gen=cur_ptr->generator;
1128            for (j=0;j<ngen;j++) cur_gen=cur_gen->next; // we have to take jth generator
1129            if (coef<final_base_dim) u[i]=cur_gen->coef[coef]; else u[i]=cur_gen->ltcoef;
1130            cur_ptr=cur_ptr->next;
1131            i++;
1132         }
1133         v[0]=u[0]; // now CRA begins
1134         for (k=1;k<n;k++)
1135         {
1136             temp=v[k-1];
1137             for (j=k-2;j>=0;j--) temp=(temp*congr[j]+v[j])%congr[k];
1138             temp=u[k]-temp;
1139             if (temp<0) temp=temp+congr[k];
1140             v[k]=(temp*in_gamma[k])%congr[k];
1141         }
1142         mpz_set_si(sol,v[n-1]);
1143         for (k=n-2;k>=0;k--)
1144         {
1145             mpz_mul_ui(sol,sol,congr[k]);
1146             mpz_add_ui(sol,sol,v[k]);
1147         }          // now CRA ends
1148         mpz_sub(nsol,sol,bigcongr);
1149         int s=mpz_cmpabs(sol,nsol);
1150         if (s>0) mpz_set(sol,nsol); // chooses representation closer to 0
1151         mpz_set(polycoef[coef],sol);
1152         if (coef<final_base_dim)
1153            memcpy(polyexp[coef],generic_column_name[coef],sizeof(exponent)*variables);
1154         else
1155            memcpy(polyexp[coef],MonListElement (generic_lt,ngen),sizeof(exponent)*variables);
1156#ifdef checksize
1157         size=mpz_sizeinbase(sol,10);
1158         if (size>maximal_size) maximal_size=size;
1159#endif
1160     }
1161     omFree(u);
1162     omFree(v);
1163     omFree(str);
1164     ClearGCD ();
1165     mpz_clear(sol);
1166     mpz_clear(nsol);
1167}
1168
1169static void Discard ()  // some unlucky prime occures
1170{
1171     modp_result_entry *temp;
1172#ifdef writemsg
1173     Print(", prime=%d", cur_result->p);
1174#endif
1175     bad_primes++;
1176     if (good_primes>bad_primes)
1177     {
1178#ifdef writemsg
1179        Print("-discarding this comp (%dth)\n", n_results);
1180#endif
1181        temp=cur_result;
1182        cur_result=cur_result->prev;
1183        cur_result->next=NULL;
1184        n_results--;
1185        FreeResultEntry (temp);
1186     }
1187     else
1188     {
1189#ifdef writemsg
1190        PrintS("-discarding ALL.\n");
1191#endif
1192        int i;
1193        modp_result_entry *ntfree;
1194        generator_entry *cur_gen;
1195        temp=cur_result->prev;
1196        while (temp!=NULL)
1197        {
1198            ntfree=temp->prev;
1199            FreeResultEntry (temp);
1200            temp=ntfree;
1201        }
1202        modp_result=cur_result;
1203        cur_result->prev=NULL;
1204        n_results=1;
1205        good_primes=1;
1206        bad_primes=0;
1207        generic_n_generators=cur_result->n_generators;
1208        cur_gen=cur_result->generator;
1209        generic_lt=FreeMonList (generic_lt);
1210        for (i=0;i<generic_n_generators;i++)
1211        {
1212            generic_lt=MonListAdd (generic_lt,cur_gen->lt);
1213            cur_gen=cur_gen->next;
1214        }
1215        for (i=0;i<final_base_dim;i++) memcpy(generic_column_name[i],column_name[i],sizeof(exponent)*variables);
1216     }
1217}
1218
1219static void modp_SetColumnNames ()  // used by modp - sets column names, the old table will be destroyed
1220{
1221    int i;
1222    for (i=0;i<final_base_dim;i++) memcpy(generic_column_name[i],column_name[i],sizeof(exponent)*variables);
1223}
1224
1225static void CheckColumnSequence () // checks if scheme of computations is as generic one
1226{
1227     int i;
1228     if (cur_result->n_generators!=generic_n_generators)
1229     {
1230#ifdef writemsg
1231        PrintS("wrong number of generators occured");
1232#else
1233        if (protocol) PrintS("ng");
1234#endif
1235        Discard ();
1236        return;
1237     }
1238     if (denom_divisible)
1239     {
1240#ifdef writemsg
1241        PrintS("denom of coef divisible by p");
1242#else
1243        if (protocol) PrintS("dp");
1244#endif
1245        Discard ();
1246        return;
1247     }
1248     generator_entry *cur_gen;
1249     mon_list_entry *cur_mon;
1250     cur_gen=cur_result->generator;
1251     cur_mon=generic_lt;
1252     for (i=0;i<generic_n_generators;i++)
1253     {
1254         if (!EqualMon(cur_mon->mon,cur_gen->lt))
1255         {
1256#ifdef writemsg
1257            PrintS("wrong leading term occured");
1258#else
1259            if (protocol) PrintS("lt");
1260#endif
1261            Discard ();
1262            return;
1263         }
1264         cur_gen=cur_gen->next;
1265         cur_mon=cur_mon->next;
1266     }
1267     for (i=0;i<final_base_dim;i++)
1268     {
1269         if (!EqualMon(generic_column_name[i],column_name[i]))
1270         {
1271#ifdef writemsg
1272            PrintS("wrong seq of cols occured");
1273#else
1274            if (protocol) PrintS("sc");
1275#endif
1276            Discard ();
1277            return;
1278         }
1279     }
1280     good_primes++;
1281}
1282#if 0 /* only debuggig */
1283void WriteGenerator () // writes generator (only for debugging)
1284{
1285     char *str;
1286     str=(char*)omAlloc0(sizeof(char)*1000);
1287     int i;
1288     for (i=0;i<=final_base_dim;i++)
1289     {
1290         str=mpz_get_str(str,10,polycoef[i]);
1291         PrintS(str);
1292         PrintS("*");
1293         WriteMono(polyexp[i]);
1294         PrintS(" ");
1295     }
1296     omFree(str);
1297     PrintLn();
1298}
1299#endif
1300
1301static bool CheckGenerator () // evaluates generator to check whether it is good
1302{
1303     mpz_t val,sum;
1304     int con,i;
1305     mpz_init(val);
1306     mpz_init(sum);
1307     for (con=0;con<final_base_dim;con++)
1308     {
1309       mpz_set_si(sum,0);
1310       for (i=0;i<=final_base_dim;i++)
1311       {
1312         int_Evaluate(val, polyexp[i], condition_list[con]);
1313         mpz_mul(val,val,polycoef[i]);
1314         mpz_add(sum,sum,val);
1315       }
1316       if (mpz_sgn(sum)!=0)
1317       {
1318          mpz_clear(val);
1319          mpz_clear(sum);
1320          return false;
1321       }
1322    }
1323    mpz_clear(val);
1324    mpz_clear(sum);
1325    return true;
1326}
1327
1328static void ClearGenList ()
1329{
1330     gen_list_entry *temp;
1331     int i;
1332     while (gen_list!=NULL)
1333     {
1334         temp=gen_list->next;
1335         for (i=0;i<=final_base_dim;i++)
1336         {
1337             mpz_clear(gen_list->polycoef[i]);
1338             omFree(gen_list->polyexp[i]);
1339         }
1340         omFree(gen_list->polycoef);
1341         omFree(gen_list->polyexp);
1342         omFree(gen_list);
1343         gen_list=temp;
1344      }
1345}
1346
1347static void UpdateGenList ()
1348{
1349     gen_list_entry *temp,*prev;
1350     int i,j;
1351     prev=NULL;
1352     temp=gen_list;
1353     exponent deg;
1354     for (i=0;i<=final_base_dim;i++)
1355     {
1356         deg=MonDegree(polyexp[i]);
1357         for (j=0;j<deg;j++)
1358         {
1359             mpz_mul(polycoef[i],polycoef[i],common_denom);
1360         }
1361     }
1362     ClearGCD ();
1363     while (temp!=NULL)
1364     {
1365         prev=temp;
1366         temp=temp->next;
1367     }
1368     temp=(gen_list_entry*)omAlloc0(sizeof(gen_list_entry));
1369     if (prev==NULL) gen_list=temp; else prev->next=temp;
1370     temp->next=NULL;
1371     temp->polycoef=(mpz_t*)omAlloc(sizeof(mpz_t)*(final_base_dim+1));
1372     temp->polyexp=(mono_type*)omAlloc(sizeof(mono_type)*(final_base_dim+1));
1373     for (i=0;i<=final_base_dim;i++)
1374     {
1375         mpz_init(temp->polycoef[i]);
1376         mpz_set(temp->polycoef[i],polycoef[i]);
1377         temp->polyexp[i]=ZeroMonomial ();
1378         memcpy(temp->polyexp[i],polyexp[i],sizeof(exponent)*variables);
1379     }
1380}
1381
1382#if 0 /* only debugging */
1383void ShowGenList ()
1384{
1385     gen_list_entry *temp;
1386     int i;
1387     char *str;
1388     str=(char*)omAlloc0(sizeof(char)*1000);
1389     temp=gen_list;
1390     while (temp!=NULL)
1391     {
1392         PrintS("generator: ");
1393         for (i=0;i<=final_base_dim;i++)
1394         {
1395             str=mpz_get_str(str,10,temp->polycoef[i]);
1396             PrintS(str);
1397             PrintS("*");
1398             WriteMono(temp->polyexp[i]);
1399         }
1400         PrintLn();
1401         temp=temp->next;
1402     }
1403     omFree(str);
1404}
1405#endif
1406
1407
1408static void modp_Main ()
1409{
1410     mono_type cur_mon;
1411     cur_mon= ZeroMonomial ();
1412     modp_denom=1;
1413     bool row_is_zero;
1414
1415#if 0 /* only debugging */
1416     Info ();
1417#endif
1418
1419     while (check_list!=NULL)
1420     {
1421           TakeNextMonomial (cur_mon);
1422           ProduceRow (cur_mon);
1423#if 0 /* only debugging */
1424           cout << "row produced for monomial ";
1425           WriteMono (cur_mon);
1426           cout << endl;
1427           Info ();
1428#endif
1429           ReduceRow ();
1430           row_is_zero = RowIsZero ();
1431           if (row_is_zero)
1432           {
1433              lt_list=MonListAdd (lt_list,cur_mon);
1434              ReduceCheckListByMon (cur_mon);
1435              NewGenerator (cur_mon);
1436#if 0 /* only debugging */
1437              cout << "row is zero - linear dependence found (should be seen in my_solve_row)" << endl;
1438              cout << "monomial added to leading terms list" << endl;
1439              cout << "check list updated" << endl;
1440              Info ();
1441#endif
1442           }
1443           else
1444           {
1445              base_list= MonListAdd (base_list,cur_mon);
1446              UpdateCheckList (cur_mon);
1447              ReduceCheckListByLTs ();
1448#if 0 /* only debugging */
1449              cout << "row is non-zero" << endl;
1450              cout << "monomial added to quotient basis list" << endl;
1451              cout << "new monomials added to check list" << endl;
1452              cout << "check list reduced by monomials from leading term list" << endl;
1453              Info ();
1454#endif
1455              PrepareRow (cur_mon);
1456#if 0 /* only debugging */
1457              cout << "row prepared and put into matrix" << endl;
1458              Info ();
1459#endif
1460           }
1461        }
1462        omFree(cur_mon);
1463}
1464
1465static void ResolveCoeff (mpq_t c, number m)
1466{
1467  if ((long)m & SR_INT)
1468  {
1469    long m_val=SR_TO_INT(m);
1470    mpq_set_si(c,m_val,1);
1471  }
1472  else
1473  {
1474    if (m->s<2)
1475    {
1476      mpz_set(mpq_numref(c),m->z);
1477      mpz_set(mpq_denref(c),m->n);
1478      mpq_canonicalize(c);
1479    }
1480    else
1481    {
1482      mpq_set_z(c,m->z);
1483    }
1484  }
1485}
1486
1487ideal interpolation(const std::vector<ideal>& L, intvec *v)
1488{
1489  protocol=TEST_OPT_PROT;  // should be set if option(prot) is enabled
1490
1491  bool data_ok=true;
1492
1493  // reading the ring data ***************************************************
1494  if ((currRing==NULL) || ((!rField_is_Zp (currRing))&&(!rField_is_Q (currRing))))
1495  {
1496     WerrorS("coefficient field should be Zp or Q!");
1497     return NULL;
1498  }
1499  if ((currRing->qideal)!=NULL)
1500  {
1501     WerrorS("quotient ring not supported!");
1502     return NULL;
1503  }
1504  if ((currRing->OrdSgn)!=1)
1505  {
1506     WerrorS("ordering must be global!");
1507     return NULL;
1508  }
1509  n_points=v->length ();
1510  if (n_points!=L.size())
1511  {
1512     WerrorS("list and intvec must have the same length!");
1513     return NULL;
1514  }
1515  assume( n_points > 0 ); 
1516  variables=currRing->N;
1517  only_modp=rField_is_Zp(currRing);
1518  if (only_modp) myp=rChar(currRing);
1519  // ring data read **********************************************************
1520
1521
1522  multiplicity=(int*)malloc(sizeof(int)*n_points); // TODO: use omalloc!
1523  int i;
1524  for (i=0;i<n_points;i++) multiplicity[i]=(*v)[i];
1525
1526  final_base_dim = CalcBaseDim ();
1527
1528#ifdef writemsg
1529  Print("number of variables: %d\n", variables);
1530  Print("number of points: %d\n", n_points);
1531  PrintS("multiplicities: ");
1532  for (i=0;i<n_points;i++) Print("%d ", multiplicity[i]);
1533  PrintLn();
1534  Print("general initialization for dimension %d ...\n", final_base_dim);
1535#endif
1536
1537  GeneralInit ();
1538
1539// reading coordinates of points from ideals **********************************
1540  mpq_t divisor;
1541  if (!only_modp) mpq_init(divisor);
1542  int j;
1543  for(i=0; i<L.size();i++)
1544  {
1545    ideal I = L[i];
1546    for(j=0;j<IDELEMS(I);j++)
1547    {
1548      poly p=I->m[j];
1549      if (p!=NULL)
1550      {
1551        poly ph=pHead(p);
1552        int pcvar=pVar(ph);
1553        if (pcvar!=0)
1554        {
1555          pcvar--;
1556          if (coord_exist[i][pcvar])
1557          {
1558             Print("coordinate %d for point %d initialized twice!\n",pcvar+1,i+1);
1559             data_ok=false;
1560          }
1561          number m;
1562          m=pGetCoeff(p); // possible coefficient standing by a leading monomial
1563          if (!only_modp) ResolveCoeff (divisor,m);
1564          number n;
1565          if (pNext(p)!=NULL) n=pGetCoeff(pNext(p));
1566          else n=nInit(0);
1567          if (only_modp)
1568          {
1569            n=nNeg(n);
1570            n=nDiv(n,m);
1571            modp_points[i][pcvar]=(int)((long)n);
1572          }
1573          else
1574          {
1575            ResolveCoeff (q_points[i][pcvar],n);
1576            mpq_neg(q_points[i][pcvar],q_points[i][pcvar]);
1577            mpq_div(q_points[i][pcvar],q_points[i][pcvar],divisor);
1578          }
1579          coord_exist[i][pcvar]=true;
1580        }
1581        else
1582        {
1583          PrintS("not a variable? ");
1584          wrp(p);
1585          PrintLn();
1586          data_ok=false;
1587        }
1588        pDelete(&ph);
1589      }
1590    }
1591  }
1592  if (!only_modp) mpq_clear(divisor);
1593  // data from ideal read *******************************************************
1594
1595  // ckecking if all coordinates are initialized
1596  for (i=0;i<n_points;i++)
1597  {
1598      for (j=0;j<variables;j++)
1599      {
1600          if (!coord_exist[i][j])
1601          {
1602             Print("coordinate %d for point %d not known!\n",j+1,i+1);
1603             data_ok=false;
1604          }
1605      }
1606  }
1607
1608  if (!data_ok)
1609  {
1610     GeneralDone();
1611     WerrorS("data structure is invalid");
1612     return NULL;
1613  }
1614
1615  if (!only_modp) IntegerPoints ();
1616  MakeConditions ();
1617#ifdef writemsg
1618  PrintS("done.\n");
1619#else
1620  if (protocol) Print("[vdim %d]",final_base_dim);
1621#endif
1622
1623
1624// main procedure *********************************************************************
1625  int modp_cycles=10;
1626  bool correct_gen=false;
1627  if (only_modp) modp_cycles=1;
1628  myp_index=cf_getNumSmallPrimes ();
1629
1630  while ((!correct_gen)&&(myp_index>1))
1631  {
1632#ifdef writemsg
1633        Print("trying %d cycles mod p...\n",modp_cycles);
1634#else
1635        if (protocol) Print("(%d)",modp_cycles);
1636#endif
1637        while ((n_results<modp_cycles)&&(myp_index>1))  // some computations mod p
1638        {
1639            if (!only_modp) myp=TakePrime (myp);
1640            NewResultEntry ();
1641            InitProcData ();
1642            if (only_modp) modp_PrepareProducts (); else int_PrepareProducts ();
1643
1644            modp_Main ();
1645
1646            if (!only_modp)
1647            {
1648               MultGenerators ();
1649               CheckColumnSequence ();
1650            }
1651            else
1652            {
1653               modp_SetColumnNames ();
1654            }
1655            FreeProcData ();
1656        }
1657
1658        if (!only_modp)
1659        {
1660           PrepareChinese (modp_cycles);
1661           correct_gen=true;
1662           for (i=0;i<generic_n_generators;i++)
1663           {
1664               ReconstructGenerator (i,modp_cycles);
1665               correct_gen=CheckGenerator ();
1666               if (!correct_gen)
1667               {
1668#ifdef writemsg
1669                  PrintS("wrong generator!\n");
1670#else
1671//                  if (protocol) PrintS("!g");
1672#endif
1673                  ClearGenList ();
1674                  break;
1675               }
1676               else
1677               {
1678                  UpdateGenList ();
1679               }
1680           }
1681#ifdef checksize
1682           Print("maximal size of output: %d, precision bound: %d.\n",maximalsize,mpz_sizeinbase(bigcongr,10));
1683#endif
1684           CloseChinese ();
1685           modp_cycles=modp_cycles+10;
1686        }
1687        else
1688        {
1689           correct_gen=true;
1690        }
1691  }
1692// end of main procedure ************************************************************************************
1693
1694#ifdef writemsg
1695  PrintS("computations finished.\n");
1696#else
1697  if (protocol) PrintLn();
1698#endif
1699
1700  if (!correct_gen)
1701  {
1702     GeneralDone ();
1703     ClearGenList ();
1704     WerrorS("internal error - coefficient too big!");
1705     return NULL;
1706  }
1707
1708// passing data to ideal *************************************************************************************
1709  ideal ret;
1710
1711  if (only_modp)
1712  {
1713    mono_type mon;
1714    ret=idInit(modp_result->n_generators,1);
1715    generator_entry *cur_gen=modp_result->generator;
1716    for(i=0;i<IDELEMS(ret);i++)
1717    {
1718      poly p,sum;
1719      sum=NULL;
1720      int a;
1721      int cf;
1722      for (a=final_base_dim;a>=0;a--)
1723      {
1724        if (a==final_base_dim) cf=cur_gen->ltcoef; else cf=cur_gen->coef[a];
1725        if (cf!=0)
1726        {
1727            p=pISet(cf);
1728            if (a==final_base_dim) mon=cur_gen->lt; else mon=generic_column_name[a];
1729            for (j=0;j<variables;j++) pSetExp(p,j+1,mon[j]);
1730            pSetm(p);
1731            sum=pAdd(sum,p);
1732        }
1733      }
1734      ret->m[i]=sum;
1735      cur_gen=cur_gen->next;
1736    }
1737  }
1738  else
1739  {
1740    ret=idInit(generic_n_generators,1);
1741    gen_list_entry *temp=gen_list;
1742    for(i=0;i<IDELEMS(ret);i++)
1743    {
1744      poly p,sum;
1745      sum=NULL;
1746      int a;
1747      for (a=final_base_dim;a>=0;a--) // build one polynomial
1748      {
1749          if (mpz_sgn(temp->polycoef[a])!=0)
1750          {
1751             number n=ALLOC_RNUMBER();
1752#ifdef LDEBUG
1753             n->debug=123456;
1754#endif
1755             mpz_init_set(n->z,temp->polycoef[a]);
1756             n->s=3;
1757             nlNormalize(n, currRing->cf);
1758             p=pNSet(n); //a monomial
1759             for (j=0;j<variables;j++) pSetExp(p,j+1,temp->polyexp[a][j]);
1760             pSetm(p); // after all pSetExp
1761             sum=pAdd(sum,p);
1762          }
1763      }
1764      ret->m[i]=sum;
1765      temp=temp->next;
1766    }
1767  }
1768// data transferred ****************************************************************************
1769
1770
1771  GeneralDone ();
1772  ClearGenList ();
1773  return ret;
1774}
1775
1776
Note: See TracBrowser for help on using the repository browser.