source: git/Singular/interpolation.cc @ e57255

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