source: git/Singular/interpolation.cc @ 0509a99

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