source: git/kernel/tgb_internal.h @ d0792a

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