source: git/kernel/GBEngine/tgb_internal.h @ e4c8dc

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