1 #ifndef TGB_INTERNAL_H
2 #define TGB_INTERNAL_H
3 //!\file tgb_internal.h
4 /****************************************
5 *  Computer Algebra System SINGULAR     *
6 ****************************************/
7 /*
8  * ABSTRACT: tgb internal .h file
9 */
10 #define USE_NORO 1
11 
12 #include "omalloc/omalloc.h"
13 
14 //#define TGB_DEBUG
15 #define FULLREDUCTIONS
16 //#define HALFREDUCTIONS
17 //#define HEAD_BIN
18 //#define HOMOGENEOUS_EXAMPLE
19 #define REDTAIL_S
20 #define PAR_N 100
21 #define PAR_N_F4 5000
22 #define AC_NEW_MIN 2
23 #define AC_FLATTEN 1
24 
25 //#define FIND_DETERMINISTIC
26 //#define REDTAIL_PROT
27 //#define QUICK_SPOLY_TEST
28 #ifdef USE_NORO
29 #define NORO_CACHE 1
30 #define NORO_SPARSE_ROWS_PRE 1
31 #define NORO_NON_POLY 1
32 #include <algorithm>
33 #endif
34 #ifdef NORO_CACHE
35 //#include <map>
36 #include <vector>
37 #endif
38 #ifdef HAVE_BOOST_DYNAMIC_BITSET_HPP
39 #define  HAVE_BOOST 1
40 #endif
41 //#define HAVE_BOOST 1
42 //#define USE_STDVECBOOL 1
43 #ifdef HAVE_BOOST
44 #include <vector>
45 using boost::dynamic_bitset;
46 using std::vector;
47 #endif
48 #ifdef USE_STDVECBOOL
49 #include <vector>
50 using std::vector;
51 #endif
52 #include <stdlib.h>
53 
54 #include "misc/options.h"
55 
56 #include "coeffs/modulop.h"
57 
58 #include "polys/monomials/p_polys.h"
59 #include "polys/monomials/ring.h"
60 #include "polys/kbuckets.h"
61 
62 #include "kernel/ideals.h"
63 #include "kernel/polys.h"
64 
65 #include "kernel/GBEngine/kutil.h"
66 #include "kernel/GBEngine/kInline.h"
67 #include "kernel/GBEngine/kstd1.h"
68 
69 #include "coeffs/modulop_inl.h" // npInit, npMult
70 
71 class PolySimple
72 {
73 public:
PolySimple(poly p)74   PolySimple(poly p)
75   {
76     impl=p;
77   }
PolySimple()78   PolySimple()
79   {
80     impl=NULL;
81   }
PolySimple(const PolySimple & a)82   PolySimple(const PolySimple& a)
83   {
84     //impl=p_Copy(a.impl,currRing);
85     impl=a.impl;
86   }
87   PolySimple& operator=(const PolySimple& p2)
88   {
89     //p_Delete(&impl,currRing);
90     //impl=p_Copy(p2.impl,currRing);
91     impl=p2.impl;
92     return *this;
93   }
~PolySimple()94   ~PolySimple()
95   {
96     //p_Delete(&impl,currRing);
97   }
98   bool operator< (const PolySimple& other) const
99   {
100     return pLmCmp(impl,other.impl)<0;
101   }
102   bool operator==(const PolySimple& other)
103   {
104     return pLmEqual(impl,other.impl);
105   }
106   poly impl;
107 
108 };
109 template<class number_type> class DataNoroCacheNode;
110 /*class MonRedRes{
111 public:
112   poly p;
113   number coef;
114   BOOLEAN changed;
115   int len;
116   BOOLEAN onlyBorrowed;
117   bool operator<(const MonRedRes& other) const
118   {
119     int cmp=p_LmCmp(p,other.p,currRing);
120     if ((cmp<0)||((cmp==0)&&((onlyBorrowed)&&(!(other.onlyBorrowed)))))
121     {
122       return true;
123     } else return false;
124   }
125   DataNoroCacheNode* ref;
126   MonRedRes()
127   {
128     ref=NULL;
129     p=NULL;
130   }
131 };*/
132 template <class number_type> class MonRedResNP
133 {
134 public:
135   number coef;
136 
137 
138   DataNoroCacheNode<number_type>* ref;
MonRedResNP()139   MonRedResNP()
140   {
141     ref=NULL;
142   }
143 };
144 struct sorted_pair_node
145 {
146   //criterium, which is stable 0. small lcm 1. small i 2. small j
147   wlen_type expected_length;
148   poly lcm_of_lm;
149   int i;
150   int j;
151   int deg;
152 
153 
154 };
155 #ifdef NORO_CACHE
156 #ifndef NORO_NON_POLY
157 class NoroPlaceHolder
158 {
159 public:
160   DataNoroCacheNode* ref;
161   number coef;
162 };
163 #endif
164 #endif
165 //static ideal debug_Ideal;
166 
167 
168 struct poly_list_node
169 {
170   poly p;
171   poly_list_node* next;
172 };
173 
174 struct int_pair_node
175 {
176   int_pair_node* next;
177   int a;
178   int b;
179 };
180 struct monom_poly
181 {
182   poly m;
183   poly f;
184 };
185 struct mp_array_list
186 {
187   monom_poly* mp;
188   int size;
189   mp_array_list* next;
190 };
191 
192 
193 struct poly_array_list
194 {
195   poly* p;
196   int size;
197   poly_array_list* next;
198 };
199 class slimgb_alg
200 {
201   public:
202     slimgb_alg(ideal I, int syz_comp,BOOLEAN F4,int deg_pos);
203                 void introduceDelayedPairs(poly* pa,int s);
204     virtual ~slimgb_alg();
205     void cleanDegs(int lower, int upper);
206 #ifndef HAVE_BOOST
207 #ifdef USE_STDVECBOOL
208   vector<vector<bool> > states;
209 #else
210   char** states;
211 #endif
212 #else
213   vector<dynamic_bitset<> > states;
214 #endif
215   ideal add_later;
216   ideal S;
217   ring r;
218   int* lengths;
219   wlen_type* weighted_lengths;
220   long* short_Exps;
221   kStrategy strat;
222   int* T_deg;
223   int* T_deg_full;
224   poly tmp_lm;
225   poly* tmp_pair_lm;
226   sorted_pair_node** tmp_spn;
227   poly* expandS;
228   poly* gcd_of_terms;
229   int_pair_node* soon_free;
230   sorted_pair_node** apairs;
231   #if 0
232   BOOLEAN* modifiedS;
233   #endif
234   #ifdef TGB_RESORT_PAIRS
235   bool* replaced;
236   #endif
237   poly_list_node* to_destroy;
238   //for F4
239   mp_array_list* F;
240   poly_array_list* F_minus;
241 
242   //end for F4
243 #ifdef HEAD_BIN
244   omBin   HeadBin;
245 #endif
246   unsigned int reduction_steps;
247   int n;
248   //! array_lengths should be greater equal n;
249   int syz_comp;
250   int array_lengths;
251   int normal_forms;
252   int current_degree;
253   int Rcounter;
254   int last_index;
255   int max_pairs;
256   int pair_top;
257   int easy_product_crit;
258   int extended_product_crit;
259   int average_length;
260   int lastDpBlockStart;
261   int lastCleanedDeg;
262   int deg_pos;
263   BOOLEAN use_noro;
264   BOOLEAN use_noro_last_block;
265   BOOLEAN isDifficultField;
266   BOOLEAN completed;
267   BOOLEAN is_homog;
268   BOOLEAN tailReductions;
269   BOOLEAN eliminationProblem;
270   BOOLEAN F4_mode;
271   BOOLEAN nc;
272   #ifdef TGB_RESORT_PAIRS
273   BOOLEAN used_b;
274   #endif
pTotaldegree(poly p)275   unsigned long pTotaldegree(poly p)
276   {
277       pTest(p);
278       //assume(pDeg(p,r)==::p_Totaldegree(p,r));
279       assume(((unsigned long)::p_Totaldegree(p,r))==p->exp[deg_pos]);
280       return p->exp[deg_pos];
281       //return ::pTotaldegree(p,this->r);
282   }
pTotaldegree_full(poly p)283   int pTotaldegree_full(poly p)
284   {
285     int rr=0;
286     while(p)
287     {
288       int d=this->pTotaldegree(p);
289       rr=si_max(rr,d);
290       pIter(p);
291     }
292     return rr;
293   }
294 };
295 class red_object
296 {
297  public:
298   kBucket_pt bucket;
299   poly p;
300   unsigned long sev;
301   void flatten();
302   void validate();
303   wlen_type initial_quality;
304   void adjust_coefs(number c_r, number c_ac_r);
305   wlen_type guess_quality(slimgb_alg* c);
306   int clear_to_poly();
307   void canonicalize();
308 };
309 
310 
311 enum calc_state
312   {
313     UNCALCULATED,
314     HASTREP//,
315     //UNIMPORTANT,
316     //SOONTREP
317   };
318 template <class len_type, class set_type>  int pos_helper(kStrategy strat, poly p, len_type len, set_type setL, polyset set);
319 void free_sorted_pair_node(sorted_pair_node* s, const ring r);
320 ideal do_t_rep_gb(ring r,ideal arg_I, int syz_comp, BOOLEAN F4_mode,int deg_pos);
321 void now_t_rep(const int & arg_i, const int & arg_j, slimgb_alg* c);
322 
323 void clean_top_of_pair_list(slimgb_alg* c);
324 int slim_nsize(number n, ring r);
325 sorted_pair_node* quick_pop_pair(slimgb_alg* c);
326 sorted_pair_node* top_pair(slimgb_alg* c);
327 sorted_pair_node** add_to_basis_ideal_quotient(poly h, slimgb_alg* c, int* ip);//, BOOLEAN new_pairs=TRUE);
328 sorted_pair_node**  spn_merge(sorted_pair_node** p, int pn,sorted_pair_node **q, int qn,slimgb_alg* c);
329 int kFindDivisibleByInS_easy(kStrategy strat,const red_object & obj);
330 int tgb_pair_better_gen2(const void* ap,const void* bp);
331 int kFindDivisibleByInS_easy(kStrategy strat,poly p, long sev);
332 /**
333    makes on each red_object in a region a single_step
334  **/
335 class reduction_step
336 {
337  public:
338   /// we assume hat all occuring red_objects have same lm, and all
339   /// occ. lm's in r[l...u] are the same, only reductor does not occur
340   virtual void reduce(red_object* r, int l, int u);
341   //int reduction_id;
342   virtual ~reduction_step();
343   slimgb_alg* c;
344   int reduction_id;
345 };
346 class simple_reducer:public reduction_step
347 {
348  public:
349   poly p;
350   kBucket_pt fill_back;
351   int p_len;
352   int reducer_deg;
353   simple_reducer(poly pp, int pp_len,int pp_reducer_deg, slimgb_alg* pp_c =NULL)
354   {
355     this->p=pp;
356     this->reducer_deg=pp_reducer_deg;
357     assume(pp_len==pLength(pp));
358     this->p_len=pp_len;
359     this->c=pp_c;
360   }
361   virtual void pre_reduce(red_object* r, int l, int u);
362   virtual void reduce(red_object* r, int l, int u);
363   ~simple_reducer();
364 
365 
366   virtual void do_reduce(red_object & ro);
367 };
368 
369 //class sum_canceling_reducer:public reduction_step {
370 //  void reduce(red_object* r, int l, int u);
371 //};
372 struct find_erg
373 {
374   poly expand;
375   int expand_length;
376   int to_reduce_u;
377   int to_reduce_l;
378   int reduce_by;//index of reductor
379   BOOLEAN fromS;//else from los
380 
381 };
382 
pos_helper(kStrategy strat,poly p,len_type len,set_type setL,polyset set)383 template <class len_type, class set_type>  int pos_helper(kStrategy strat, poly p, len_type len, set_type setL, polyset set)
384 {
385   //Print("POSHELER:%d",sizeof(wlen_type));
386   int length=strat->sl;
387   int i;
388   int an = 0;
389   int en= length;
390 
391   if ((len>setL[length])
392       || ((len==setL[length]) && (pLmCmp(set[length],p)== -1)))
393     return length+1;
394 
395   loop
396   {
397     if (an >= en-1)
398     {
399       if ((len<setL[an])
400           || ((len==setL[an]) && (pLmCmp(set[an],p) == 1))) return an;
401       return en;
402     }
403     i=(an+en) / 2;
404     if ((len<setL[i])
405         || ((len==setL[i]) && (pLmCmp(set[i],p) == 1))) en=i;
406     //else if ((len>setL[i])
407     //|| ((len==setL[i]) && (pLmCmp(set[i],p) == -1))) an=i;
408     else an=i;
409   }
410 
411 }
412 #ifdef NORO_CACHE
413 #define slim_prec_cast(a) (unsigned int) (unsigned long) (a)
414 #define F4mat_to_number_type(a) (number_type) slim_prec_cast(a)
415 typedef unsigned short tgb_uint16;
416 typedef unsigned char tgb_uint8;
417 typedef unsigned int tgb_uint32;
418 class NoroCacheNode
419 {
420 public:
421   NoroCacheNode** branches;
422   int branches_len;
423 
424 
NoroCacheNode()425   NoroCacheNode()
426   {
427     branches=NULL;
428     branches_len=0;
429 
430   }
setNode(int branch,NoroCacheNode * node)431   NoroCacheNode* setNode(int branch, NoroCacheNode* node)
432   {
433     if (branch>=branches_len)
434     {
435       if (branches==NULL)
436       {
437         branches_len=branch+1;
438         branches_len=si_max(branches_len,3);
439         branches=(NoroCacheNode**) omAlloc(branches_len*sizeof(NoroCacheNode*));
440         int i;
441         for(i=0;i<branches_len;i++)
442         {
443           branches[i]=NULL;
444         }
445       }
446       else
447       {
448         int branches_len_old=branches_len;
449         branches_len=branch+1;
450         branches=(NoroCacheNode**) omrealloc(branches,branches_len*sizeof(NoroCacheNode*));
451         int i;
452         for(i=branches_len_old;i<branches_len;i++)
453         {
454           branches[i]=NULL;
455         }
456       }
457     }
458     assume(branches[branch]==NULL);
459     branches[branch]=node;
460     return node;
461   }
getBranch(int branch)462   NoroCacheNode* getBranch(int branch)
463   {
464     if (branch<branches_len) return branches[branch];
465     return NULL;
466   }
~NoroCacheNode()467   virtual ~NoroCacheNode()
468   {
469     int i;
470     for(i=0;i<branches_len;i++)
471     {
472       delete branches[i];
473     }
474     omfree(branches);
475   }
getOrInsertBranch(int branch)476   NoroCacheNode* getOrInsertBranch(int branch)
477   {
478     if ((branch<branches_len)&&(branches[branch]))
479       return branches[branch];
480     else
481     {
482       return setNode(branch,new NoroCacheNode());
483     }
484   }
485 };
486 class DenseRow{
487 public:
488   number* array;
489   int begin;
490   int end;
DenseRow()491   DenseRow()
492   {
493     array=NULL;
494   }
~DenseRow()495   ~DenseRow()
496   {
497     omfree(array);
498   }
499 };
500 template <class number_type> class SparseRow
501 {
502 public:
503   int* idx_array;
504   number_type* coef_array;
505   int len;
SparseRow()506   SparseRow()
507   {
508     len=0;
509     idx_array=NULL;
510     coef_array=NULL;
511   }
512   SparseRow<number_type>(int n)
513   {
514     len=n;
515     idx_array=(int*) omAlloc(n*sizeof(int));
516     coef_array=(number_type*) omAlloc(n*sizeof(number_type));
517   }
518   SparseRow<number_type>(int n, const number_type* source)
519   {
520     len=n;
521     idx_array=NULL;
522     coef_array=(number_type*) omAlloc(n*sizeof(number_type));
523     memcpy(coef_array,source,n*sizeof(number_type));
524   }
525   ~SparseRow<number_type>()
526   {
527     omfree(idx_array);
528     omfree(coef_array);
529   }
530 };
531 
532 template <class number_type> class DataNoroCacheNode:public NoroCacheNode
533 {
534 public:
535 
536   int value_len;
537   poly value_poly;
538   #ifdef NORO_SPARSE_ROWS_PRE
539   SparseRow<number_type>* row;
540   #else
541   DenseRow* row;
542   #endif
543   int term_index;
DataNoroCacheNode(poly p,int len)544   DataNoroCacheNode(poly p, int len)
545   {
546     value_len=len;
547     value_poly=p;
548     row=NULL;
549     term_index=-1;
550   }
551   #ifdef NORO_SPARSE_ROWS_PRE
DataNoroCacheNode(SparseRow<number_type> * row)552   DataNoroCacheNode(SparseRow<number_type>* row)
553   {
554     if (row!=NULL)
555       value_len=row->len;
556     else
557       value_len=0;
558     value_poly=NULL;
559     this->row=row;
560     term_index=-1;
561   }
562   #endif
~DataNoroCacheNode()563   ~DataNoroCacheNode()
564   {
565     //p_Delete(&value_poly,currRing);
566     if (row) delete row;
567   }
568 };
569 template <class number_type> class TermNoroDataNode
570 {
571 public:
572   DataNoroCacheNode<number_type>* node;
573   poly t;
574 };
575 
576 template <class number_type> class NoroCache
577 {
578 public:
579   poly temp_term;
580 #ifndef NORO_NON_POLY
581   void evaluatePlaceHolder(number* row,std::vector<NoroPlaceHolder>& place_holders);
582   void evaluateRows();
583   void evaluateRows(int level, NoroCacheNode* node);
584 #endif
585   void collectIrreducibleMonomials( std::vector<DataNoroCacheNode<number_type>* >& res);
586   void collectIrreducibleMonomials(int level,  NoroCacheNode* node, std::vector<DataNoroCacheNode<number_type>* >& res);
587 
588 #ifdef NORO_RED_ARRAY_RESERVER
589   int reserved;
590   poly* recursionPolyBuffer;
591 #endif
592   static const int backLinkCode=-222;
insert(poly term,poly nf,int len)593   DataNoroCacheNode<number_type>* insert(poly term, poly nf, int len)
594   {
595     //assume(impl.find(p_Copy(term,currRing))==impl.end());
596     //assume(len==pLength(nf));
597     assume(npIsOne(p_GetCoeff(term,currRing),currRing->cf));
598     if (term==nf)
599     {
600       term=p_Copy(term,currRing);
601 
602       ressources.push_back(term);
603       nIrreducibleMonomials++;
604       return treeInsertBackLink(term);
605 
606     }
607     else
608     {
609       if (nf)
610       {
611         //nf=p_Copy(nf,currRing);
612         assume(p_LmCmp(nf,term,currRing)==-1);
613         ressources.push_back(nf);
614       }
615       return treeInsert(term,nf,len);
616 
617     }
618 
619     //impl[term]=std::pair<PolySimple,int> (nf,len);
620   }
621   #ifdef NORO_SPARSE_ROWS_PRE
insert(poly term,SparseRow<number_type> * srow)622   DataNoroCacheNode<number_type>* insert(poly term, SparseRow<number_type>* srow)
623   {
624     //assume(impl.find(p_Copy(term,currRing))==impl.end());
625     //assume(len==pLength(nf));
626 
627       return treeInsert(term,srow);
628 
629 
630     //impl[term]=std::pair<PolySimple,int> (nf,len);
631   }
632   #endif
insertAndTransferOwnerShip(poly t,ring)633   DataNoroCacheNode<number_type>* insertAndTransferOwnerShip(poly t, ring /*r*/)
634   {
635     ressources.push_back(t);
636     DataNoroCacheNode<number_type>* res=treeInsertBackLink(t);
637     res->term_index=nIrreducibleMonomials;
638     nIrreducibleMonomials++;
639     return res;
640   }
641   poly lookup(poly term, BOOLEAN& succ, int & len);
642   DataNoroCacheNode<number_type>* getCacheReference(poly term);
NoroCache()643   NoroCache()
644   {
645     buffer=NULL;
646 #ifdef NORO_RED_ARRAY_RESERVER
647     reserved=0;
648     recursionPolyBuffer=(poly*)omAlloc(1000000*sizeof(poly));
649 #endif
650     nIrreducibleMonomials=0;
651     nReducibleMonomials=0;
652     temp_term=pOne();
653     tempBufferSize=3000;
654     tempBuffer=omAlloc(tempBufferSize);
655   }
ensureTempBufferSize(size_t size)656   void ensureTempBufferSize(size_t size)
657   {
658     if (tempBufferSize<size)
659     {
660       tempBufferSize=2*size;
661       omFree(tempBuffer);
662       tempBuffer=omAlloc(tempBufferSize);
663     }
664   }
665 #ifdef NORO_RED_ARRAY_RESERVER
reserve(int n)666   poly* reserve(int n)
667   {
668     poly* res=recursionPolyBuffer+reserved;
669     reserved+=n;
670     return res;
671   }
free(int n)672   void free(int n)
673   {
674     reserved-=n;
675   }
676 #endif
~NoroCache()677   ~NoroCache()
678   {
679     int s=ressources.size();
680     int i;
681     for(i=0;i<s;i++)
682     {
683       p_Delete(&ressources[i].impl,currRing);
684     }
685     p_Delete(&temp_term,currRing);
686 #ifdef NORO_RED_ARRAY_RESERVER
687     omfree(recursionPolyBuffer);
688 #endif
689    omFree(tempBuffer);
690   }
691 
692   int nIrreducibleMonomials;
693   int nReducibleMonomials;
694   void* tempBuffer;
695   size_t tempBufferSize;
696 protected:
treeInsert(poly term,poly nf,int len)697   DataNoroCacheNode<number_type>* treeInsert(poly term,poly nf,int len)
698   {
699     int i;
700     nReducibleMonomials++;
701     int nvars=(currRing->N);
702     NoroCacheNode* parent=&root;
703     for(i=1;i<nvars;i++)
704     {
705       parent=parent->getOrInsertBranch(p_GetExp(term,i,currRing));
706     }
707     return (DataNoroCacheNode<number_type>*) parent->setNode(p_GetExp(term,nvars,currRing),new DataNoroCacheNode<number_type>(nf,len));
708   }
709   #ifdef NORO_SPARSE_ROWS_PRE
treeInsert(poly term,SparseRow<number_type> * srow)710   DataNoroCacheNode<number_type>* treeInsert(poly term,SparseRow<number_type>* srow)
711   {
712     int i;
713     nReducibleMonomials++;
714     int nvars=(currRing->N);
715     NoroCacheNode* parent=&root;
716     for(i=1;i<nvars;i++)
717     {
718       parent=parent->getOrInsertBranch(p_GetExp(term,i,currRing));
719     }
720     return (DataNoroCacheNode<number_type>*) parent->setNode(p_GetExp(term,nvars,currRing),new DataNoroCacheNode<number_type>(srow));
721   }
722   #endif
treeInsertBackLink(poly term)723   DataNoroCacheNode<number_type>* treeInsertBackLink(poly term)
724   {
725     int i;
726     int nvars=(currRing->N);
727     NoroCacheNode* parent=&root;
728     for(i=1;i<nvars;i++)
729     {
730       parent=parent->getOrInsertBranch(p_GetExp(term,i,currRing));
731     }
732     return (DataNoroCacheNode<number_type>*) parent->setNode(p_GetExp(term,nvars,currRing),new DataNoroCacheNode<number_type>(term,backLinkCode));
733   }
734 
735   //@TODO descruct nodes;
736   typedef std::vector<PolySimple> poly_vec;
737   poly_vec ressources;
738   //typedef std::map<PolySimple,std::pair<PolySimple,int> > cache_map;
739   //cache_map impl;
740   NoroCacheNode root;
741   number* buffer;
742 };
743 template<class number_type> SparseRow<number_type> * noro_red_to_non_poly_t(poly p, int &len, NoroCache<number_type>* cache,slimgb_alg* c);
noro_red_mon_to_non_poly(poly t,NoroCache<number_type> * cache,slimgb_alg * c)744 template<class number_type> MonRedResNP<number_type> noro_red_mon_to_non_poly(poly t,  NoroCache<number_type> * cache,slimgb_alg* c)
745 {
746   MonRedResNP<number_type> res_holder;
747 
748 
749     DataNoroCacheNode<number_type>* ref=cache->getCacheReference(t);
750     if (ref!=NULL)
751     {
752       res_holder.coef=p_GetCoeff(t,c->r);
753 
754       res_holder.ref=ref;
755       p_Delete(&t,c->r);
756       return res_holder;
757     }
758 
759   unsigned long sev=p_GetShortExpVector(t,currRing);
760   int i=kFindDivisibleByInS_easy(c->strat,t,sev);
761   if (i>=0)
762   {
763     number coef_bak=p_GetCoeff(t,c->r);
764 
765     p_SetCoeff(t,npInit(1,c->r->cf),c->r);
766     assume(npIsOne(p_GetCoeff(c->strat->S[i],c->r),c->r->cf));
767     number coefstrat=p_GetCoeff(c->strat->S[i],c->r);
768 
769 
770     poly exp_diff=cache->temp_term;
771     p_ExpVectorDiff(exp_diff,t,c->strat->S[i],c->r);
772     p_SetCoeff(exp_diff,npNegM(npInversM(coefstrat,c->r->cf),c->r->cf),c->r);
773     p_Setm(exp_diff,c->r);
774     assume(c->strat->S[i]!=NULL);
775 
776     poly res;
777     res=pp_Mult_mm(pNext(c->strat->S[i]),exp_diff,c->r);
778 
779     int len=c->strat->lenS[i]-1;
780     SparseRow<number_type>* srow;
781     srow=noro_red_to_non_poly_t<number_type>(res,len,cache,c);
782     ref=cache->insert(t,srow);
783     p_Delete(&t,c->r);
784 
785 
786     res_holder.coef=coef_bak;
787     res_holder.ref=ref;
788     return res_holder;
789 
790   } else {
791     number coef_bak=p_GetCoeff(t,c->r);
792     number one=npInit(1, c->r->cf);
793     p_SetCoeff(t,one,c->r);
794 
795     res_holder.ref=cache->insertAndTransferOwnerShip(t,c->r);
796     assume(res_holder.ref!=NULL);
797     res_holder.coef=coef_bak;
798 
799     return res_holder;
800 
801   }
802 
803 }
804 /*
805 poly tree_add(poly* a,int begin, int end,ring r)
806 {
807   int d=end-begin;
808   switch(d)
809   {
810     case 0:
811       return NULL;
812     case 1:
813       return a[begin];
814     case 2:
815       return p_Add_q(a[begin],a[begin+1],r);
816     default:
817       int s=d/2;
818       return p_Add_q(tree_add(a,begin,begin+s,r),tree_add(a,begin+s,end,r),r);
819   }
820 }
821 */
822 
convert_to_sparse_row(number_type * temp_array,int temp_size,int non_zeros)823 template<class number_type> SparseRow<number_type>* convert_to_sparse_row(number_type* temp_array,int temp_size,int non_zeros)
824 {
825 SparseRow<number_type>* res=new SparseRow<number_type>(non_zeros);
826 //int pos=0;
827 //Print("denseness:%f\n",((double) non_zeros/(double) temp_size));
828 number_type* it_coef=res->coef_array;
829 int* it_idx=res->idx_array;
830 #if 0
831 for(i=0;i<cache->nIrreducibleMonomials;i++)
832 {
833   if (!(0==temp_array[i]))
834   {
835 
836     res->idx_array[pos]=i;
837     res->coef_array[pos]=temp_array[i];
838 
839     pos++;
840     non_zeros--;
841     if (non_zeros==0) break;
842   }
843 
844 }
845 #else
846 int64* start=(int64*) ((void*)temp_array);
847 int64* end;
848 const int multiple=sizeof(int64)/sizeof(number_type);
849 if (temp_size==0) end=start;
850 
851 else
852 {
853   int temp_size_rounded=temp_size+(multiple-(temp_size%multiple));
854   assume(temp_size_rounded>=temp_size);
855   assume(temp_size_rounded%multiple==0);
856   assume(temp_size_rounded<temp_size+multiple);
857   number_type* nt_end=temp_array+temp_size_rounded;
858   end=(int64*)((void*)nt_end);
859 }
860 int64* it=start;
861 while(it!=end)
862 {
863   if UNLIKELY((*it)!=0)
864   {
865     int small_i;
866     const int temp_index=((number_type*)((void*) it))-temp_array;
867     const int bound=temp_index+multiple;
868     number_type c;
869     for(small_i=temp_index;small_i<bound;small_i++)
870     {
871       if((c=temp_array[small_i])!=0)
872       {
873         //res->idx_array[pos]=small_i;
874         //res->coef_array[pos]=temp_array[small_i];
875         (*(it_idx++))=small_i;
876         (*(it_coef++))=c;
877         //pos++;
878         non_zeros--;
879 
880       }
881       if UNLIKELY(non_zeros==0) break;
882     }
883 
884   }
885   ++it;
886 }
887 #endif
888 return res;
889 }
890 #ifdef SING_NDEBUG
add_coef_times_sparse(number_type * const temp_array,int,SparseRow<number_type> * row,number coef)891 template <class number_type> void add_coef_times_sparse(number_type* const temp_array,
892 int /*temp_size*/,SparseRow<number_type>* row, number coef)
893 #else
894 template <class number_type> void add_coef_times_sparse(number_type* const temp_array,
895 int temp_size,SparseRow<number_type>* row, number coef)
896 #endif
897 {
898   int j;
899   number_type* const coef_array=row->coef_array;
900   int* const idx_array=row->idx_array;
901   const int len=row->len;
902   tgb_uint32 buffer[256];
903   const tgb_uint32 prime=n_GetChar(currRing->cf);
904   const tgb_uint32 c=F4mat_to_number_type(coef);
905   assume(!(npIsZero(coef,currRing->cf)));
906   for(j=0;j<len;j=j+256)
907   {
908     const int bound=std::min(j+256,len);
909     int i;
910     int bpos=0;
911     for(i=j;i<bound;i++)
912     {
913       buffer[bpos++]=coef_array[i];
914     }
915     int bpos_bound=bound-j;
916     for(i=0;i<bpos_bound;i++)
917     {
918        buffer[i]*=c;
919      }
920     for(i=0;i<bpos_bound;i++)
921     {
922        buffer[i]=buffer[i]%prime;
923     }
924     bpos=0;
925     for(i=j;i<bound;i++)
926     {
927       int idx=idx_array[i];
928       assume(bpos<256);
929       assume(!(npIsZero((number)(long) buffer[bpos],currRing->cf)));
930       temp_array[idx]=F4mat_to_number_type(npAddM((number)(long) temp_array[idx], (number)(long) buffer[bpos++],currRing->cf));
931       #ifndef SING_NDEBUG
932       assume(idx<temp_size);
933       #endif
934     }
935 
936   }
937 }
938 #ifdef SING_NDEBUG
add_coef_times_dense(number_type * const temp_array,int,const number_type * row,int len,number coef)939 template <class number_type> void add_coef_times_dense(number_type* const temp_array,
940 int /*temp_size*/,const number_type* row, int len,number coef)
941 #else
942 template <class number_type> void add_coef_times_dense(number_type* const temp_array,
943 int temp_size,const number_type* row, int len,number coef)
944 #endif
945 {
946   int j;
947   const number_type* const coef_array=row;
948   //int* const idx_array=row->idx_array;
949   //const int len=temp_size;
950   tgb_uint32 buffer[256];
951   const tgb_uint32 prime=n_GetChar(currRing->cf);
952   const tgb_uint32 c=F4mat_to_number_type(coef);
953   assume(!(npIsZero(coef,currRing->cf)));
954   for(j=0;j<len;j=j+256)
955   {
956     const int bound=std::min(j+256,len);
957     int i;
958     int bpos=0;
959     for(i=j;i<bound;i++)
960     {
961       buffer[bpos++]=coef_array[i];
962     }
963     int bpos_bound=bound-j;
964     for(i=0;i<bpos_bound;i++)
965     {
966        buffer[i]*=c;
967      }
968     for(i=0;i<bpos_bound;i++)
969     {
970        buffer[i]=buffer[i]%prime;
971     }
972     bpos=0;
973     for(i=j;i<bound;i++)
974     {
975       //int idx=idx_array[i];
976       assume(bpos<256);
977       //assume(!(npIsZero((number) buffer[bpos])));
978       temp_array[i]=F4mat_to_number_type(npAddM((number)(long) temp_array[i], (number)(long) buffer[bpos++],currRing->cf));
979       #ifndef SING_NDEBUG
980       assume(i<temp_size);
981       #endif
982     }
983 
984   }
985 }
986 #ifdef SING_NDEBUG
add_dense(number_type * const temp_array,int,const number_type * row,int len)987 template <class number_type> void add_dense(number_type* const temp_array,
988 int /*temp_size*/,const number_type* row, int len)
989 #else
990 template <class number_type> void add_dense(number_type* const temp_array,
991 int temp_size,const number_type* row, int len)
992 #endif
993 {
994   //int j;
995   //const number_type* const coef_array=row;
996   //int* const idx_array=row->idx_array;
997   //const int len=temp_size;
998   //tgb_uint32 buffer[256];
999   //const tgb_uint32 prime=npPrimeM;
1000   //const tgb_uint32 c=F4mat_to_number_type(coef);
1001 
1002   int i;
1003   for(i=0;i<len;i++)
1004   {
1005     temp_array[i]=F4mat_to_number_type(npAddM((number)(long) temp_array[i], (number)(long) row[i],currRing->cf));
1006     #ifndef SING_NDEBUG
1007     assume(i<temp_size);
1008     #endif
1009   }
1010 
1011 }
1012 #ifdef SING_NDEBUG
sub_dense(number_type * const temp_array,int,const number_type * row,int len)1013 template <class number_type> void sub_dense(number_type* const temp_array,
1014 int /*temp_size*/,const number_type* row, int len)
1015 #else
1016 template <class number_type> void sub_dense(number_type* const temp_array,
1017 int temp_size,const number_type* row, int len)
1018 #endif
1019 {
1020   //int j;
1021   //const number_type* const coef_array=row;
1022   //int* const idx_array=row->idx_array;
1023   //const int len=temp_size;
1024   //tgb_uint32 buffer[256];
1025   //const tgb_uint32 prime=npPrimeM;
1026   //const tgb_uint32 c=F4mat_to_number_type(coef);
1027 
1028   int i;
1029   for(i=0;i<len;i++)
1030   {
1031     temp_array[i]=F4mat_to_number_type(npSubM((number)(long) temp_array[i], (number)(long) row[i],currRing->cf));
1032     #ifndef SING_NDEBUG
1033     assume(i<temp_size);
1034     #endif
1035   }
1036 }
1037 
1038 #ifdef SING_NDEBUG
add_sparse(number_type * const temp_array,int,SparseRow<number_type> * row)1039 template <class number_type> void add_sparse(number_type* const temp_array,int /*temp_size*/,SparseRow<number_type>* row)
1040 #else
1041 template <class number_type> void add_sparse(number_type* const temp_array,int temp_size,SparseRow<number_type>* row)
1042 #endif
1043 {
1044   int j;
1045 
1046           number_type* const coef_array=row->coef_array;
1047           int* const idx_array=row->idx_array;
1048           const int len=row->len;
1049         for(j=0;j<len;j++)
1050         {
1051           int idx=idx_array[j];
1052           temp_array[idx]=F4mat_to_number_type(   (number_type)(long)npAddM((number) (long)temp_array[idx],(number)(long) coef_array[j],currRing->cf));
1053           #ifndef SING_NDEBUG
1054           assume(idx<temp_size);
1055           #endif
1056         }
1057 }
1058 #ifdef SING_NDEBUG
sub_sparse(number_type * const temp_array,int,SparseRow<number_type> * row)1059 template <class number_type> void sub_sparse(number_type* const temp_array,int /*temp_size*/,SparseRow<number_type>* row)
1060 #else
1061 template <class number_type> void sub_sparse(number_type* const temp_array,int temp_size,SparseRow<number_type>* row)
1062 #endif
1063 {
1064   int j;
1065 
1066           number_type* const coef_array=row->coef_array;
1067           int* const idx_array=row->idx_array;
1068           const int len=row->len;
1069         for(j=0;j<len;j++)
1070         {
1071           int idx=idx_array[j];
1072           temp_array[idx]=F4mat_to_number_type(  (number_type)(long) npSubM((number) (long)temp_array[idx],(number)(long) coef_array[j],currRing->cf));
1073           #ifndef SING_NDEBUG
1074           assume(idx<temp_size);
1075           #endif
1076         }
1077 }
noro_red_to_non_poly_dense(MonRedResNP<number_type> * mon,int len,NoroCache<number_type> * cache)1078 template <class number_type> SparseRow<number_type>* noro_red_to_non_poly_dense(MonRedResNP<number_type>* mon, int len,NoroCache<number_type>* cache)
1079 {
1080   size_t temp_size_bytes=cache->nIrreducibleMonomials*sizeof(number_type)+8;//use 8bit int for testing
1081    assume(sizeof(int64)==8);
1082    cache->ensureTempBufferSize(temp_size_bytes);
1083    number_type* temp_array=(number_type*) cache->tempBuffer;//omalloc(cache->nIrreducibleMonomials*sizeof(number_type));
1084    int temp_size=cache->nIrreducibleMonomials;
1085    memset(temp_array,0,temp_size_bytes);
1086    number minus_one=npInit(-1,currRing->cf);
1087    int i;
1088    for(i=0;i<len;i++)
1089    {
1090      MonRedResNP<number_type> red=mon[i];
1091      if ( /*(*/ red.ref /*)*/ )
1092      {
1093        if (red.ref->row)
1094        {
1095          SparseRow<number_type>* row=red.ref->row;
1096          number coef=red.coef;
1097          if (row->idx_array)
1098          {
1099            if (!((coef==(number)1L)||(coef==minus_one)))
1100            {
1101              add_coef_times_sparse(temp_array,temp_size,row,coef);
1102            }
1103            else
1104            {
1105              if (coef==(number)1L)
1106              {
1107                add_sparse(temp_array,temp_size,row);
1108              }
1109              else
1110              {
1111                sub_sparse(temp_array,temp_size,row);
1112              }
1113            }
1114          }
1115          else
1116          //TODO: treat, 1,-1
1117          if (!((coef==(number)1L)||(coef==minus_one)))
1118          {
1119           add_coef_times_dense(temp_array,temp_size,row->coef_array,row->len,coef);
1120          }
1121          else
1122          {
1123            if (coef==(number)1L)
1124              add_dense(temp_array,temp_size,row->coef_array,row->len);
1125            else
1126            {
1127              assume(coef==minus_one);
1128              sub_dense(temp_array,temp_size,row->coef_array,row->len);
1129              //add_coef_times_dense(temp_array,temp_size,row->coef_array,row->len,coef);
1130            }
1131          }
1132        }
1133        else
1134        {
1135          if (red.ref->value_len==NoroCache<number_type>::backLinkCode)
1136          {
1137            temp_array[red.ref->term_index]=F4mat_to_number_type( npAddM((number)(long) temp_array[red.ref->term_index],red.coef,currRing->cf));
1138          }
1139          else
1140          {
1141            //PrintS("third case\n");
1142          }
1143        }
1144      }
1145    }
1146    int non_zeros=0;
1147    for(i=0;i<cache->nIrreducibleMonomials;i++)
1148    {
1149      //if (!(temp_array[i]==0))
1150      //{
1151      //  non_zeros++;
1152      //}
1153      assume(((temp_array[i]!=0)==0)|| (((temp_array[i]!=0)==1)));
1154      non_zeros+=(temp_array[i]!=0);
1155    }
1156 
1157    if (non_zeros==0)
1158    {
1159      //omfree(mon);
1160      return NULL;
1161    }
1162    SparseRow<number_type>* res=new SparseRow<number_type>(temp_size,temp_array);//convert_to_sparse_row(temp_array,temp_size, non_zeros);
1163 
1164    //omfree(temp_array);
1165 
1166 
1167    return res;
1168 }
1169 template<class number_type> class CoefIdx
1170 {
1171 public:
1172   number_type coef;
1173   int idx;
1174   bool operator<(const CoefIdx<number_type>& other) const
1175   {
1176     return (idx<other.idx);
1177   }
1178 };
write_coef_times_xx_idx_to_buffer(CoefIdx<number_type> * const pairs,int & pos,int * const idx_array,number_type * const coef_array,const int rlen,const number coef)1179 template<class number_type> void write_coef_times_xx_idx_to_buffer(CoefIdx<number_type>* const pairs,int& pos,int* const idx_array, number_type* const coef_array,const int rlen, const number coef)
1180 {
1181   int j;
1182   for(j=0;j<rlen;j++)
1183   {
1184     assume(coef_array[j]!=0);
1185     CoefIdx<number_type> ci;
1186     ci.coef=F4mat_to_number_type(npMultM((number)(long) coef,(number)(long) coef_array[j],currRing->cf));
1187     ci.idx=idx_array[j];
1188     pairs[pos++]=ci;
1189   }
1190 }
write_coef_times_xx_idx_to_buffer_dense(CoefIdx<number_type> * const pairs,int & pos,number_type * const coef_array,const int rlen,const number coef)1191 template<class number_type> void write_coef_times_xx_idx_to_buffer_dense(CoefIdx<number_type>* const pairs,int& pos, number_type* const coef_array,const int rlen, const number coef)
1192 {
1193   int j;
1194 
1195   for(j=0;j<rlen;j++)
1196   {
1197     if (coef_array[j]!=0)
1198     {
1199       assume(coef_array[j]!=0);
1200       CoefIdx<number_type> ci;
1201       ci.coef=F4mat_to_number_type(npMultM((number)(long) coef,(number)(long) coef_array[j],currRing->cf));
1202       assume(ci.coef!=0);
1203       ci.idx=j;
1204       pairs[pos++]=ci;
1205     }
1206   }
1207 }
write_coef_idx_to_buffer_dense(CoefIdx<number_type> * const pairs,int & pos,number_type * const coef_array,const int rlen)1208 template<class number_type> void write_coef_idx_to_buffer_dense(CoefIdx<number_type>* const pairs,int& pos, number_type* const coef_array,const int rlen)
1209 {
1210   int j;
1211 
1212   for(j=0;j<rlen;j++)
1213   {
1214     if (coef_array[j]!=0)
1215     {
1216       assume(coef_array[j]!=0);
1217       CoefIdx<number_type> ci;
1218       ci.coef=coef_array[j];
1219       assume(ci.coef!=0);
1220       ci.idx=j;
1221       pairs[pos++]=ci;
1222     }
1223   }
1224 }
1225 
write_minus_coef_idx_to_buffer_dense(CoefIdx<number_type> * const pairs,int & pos,number_type * const coef_array,const int rlen)1226 template<class number_type> void write_minus_coef_idx_to_buffer_dense(CoefIdx<number_type>* const pairs,int& pos, number_type* const coef_array,const int rlen)
1227 {
1228   int j;
1229 
1230   for(j=0;j<rlen;j++)
1231   {
1232     if (coef_array[j]!=0)
1233     {
1234       assume(coef_array[j]!=0);
1235       CoefIdx<number_type> ci;
1236       ci.coef=F4mat_to_number_type(npNegM((number)(long) coef_array[j],currRing->cf)); // FIXME: inplace negation! // TODO: check if this is not a bug!?
1237       assume(ci.coef!=0);
1238       ci.idx=j;
1239       pairs[pos++]=ci;
1240     }
1241   }
1242 }
write_coef_idx_to_buffer(CoefIdx<number_type> * const pairs,int & pos,int * const idx_array,number_type * const coef_array,const int rlen)1243 template<class number_type> void write_coef_idx_to_buffer(CoefIdx<number_type>* const pairs,int& pos,int* const idx_array, number_type* const coef_array,const int rlen)
1244 {
1245   int j;
1246   for(j=0;j<rlen;j++)
1247   {
1248     assume(coef_array[j]!=0);
1249     CoefIdx<number_type> ci;
1250     ci.coef=coef_array[j];
1251     ci.idx=idx_array[j];
1252     pairs[pos++]=ci;
1253   }
1254 }
1255 
write_minus_coef_idx_to_buffer(CoefIdx<number_type> * const pairs,int & pos,int * const idx_array,number_type * const coef_array,const int rlen)1256 template<class number_type> void write_minus_coef_idx_to_buffer(CoefIdx<number_type>* const pairs,int& pos,int* const idx_array, number_type* const coef_array,const int rlen)
1257 {
1258   int j;
1259   for(j=0;j<rlen;j++)
1260   {
1261     assume(coef_array[j]!=0);
1262     CoefIdx<number_type> ci;
1263     ci.coef=F4mat_to_number_type(npNegM((number)(unsigned long)coef_array[j],currRing->cf));  // FIXME: inplace negation! // TODO: check if this is not a bug!?
1264     ci.idx=idx_array[j];
1265     pairs[pos++]=ci;
1266   }
1267 }
noro_red_to_non_poly_sparse(MonRedResNP<number_type> * mon,int len,NoroCache<number_type> * cache)1268 template <class number_type> SparseRow<number_type>* noro_red_to_non_poly_sparse(MonRedResNP<number_type>* mon, int len,NoroCache<number_type>* cache)
1269 {
1270   int i;
1271   int together=0;
1272   for(i=0;i<len;i++)
1273   {
1274     MonRedResNP<number_type> red=mon[i];
1275     if ((red.ref) &&( red.ref->row))
1276     {
1277       together+=red.ref->row->len;
1278     }
1279     else
1280     {
1281       if ((red.ref) &&(red.ref->value_len==NoroCache<number_type>::backLinkCode))
1282       together++;
1283     }
1284   }
1285   //PrintS("here\n");
1286   if (together==0) return 0;
1287   //PrintS("there\n");
1288   cache->ensureTempBufferSize(together*sizeof(CoefIdx<number_type>));
1289   CoefIdx<number_type>* pairs=(CoefIdx<number_type>*) cache->tempBuffer; //omalloc(together*sizeof(CoefIdx<number_type>));
1290   int pos=0;
1291   const number one=npInit(1, currRing->cf);
1292   const number minus_one=npInit(-1, currRing->cf);
1293   for(i=0;i<len;i++)
1294   {
1295     MonRedResNP<number_type> red=mon[i];
1296     if ((red.ref) &&( red.ref->row))
1297     {
1298       //together+=red.ref->row->len;
1299       int* idx_array=red.ref->row->idx_array;
1300       number_type* coef_array=red.ref->row->coef_array;
1301       int rlen=red.ref->row->len;
1302       number coef=red.coef;
1303       if (idx_array)
1304       {
1305         if ((coef!=one)&&(coef!=minus_one))
1306         {
1307           write_coef_times_xx_idx_to_buffer(pairs,pos,idx_array, coef_array,rlen, coef);
1308         }
1309         else
1310         {
1311           if (coef==one)
1312           {
1313             write_coef_idx_to_buffer(pairs,pos,idx_array, coef_array,rlen);
1314           }
1315           else
1316           {
1317             assume(coef==minus_one);
1318             write_minus_coef_idx_to_buffer(pairs,pos,idx_array, coef_array,rlen);
1319           }
1320         }
1321       }
1322       else
1323       {
1324         if ((coef!=one)&&(coef!=minus_one))
1325         {
1326           write_coef_times_xx_idx_to_buffer_dense(pairs,pos,coef_array,rlen,coef);
1327         }
1328         else
1329         {
1330           if (coef==one)
1331             write_coef_idx_to_buffer_dense(pairs,pos,coef_array,rlen);
1332           else
1333           {
1334             assume(coef==minus_one);
1335             write_minus_coef_idx_to_buffer_dense(pairs,pos,coef_array,rlen);
1336           }
1337         }
1338       }
1339     }
1340     else
1341     {
1342       if ((red.ref) &&(red.ref->value_len==NoroCache<number_type>::backLinkCode))
1343       {
1344         CoefIdx<number_type> ci;
1345         ci.coef=F4mat_to_number_type(red.coef);
1346         ci.idx=red.ref->term_index;
1347         pairs[pos++]=ci;
1348       }
1349     }
1350   }
1351   assume(pos<=together);
1352   together=pos;
1353 
1354   std::sort(pairs,pairs+together);
1355 
1356   int act=0;
1357 
1358   assume(pairs[0].coef!=0);
1359   for(i=1;i<together;i++)
1360   {
1361     if (pairs[i].idx!=pairs[act].idx)
1362     {
1363       if (pairs[act].coef!=0)
1364       {
1365         act=act+1;
1366       }
1367       pairs[act]=pairs[i];
1368     }
1369     else
1370     {
1371       pairs[act].coef=F4mat_to_number_type(npAddM((number)(long)pairs[act].coef,(number)(long)pairs[i].coef,currRing->cf));
1372     }
1373   }
1374 
1375   if (pairs[act].coef==0)
1376   {
1377     act--;
1378   }
1379   int sparse_row_len=act+1;
1380   //Print("res len:%d",sparse_row_len);
1381   if (sparse_row_len==0) {return NULL;}
1382   SparseRow<number_type>* res=new SparseRow<number_type>(sparse_row_len);
1383   {
1384     number_type* coef_array=res->coef_array;
1385     int* idx_array=res->idx_array;
1386     for(i=0;i<sparse_row_len;i++)
1387     {
1388       idx_array[i]=pairs[i].idx;
1389       coef_array[i]=pairs[i].coef;
1390     }
1391   }
1392   //omfree(pairs);
1393 
1394   return res;
1395 }
noro_red_to_non_poly_t(poly p,int & len,NoroCache<number_type> * cache,slimgb_alg * c)1396 template<class number_type> SparseRow<number_type> * noro_red_to_non_poly_t(poly p, int &len, NoroCache<number_type>* cache,slimgb_alg* c)
1397 {
1398   assume(len==pLength(p));
1399   if (p==NULL)
1400   {
1401     len=0;
1402     return NULL;
1403   }
1404 
1405   MonRedResNP<number_type>* mon=(MonRedResNP<number_type>*) omalloc(len*sizeof(MonRedResNP<number_type>));
1406   int i=0;
1407   double max_density=0.0;
1408   while(p!=NULL)
1409   {
1410     poly t=p;
1411     pIter(p);
1412     pNext(t)=NULL;
1413 
1414     MonRedResNP<number_type> red=noro_red_mon_to_non_poly(t,cache,c);
1415     if ((red.ref) && (red.ref->row))
1416     {
1417       double act_density=(double) red.ref->row->len;
1418       act_density/=(double) cache->nIrreducibleMonomials;
1419       max_density=std::max(act_density,max_density);
1420     }
1421     mon[i]=red;
1422     i++;
1423   }
1424 
1425   assume(i==len);
1426   len=i;
1427   bool dense=true;
1428   if (max_density<0.3) dense=false;
1429   if (dense)
1430   {
1431     SparseRow<number_type>* res=noro_red_to_non_poly_dense(mon,len,cache);
1432     omfree(mon);
1433     return res;
1434   }
1435   else
1436   {
1437     SparseRow<number_type>* res=noro_red_to_non_poly_sparse(mon,len,cache);
1438     omfree(mon);
1439     return res;
1440   }
1441   //in the loop before nIrreducibleMonomials increases, so position here is important
1442 
1443 }
1444 #endif
1445 wlen_type pELength(poly p, ring r);
1446 int terms_sort_crit(const void* a, const void* b);
1447 //void simplest_gauss_modp(number* a, int nrows,int ncols);
1448 // a: a[0,0],a[0,1]....a[nrows-1,ncols-1]
1449 // assume: field is Zp
1450 #ifdef USE_NORO
1451 
1452 
write_poly_to_row(number_type * row,poly h,poly * terms,int tn,ring r)1453 template <class number_type > void write_poly_to_row(number_type* row, poly h, poly*terms, int tn, ring r)
1454 {
1455   //poly* base=row;
1456   while(h!=NULL)
1457   {
1458     //Print("h:%i\n",h);
1459     number coef=p_GetCoeff(h,r);
1460     poly* ptr_to_h=(poly*) bsearch(&h,terms,tn,sizeof(poly),terms_sort_crit);
1461     assume(ptr_to_h!=NULL);
1462     int pos=ptr_to_h-terms;
1463     row[pos]=F4mat_to_number_type(coef);
1464     //number_type_array[base+pos]=coef;
1465     pIter(h);
1466   }
1467 }
row_to_poly(number_type * row,poly * terms,int tn,ring r)1468 template <class number_type > poly row_to_poly(number_type* row, poly* terms, int tn, ring r)
1469 {
1470   poly h=NULL;
1471   int j;
1472   number_type zero=0;//;npInit(0);
1473   for(j=tn-1;j>=0;j--)
1474   {
1475     if (!(zero==(row[j])))
1476     {
1477       poly t=terms[j];
1478       t=p_LmInit(t,r);
1479       p_SetCoeff(t,(number)(long) row[j],r);
1480       pNext(t)=h;
1481       h=t;
1482     }
1483 
1484   }
1485   return h;
1486 }
modP_lastIndexRow(number_type * row,int ncols)1487 template <class number_type > int modP_lastIndexRow(number_type* row,int ncols)
1488 {
1489   int lastIndex;
1490   const number_type zero=0;//npInit(0);
1491   for(lastIndex=ncols-1;lastIndex>=0;lastIndex--)
1492   {
1493     if (!(row[lastIndex]==zero))
1494     {
1495       return lastIndex;
1496     }
1497   }
1498   return -1;
1499 }
term_nodes_sort_crit(const void * a,const void * b)1500 template <class number_type> int term_nodes_sort_crit(const void* a, const void* b)
1501 {
1502   return -pLmCmp(((TermNoroDataNode<number_type>*) a)->t,((TermNoroDataNode<number_type>*) b)->t);
1503 }
1504 
1505 template <class number_type>class ModPMatrixBackSubstProxyOnArray;
1506 template <class number_type > class ModPMatrixProxyOnArray
1507 {
1508 public:
1509   friend class ModPMatrixBackSubstProxyOnArray<number_type>;
1510 
1511   int ncols,nrows;
ModPMatrixProxyOnArray(number_type * array,int nnrows,int nncols)1512   ModPMatrixProxyOnArray(number_type* array, int nnrows, int nncols)
1513   {
1514     this->ncols=nncols;
1515     this->nrows=nnrows;
1516     rows=(number_type**) omalloc((size_t)nnrows*sizeof(number_type*));
1517     startIndices=(int*)omalloc((size_t)nnrows*sizeof(int));
1518     int i;
1519     for(i=0;i<nnrows;i++)
1520     {
1521       rows[i]=array+((long)i*(long)nncols);
1522       updateStartIndex(i,-1);
1523     }
1524   }
~ModPMatrixProxyOnArray()1525   ~ModPMatrixProxyOnArray()
1526   {
1527     omfree(rows);
1528     omfree(startIndices);
1529   }
1530 
permRows(int i,int j)1531   void permRows(int i, int j)
1532   {
1533     number_type* h=rows[i];
1534     rows[i]=rows[j];
1535     rows[j]=h;
1536     int hs=startIndices[i];
1537     startIndices[i]=startIndices[j];
1538     startIndices[j]=hs;
1539   }
multiplyRow(int row,number_type coef)1540   void multiplyRow(int row, number_type coef)
1541   {
1542     int i;
1543     number_type* row_array=rows[row];
1544     if(currRing->cf->ch<=NV_MAX_PRIME)
1545     {
1546       for(i=startIndices[row];i<ncols;i++)
1547       {
1548         row_array[i]=F4mat_to_number_type(npMult((number)(long) row_array[i],(number)(long) coef,currRing->cf));
1549       }
1550     }
1551     else
1552     {
1553       for(i=startIndices[row];i<ncols;i++)
1554       {
1555         row_array[i]=F4mat_to_number_type(nvMult((number)(long) row_array[i],(number)(long) coef,currRing->cf));
1556       }
1557     }
1558   }
reduceOtherRowsForward(int r)1559   void reduceOtherRowsForward(int r)
1560   {
1561     //assume rows "under r" have bigger or equal start index
1562     number_type* row_array=rows[r];
1563     number_type zero=F4mat_to_number_type((number)0 /*npInit(0, currRing)*/);
1564     int start=startIndices[r];
1565     number_type coef=row_array[start];
1566     assume(start<ncols);
1567     int other_row;
1568     assume(!(npIsZero((number)(long) row_array[start],currRing->cf)));
1569     if (!(npIsOne((number)(long) coef,currRing->cf)))
1570       multiplyRow(r,F4mat_to_number_type(npInversM((number)(long) coef,currRing->cf)));
1571     assume(npIsOne((number)(long) row_array[start],currRing->cf));
1572     int lastIndex=modP_lastIndexRow(row_array, ncols);
1573     number minus_one=npInit(-1, currRing->cf);
1574     if(currRing->cf->ch<=NV_MAX_PRIME)
1575     {
1576       for (other_row=r+1;other_row<nrows;other_row++)
1577       {
1578         assume(startIndices[other_row]>=start);
1579         if (startIndices[other_row]==start)
1580         {
1581           int i;
1582           number_type* other_row_array=rows[other_row];
1583           number coef2=npNegM((number)(long) other_row_array[start],currRing->cf);
1584           if (coef2==minus_one)
1585           {
1586             for(i=start;i<=lastIndex;i++)
1587             {
1588               if (row_array[i]!=zero)
1589               {
1590                 other_row_array[i]=F4mat_to_number_type(npSubM((number)(long) other_row_array[i], (number)(long) row_array[i],currRing->cf));
1591               }
1592             }
1593           }
1594           else
1595           {
1596             for(i=start;i<=lastIndex;i++)
1597             {
1598               if (row_array[i]!=zero)
1599               {
1600                 other_row_array[i]=F4mat_to_number_type(npAddM(npMult(coef2,(number)(long) row_array[i],currRing->cf),(number)(long) other_row_array[i],currRing->cf));
1601               }
1602             }
1603           }
1604           updateStartIndex(other_row,start);
1605           assume(npIsZero((number)(long) other_row_array[start],currRing->cf));
1606         }
1607       }
1608     }
1609     else /* ch>NV_MAX_PRIME*/
1610     {
1611       for (other_row=r+1;other_row<nrows;other_row++)
1612       {
1613         assume(startIndices[other_row]>=start);
1614         if (startIndices[other_row]==start)
1615         {
1616           int i;
1617           number_type* other_row_array=rows[other_row];
1618           number coef2=npNegM((number)(long) other_row_array[start],currRing->cf);
1619           if (coef2==minus_one)
1620           {
1621             for(i=start;i<=lastIndex;i++)
1622             {
1623               if (row_array[i]!=zero)
1624               {
1625                 other_row_array[i]=F4mat_to_number_type(npSubM((number)(long) other_row_array[i], (number)(long) row_array[i],currRing->cf));
1626               }
1627             }
1628           }
1629           else
1630           {
1631             for(i=start;i<=lastIndex;i++)
1632             {
1633               if (row_array[i]!=zero)
1634               {
1635                 other_row_array[i]=F4mat_to_number_type(npAddM(nvMult(coef2,(number)(long) row_array[i],currRing->cf),(number)(long) other_row_array[i],currRing->cf));
1636               }
1637             }
1638           }
1639           updateStartIndex(other_row,start);
1640           assume(npIsZero((number)(long) other_row_array[start],currRing->cf));
1641         }
1642       }
1643     }
1644 }
updateStartIndex(int row,int lower_bound)1645 void updateStartIndex(int row,int lower_bound)
1646 {
1647   number_type* row_array=rows[row];
1648   assume((lower_bound<0)||(npIsZero((number)(long) row_array[lower_bound],currRing->cf)));
1649   int i;
1650   //number_type zero=npInit(0);
1651   for(i=lower_bound+1;i<ncols;i++)
1652   {
1653     if (!(row_array[i]==0))
1654       break;
1655   }
1656   startIndices[row]=i;
1657 }
getStartIndex(int row)1658 int getStartIndex(int row)
1659 {
1660   return startIndices[row];
1661 }
findPivot(int & r,int & c)1662 BOOLEAN findPivot(int &r, int &c)
1663 {
1664   //row>=r, col>=c
1665 
1666   while(c<ncols)
1667   {
1668     int i;
1669     for(i=r;i<nrows;i++)
1670     {
1671       assume(startIndices[i]>=c);
1672       if (startIndices[i]==c)
1673       {
1674         //r=i;
1675         if (r!=i)
1676           permRows(r,i);
1677         return TRUE;
1678       }
1679     }
1680     c++;
1681   }
1682   return FALSE;
1683 }
1684 protected:
1685   number_type** rows;
1686   int* startIndices;
1687 };
1688 template <class number_type > class ModPMatrixBackSubstProxyOnArray
1689 {
1690   int *startIndices;
1691   number_type** rows;
1692   int *lastReducibleIndices;
1693   int ncols;
1694   int nrows;
1695   int nonZeroUntil;
1696 public:
multiplyRow(int row,number_type coef)1697   void multiplyRow(int row, number_type coef)
1698   {
1699     int i;
1700     number_type* row_array=rows[row];
1701     if (currRing->cf->ch<=NV_MAX_PRIME)
1702     {
1703       for(i=startIndices[row];i<ncols;i++)
1704       {
1705         row_array[i]=F4mat_to_number_type(npMult((number)(long) row_array[i],(number)(long) coef,currRing->cf));
1706       }
1707     }
1708     else
1709     {
1710       for(i=startIndices[row];i<ncols;i++)
1711       {
1712         row_array[i]=F4mat_to_number_type(nvMult((number)(long) row_array[i],(number)(long) coef,currRing->cf));
1713       }
1714     }
1715   }
1716   ModPMatrixBackSubstProxyOnArray<number_type> (ModPMatrixProxyOnArray<number_type> & p)
1717   {
1718 //  (number_type* array, int nrows, int ncols, int* startIndices, number_type** rows){
1719     //we borrow some parameters ;-)
1720     //we assume, that nobody changes the order of the rows
1721     this->startIndices=p.startIndices;
1722     this->rows=p.rows;
1723     this->ncols=p.ncols;
1724     this->nrows=p.nrows;
1725     lastReducibleIndices=(int*) omalloc(nrows*sizeof(int));
1726     nonZeroUntil=0;
1727     while(nonZeroUntil<nrows)
1728     {
1729       if (startIndices[nonZeroUntil]<ncols)
1730       {
1731         nonZeroUntil++;
1732       }
1733       else break;
1734     }
1735     if (TEST_OPT_PROT)
1736       Print("rank:%i\n",nonZeroUntil);
1737     nonZeroUntil--;
1738     int i;
1739     for(i=0;i<=nonZeroUntil;i++)
1740     {
1741       assume(startIndices[i]<ncols);
1742       assume(!(npIsZero((number)(long) rows[i][startIndices[i]],currRing->cf)));
1743       assume(startIndices[i]>=i);
1744       updateLastReducibleIndex(i,nonZeroUntil+1);
1745     }
1746   }
updateLastReducibleIndex(int r,int upper_bound)1747   void updateLastReducibleIndex(int r, int upper_bound)
1748   {
1749     number_type* row_array=rows[r];
1750     if (upper_bound>nonZeroUntil) upper_bound=nonZeroUntil+1;
1751     int i;
1752     const number_type zero=0;//npInit(0);
1753     for(i=upper_bound-1;i>r;i--)
1754     {
1755       int start=startIndices[i];
1756       assume(start<ncols);
1757       if (!(row_array[start]==zero))
1758       {
1759         lastReducibleIndices[r]=start;
1760         return;
1761       }
1762     }
1763     lastReducibleIndices[r]=-1;
1764   }
backwardSubstitute(int r)1765   void backwardSubstitute(int r)
1766   {
1767     int start=startIndices[r];
1768     assume(start<ncols);
1769     number_type zero=0;//npInit(0);
1770     number_type* row_array=rows[r];
1771     assume((!(npIsZero((number)(long) row_array[start],currRing->cf))));
1772     assume(start<ncols);
1773     int other_row;
1774     if (!(npIsOne((number)(long) row_array[r],currRing->cf)))
1775     {
1776       //it should be one, but this safety is not expensive
1777       multiplyRow(r, F4mat_to_number_type(npInversM((number)(long) row_array[start],currRing->cf)));
1778     }
1779     int lastIndex=modP_lastIndexRow(row_array, ncols);
1780     assume(lastIndex<ncols);
1781     assume(lastIndex>=0);
1782     if(currRing->cf->ch<=NV_MAX_PRIME)
1783     {
1784       for(other_row=r-1;other_row>=0;other_row--)
1785       {
1786         assume(lastReducibleIndices[other_row]<=start);
1787         if (lastReducibleIndices[other_row]==start)
1788         {
1789           number_type* other_row_array=rows[other_row];
1790           number coef=npNegM((number)(long) other_row_array[start],currRing->cf);
1791           assume(!(npIsZero(coef,currRing->cf)));
1792           int i;
1793           assume(start>startIndices[other_row]);
1794           for(i=start;i<=lastIndex;i++)
1795           {
1796             if (row_array[i]!=zero)
1797             {
1798               other_row_array[i]=F4mat_to_number_type(npAddM(npMult(coef,(number)(long)row_array[i],currRing->cf),(number)(long)other_row_array[i],currRing->cf));
1799             }
1800           }
1801           updateLastReducibleIndex(other_row,r);
1802         }
1803       }
1804     }
1805     else
1806     {
1807       for(other_row=r-1;other_row>=0;other_row--)
1808       {
1809         assume(lastReducibleIndices[other_row]<=start);
1810         if (lastReducibleIndices[other_row]==start)
1811         {
1812           number_type* other_row_array=rows[other_row];
1813           number coef=npNegM((number)(long) other_row_array[start],currRing->cf);
1814           assume(!(npIsZero(coef,currRing->cf)));
1815           int i;
1816           assume(start>startIndices[other_row]);
1817           for(i=start;i<=lastIndex;i++)
1818           {
1819             if (row_array[i]!=zero)
1820             {
1821               other_row_array[i]=F4mat_to_number_type(npAddM(nvMult(coef,(number)(long)row_array[i],currRing->cf),(number)(long)other_row_array[i],currRing->cf));
1822             }
1823           }
1824           updateLastReducibleIndex(other_row,r);
1825         }
1826       }
1827     }
1828   }
1829   ~ModPMatrixBackSubstProxyOnArray<number_type>()
1830   {
1831     omfree(lastReducibleIndices);
1832   }
backwardSubstitute()1833   void backwardSubstitute()
1834   {
1835     int i;
1836     for(i=nonZeroUntil;i>0;i--)
1837     {
1838       backwardSubstitute(i);
1839     }
1840   }
1841 };
simplest_gauss_modp(number_type * a,int nrows,int ncols)1842 template <class number_type > void simplest_gauss_modp(number_type* a, int nrows,int ncols)
1843 {
1844   //use memmoves for changing rows
1845   //if (TEST_OPT_PROT)
1846   //    PrintS("StartGauss\n");
1847   ModPMatrixProxyOnArray<number_type> mat(a,nrows,ncols);
1848 
1849   int c=0;
1850   int r=0;
1851   while(mat.findPivot(r,c))
1852   {
1853     //int pivot=find_pivot()
1854       mat.reduceOtherRowsForward(r);
1855     r++;
1856     c++;
1857   }
1858   ModPMatrixBackSubstProxyOnArray<number_type> backmat(mat);
1859   backmat.backwardSubstitute();
1860   //backward substitutions
1861   //if (TEST_OPT_PROT)
1862   //PrintS("StopGauss\n");
1863 }
1864 //int term_nodes_sort_crit(const void* a, const void* b);
noro_step(poly * p,int & pn,slimgb_alg * c)1865 template <class number_type> void noro_step(poly*p,int &pn,slimgb_alg* c)
1866 {
1867   //Print("Input rows %d\n",pn);
1868   int j;
1869   if (TEST_OPT_PROT)
1870   {
1871     Print("Input rows %d\n",pn);
1872   }
1873 
1874   NoroCache<number_type> cache;
1875 
1876   SparseRow<number_type> ** srows=(SparseRow<number_type>**) omAlloc(pn*sizeof(SparseRow<number_type>*));
1877   int non_zeros=0;
1878   for(j=0;j<pn;j++)
1879   {
1880     poly h=p[j];
1881     int h_len=pLength(h);
1882     //number coef;
1883     srows[non_zeros]=noro_red_to_non_poly_t<number_type>(h,h_len,&cache,c);
1884     if (srows[non_zeros]!=NULL) non_zeros++;
1885   }
1886   std::vector<DataNoroCacheNode<number_type>*> irr_nodes;
1887   cache.collectIrreducibleMonomials(irr_nodes);
1888   //now can build up terms array
1889   //Print("historic irred Mon%d\n",cache.nIrreducibleMonomials);
1890   int n=irr_nodes.size();//cache.countIrreducibleMonomials();
1891   cache.nIrreducibleMonomials=n;
1892   if (TEST_OPT_PROT)
1893   {
1894     Print("Irred Mon:%d\n",n);
1895     Print("red Mon:%d\n",cache.nReducibleMonomials);
1896   }
1897   TermNoroDataNode<number_type>* term_nodes=(TermNoroDataNode<number_type>*) omalloc(n*sizeof(TermNoroDataNode<number_type>));
1898 
1899   for(j=0;j<n;j++)
1900   {
1901     assume(irr_nodes[j]!=NULL);
1902     assume(irr_nodes[j]->value_len==NoroCache<number_type>::backLinkCode);
1903     term_nodes[j].t=irr_nodes[j]->value_poly;
1904     assume(term_nodes[j].t!=NULL);
1905     term_nodes[j].node=irr_nodes[j];
1906   }
1907 
1908   qsort(term_nodes,n,sizeof(TermNoroDataNode<number_type>),term_nodes_sort_crit<number_type>);
1909   poly* terms=(poly*) omalloc(n*sizeof(poly));
1910 
1911   int* old_to_new_indices=(int*) omalloc(cache.nIrreducibleMonomials*sizeof(int));
1912   for(j=0;j<n;j++)
1913   {
1914     old_to_new_indices[term_nodes[j].node->term_index]=j;
1915     term_nodes[j].node->term_index=j;
1916     terms[j]=term_nodes[j].t;
1917   }
1918 
1919   //if (TEST_OPT_PROT)
1920   //  Print("Evaluate Rows \n");
1921   pn=non_zeros;
1922   number_type* number_array=(number_type*) omalloc0(((size_t)n)*pn*sizeof(number_type));
1923 
1924   for(j=0;j<pn;j++)
1925   {
1926     int i;
1927     number_type* row=number_array+((long)n)*(long)j;
1928     /*for(i=0;i<n;i++)
1929     {
1930       row[i]=zero;
1931     }*/
1932 
1933     SparseRow<number_type>* srow=srows[j];
1934 
1935     if (srow)
1936     {
1937       int* const idx_array=srow->idx_array;
1938       number_type* const coef_array=srow->coef_array;
1939       const int len=srow->len;
1940       if (srow->idx_array)
1941       {
1942         for(i=0;i<len;i++)
1943         {
1944          int idx=old_to_new_indices[idx_array[i]];
1945          row[idx]=F4mat_to_number_type(coef_array[i]);
1946         }
1947       }
1948       else
1949       {
1950         for(i=0;i<len;i++)
1951         {
1952           row[old_to_new_indices[i]]=F4mat_to_number_type(coef_array[i]);
1953         }
1954       }
1955       delete srow;
1956     }
1957   }
1958 
1959   //static int export_n=0;
1960   //export_mat(number_array,pn,n,"mat%i.py",++export_n);
1961   simplest_gauss_modp(number_array,pn,n);
1962 
1963   int p_pos=0;
1964   for(j=0;j<pn;j++)
1965   {
1966     poly h=row_to_poly(number_array+((long)j)*((long)n),terms,n,c->r);
1967     if(h!=NULL)
1968     {
1969       p[p_pos++]=h;
1970     }
1971   }
1972   pn=p_pos;
1973   omfree(terms);
1974   omfree(term_nodes);
1975   omfree(number_array);
1976   #ifdef NORO_NON_POLY
1977   omfree(srows);
1978   omfree(old_to_new_indices);
1979   #endif
1980   //don't forget the rank
1981 
1982 }
1983 
collectIrreducibleMonomials(std::vector<DataNoroCacheNode<number_type> * > & res)1984 template <class number_type> void NoroCache<number_type>::collectIrreducibleMonomials( std::vector<DataNoroCacheNode<number_type> *>& res)
1985 {
1986   int i;
1987   for(i=0;i<root.branches_len;i++)
1988   {
1989     collectIrreducibleMonomials(1,root.branches[i],res);
1990   }
1991 }
collectIrreducibleMonomials(int level,NoroCacheNode * node,std::vector<DataNoroCacheNode<number_type> * > & res)1992 template <class number_type> void NoroCache<number_type>::collectIrreducibleMonomials(int level, NoroCacheNode* node, std::vector<DataNoroCacheNode<number_type>*>& res)
1993 {
1994   assume(level>=0);
1995   if (node==NULL) return;
1996   if (level<(currRing->N))
1997   {
1998     int i;
1999     for(i=0;i<node->branches_len;i++)
2000     {
2001       collectIrreducibleMonomials(level+1,node->branches[i],res);
2002     }
2003   }
2004   else
2005   {
2006     DataNoroCacheNode<number_type>* dn=(DataNoroCacheNode<number_type>*) node;
2007     if (dn->value_len==backLinkCode)
2008     {
2009       res.push_back(dn);
2010     }
2011   }
2012 }
2013 
getCacheReference(poly term)2014 template<class number_type> DataNoroCacheNode<number_type>* NoroCache<number_type>::getCacheReference(poly term)
2015 {
2016   int i;
2017   NoroCacheNode* parent=&root;
2018   for(i=1;i<(currRing->N);i++)
2019   {
2020     parent=parent->getBranch(p_GetExp(term,i,currRing));
2021     if (!(parent))
2022     {
2023       return NULL;
2024     }
2025   }
2026   DataNoroCacheNode<number_type>* res_holder=(DataNoroCacheNode<number_type>*) parent->getBranch(p_GetExp(term,i,currRing));
2027   return res_holder;
2028 }
lookup(poly term,BOOLEAN & succ,int & len)2029 template<class number_type> poly NoroCache<number_type>::lookup(poly term, BOOLEAN& succ, int & len)
2030 {
2031   int i;
2032   NoroCacheNode* parent=&root;
2033   for(i=1;i<(currRing->N);i++)
2034   {
2035     parent=parent->getBranch(p_GetExp(term,i,currRing));
2036     if (!(parent))
2037     {
2038       succ=FALSE;
2039       return NULL;
2040     }
2041   }
2042   DataNoroCacheNode<number_type>* res_holder=(DataNoroCacheNode<number_type>*) parent->getBranch(p_GetExp(term,i,currRing));
2043   if (res_holder)
2044   {
2045     succ=TRUE;
2046     if ( /*(*/ res_holder->value_len==backLinkCode /*)*/ )
2047     {
2048       len=1;
2049       return term;
2050     }
2051     len=res_holder->value_len;
2052     return res_holder->value_poly;
2053   } else {
2054     succ=FALSE;
2055     return NULL;
2056   }
2057 }
2058 #endif
2059 
2060 #endif
2061