source: git/kernel/GBEngine/tgb_internal.h @ 29f433

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