source: git/kernel/tgb_internal.h @ 74802b

spielwiese
Last change on this file since 74802b was 74802b, checked in by Michael Brickenstein <bricken@…>, 17 years ago
*bricken: more structure for profiling git-svn-id: file:///usr/local/Singular/svn/trunk@9898 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 36.6 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/* $Id: tgb_internal.h,v 1.63 2007-02-25 09:40:24 bricken Exp $ */
8/*
9 * ABSTRACT: tgb internal .h file
10*/
11#include <omalloc.h>
12#include "p_polys.h"
13
14#include "ideals.h"
15#include "ring.h"
16#include "febase.h"
17#include "structs.h"
18#include "polys.h"
19#include "stdlib.h"
20#include <modulop.h>
21//#define USE_NORO 1
22
23
24#ifdef USE_NORO
25#define NORO_CACHE 1
26#define NORO_SPARSE_ROWS_PRE 1
27#define NORO_NON_POLY 1
28#endif
29#ifdef NORO_CACHE
30//#include <map>
31#include <vector>
32#endif
33#ifdef HAVE_BOOST_DYNAMIC_BITSET_HPP
34#define  HAVE_BOOST 1
35#endif
36//#define HAVE_BOOST 1
37//#define USE_STDVECBOOL 1
38#ifdef HAVE_BOOST
39#include "boost/dynamic_bitset.hpp"
40#include <vector>
41using boost::dynamic_bitset;
42using std::vector;
43#endif
44#ifdef USE_STDVECBOOL
45#include <vector>
46using std::vector;
47#endif
48#include "kutil.h"
49#include "kInline.cc"
50#include "kstd1.h"
51#include "kbuckets.h"
52
53
54
55
56//#define TGB_DEBUG
57#define FULLREDUCTIONS
58#define HANS_IDEA
59//#define HALFREDUCTIONS
60//#define HEAD_BIN
61//#define HOMOGENEOUS_EXAMPLE
62#define REDTAIL_S
63#define PAR_N 100
64#define PAR_N_F4 5000
65#define AC_NEW_MIN 2
66#define AC_FLATTEN 1
67
68//#define FIND_DETERMINISTIC
69//#define REDTAIL_PROT
70//#define QUICK_SPOLY_TEST
71class PolySimple{
72public:
73  PolySimple(poly p){
74    impl=p;
75  }
76  PolySimple(){
77    impl=NULL;
78  }
79  PolySimple(const PolySimple& a){
80    //impl=p_Copy(a.impl,currRing);
81    impl=a.impl;
82  }
83  PolySimple& operator=(const PolySimple& p2){
84    //p_Delete(&impl,currRing);
85    //impl=p_Copy(p2.impl,currRing);
86    impl=p2.impl;
87    return *this;
88  }
89  ~PolySimple(){
90    //p_Delete(&impl,currRing);
91  }
92  bool operator< (const PolySimple& other) const{
93    return pLmCmp(impl,other.impl)<0;
94  }
95  bool operator==(const PolySimple& other){
96    return pLmEqual(impl,other.impl);
97  }
98  poly impl;
99 
100};
101template<class number_type> class DataNoroCacheNode;
102/*class MonRedRes{
103public:
104  poly p;
105  number coef;
106  BOOLEAN changed;
107  int len;
108  BOOLEAN onlyBorrowed;
109  bool operator<(const MonRedRes& other) const{
110    int cmp=p_LmCmp(p,other.p,currRing);
111    if ((cmp<0)||((cmp==0)&&((onlyBorrowed)&&(!(other.onlyBorrowed))))){
112      return true;
113    } else return false;
114  }
115  DataNoroCacheNode* ref;
116  MonRedRes(){
117    ref=NULL;
118    p=NULL;
119  }
120};*/
121template <class number_type> class MonRedResNP{
122public:
123  number coef;
124
125
126  DataNoroCacheNode<number_type>* ref;
127  MonRedResNP(){
128    ref=NULL;
129  }
130};
131struct sorted_pair_node{
132  //criterium, which is stable 0. small lcm 1. small i 2. small j
133  wlen_type expected_length;
134  poly lcm_of_lm;
135  int i;
136  int j;
137  int deg;
138 
139 
140};
141#ifdef NORO_CACHE
142#ifndef NORO_NON_POLY
143class NoroPlaceHolder{
144public:
145  DataNoroCacheNode* ref;
146  number coef;
147};
148#endif
149#endif
150//static ideal debug_Ideal;
151
152
153struct poly_list_node{
154  poly p;
155  poly_list_node* next;
156};
157
158struct int_pair_node{
159  int_pair_node* next;
160  int a;
161  int b;
162};
163struct monom_poly{
164  poly m;
165  poly f;
166};
167struct mp_array_list{
168  monom_poly* mp;
169  int size;
170  mp_array_list* next;
171};
172
173
174struct poly_array_list{
175  poly* p;
176  int size;
177  poly_array_list* next;
178};
179class slimgb_alg
180{
181  public:
182    slimgb_alg(ideal I, int syz_comp,BOOLEAN F4);
183                void introduceDelayedPairs(poly* pa,int s);
184    virtual ~slimgb_alg();
185    void cleanDegs(int lower, int upper);
186#ifndef HAVE_BOOST
187#ifdef USE_STDVECBOOL
188  vector<vector<bool> > states;
189#else
190  char** states;
191#endif
192#else
193  vector<dynamic_bitset<> > states;
194#endif
195  ideal add_later;
196  ideal S;
197  ring r;
198  int* lengths;
199  wlen_type* weighted_lengths;
200  long* short_Exps;
201  kStrategy strat;
202  int* T_deg;
203  int* T_deg_full;
204  poly tmp_lm;
205  poly* tmp_pair_lm;
206  sorted_pair_node** tmp_spn;
207  poly* expandS;
208  poly* gcd_of_terms;
209  int_pair_node* soon_free;
210  sorted_pair_node** apairs;
211  #if 0
212  BOOLEAN* modifiedS;
213  #endif
214  #ifdef TGB_RESORT_PAIRS
215  bool* replaced;
216  #endif
217  poly_list_node* to_destroy;
218  //for F4
219  mp_array_list* F;
220  poly_array_list* F_minus;
221
222  //end for F4
223#ifdef HEAD_BIN
224  struct omBin_s*   HeadBin;
225#endif
226  unsigned int reduction_steps;
227  int n;
228  //! array_lengths should be greater equal n;
229  int syz_comp;
230  int array_lengths; 
231  int normal_forms;
232  int current_degree;
233  int Rcounter;
234  int last_index;
235  int max_pairs;
236  int pair_top;
237  int easy_product_crit;
238  int extended_product_crit;
239  int average_length;
240  int lastDpBlockStart;
241  int lastCleanedDeg;
242  BOOLEAN isDifficultField;
243  BOOLEAN completed;
244  BOOLEAN is_homog;
245  BOOLEAN tailReductions;
246  BOOLEAN eliminationProblem;
247  BOOLEAN F4_mode;
248  BOOLEAN nc;
249  #ifdef TGB_RESORT_PAIRS
250  BOOLEAN used_b;
251  #endif
252};
253class red_object{
254 public:
255  kBucket_pt bucket;
256  poly p;
257  unsigned long sev;
258  int sugar;
259  void flatten();
260  void validate();
261  wlen_type initial_quality;
262  void adjust_coefs(number c_r, number c_ac_r);
263  wlen_type guess_quality(slimgb_alg* c);
264  int clear_to_poly();
265  void canonicalize();
266};
267
268
269enum calc_state
270  {
271    UNCALCULATED,
272    HASTREP//,
273    //UNIMPORTANT,
274    //SOONTREP
275  };
276static BOOLEAN pair_cmp(sorted_pair_node* a,sorted_pair_node* b);
277template <class len_type, class set_type>  int pos_helper(kStrategy strat, poly p, len_type len, set_type setL, polyset set);
278static int add_to_reductors(slimgb_alg* c, poly h, int len, int ecart, BOOLEAN simplified=FALSE);
279static int bucket_guess(kBucket* bucket);
280static poly redNFTail (poly h,const int sl,kStrategy strat, int len);
281static poly redNF2 (poly h,slimgb_alg* c , int &len, number&  m,int n=0);
282void free_sorted_pair_node(sorted_pair_node* s, ring r);
283static void shorten_tails(slimgb_alg* c, poly monom);
284static void replace_pair(int & i, int & j, slimgb_alg* c);
285//static sorted_pair_node** add_to_basis(poly h, int i, int j,slimgb_alg* c, int* ip=NULL);
286static void do_this_spoly_stuff(int i,int j,slimgb_alg* c);
287//ideal t_rep_gb(ring r,ideal arg_I);
288static BOOLEAN has_t_rep(const int & arg_i, const int & arg_j, slimgb_alg* state);
289static int* make_connections(int from, poly bound, slimgb_alg* c);
290static int* make_connections(int from, int to, poly bound, slimgb_alg* c);
291void now_t_rep(const int & arg_i, const int & arg_j, slimgb_alg* c);
292static void soon_t_rep(const int & arg_i, const int & arg_j, slimgb_alg* c);
293static int pLcmDeg(poly a, poly b);
294static int simple_posInS (kStrategy strat, poly p,int len, wlen_type wlen);
295static BOOLEAN find_next_pair(slimgb_alg* c, BOOLEAN go_higher=TRUE);
296
297static sorted_pair_node* pop_pair(slimgb_alg* c);
298static BOOLEAN no_pairs(slimgb_alg* c);
299void clean_top_of_pair_list(slimgb_alg* c);
300static void super_clean_top_of_pair_list(slimgb_alg* c);
301static BOOLEAN state_is(calc_state state, const int & i, const int & j, slimgb_alg* c);
302static BOOLEAN pair_better(sorted_pair_node* a,sorted_pair_node* b, slimgb_alg* c=NULL);
303static int tgb_pair_better_gen(const void* ap,const void* bp);
304static poly redTailShort(poly h, kStrategy strat);
305static poly gcd_of_terms(poly p, ring r);
306static BOOLEAN extended_product_criterion(poly p1, poly gcd1, poly p2, poly gcd2, slimgb_alg* c);
307static poly kBucketGcd(kBucket* b, ring r);
308static void multi_reduction(red_object* los, int & losl, slimgb_alg* c);
309int slim_nsize(number n, ring r);
310sorted_pair_node* quick_pop_pair(slimgb_alg* c);
311sorted_pair_node* top_pair(slimgb_alg* c);
312sorted_pair_node** add_to_basis_ideal_quotient(poly h, slimgb_alg* c, int* ip);//, BOOLEAN new_pairs=TRUE);
313sorted_pair_node**  spn_merge(sorted_pair_node** p, int pn,sorted_pair_node **q, int qn,slimgb_alg* c);
314int kFindDivisibleByInS_easy(kStrategy strat,const red_object & obj);
315int tgb_pair_better_gen2(const void* ap,const void* bp);
316int kFindDivisibleByInS_easy(kStrategy strat,poly p, long sev);
317//static int quality(poly p, int len, slimgb_alg* c);
318/**
319   makes on each red_object in a region a single_step
320 **/
321class reduction_step{
322 public:
323  /// we assume hat all occuring red_objects have same lm, and all
324  /// occ. lm's in r[l...u] are the same, only reductor does not occur
325  virtual void reduce(red_object* r, int l, int u);
326  //int reduction_id;
327  virtual ~reduction_step();
328  slimgb_alg* c;
329  int reduction_id;
330};
331class simple_reducer:public reduction_step{
332 public:
333  poly p;
334  kBucket_pt fill_back;
335  int p_len;
336  int reducer_deg;
337  simple_reducer(poly p, int p_len,int reducer_deg, slimgb_alg* c =NULL){
338    this->p=p;
339    this->reducer_deg=reducer_deg;
340    assume(p_len==pLength(p));
341    this->p_len=p_len;
342    this->c=c;
343  }
344  virtual void pre_reduce(red_object* r, int l, int u);
345  virtual void reduce(red_object* r, int l, int u);
346  ~simple_reducer();
347
348
349  virtual void do_reduce(red_object & ro);
350};
351
352//class sum_canceling_reducer:public reduction_step {
353//  void reduce(red_object* r, int l, int u);
354//};
355struct find_erg{
356  poly expand;
357  int expand_length;
358  int to_reduce_u;
359  int to_reduce_l;
360  int reduce_by;//index of reductor
361  BOOLEAN fromS;//else from los
362
363};
364
365static void multi_reduce_step(find_erg & erg, red_object* r, slimgb_alg* c);
366static void finalize_reduction_step(reduction_step* r);
367
368template <class len_type, class set_type>  int pos_helper(kStrategy strat, poly p, len_type len, set_type setL, polyset set){
369  //Print("POSHELER:%d",sizeof(wlen_type));
370  int length=strat->sl;
371  int i;
372  int an = 0;
373  int en= length;
374
375  if ((len>setL[length])
376      || ((len==setL[length]) && (pLmCmp(set[length],p)== -1)))
377    return length+1;
378
379  loop
380  {
381    if (an >= en-1)
382    {
383      if ((len<setL[an])
384          || ((len==setL[an]) && (pLmCmp(set[an],p) == 1))) return an;
385      return en;
386    }
387    i=(an+en) / 2;
388    if ((len<setL[i])
389        || ((len==setL[i]) && (pLmCmp(set[i],p) == 1))) en=i;
390    //else if ((len>setL[i])
391    //|| ((len==setL[i]) && (pLmCmp(set[i],p) == -1))) an=i;
392    else an=i;
393  }
394
395}
396#ifdef NORO_CACHE
397#define slim_prec_cast(a) (unsigned int) (unsigned long) (a)
398#define F4mat_to_number_type(a) (number_type) slim_prec_cast(a)
399typedef unsigned short tgb_uint16;
400typedef unsigned char tgb_uint8;
401typedef unsigned int tgb_uint32;
402class NoroCacheNode{
403public:
404  NoroCacheNode** branches;
405  int branches_len;
406
407 
408  NoroCacheNode(){
409    branches=NULL;
410    branches_len=0;
411   
412  }
413  NoroCacheNode* setNode(int branch, NoroCacheNode* node){
414    if (branch>=branches_len){
415      if (branches==NULL){
416        branches_len=branch+1;
417        branches_len=si_max(branches_len,3);
418        branches=(NoroCacheNode**) omalloc(branches_len*sizeof(NoroCacheNode*));
419        int i;
420        for(i=0;i<branches_len;i++){
421          branches[i]=NULL;
422        }
423      }else{
424        int branches_len_old=branches_len;
425        branches_len=branch+1;
426        branches=(NoroCacheNode**) omrealloc(branches,branches_len*sizeof(NoroCacheNode*));
427        int i;
428        for(i=branches_len_old;i<branches_len;i++){
429          branches[i]=NULL;
430        }
431      }
432    }
433    assume(branches[branch]==NULL);
434    branches[branch]=node;
435    return node;
436  }
437  NoroCacheNode* getBranch(int branch){
438    if (branch<branches_len) return branches[branch];
439    return NULL;
440  }
441  virtual ~NoroCacheNode(){
442    int i;
443    for(i=0;i<branches_len;i++){
444      delete branches[i];
445    }
446    omfree(branches);
447  }
448  NoroCacheNode* getOrInsertBranch(int branch){
449    if ((branch<branches_len)&&(branches[branch]))
450      return branches[branch];
451    else{
452      return setNode(branch,new NoroCacheNode());
453    }
454  }
455};
456class DenseRow{
457public:
458  number* array;
459  int begin;
460  int end;
461  DenseRow(){
462    array=NULL;
463  }
464  ~DenseRow(){
465    omfree(array);
466  }
467};
468template <class number_type> class SparseRow{
469public:
470  int* idx_array;
471  number_type* coef_array;
472  int len;
473  SparseRow(){
474    len=0;
475    idx_array=NULL;
476    coef_array=NULL;
477  }
478  SparseRow<number_type>(int n){
479    len=n;
480    idx_array=(int*) omalloc(n*sizeof(int));
481    coef_array=(number_type*) omalloc(n*sizeof(number_type));
482  }
483  ~SparseRow<number_type>(){
484    omfree(idx_array);
485    omfree(coef_array);
486  }
487};
488
489template <class number_type> class DataNoroCacheNode:public NoroCacheNode{
490public:
491 
492  int value_len;
493  poly value_poly;
494  #ifdef NORO_SPARSE_ROWS_PRE
495  SparseRow<number_type>* row;
496  #else
497  DenseRow* row;
498  #endif
499  int term_index;
500  DataNoroCacheNode(poly p, int len){
501    value_len=len;
502    value_poly=p;
503    row=NULL;
504    term_index=-1;
505  }
506  #ifdef NORO_SPARSE_ROWS_PRE
507  DataNoroCacheNode(SparseRow<number_type>* row){
508    if (row!=NULL)
509      value_len=row->len;
510    else
511      value_len=0;
512    value_poly=NULL;
513    this->row=row;
514    term_index=-1;
515  }
516  #endif
517  ~DataNoroCacheNode(
518  ){
519    //p_Delete(&value_poly,currRing);
520    if (row) delete row;
521  }
522};
523template <class number_type> class TermNoroDataNode{
524public:
525  DataNoroCacheNode<number_type>* node;
526  poly t;
527};
528
529template <class number_type> class NoroCache{
530public:
531  poly temp_term;
532#ifndef NORO_NON_POLY
533  void evaluatePlaceHolder(number* row,std::vector<NoroPlaceHolder>& place_holders);
534  void evaluateRows();
535  void evaluateRows(int level, NoroCacheNode* node);
536#endif
537  void collectIrreducibleMonomials( std::vector<DataNoroCacheNode<number_type>* >& res);
538  void collectIrreducibleMonomials(int level,  NoroCacheNode* node, std::vector<DataNoroCacheNode<number_type>* >& res);
539
540#ifdef NORO_RED_ARRAY_RESERVER
541  int reserved;
542  poly* recursionPolyBuffer;
543#endif
544  static const int backLinkCode=-222;
545  DataNoroCacheNode<number_type>* insert(poly term, poly nf, int len){
546    //assume(impl.find(p_Copy(term,currRing))==impl.end());
547    //assume(len==pLength(nf));
548    assume(npIsOne(p_GetCoeff(term,currRing)));
549    if (term==nf){
550      term=p_Copy(term,currRing);
551
552      ressources.push_back(term);
553      nIrreducibleMonomials++;
554      return treeInsertBackLink(term);
555     
556    } else{
557     
558      if (nf){
559        //nf=p_Copy(nf,currRing);
560        assume(p_LmCmp(nf,term,currRing)==-1);
561        ressources.push_back(nf);
562      }
563      return treeInsert(term,nf,len);
564     
565    }
566   
567    //impl[term]=std::pair<PolySimple,int> (nf,len);
568  }
569  #ifdef NORO_SPARSE_ROWS_PRE
570  DataNoroCacheNode<number_type>* insert(poly term, SparseRow<number_type>* srow){
571    //assume(impl.find(p_Copy(term,currRing))==impl.end());
572    //assume(len==pLength(nf));
573
574      return treeInsert(term,srow);
575     
576 
577    //impl[term]=std::pair<PolySimple,int> (nf,len);
578  }
579  #endif
580  DataNoroCacheNode<number_type>* insertAndTransferOwnerShip(poly t, ring r){
581   
582    ressources.push_back(t);
583    DataNoroCacheNode<number_type>* res=treeInsertBackLink(t);
584    res->term_index=nIrreducibleMonomials;
585    nIrreducibleMonomials++;
586    return res;
587  }
588  poly lookup(poly term, BOOLEAN& succ, int & len);
589  DataNoroCacheNode<number_type>* getCacheReference(poly term);
590  NoroCache(){
591    buffer=NULL;
592#ifdef NORO_RED_ARRAY_RESERVER
593    reserved=0;
594    recursionPolyBuffer=(poly*)omalloc(1000000*sizeof(poly));
595#endif
596    nIrreducibleMonomials=0;
597    nReducibleMonomials=0;
598    temp_term=pOne();
599    tempBufferSize=3000;
600    tempBuffer=omalloc(tempBufferSize);
601  }
602  void ensureTempBufferSize(size_t size){
603    if (tempBufferSize<size){
604      tempBufferSize=2*size;
605      omfree(tempBuffer);
606      tempBuffer=omalloc(tempBufferSize);
607    }
608  }
609#ifdef NORO_RED_ARRAY_RESERVER
610  poly* reserve(int n){
611    poly* res=recursionPolyBuffer+reserved;
612    reserved+=n;
613    return res;
614  }
615  void free(int n){
616    reserved-=n;
617  }
618#endif
619  ~NoroCache(){
620    int s=ressources.size();
621    int i;
622    for(i=0;i<s;i++){
623      p_Delete(&ressources[i].impl,currRing);
624    }
625    p_Delete(&temp_term,currRing);
626#ifdef NORO_RED_ARRAY_RESERVER
627    omfree(recursionPolyBuffer);
628#endif
629   omfree(tempBuffer);
630  }
631 
632  int nIrreducibleMonomials;
633  int nReducibleMonomials;
634  void* tempBuffer;
635  size_t tempBufferSize;
636protected:
637  DataNoroCacheNode<number_type>* treeInsert(poly term,poly nf,int len){
638    int i;
639    nReducibleMonomials++;
640    int nvars=pVariables;
641    NoroCacheNode* parent=&root;
642    for(i=1;i<nvars;i++){
643      parent=parent->getOrInsertBranch(p_GetExp(term,i,currRing));
644    }
645    return (DataNoroCacheNode<number_type>*) parent->setNode(p_GetExp(term,nvars,currRing),new DataNoroCacheNode<number_type>(nf,len));
646  }
647  #ifdef NORO_SPARSE_ROWS_PRE
648  DataNoroCacheNode<number_type>* treeInsert(poly term,SparseRow<number_type>* srow){
649    int i;
650    nReducibleMonomials++;
651    int nvars=pVariables;
652    NoroCacheNode* parent=&root;
653    for(i=1;i<nvars;i++){
654      parent=parent->getOrInsertBranch(p_GetExp(term,i,currRing));
655    }
656    return (DataNoroCacheNode<number_type>*) parent->setNode(p_GetExp(term,nvars,currRing),new DataNoroCacheNode<number_type>(srow));
657  }
658  #endif
659  DataNoroCacheNode<number_type>* treeInsertBackLink(poly term){
660    int i;
661    int nvars=pVariables;
662    NoroCacheNode* parent=&root;
663    for(i=1;i<nvars;i++){
664      parent=parent->getOrInsertBranch(p_GetExp(term,i,currRing));
665    }
666    return (DataNoroCacheNode<number_type>*) parent->setNode(p_GetExp(term,nvars,currRing),new DataNoroCacheNode<number_type>(term,backLinkCode));
667  }
668 
669  //@TODO descruct nodes;
670  typedef std::vector<PolySimple> poly_vec;
671  poly_vec ressources;
672  //typedef std::map<PolySimple,std::pair<PolySimple,int> > cache_map;
673  //cache_map impl;
674  NoroCacheNode root;
675  number* buffer;
676};
677template<class number_type> SparseRow<number_type> * noro_red_to_non_poly_t(poly p, int &len, NoroCache<number_type>* cache,slimgb_alg* c);
678template<class number_type> MonRedResNP<number_type> noro_red_mon_to_non_poly(poly t,  NoroCache<number_type> * cache,slimgb_alg* c)
679{
680  MonRedResNP<number_type> res_holder;
681
682
683    DataNoroCacheNode<number_type>* ref=cache->getCacheReference(t);
684    if (ref!=NULL){
685
686
687      res_holder.coef=p_GetCoeff(t,c->r);
688     
689      res_holder.ref=ref;
690      p_Delete(&t,c->r);
691      return res_holder;
692    }
693 
694  unsigned long sev=p_GetShortExpVector(t,currRing);
695  int i=kFindDivisibleByInS_easy(c->strat,t,sev);
696  if (i>=0){
697    number coef_bak=p_GetCoeff(t,c->r);
698
699    p_SetCoeff(t,npInit(1),c->r);
700    assume(npIsOne(p_GetCoeff(c->strat->S[i],c->r)));
701    number coefstrat=p_GetCoeff(c->strat->S[i],c->r);
702
703
704    poly exp_diff=cache->temp_term;
705    p_ExpVectorDiff(exp_diff,t,c->strat->S[i],c->r);
706    p_SetCoeff(exp_diff,npNeg(npInvers(coefstrat)),c->r);
707    p_Setm(exp_diff,c->r);
708    assume(c->strat->S[i]!=NULL);
709
710    poly res;
711    res=pp_Mult_mm(pNext(c->strat->S[i]),exp_diff,c->r);
712
713    int len=c->strat->lenS[i]-1;
714    SparseRow<number_type>* srow;
715    srow=noro_red_to_non_poly_t<number_type>(res,len,cache,c);
716    ref=cache->insert(t,srow);
717    p_Delete(&t,c->r);
718
719
720    res_holder.coef=coef_bak;
721    res_holder.ref=ref;
722    return res_holder;
723
724  } else {
725    number coef_bak=p_GetCoeff(t,c->r);
726    number one=npInit(1);
727    p_SetCoeff(t,one,c->r);
728 
729    res_holder.ref=cache->insertAndTransferOwnerShip(t,c->r);
730    assume(res_holder.ref!=NULL);
731    res_holder.coef=coef_bak;
732   
733    return res_holder;
734   
735  }
736
737}
738/*
739poly tree_add(poly* a,int begin, int end,ring r){
740  int d=end-begin;
741  switch(d){
742    case 0:
743      return NULL;
744    case 1:
745      return a[begin];
746    case 2:
747      return p_Add_q(a[begin],a[begin+1],r);
748    default:
749      int s=d/2;
750      return p_Add_q(tree_add(a,begin,begin+s,r),tree_add(a,begin+s,end,r),r);
751  }
752}
753*/
754#ifdef __GNUC__
755#define LIKELY(expression) (__builtin_expect(!!(expression), 1))
756#define UNLIKELY(expression) (__builtin_expect(!!(expression), 0))
757#else
758#define LIKELY(expression) (expression)
759#define UNLIKELY(expression) (expression)
760#endif
761
762template<class number_type> SparseRow<number_type>* convert_to_sparse_row(number_type* temp_array,int temp_size,int non_zeros){
763SparseRow<number_type>* res=new SparseRow<number_type>(non_zeros);
764//int pos=0;
765number_type* it_coef=res->coef_array;
766int* it_idx=res->idx_array;
767#if 0
768for(i=0;i<cache->nIrreducibleMonomials;i++){
769  if (!(0==temp_array[i])){
770 
771    res->idx_array[pos]=i;
772    res->coef_array[pos]=temp_array[i];
773
774    pos++;
775    non_zeros--;
776    if (non_zeros==0) break;
777  }
778 
779}
780#else
781int64* start=(int64*) ((void*)temp_array);
782int64* end;
783const int multiple=sizeof(int64)/sizeof(number_type);
784if (temp_size==0) end=start;
785
786else
787{ 
788  int temp_size_rounded=temp_size+(multiple-(temp_size%multiple));
789  assume(temp_size_rounded>=temp_size);
790  assume(temp_size_rounded%multiple==0);
791  assume(temp_size_rounded<temp_size+multiple);
792  number_type* nt_end=temp_array+temp_size_rounded;
793  end=(int64*)((void*)nt_end);
794}
795int64* it=start;
796while(it!=end){
797  if UNLIKELY((*it)!=0){
798    int small_i;
799    const int temp_index=((number_type*)((void*) it))-temp_array;
800    const int bound=temp_index+multiple;
801    number_type c;
802    for(small_i=temp_index;small_i<bound;small_i++){
803      if((c=temp_array[small_i])!=0){
804        //res->idx_array[pos]=small_i;
805        //res->coef_array[pos]=temp_array[small_i];
806        (*(it_idx++))=small_i;
807        (*(it_coef++))=c;
808        //pos++;
809        non_zeros--;
810       
811      }
812      if UNLIKELY(non_zeros==0) break;
813    }
814   
815  }
816  ++it;
817}
818#endif
819return res;
820}
821template <class number_type> void add_coef_times_sparse(number_type* temp_array,int temp_size,SparseRow<number_type>* row, number coef){
822  int j;
823  for(j=0;j<row->len;j++){
824    int idx=row->idx_array[j];
825    assume(!(npIsZero(coef)));
826    assume(!(npIsZero((number) row->coef_array[j])));
827    temp_array[idx]=F4mat_to_number_type(npAddM((number) temp_array[idx],npMultM((number) row->coef_array[j],coef)));
828    assume(idx<temp_size);
829  }
830}
831template<class number_type> SparseRow<number_type> * noro_red_to_non_poly_t(poly p, int &len, NoroCache<number_type>* cache,slimgb_alg* c){
832  assume(len==pLength(p));
833  poly orig_p=p;
834  if (p==NULL) {
835    len=0;
836    return NULL;
837  }
838 
839  number zero=npInit(0);
840  MonRedResNP<number_type>* mon=(MonRedResNP<number_type>*) omalloc(len*sizeof(MonRedResNP<number_type>));
841  int i=0;
842
843  while(p){
844
845    poly t=p;
846    pIter(p);
847    pNext(t)=NULL;
848   
849#ifndef NDEBUG
850    number coef_debug=p_GetCoeff(t,currRing);
851#endif
852    MonRedResNP<number_type> red=noro_red_mon_to_non_poly(t,cache,c);
853    mon[i]=red;
854    i++;
855  }
856 
857  assume(i==len);
858  len=i;
859  //in the loop before nIrreducibleMonomials increases, so position here is important
860  size_t temp_size_bytes=cache->nIrreducibleMonomials*sizeof(number_type)+8;//use 8bit int for testing
861  assume(sizeof(int64)==8);
862  cache->ensureTempBufferSize(temp_size_bytes);
863  number_type* temp_array=(number_type*) cache->tempBuffer;//omalloc(cache->nIrreducibleMonomials*sizeof(number_type));
864  int temp_size=cache->nIrreducibleMonomials;
865  memset(temp_array,0,temp_size_bytes);
866  number minus_one=npInit(-1);
867  for(i=0;i<len;i++){
868    MonRedResNP<number_type> red=mon[i];
869    if ((red.ref)){
870      if (red.ref->row){
871        SparseRow<number_type>* row=red.ref->row;
872        number coef=red.coef;
873        int j;
874        if (!((coef==(number) 1)||(coef==minus_one))){
875          add_coef_times_sparse(temp_array,temp_size,row,coef);
876       
877       
878       
879        }else{
880          if (coef==(number) 1){
881          for(j=0;j<row->len;j++){
882            int idx=row->idx_array[j];
883            temp_array[idx]=F4mat_to_number_type(   npAddM((number) temp_array[idx],(number) row->coef_array[j]));
884            assume(idx<temp_size);
885          }
886          } else {
887            for(j=0;j<row->len;j++){
888            int idx=row->idx_array[j];
889            temp_array[idx]=F4mat_to_number_type(   npSubM((number) temp_array[idx],(number) row->coef_array[j]));
890            assume(idx<temp_size);
891          }}
892        }
893      }
894      else{
895        if (red.ref->value_len==NoroCache<number_type>::backLinkCode){
896          temp_array[red.ref->term_index]=F4mat_to_number_type( npAddM((number) temp_array[red.ref->term_index],red.coef));
897        } else {
898          //PrintS("third case\n");
899        }
900      }
901    }
902  }
903  int non_zeros=0;
904  for(i=0;i<cache->nIrreducibleMonomials;i++){
905    //if (!(temp_array[i]==0)){
906    //  non_zeros++;
907    //}
908    assume(((temp_array[i]!=0)==0)|| (((temp_array[i]!=0)==1)));
909    non_zeros+=(temp_array[i]!=0);
910  }
911 
912  if (non_zeros==0){
913    omfree(mon);
914    return NULL;
915  }
916  SparseRow<number_type>* res=convert_to_sparse_row(temp_array,temp_size, non_zeros);
917
918  //omfree(temp_array);
919
920  omfree(mon);
921  return res;
922}
923#endif
924static wlen_type pair_weighted_length(int i, int j, slimgb_alg* c);
925wlen_type pELength(poly p, ring r);
926int terms_sort_crit(const void* a, const void* b);
927//void simplest_gauss_modp(number* a, int nrows,int ncols);
928// a: a[0,0],a[0,1]....a[nrows-1,ncols-1]
929// assume: field is Zp
930#ifdef USE_NORO
931
932
933template <class number_type > void write_poly_to_row(number_type* row, poly h, poly*terms, int tn, ring r){
934  //poly* base=row;
935  while(h!=NULL){
936    //Print("h:%i\n",h);
937    number coef=p_GetCoeff(h,r);
938    poly* ptr_to_h=(poly*) bsearch(&h,terms,tn,sizeof(poly),terms_sort_crit);
939    assume(ptr_to_h!=NULL);
940    int pos=ptr_to_h-terms;
941    row[pos]=F4mat_to_number_type(coef);
942    //number_type_array[base+pos]=coef;
943    pIter(h);
944  }
945}
946template <class number_type > poly row_to_poly(number_type* row, poly* terms, int tn, ring r){
947  poly h=NULL;
948  int j;
949  number_type zero=0;//;npInit(0);
950  for(j=tn-1;j>=0;j--){
951    if (!(zero==(row[j]))){
952      poly t=terms[j];
953      t=p_LmInit(t,r);
954      p_SetCoeff(t,(number) row[j],r);
955      pNext(t)=h;
956      h=t;
957    }
958   
959  }
960  return h;
961}
962template <class number_type > int modP_lastIndexRow(number_type* row,int ncols){
963  int lastIndex;
964  const number_type zero=0;//npInit(0);
965  for(lastIndex=ncols-1;lastIndex>=0;lastIndex--){
966    if (!(row[lastIndex]==zero)){
967      return lastIndex;
968    }
969  }
970  return -1;
971}
972template <class number_type> int term_nodes_sort_crit(const void* a, const void* b){
973  return -pLmCmp(((TermNoroDataNode<number_type>*) a)->t,((TermNoroDataNode<number_type>*) b)->t);
974}
975
976template <class number_type>class ModPMatrixBackSubstProxyOnArray;
977template <class number_type > class ModPMatrixProxyOnArray{
978public:
979  friend class ModPMatrixBackSubstProxyOnArray<number_type>;
980               
981  int ncols,nrows;
982  ModPMatrixProxyOnArray(number_type* array, int nrows, int ncols){
983    this->ncols=ncols;
984    this->nrows=nrows;
985    rows=(number_type**) omalloc(nrows*sizeof(number_type*));
986    startIndices=(int*)omalloc(nrows*sizeof(int));
987    int i;
988    for(i=0;i<nrows;i++){
989      rows[i]=array+(i*ncols);
990      updateStartIndex(i,-1);
991    }
992  }
993  ~ModPMatrixProxyOnArray(){
994    omfree(rows);
995    omfree(startIndices);
996  }
997 
998  void permRows(int i, int j){
999    number_type* h=rows[i];
1000    rows[i]=rows[j];
1001    rows[j]=h;
1002    int hs=startIndices[i];
1003    startIndices[i]=startIndices[j];
1004    startIndices[j]=hs;
1005  }
1006  void multiplyRow(int row, number_type coef){
1007    int i;
1008    number_type* row_array=rows[row];
1009    for(i=startIndices[row];i<ncols;i++){
1010      row_array[i]=F4mat_to_number_type(npMult((number) row_array[i],(number) coef));
1011    }
1012  }
1013  void reduceOtherRowsForward(int r){
1014
1015    //assume rows "under r" have bigger or equal start index
1016    number_type* row_array=rows[r];
1017    number_type zero=F4mat_to_number_type(npInit(0));
1018    int start=startIndices[r];
1019    number_type coef=row_array[start];
1020    assume(start<ncols);
1021    int other_row;
1022    assume(!(npIsZero((number) row_array[start])));
1023    if (!(npIsOne((number) coef)))
1024      multiplyRow(r,F4mat_to_number_type(npInvers((number) coef)));
1025    assume(npIsOne((number) row_array[start]));
1026    int lastIndex=modP_lastIndexRow(row_array, ncols);
1027    number minus_one=npInit(-1);
1028    for (other_row=r+1;other_row<nrows;other_row++){
1029      assume(startIndices[other_row]>=start);
1030      if (startIndices[other_row]==start){
1031        int i;
1032        number_type* other_row_array=rows[other_row];
1033        number coef2=npNeg((number) other_row_array[start]);
1034        if (coef2==minus_one){
1035          for(i=start;i<=lastIndex;i++){
1036            if (row_array[i]!=zero)
1037              other_row_array[i]=F4mat_to_number_type(npSubM((number) other_row_array[i], (number) row_array[i]));
1038          }
1039      }else {
1040          //assume(FALSE);
1041          for(i=start;i<=lastIndex;i++){
1042            if (row_array[i]!=zero)
1043            other_row_array[i]=F4mat_to_number_type(npAddM(npMult(coef2,(number) row_array[i]),(number) other_row_array[i]));
1044          }
1045        }
1046        updateStartIndex(other_row,start);
1047        assume(npIsZero((number) other_row_array[start]));
1048      }
1049    }
1050  }
1051  void updateStartIndex(int row,int lower_bound){
1052    number_type* row_array=rows[row];
1053    assume((lower_bound<0)||(npIsZero((number) row_array[lower_bound])));
1054    int i;
1055    //number_type zero=npInit(0);
1056    for(i=lower_bound+1;i<ncols;i++){
1057      if (!(row_array[i]==0))
1058        break;
1059    }
1060    startIndices[row]=i;
1061  }
1062  int getStartIndex(int row){
1063    return startIndices[row];
1064  }
1065  BOOLEAN findPivot(int &r, int &c){
1066    //row>=r, col>=c
1067   
1068    while(c<ncols){
1069      int i;
1070      for(i=r;i<nrows;i++){
1071        assume(startIndices[i]>=c);
1072        if (startIndices[i]==c){
1073          //r=i;
1074          if (r!=i)
1075            permRows(r,i);
1076          return TRUE;
1077        }
1078      }
1079      c++;
1080    }
1081    return FALSE;
1082  }
1083protected:
1084  number_type** rows;
1085  int* startIndices;
1086};
1087template <class number_type > class ModPMatrixBackSubstProxyOnArray{
1088  int *startIndices;
1089  number_type** rows;
1090  int *lastReducibleIndices;
1091  int ncols;
1092  int nrows;
1093  int nonZeroUntil;
1094public:
1095  void multiplyRow(int row, number_type coef){
1096    int i;
1097    number_type* row_array=rows[row];
1098    for(i=startIndices[row];i<ncols;i++){
1099      row_array[i]=F4mat_to_number_type(npMult((number) row_array[i],(number) coef));
1100    }
1101  }
1102  ModPMatrixBackSubstProxyOnArray<number_type> (ModPMatrixProxyOnArray<number_type> & p){
1103//  (number_type* array, int nrows, int ncols, int* startIndices, number_type** rows){
1104    //we borrow some parameters ;-)
1105    //we assume, that nobody changes the order of the rows
1106    this->startIndices=p.startIndices;
1107    this->rows=p.rows;
1108    this->ncols=p.ncols;
1109    this->nrows=p.nrows;
1110    lastReducibleIndices=(int*) omalloc(nrows*sizeof(int));
1111    nonZeroUntil=0;
1112    while(nonZeroUntil<nrows){
1113      if (startIndices[nonZeroUntil]<ncols){
1114       
1115        nonZeroUntil++;
1116      } else break;
1117     
1118    }
1119    if (TEST_OPT_PROT)
1120      Print("rank:%i\n",nonZeroUntil);
1121    nonZeroUntil--;
1122    int i;
1123    for(i=0;i<=nonZeroUntil;i++){
1124      assume(startIndices[i]<ncols);
1125      assume(!(npIsZero((number) rows[i][startIndices[i]])));
1126      assume(startIndices[i]>=i);
1127      updateLastReducibleIndex(i,nonZeroUntil+1);
1128    }
1129  }
1130  void updateLastReducibleIndex(int r, int upper_bound){
1131    number_type* row_array=rows[r];
1132    if (upper_bound>nonZeroUntil) upper_bound=nonZeroUntil+1;
1133    int i;
1134    const number_type zero=0;//npInit(0);
1135    for(i=upper_bound-1;i>r;i--){
1136      int start=startIndices[i];
1137      assume(start<ncols);
1138      if (!(row_array[start]==zero)){
1139        lastReducibleIndices[r]=start;
1140        return;
1141      }
1142    }
1143    lastReducibleIndices[r]=-1;
1144  }
1145  void backwardSubstitute(int r){
1146    int start=startIndices[r];
1147    assume(start<ncols);
1148    number_type zero=0;//npInit(0);
1149    number_type* row_array=rows[r];
1150    assume((!(npIsZero((number) row_array[start]))));
1151    assume(start<ncols);
1152    int other_row;
1153    if (!(npIsOne((number) row_array[r]))){
1154      //it should be one, but this safety is not expensive
1155      multiplyRow(r, F4mat_to_number_type(npInvers((number) row_array[start])));
1156    }
1157    int lastIndex=modP_lastIndexRow(row_array, ncols);
1158    assume(lastIndex<ncols);
1159    assume(lastIndex>=0);
1160    for(other_row=r-1;other_row>=0;other_row--){
1161      assume(lastReducibleIndices[other_row]<=start);
1162      if (lastReducibleIndices[other_row]==start){
1163        number_type* other_row_array=rows[other_row];
1164        number coef=npNeg((number) other_row_array[start]);
1165        assume(!(npIsZero(coef)));
1166        int i;
1167        assume(start>startIndices[other_row]);
1168        for(i=start;i<=lastIndex;i++){
1169          if (row_array[i]!=zero)
1170            other_row_array[i]=F4mat_to_number_type(npAddM(npMult(coef,(number)row_array[i]),(number)other_row_array[i]));
1171        }
1172        updateLastReducibleIndex(other_row,r);
1173      }
1174    }
1175  }
1176  ~ModPMatrixBackSubstProxyOnArray<number_type>(){
1177    omfree(lastReducibleIndices);
1178  }
1179  void backwardSubstitute(){
1180    int i;
1181    for(i=nonZeroUntil;i>0;i--){
1182      backwardSubstitute(i);
1183    }
1184  }
1185};
1186template <class number_type > void simplest_gauss_modp(number_type* a, int nrows,int ncols){
1187  //use memmoves for changing rows
1188  if (TEST_OPT_PROT)
1189    PrintS("StartGauss\n");
1190  ModPMatrixProxyOnArray<number_type> mat(a,nrows,ncols);
1191 
1192  int c=0;
1193  int r=0;
1194  while(mat.findPivot(r,c)){
1195    //int pivot=find_pivot()
1196      mat.reduceOtherRowsForward(r);
1197    r++;
1198    c++;
1199  }
1200  ModPMatrixBackSubstProxyOnArray<number_type> backmat(mat);
1201  backmat.backwardSubstitute();
1202  //backward substitutions
1203  if (TEST_OPT_PROT)
1204    PrintS("StopGauss\n");
1205}
1206//int term_nodes_sort_crit(const void* a, const void* b);
1207template <class number_type> void noro_step(poly*p,int &pn,slimgb_alg* c){
1208  //Print("Input rows %d\n",pn);
1209  int j;
1210  if (TEST_OPT_PROT){
1211    Print("Input rows %d\n",pn);
1212  }
1213
1214  NoroCache<number_type> cache;
1215
1216  SparseRow<number_type> ** srows=(SparseRow<number_type>**) omalloc(pn*sizeof(SparseRow<number_type>*));
1217  int non_zeros=0;
1218  for(j=0;j<pn;j++){
1219   
1220    poly h=p[j];
1221    int h_len=pLength(h);
1222
1223    //number coef;
1224
1225
1226    srows[non_zeros]=noro_red_to_non_poly_t<number_type>(h,h_len,&cache,c);
1227    if (srows[non_zeros]!=NULL) non_zeros++;
1228  }
1229  std::vector<DataNoroCacheNode<number_type>*> irr_nodes;
1230  cache.collectIrreducibleMonomials(irr_nodes);
1231  //now can build up terms array
1232  //Print("historic irred Mon%d\n",cache.nIrreducibleMonomials);
1233  int n=irr_nodes.size();//cache.countIrreducibleMonomials();
1234  cache.nIrreducibleMonomials=n;
1235  if (TEST_OPT_PROT){
1236    Print("Irred Mon:%d\n",n);
1237    Print("red Mon:%d\n",cache.nReducibleMonomials);
1238  }
1239  TermNoroDataNode<number_type>* term_nodes=(TermNoroDataNode<number_type>*) omalloc(n*sizeof(TermNoroDataNode<number_type>));
1240 
1241  for(j=0;j<n;j++){
1242    assume(irr_nodes[j]!=NULL);
1243    assume(irr_nodes[j]->value_len==NoroCache<number_type>::backLinkCode);
1244    term_nodes[j].t=irr_nodes[j]->value_poly;
1245    assume(term_nodes[j].t!=NULL);
1246    term_nodes[j].node=irr_nodes[j];
1247  }
1248 
1249 
1250  qsort(term_nodes,n,sizeof(TermNoroDataNode<number_type>),term_nodes_sort_crit<number_type>);
1251  poly* terms=(poly*) omalloc(n*sizeof(poly));
1252
1253  int* old_to_new_indices=(int*) omalloc(cache.nIrreducibleMonomials*sizeof(int));
1254  for(j=0;j<n;j++){
1255    old_to_new_indices[term_nodes[j].node->term_index]=j;
1256    term_nodes[j].node->term_index=j;
1257    terms[j]=term_nodes[j].t;
1258  }
1259
1260  //if (TEST_OPT_PROT)
1261  //  Print("Evaluate Rows \n");
1262  pn=non_zeros;
1263  number_type* number_array=(number_type*) omalloc(n*pn*sizeof(number_type));
1264  memset(number_array,0,sizeof(number_type)*n*pn);
1265  number zero=npInit(0);
1266
1267  for(j=0;j<pn;j++){
1268    int i;
1269    number_type* row=number_array+n*j;
1270    /*for(i=0;i<n;i++){
1271      row[i]=zero;
1272    }*/
1273
1274    SparseRow<number_type>* srow=srows[j];
1275    if (srow){
1276    for(i=0;i<srow->len;i++){
1277      int idx=old_to_new_indices[srow->idx_array[i]];
1278      row[idx]=F4mat_to_number_type(srow->coef_array[i]);
1279    }
1280    delete srow;
1281    }
1282  }
1283 
1284  static int export_n=0;
1285  //export_mat(number_array,pn,n,"mat%i.py",++export_n);
1286  simplest_gauss_modp(number_array,pn,n);
1287
1288  int p_pos=0;
1289  for(j=0;j<pn;j++){
1290    poly h=row_to_poly(number_array+j*n,terms,n,c->r);
1291    if(h!=NULL){
1292      p[p_pos++]=h;
1293    }
1294  }
1295  pn=p_pos;
1296  omfree(terms);
1297  omfree(term_nodes);
1298  omfree(number_array);
1299  #ifdef NORO_NON_POLY
1300  omfree(srows);
1301  omfree(old_to_new_indices);
1302  #endif
1303  //don't forget the rank
1304 
1305}
1306
1307template <class number_type> void NoroCache<number_type>::collectIrreducibleMonomials( std::vector<DataNoroCacheNode<number_type> *>& res){
1308  int i;
1309  for(i=0;i<root.branches_len;i++){
1310    collectIrreducibleMonomials(1,root.branches[i],res);
1311  }
1312}
1313template <class number_type> void NoroCache<number_type>::collectIrreducibleMonomials(int level, NoroCacheNode* node, std::vector<DataNoroCacheNode<number_type>*>& res){
1314  assume(level>=0);
1315  if (node==NULL) return;
1316  if (level<pVariables){
1317    int i,sum;
1318    for(i=0;i<node->branches_len;i++){
1319      collectIrreducibleMonomials(level+1,node->branches[i],res);
1320    }
1321  } else {
1322    DataNoroCacheNode<number_type>* dn=(DataNoroCacheNode<number_type>*) node;
1323    if (dn->value_len==backLinkCode){
1324      res.push_back(dn);
1325    } 
1326  }
1327}
1328
1329template<class number_type> DataNoroCacheNode<number_type>* NoroCache<number_type>::getCacheReference(poly term){
1330  int i;
1331  NoroCacheNode* parent=&root;
1332  for(i=1;i<pVariables;i++){
1333    parent=parent->getBranch(p_GetExp(term,i,currRing));
1334    if (!(parent)){
1335      return NULL;
1336    }
1337  }
1338  DataNoroCacheNode<number_type>* res_holder=(DataNoroCacheNode<number_type>*) parent->getBranch(p_GetExp(term,i,currRing));
1339  return res_holder;
1340}
1341template<class number_type> poly NoroCache<number_type>::lookup(poly term, BOOLEAN& succ, int & len){
1342  int i;
1343  NoroCacheNode* parent=&root;
1344  for(i=1;i<pVariables;i++){
1345    parent=parent->getBranch(p_GetExp(term,i,currRing));
1346    if (!(parent)){
1347      succ=FALSE;
1348      return NULL;
1349    }
1350  }
1351  DataNoroCacheNode<number_type>* res_holder=(DataNoroCacheNode<number_type>*) parent->getBranch(p_GetExp(term,i,currRing));
1352  if (res_holder){
1353    succ=TRUE;
1354    if ((res_holder->value_len==backLinkCode)){
1355      len=1;
1356      return term;
1357    }
1358    len=res_holder->value_len;
1359    return res_holder->value_poly;
1360  } else {
1361    succ=FALSE;
1362    return NULL;
1363  }
1364}
1365#endif
1366
1367#endif
Note: See TracBrowser for help on using the repository browser.