source: git/Singular/interpolation.cc @ 09830b6

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