source: git/Singular/interpolation.cc @ 30d574

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