source: git/kernel/GBEngine/tgb_internal.h @ 461a94

spielwiese
Last change on this file since 461a94 was 461a94, checked in by Andreas Steenpass <steenpass@…>, 6 years ago
chg: transfer #define (un)likely to auxiliary.h
  • 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 HANS_IDEA
17//#define HALFREDUCTIONS
18//#define HEAD_BIN
19//#define HOMOGENEOUS_EXAMPLE
20#define REDTAIL_S
21#define PAR_N 100
22#define PAR_N_F4 5000
23#define AC_NEW_MIN 2
24#define AC_FLATTEN 1
25
26//#define FIND_DETERMINISTIC
27//#define REDTAIL_PROT
28//#define QUICK_SPOLY_TEST
29#ifdef USE_NORO
30#define NORO_CACHE 1
31#define NORO_SPARSE_ROWS_PRE 1
32#define NORO_NON_POLY 1
33#include <algorithm>
34#endif
35#ifdef NORO_CACHE
36//#include <map>
37#include <vector>
38#endif
39#ifdef HAVE_BOOST_DYNAMIC_BITSET_HPP
40#define  HAVE_BOOST 1
41#endif
42//#define HAVE_BOOST 1
43//#define USE_STDVECBOOL 1
44#ifdef HAVE_BOOST
45#include <vector>
46using boost::dynamic_bitset;
47using std::vector;
48#endif
49#ifdef USE_STDVECBOOL
50#include <vector>
51using std::vector;
52#endif
53#include <stdlib.h>
54
55#include "misc/options.h"
56
57#include "coeffs/modulop.h"
58
59#include "polys/monomials/p_polys.h"
60#include "polys/monomials/ring.h"
61#include "polys/kbuckets.h"
62
63#include "kernel/ideals.h"
64#include "kernel/polys.h"
65
66#include "kernel/GBEngine/kutil.h"
67#include "kernel/GBEngine/kInline.h"
68#include "kernel/GBEngine/kstd1.h"
69
70
71#if 1
72
73#define npInit n_Init
74#define npNeg n_InpNeg
75#define npInvers n_Invers
76#define npMult n_Mult
77#define npIsOne n_IsOne
78#define npIsZero n_IsZero
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, 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      assume(idx<temp_size);
940    }
941
942  }
943}
944#ifdef SING_NDEBUG
945template <class number_type> void add_coef_times_dense(number_type* const temp_array,
946int /*temp_size*/,const number_type* row, int len,number coef)
947#else
948template <class number_type> void add_coef_times_dense(number_type* const temp_array,
949int temp_size,const number_type* row, int len,number coef)
950#endif
951{
952  int j;
953  const number_type* const coef_array=row;
954  //int* const idx_array=row->idx_array;
955  //const int len=temp_size;
956  tgb_uint32 buffer[256];
957  const tgb_uint32 prime=n_GetChar(currRing->cf);
958  const tgb_uint32 c=F4mat_to_number_type(coef);
959  assume(!(npIsZero(coef,currRing->cf)));
960  for(j=0;j<len;j=j+256)
961  {
962    const int bound=std::min(j+256,len);
963    int i;
964    int bpos=0;
965    for(i=j;i<bound;i++)
966    {
967      buffer[bpos++]=coef_array[i];
968    }
969    int bpos_bound=bound-j;
970    for(i=0;i<bpos_bound;i++)
971    {
972       buffer[i]*=c;
973     }
974    for(i=0;i<bpos_bound;i++)
975    {
976       buffer[i]=buffer[i]%prime;
977    }
978    bpos=0;
979    for(i=j;i<bound;i++)
980    {
981      //int idx=idx_array[i];
982      assume(bpos<256);
983      //assume(!(npIsZero((number) buffer[bpos])));
984      STATISTIC(n_Add); temp_array[i]=F4mat_to_number_type(npAddM((number)(long) temp_array[i], (number)(long) buffer[bpos++],currRing->cf));
985      assume(i<temp_size);
986    }
987
988  }
989}
990#ifdef SING_NDEBUG
991template <class number_type> void add_dense(number_type* const temp_array,
992int /*temp_size*/,const number_type* row, int len)
993#else
994template <class number_type> void add_dense(number_type* const temp_array,
995int temp_size,const number_type* row, int len)
996#endif
997{
998  //int j;
999  //const number_type* const coef_array=row;
1000  //int* const idx_array=row->idx_array;
1001  //const int len=temp_size;
1002  //tgb_uint32 buffer[256];
1003  //const tgb_uint32 prime=npPrimeM;
1004  //const tgb_uint32 c=F4mat_to_number_type(coef);
1005
1006  int i;
1007  for(i=0;i<len;i++)
1008  {
1009      STATISTIC(n_Add); temp_array[i]=F4mat_to_number_type(npAddM((number)(long) temp_array[i], (number)(long) row[i],currRing->cf));
1010      assume(i<temp_size);
1011  }
1012
1013}
1014#ifdef SING_NDEBUG
1015template <class number_type> void sub_dense(number_type* const temp_array,
1016int /*temp_size*/,const number_type* row, int len)
1017#else
1018template <class number_type> void sub_dense(number_type* const temp_array,
1019int temp_size,const number_type* row, int len)
1020#endif
1021{
1022  //int j;
1023  //const number_type* const coef_array=row;
1024  //int* const idx_array=row->idx_array;
1025  //const int len=temp_size;
1026  //tgb_uint32 buffer[256];
1027  //const tgb_uint32 prime=npPrimeM;
1028  //const tgb_uint32 c=F4mat_to_number_type(coef);
1029
1030  int i;
1031  for(i=0;i<len;i++)
1032  {
1033
1034      STATISTIC(n_Sub); temp_array[i]=F4mat_to_number_type(npSubM((number)(long) temp_array[i], (number)(long) row[i],currRing->cf));
1035      assume(i<temp_size);
1036  }
1037
1038}
1039
1040#ifdef SING_NDEBUG
1041template <class number_type> void add_sparse(number_type* const temp_array,int /*temp_size*/,SparseRow<number_type>* row)
1042#else
1043template <class number_type> void add_sparse(number_type* const temp_array,int temp_size,SparseRow<number_type>* row)
1044#endif
1045{
1046  int j;
1047
1048          number_type* const coef_array=row->coef_array;
1049          int* const idx_array=row->idx_array;
1050          const int len=row->len;
1051        for(j=0;j<len;j++)
1052        {
1053          int idx=idx_array[j];
1054          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));
1055          assume(idx<temp_size);
1056        }
1057}
1058#ifdef SING_NDEBUG
1059template <class number_type> void sub_sparse(number_type* const temp_array,int /*temp_size*/,SparseRow<number_type>* row)
1060#else
1061template <class number_type> void sub_sparse(number_type* const temp_array,int temp_size,SparseRow<number_type>* row)
1062#endif
1063{
1064  int j;
1065
1066          number_type* const coef_array=row->coef_array;
1067          int* const idx_array=row->idx_array;
1068          const int len=row->len;
1069        for(j=0;j<len;j++)
1070        {
1071          int idx=idx_array[j];
1072          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));
1073          assume(idx<temp_size);
1074        }
1075}
1076template <class number_type> SparseRow<number_type>* noro_red_to_non_poly_dense(MonRedResNP<number_type>* mon, int len,NoroCache<number_type>* cache)
1077{
1078  size_t temp_size_bytes=cache->nIrreducibleMonomials*sizeof(number_type)+8;//use 8bit int for testing
1079   assume(sizeof(int64)==8);
1080   cache->ensureTempBufferSize(temp_size_bytes);
1081   number_type* temp_array=(number_type*) cache->tempBuffer;//omalloc(cache->nIrreducibleMonomials*sizeof(number_type));
1082   int temp_size=cache->nIrreducibleMonomials;
1083   memset(temp_array,0,temp_size_bytes);
1084   number minus_one=npInit(-1,currRing->cf);
1085   int i;
1086   for(i=0;i<len;i++)
1087   {
1088     MonRedResNP<number_type> red=mon[i];
1089     if ( /*(*/ red.ref /*)*/ )
1090     {
1091       if (red.ref->row)
1092       {
1093         SparseRow<number_type>* row=red.ref->row;
1094         number coef=red.coef;
1095         if (row->idx_array)
1096         {
1097           if (!((coef==(number)1L)||(coef==minus_one)))
1098           {
1099             add_coef_times_sparse(temp_array,temp_size,row,coef);
1100           }
1101           else
1102           {
1103             if (coef==(number)1L)
1104             {
1105               add_sparse(temp_array,temp_size,row);
1106             }
1107             else
1108             {
1109               sub_sparse(temp_array,temp_size,row);
1110             }
1111           }
1112         }
1113         else
1114         //TODO: treat, 1,-1
1115         if (!((coef==(number)1L)||(coef==minus_one)))
1116         {
1117          add_coef_times_dense(temp_array,temp_size,row->coef_array,row->len,coef);
1118         }
1119         else
1120         {
1121           if (coef==(number)1L)
1122             add_dense(temp_array,temp_size,row->coef_array,row->len);
1123           else
1124           {
1125             assume(coef==minus_one);
1126             sub_dense(temp_array,temp_size,row->coef_array,row->len);
1127             //add_coef_times_dense(temp_array,temp_size,row->coef_array,row->len,coef);
1128           }
1129         }
1130       }
1131       else
1132       {
1133         if (red.ref->value_len==NoroCache<number_type>::backLinkCode)
1134         {
1135           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));
1136         }
1137         else
1138         {
1139           //PrintS("third case\n");
1140         }
1141       }
1142     }
1143   }
1144   int non_zeros=0;
1145   for(i=0;i<cache->nIrreducibleMonomials;i++)
1146   {
1147     //if (!(temp_array[i]==0)){
1148     //  non_zeros++;
1149     //}
1150     assume(((temp_array[i]!=0)==0)|| (((temp_array[i]!=0)==1)));
1151     non_zeros+=(temp_array[i]!=0);
1152   }
1153
1154   if (non_zeros==0)
1155   {
1156     //omfree(mon);
1157     return NULL;
1158   }
1159   SparseRow<number_type>* res=new SparseRow<number_type>(temp_size,temp_array);//convert_to_sparse_row(temp_array,temp_size, non_zeros);
1160
1161   //omfree(temp_array);
1162
1163
1164   return res;
1165}
1166template<class number_type> class CoefIdx
1167{
1168public:
1169  number_type coef;
1170  int idx;
1171  bool operator<(const CoefIdx<number_type>& other) const
1172  {
1173    return (idx<other.idx);
1174  }
1175};
1176template<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)
1177{
1178  int j;
1179  for(j=0;j<rlen;j++)
1180  {
1181    assume(coef_array[j]!=0);
1182    CoefIdx<number_type> ci;
1183    STATISTIC(n_Mult); ci.coef=F4mat_to_number_type(npMultM((number)(long) coef,(number)(long) coef_array[j],currRing->cf));
1184    ci.idx=idx_array[j];
1185    pairs[pos++]=ci;
1186  }
1187}
1188template<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)
1189{
1190  int j;
1191
1192  for(j=0;j<rlen;j++)
1193  {
1194    if (coef_array[j]!=0)
1195    {
1196      assume(coef_array[j]!=0);
1197      CoefIdx<number_type> ci;
1198      STATISTIC(n_Mult); ci.coef=F4mat_to_number_type(npMultM((number)(long) coef,(number)(long) coef_array[j],currRing->cf));
1199      assume(ci.coef!=0);
1200      ci.idx=j;
1201      pairs[pos++]=ci;
1202    }
1203  }
1204}
1205template<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)
1206{
1207  int j;
1208
1209  for(j=0;j<rlen;j++)
1210  {
1211    if (coef_array[j]!=0)
1212    {
1213      assume(coef_array[j]!=0);
1214      CoefIdx<number_type> ci;
1215      ci.coef=coef_array[j];
1216      assume(ci.coef!=0);
1217      ci.idx=j;
1218      pairs[pos++]=ci;
1219    }
1220  }
1221}
1222
1223template<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)
1224{
1225  int j;
1226
1227  for(j=0;j<rlen;j++)
1228  {
1229    if (coef_array[j]!=0)
1230    {
1231      assume(coef_array[j]!=0);
1232      CoefIdx<number_type> ci;
1233      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!?
1234      assume(ci.coef!=0);
1235      ci.idx=j;
1236      pairs[pos++]=ci;
1237    }
1238  }
1239}
1240template<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)
1241{
1242  int j;
1243  for(j=0;j<rlen;j++)
1244  {
1245    assume(coef_array[j]!=0);
1246    CoefIdx<number_type> ci;
1247    ci.coef=coef_array[j];
1248    ci.idx=idx_array[j];
1249    pairs[pos++]=ci;
1250  }
1251}
1252
1253template<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)
1254{
1255  int j;
1256  for(j=0;j<rlen;j++)
1257  {
1258    assume(coef_array[j]!=0);
1259    CoefIdx<number_type> ci;
1260    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!?
1261    ci.idx=idx_array[j];
1262    pairs[pos++]=ci;
1263  }
1264}
1265template <class number_type> SparseRow<number_type>* noro_red_to_non_poly_sparse(MonRedResNP<number_type>* mon, int len,NoroCache<number_type>* cache)
1266{
1267  int i;
1268  int together=0;
1269  for(i=0;i<len;i++)
1270  {
1271    MonRedResNP<number_type> red=mon[i];
1272    if ((red.ref) &&( red.ref->row))
1273    {
1274      together+=red.ref->row->len;
1275    }
1276    else
1277    {
1278      if ((red.ref) &&(red.ref->value_len==NoroCache<number_type>::backLinkCode))
1279      together++;
1280    }
1281  }
1282  //PrintS("here\n");
1283  if (together==0) return 0;
1284  //PrintS("there\n");
1285  cache->ensureTempBufferSize(together*sizeof(CoefIdx<number_type>));
1286  CoefIdx<number_type>* pairs=(CoefIdx<number_type>*) cache->tempBuffer; //omalloc(together*sizeof(CoefIdx<number_type>));
1287  int pos=0;
1288  const number one=npInit(1, currRing->cf);
1289  const number minus_one=npInit(-1, currRing->cf);
1290  for(i=0;i<len;i++)
1291  {
1292    MonRedResNP<number_type> red=mon[i];
1293    if ((red.ref) &&( red.ref->row))
1294    {
1295      //together+=red.ref->row->len;
1296      int* idx_array=red.ref->row->idx_array;
1297      number_type* coef_array=red.ref->row->coef_array;
1298      int rlen=red.ref->row->len;
1299      number coef=red.coef;
1300      if (idx_array)
1301      {
1302        if ((coef!=one)&&(coef!=minus_one))
1303        {
1304          write_coef_times_xx_idx_to_buffer(pairs,pos,idx_array, coef_array,rlen, coef);
1305        }
1306        else
1307        {
1308          if (coef==one)
1309          {
1310            write_coef_idx_to_buffer(pairs,pos,idx_array, coef_array,rlen);
1311          }
1312          else
1313          {
1314            assume(coef==minus_one);
1315            write_minus_coef_idx_to_buffer(pairs,pos,idx_array, coef_array,rlen);
1316          }
1317        }
1318      }
1319      else
1320      {
1321        if ((coef!=one)&&(coef!=minus_one))
1322        {
1323          write_coef_times_xx_idx_to_buffer_dense(pairs,pos,coef_array,rlen,coef);
1324        }
1325        else
1326        {
1327          if (coef==one)
1328            write_coef_idx_to_buffer_dense(pairs,pos,coef_array,rlen);
1329          else
1330          {
1331            assume(coef==minus_one);
1332            write_minus_coef_idx_to_buffer_dense(pairs,pos,coef_array,rlen);
1333          }
1334        }
1335      }
1336    }
1337    else
1338    {
1339      if ((red.ref) &&(red.ref->value_len==NoroCache<number_type>::backLinkCode))
1340      {
1341        CoefIdx<number_type> ci;
1342        ci.coef=F4mat_to_number_type(red.coef);
1343        ci.idx=red.ref->term_index;
1344        pairs[pos++]=ci;
1345      }
1346    }
1347  }
1348  assume(pos<=together);
1349  together=pos;
1350
1351  std::sort(pairs,pairs+together);
1352
1353  int act=0;
1354
1355  assume(pairs[0].coef!=0);
1356  for(i=1;i<together;i++)
1357  {
1358    if (pairs[i].idx!=pairs[act].idx)
1359    {
1360      if (pairs[act].coef!=0)
1361      {
1362        act=act+1;
1363      }
1364      pairs[act]=pairs[i];
1365    }
1366    else
1367    {
1368      STATISTIC(n_Add); pairs[act].coef=F4mat_to_number_type(npAddM((number)(long)pairs[act].coef,(number)(long)pairs[i].coef,currRing->cf));
1369    }
1370  }
1371
1372  if (pairs[act].coef==0)
1373  {
1374    act--;
1375  }
1376  int sparse_row_len=act+1;
1377  //Print("res len:%d",sparse_row_len);
1378  if (sparse_row_len==0) {return NULL;}
1379  SparseRow<number_type>* res=new SparseRow<number_type>(sparse_row_len);
1380  {
1381    number_type* coef_array=res->coef_array;
1382    int* idx_array=res->idx_array;
1383    for(i=0;i<sparse_row_len;i++)
1384    {
1385      idx_array[i]=pairs[i].idx;
1386      coef_array[i]=pairs[i].coef;
1387    }
1388  }
1389  //omfree(pairs);
1390
1391  return res;
1392}
1393template<class number_type> SparseRow<number_type> * noro_red_to_non_poly_t(poly p, int &len, NoroCache<number_type>* cache,slimgb_alg* c){
1394  assume(len==pLength(p));
1395  if (p==NULL)
1396  {
1397    len=0;
1398    return NULL;
1399  }
1400
1401  MonRedResNP<number_type>* mon=(MonRedResNP<number_type>*) omalloc(len*sizeof(MonRedResNP<number_type>));
1402  int i=0;
1403  double max_density=0.0;
1404  while(p!=NULL)
1405  {
1406    poly t=p;
1407    pIter(p);
1408    pNext(t)=NULL;
1409
1410    MonRedResNP<number_type> red=noro_red_mon_to_non_poly(t,cache,c);
1411    if ((red.ref) && (red.ref->row))
1412    {
1413      double act_density=(double) red.ref->row->len;
1414      act_density/=(double) cache->nIrreducibleMonomials;
1415      max_density=std::max(act_density,max_density);
1416    }
1417    mon[i]=red;
1418    i++;
1419  }
1420
1421  assume(i==len);
1422  len=i;
1423  bool dense=true;
1424  if (max_density<0.3) dense=false;
1425  if (dense){
1426    SparseRow<number_type>* res=noro_red_to_non_poly_dense(mon,len,cache);
1427    omfree(mon);
1428    return res;
1429  } else   {
1430      SparseRow<number_type>* res=noro_red_to_non_poly_sparse(mon,len,cache);
1431      omfree(mon);
1432      return res;
1433    }
1434  //in the loop before nIrreducibleMonomials increases, so position here is important
1435
1436}
1437#endif
1438wlen_type pELength(poly p, ring r);
1439int terms_sort_crit(const void* a, const void* b);
1440//void simplest_gauss_modp(number* a, int nrows,int ncols);
1441// a: a[0,0],a[0,1]....a[nrows-1,ncols-1]
1442// assume: field is Zp
1443#ifdef USE_NORO
1444
1445
1446template <class number_type > void write_poly_to_row(number_type* row, poly h, poly*terms, int tn, ring r){
1447  //poly* base=row;
1448  while(h!=NULL){
1449    //Print("h:%i\n",h);
1450    number coef=p_GetCoeff(h,r);
1451    poly* ptr_to_h=(poly*) bsearch(&h,terms,tn,sizeof(poly),terms_sort_crit);
1452    assume(ptr_to_h!=NULL);
1453    int pos=ptr_to_h-terms;
1454    row[pos]=F4mat_to_number_type(coef);
1455    //number_type_array[base+pos]=coef;
1456    pIter(h);
1457  }
1458}
1459template <class number_type > poly row_to_poly(number_type* row, poly* terms, int tn, ring r){
1460  poly h=NULL;
1461  int j;
1462  number_type zero=0;//;npInit(0);
1463  for(j=tn-1;j>=0;j--){
1464    if (!(zero==(row[j]))){
1465      poly t=terms[j];
1466      t=p_LmInit(t,r);
1467      p_SetCoeff(t,(number)(long) row[j],r);
1468      pNext(t)=h;
1469      h=t;
1470    }
1471
1472  }
1473  return h;
1474}
1475template <class number_type > int modP_lastIndexRow(number_type* row,int ncols)
1476{
1477  int lastIndex;
1478  const number_type zero=0;//npInit(0);
1479  for(lastIndex=ncols-1;lastIndex>=0;lastIndex--)
1480  {
1481    if (!(row[lastIndex]==zero))
1482    {
1483      return lastIndex;
1484    }
1485  }
1486  return -1;
1487}
1488template <class number_type> int term_nodes_sort_crit(const void* a, const void* b)
1489{
1490  return -pLmCmp(((TermNoroDataNode<number_type>*) a)->t,((TermNoroDataNode<number_type>*) b)->t);
1491}
1492
1493template <class number_type>class ModPMatrixBackSubstProxyOnArray;
1494template <class number_type > class ModPMatrixProxyOnArray
1495{
1496public:
1497  friend class ModPMatrixBackSubstProxyOnArray<number_type>;
1498
1499  int ncols,nrows;
1500  ModPMatrixProxyOnArray(number_type* array, int nnrows, int nncols)
1501  {
1502    this->ncols=nncols;
1503    this->nrows=nnrows;
1504    rows=(number_type**) omalloc(nnrows*sizeof(number_type*));
1505    startIndices=(int*)omalloc(nnrows*sizeof(int));
1506    int i;
1507    for(i=0;i<nnrows;i++)
1508    {
1509      rows[i]=array+(i*nncols);
1510      updateStartIndex(i,-1);
1511    }
1512  }
1513  ~ModPMatrixProxyOnArray()
1514  {
1515    omfree(rows);
1516    omfree(startIndices);
1517  }
1518
1519  void permRows(int i, int j)
1520  {
1521    number_type* h=rows[i];
1522    rows[i]=rows[j];
1523    rows[j]=h;
1524    int hs=startIndices[i];
1525    startIndices[i]=startIndices[j];
1526    startIndices[j]=hs;
1527  }
1528  void multiplyRow(int row, number_type coef)
1529  {
1530    int i;
1531    number_type* row_array=rows[row];
1532    for(i=startIndices[row];i<ncols;i++)
1533    {
1534      row_array[i]=F4mat_to_number_type(npMult((number)(long) row_array[i],(number)(long) coef,currRing->cf));
1535    }
1536  }
1537  void reduceOtherRowsForward(int r)
1538  {
1539    //assume rows "under r" have bigger or equal start index
1540    number_type* row_array=rows[r];
1541    number_type zero=F4mat_to_number_type((number)0 /*npInit(0, currRing)*/);
1542    int start=startIndices[r];
1543    number_type coef=row_array[start];
1544    assume(start<ncols);
1545    int other_row;
1546    assume(!(npIsZero((number)(long) row_array[start],currRing->cf)));
1547    if (!(npIsOne((number)(long) coef,currRing->cf)))
1548      multiplyRow(r,F4mat_to_number_type(npInvers((number)(long) coef,currRing->cf)));
1549    assume(npIsOne((number)(long) row_array[start],currRing->cf));
1550    int lastIndex=modP_lastIndexRow(row_array, ncols);
1551    number minus_one=npInit(-1, currRing->cf);
1552    for (other_row=r+1;other_row<nrows;other_row++)
1553    {
1554      assume(startIndices[other_row]>=start);
1555      if (startIndices[other_row]==start)
1556      {
1557        int i;
1558        number_type* other_row_array=rows[other_row];
1559        number coef2=npNeg((number)(long) other_row_array[start],currRing->cf);
1560        if (coef2==minus_one)
1561        {
1562          for(i=start;i<=lastIndex;i++)
1563          {
1564            if (row_array[i]!=zero)
1565            { STATISTIC(n_Sub);
1566              other_row_array[i]=F4mat_to_number_type(npSubM((number)(long) other_row_array[i], (number)(long) row_array[i],currRing->cf));
1567            }
1568
1569          }
1570      }
1571      else
1572      {
1573          //assume(FALSE);
1574          for(i=start;i<=lastIndex;i++)
1575          {
1576            if (row_array[i]!=zero)
1577            { STATISTIC(n_Add);
1578              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));
1579            }
1580
1581          }
1582        }
1583        updateStartIndex(other_row,start);
1584        assume(npIsZero((number)(long) other_row_array[start],currRing->cf));
1585      }
1586    }
1587  }
1588  void updateStartIndex(int row,int lower_bound)
1589  {
1590    number_type* row_array=rows[row];
1591    assume((lower_bound<0)||(npIsZero((number)(long) row_array[lower_bound],currRing->cf)));
1592    int i;
1593    //number_type zero=npInit(0);
1594    for(i=lower_bound+1;i<ncols;i++)
1595    {
1596      if (!(row_array[i]==0))
1597        break;
1598    }
1599    startIndices[row]=i;
1600  }
1601  int getStartIndex(int row)
1602  {
1603    return startIndices[row];
1604  }
1605  BOOLEAN findPivot(int &r, int &c)
1606  {
1607    //row>=r, col>=c
1608
1609    while(c<ncols)
1610    {
1611      int i;
1612      for(i=r;i<nrows;i++)
1613      {
1614        assume(startIndices[i]>=c);
1615        if (startIndices[i]==c)
1616        {
1617          //r=i;
1618          if (r!=i)
1619            permRows(r,i);
1620          return TRUE;
1621        }
1622      }
1623      c++;
1624    }
1625    return FALSE;
1626  }
1627protected:
1628  number_type** rows;
1629  int* startIndices;
1630};
1631template <class number_type > class ModPMatrixBackSubstProxyOnArray
1632{
1633  int *startIndices;
1634  number_type** rows;
1635  int *lastReducibleIndices;
1636  int ncols;
1637  int nrows;
1638  int nonZeroUntil;
1639public:
1640  void multiplyRow(int row, number_type coef)
1641  {
1642    int i;
1643    number_type* row_array=rows[row];
1644    for(i=startIndices[row];i<ncols;i++)
1645    {
1646      row_array[i]=F4mat_to_number_type(npMult((number)(long) row_array[i],(number)(long) coef,currRing->cf));
1647    }
1648  }
1649  ModPMatrixBackSubstProxyOnArray<number_type> (ModPMatrixProxyOnArray<number_type> & p)
1650  {
1651//  (number_type* array, int nrows, int ncols, int* startIndices, number_type** rows){
1652    //we borrow some parameters ;-)
1653    //we assume, that nobody changes the order of the rows
1654    this->startIndices=p.startIndices;
1655    this->rows=p.rows;
1656    this->ncols=p.ncols;
1657    this->nrows=p.nrows;
1658    lastReducibleIndices=(int*) omalloc(nrows*sizeof(int));
1659    nonZeroUntil=0;
1660    while(nonZeroUntil<nrows)
1661    {
1662      if (startIndices[nonZeroUntil]<ncols)
1663      {
1664        nonZeroUntil++;
1665      }
1666      else break;
1667    }
1668    if (TEST_OPT_PROT)
1669      Print("rank:%i\n",nonZeroUntil);
1670    nonZeroUntil--;
1671    int i;
1672    for(i=0;i<=nonZeroUntil;i++)
1673    {
1674      assume(startIndices[i]<ncols);
1675      assume(!(npIsZero((number)(long) rows[i][startIndices[i]],currRing->cf)));
1676      assume(startIndices[i]>=i);
1677      updateLastReducibleIndex(i,nonZeroUntil+1);
1678    }
1679  }
1680  void updateLastReducibleIndex(int r, int upper_bound)
1681  {
1682    number_type* row_array=rows[r];
1683    if (upper_bound>nonZeroUntil) upper_bound=nonZeroUntil+1;
1684    int i;
1685    const number_type zero=0;//npInit(0);
1686    for(i=upper_bound-1;i>r;i--)
1687    {
1688      int start=startIndices[i];
1689      assume(start<ncols);
1690      if (!(row_array[start]==zero))
1691      {
1692        lastReducibleIndices[r]=start;
1693        return;
1694      }
1695    }
1696    lastReducibleIndices[r]=-1;
1697  }
1698  void backwardSubstitute(int r)
1699  {
1700    int start=startIndices[r];
1701    assume(start<ncols);
1702    number_type zero=0;//npInit(0);
1703    number_type* row_array=rows[r];
1704    assume((!(npIsZero((number)(long) row_array[start],currRing->cf))));
1705    assume(start<ncols);
1706    int other_row;
1707    if (!(npIsOne((number)(long) row_array[r],currRing->cf)))
1708    {
1709      //it should be one, but this safety is not expensive
1710      multiplyRow(r, F4mat_to_number_type(npInvers((number)(long) row_array[start],currRing->cf)));
1711    }
1712    int lastIndex=modP_lastIndexRow(row_array, ncols);
1713    assume(lastIndex<ncols);
1714    assume(lastIndex>=0);
1715    for(other_row=r-1;other_row>=0;other_row--)
1716    {
1717      assume(lastReducibleIndices[other_row]<=start);
1718      if (lastReducibleIndices[other_row]==start)
1719      {
1720        number_type* other_row_array=rows[other_row];
1721        number coef=npNeg((number)(long) other_row_array[start],currRing->cf);
1722        assume(!(npIsZero(coef,currRing->cf)));
1723        int i;
1724        assume(start>startIndices[other_row]);
1725        for(i=start;i<=lastIndex;i++)
1726        {
1727          if (row_array[i]!=zero)
1728          {
1729            STATISTIC(n_Add);
1730            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));
1731          }
1732        }
1733        updateLastReducibleIndex(other_row,r);
1734      }
1735    }
1736  }
1737  ~ModPMatrixBackSubstProxyOnArray<number_type>()
1738  {
1739    omfree(lastReducibleIndices);
1740  }
1741  void backwardSubstitute()
1742  {
1743    int i;
1744    for(i=nonZeroUntil;i>0;i--)
1745    {
1746      backwardSubstitute(i);
1747    }
1748  }
1749};
1750template <class number_type > void simplest_gauss_modp(number_type* a, int nrows,int ncols)
1751{
1752  //use memmoves for changing rows
1753  //if (TEST_OPT_PROT)
1754  //    PrintS("StartGauss\n");
1755  ModPMatrixProxyOnArray<number_type> mat(a,nrows,ncols);
1756
1757  int c=0;
1758  int r=0;
1759  while(mat.findPivot(r,c)){
1760    //int pivot=find_pivot()
1761      mat.reduceOtherRowsForward(r);
1762    r++;
1763    c++;
1764  }
1765  ModPMatrixBackSubstProxyOnArray<number_type> backmat(mat);
1766  backmat.backwardSubstitute();
1767  //backward substitutions
1768  //if (TEST_OPT_PROT)
1769  //PrintS("StopGauss\n");
1770}
1771//int term_nodes_sort_crit(const void* a, const void* b);
1772template <class number_type> void noro_step(poly*p,int &pn,slimgb_alg* c){
1773  //Print("Input rows %d\n",pn);
1774  int j;
1775  if (TEST_OPT_PROT)
1776  {
1777    Print("Input rows %d\n",pn);
1778  }
1779
1780  NoroCache<number_type> cache;
1781
1782  SparseRow<number_type> ** srows=(SparseRow<number_type>**) omAlloc(pn*sizeof(SparseRow<number_type>*));
1783  int non_zeros=0;
1784  for(j=0;j<pn;j++)
1785  {
1786    poly h=p[j];
1787    int h_len=pLength(h);
1788    //number coef;
1789    srows[non_zeros]=noro_red_to_non_poly_t<number_type>(h,h_len,&cache,c);
1790    if (srows[non_zeros]!=NULL) non_zeros++;
1791  }
1792  std::vector<DataNoroCacheNode<number_type>*> irr_nodes;
1793  cache.collectIrreducibleMonomials(irr_nodes);
1794  //now can build up terms array
1795  //Print("historic irred Mon%d\n",cache.nIrreducibleMonomials);
1796  int n=irr_nodes.size();//cache.countIrreducibleMonomials();
1797  cache.nIrreducibleMonomials=n;
1798  if (TEST_OPT_PROT)
1799  {
1800    Print("Irred Mon:%d\n",n);
1801    Print("red Mon:%d\n",cache.nReducibleMonomials);
1802  }
1803  TermNoroDataNode<number_type>* term_nodes=(TermNoroDataNode<number_type>*) omalloc(n*sizeof(TermNoroDataNode<number_type>));
1804
1805  for(j=0;j<n;j++)
1806  {
1807    assume(irr_nodes[j]!=NULL);
1808    assume(irr_nodes[j]->value_len==NoroCache<number_type>::backLinkCode);
1809    term_nodes[j].t=irr_nodes[j]->value_poly;
1810    assume(term_nodes[j].t!=NULL);
1811    term_nodes[j].node=irr_nodes[j];
1812  }
1813
1814  qsort(term_nodes,n,sizeof(TermNoroDataNode<number_type>),term_nodes_sort_crit<number_type>);
1815  poly* terms=(poly*) omalloc(n*sizeof(poly));
1816
1817  int* old_to_new_indices=(int*) omalloc(cache.nIrreducibleMonomials*sizeof(int));
1818  for(j=0;j<n;j++)
1819  {
1820    old_to_new_indices[term_nodes[j].node->term_index]=j;
1821    term_nodes[j].node->term_index=j;
1822    terms[j]=term_nodes[j].t;
1823  }
1824
1825  //if (TEST_OPT_PROT)
1826  //  Print("Evaluate Rows \n");
1827  pn=non_zeros;
1828  number_type* number_array=(number_type*) omalloc0(n*pn*sizeof(number_type));
1829
1830  for(j=0;j<pn;j++)
1831  {
1832    int i;
1833    number_type* row=number_array+n*j;
1834    /*for(i=0;i<n;i++)
1835    {
1836      row[i]=zero;
1837    }*/
1838
1839    SparseRow<number_type>* srow=srows[j];
1840
1841    if (srow)
1842    {
1843      int* const idx_array=srow->idx_array;
1844      number_type* const coef_array=srow->coef_array;
1845      const int len=srow->len;
1846      if (srow->idx_array)
1847      {
1848        for(i=0;i<len;i++)
1849        {
1850         int idx=old_to_new_indices[idx_array[i]];
1851         row[idx]=F4mat_to_number_type(coef_array[i]);
1852        }
1853      }
1854      else
1855      {
1856        for(i=0;i<len;i++)
1857        {
1858          row[old_to_new_indices[i]]=F4mat_to_number_type(coef_array[i]);
1859        }
1860      }
1861      delete srow;
1862    }
1863  }
1864
1865  //static int export_n=0;
1866  //export_mat(number_array,pn,n,"mat%i.py",++export_n);
1867  simplest_gauss_modp(number_array,pn,n);
1868
1869  int p_pos=0;
1870  for(j=0;j<pn;j++){
1871    poly h=row_to_poly(number_array+j*n,terms,n,c->r);
1872    if(h!=NULL){
1873      p[p_pos++]=h;
1874    }
1875  }
1876  pn=p_pos;
1877  omfree(terms);
1878  omfree(term_nodes);
1879  omfree(number_array);
1880  #ifdef NORO_NON_POLY
1881  omfree(srows);
1882  omfree(old_to_new_indices);
1883  #endif
1884  //don't forget the rank
1885
1886}
1887
1888template <class number_type> void NoroCache<number_type>::collectIrreducibleMonomials( std::vector<DataNoroCacheNode<number_type> *>& res){
1889  int i;
1890  for(i=0;i<root.branches_len;i++){
1891    collectIrreducibleMonomials(1,root.branches[i],res);
1892  }
1893}
1894template <class number_type> void NoroCache<number_type>::collectIrreducibleMonomials(int level, NoroCacheNode* node, std::vector<DataNoroCacheNode<number_type>*>& res){
1895  assume(level>=0);
1896  if (node==NULL) return;
1897  if (level<(currRing->N))
1898  {
1899    int i;
1900    for(i=0;i<node->branches_len;i++)
1901    {
1902      collectIrreducibleMonomials(level+1,node->branches[i],res);
1903    }
1904  }
1905  else
1906  {
1907    DataNoroCacheNode<number_type>* dn=(DataNoroCacheNode<number_type>*) node;
1908    if (dn->value_len==backLinkCode)
1909    {
1910      res.push_back(dn);
1911    }
1912  }
1913}
1914
1915template<class number_type> DataNoroCacheNode<number_type>* NoroCache<number_type>::getCacheReference(poly term){
1916  int i;
1917  NoroCacheNode* parent=&root;
1918  for(i=1;i<(currRing->N);i++){
1919    parent=parent->getBranch(p_GetExp(term,i,currRing));
1920    if (!(parent)){
1921      return NULL;
1922    }
1923  }
1924  DataNoroCacheNode<number_type>* res_holder=(DataNoroCacheNode<number_type>*) parent->getBranch(p_GetExp(term,i,currRing));
1925  return res_holder;
1926}
1927template<class number_type> poly NoroCache<number_type>::lookup(poly term, BOOLEAN& succ, int & len){
1928  int i;
1929  NoroCacheNode* parent=&root;
1930  for(i=1;i<(currRing->N);i++){
1931    parent=parent->getBranch(p_GetExp(term,i,currRing));
1932    if (!(parent)){
1933      succ=FALSE;
1934      return NULL;
1935    }
1936  }
1937  DataNoroCacheNode<number_type>* res_holder=(DataNoroCacheNode<number_type>*) parent->getBranch(p_GetExp(term,i,currRing));
1938  if (res_holder){
1939    succ=TRUE;
1940    if ( /*(*/ res_holder->value_len==backLinkCode /*)*/ ){
1941      len=1;
1942      return term;
1943    }
1944    len=res_holder->value_len;
1945    return res_holder->value_poly;
1946  } else {
1947    succ=FALSE;
1948    return NULL;
1949  }
1950}
1951#endif
1952
1953#endif
Note: See TracBrowser for help on using the repository browser.