1 // -*- mode: C++ ; compile-command: "g++ -I.. -g -O2 -c index.cc" -*-
2 /*
3  *  Copyright (C) 2000,2014 B. Parisse, Institut Fourier, 38402 St Martin d'Heres
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 3 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18 #ifndef _GIAC_INDEX_H_
19 #define _GIAC_INDEX_H_
20 #include "first.h"
21 #include "vector.h"
22 #include <iostream>
23 #include <string>
24 #include <cassert>
25 
26 //////////////////////////////////////////
27 /// this commented and the old put back due to build issues... temporary change to get build going
28 //#if defined(VISUALC) && !defined(ConnectivityKit)
29 //#pragma anon_unions
30 //#endif
31 //========================================
32 #if !defined ConnectivityKit && !defined _MSC_VER && !defined FREERTOS
33 #pragma anon_unions
34 #endif
35 ///////////////////////////////////////////
36 
37 #if defined C11_UNORDERED_MAP && (defined __clang__ || !defined __APPLE__)
38 #undef HASH_MAP
39 #undef EXT_HASH_MAP
40 #undef UNORDERED_MAP
41 #define HASH_MAP_NAMESPACE std
42 #define hash_map unordered_map
43 #include <unordered_map>
44 #endif
45 
46 #if defined UNORDERED_MAP  && !defined(VISUALC) // && !defined(__APPLE__) && !defined(__clang__)
47 #include <tr1/unordered_map>
48 #define HASH_MAP_NAMESPACE std::tr1
49 #define hash_map unordered_map
50 #else // UNORDERED_MAP
51 
52 #if defined(VISUALC) || defined(FIR) || defined(__ANDROID__) // || defined(OSX) || defined(IOS))
53 #undef HASH_MAP
54 #undef EXT_HASH_MAP
55 #endif
56 
57 #ifdef HASH_MAP
58 #include <hash_map>
59 #ifndef HASH_MAP_NAMESPACE
60 #ifndef VISUALC
61 #define HASH_MAP_NAMESPACE std
62 #endif // VISUALC
63 #endif // HASH_MAP_NAMESPACE
64 #endif
65 
66 #ifdef EXT_HASH_MAP
67 #include <ext/hash_map>
68 #ifndef HASH_MAP_NAMESPACE
69 #define HASH_MAP_NAMESPACE __gnu_cxx
70 #endif
71 #endif
72 
73 #endif // UNORDERED_MAP
74 
75 #ifndef NO_NAMESPACE_GIAC
76 namespace giac {
77 #endif // ndef NO_NAMESPACE_GIAC
78 
79   typedef short int deg_t;
80   typedef std::vector<deg_t> index_t;
81 
82   int mygcd(int a,int b);
83   void swapint(int & a,int & b);
84   void swapdouble(double & a,double & b);
85 
86   // index type for tensors
87   void add(const index_t & a, const index_t & b,index_t & res);
88 
89   index_t operator + (const index_t & a, const index_t & b);
90   index_t operator - (const index_t & a, const index_t & b);
91   index_t operator | (const index_t & a, const index_t & b);
92   index_t operator - (const index_t & a);
93   index_t operator * (const index_t & a, int fois);
94   inline index_t operator * (int fois,const index_t & a){ return a*fois; }
95   index_t operator / (const index_t & a, int divisepar);
96   int operator / (const index_t & a, const index_t & b);
97   // >= and <= are *partial* ordering on index_t
98   // they return TRUE if and only if >= or <= is true for *all* coordinates
99   bool all_sup_equal (const index_t & a, const index_t & b);
100   inline bool operator >= (const index_t & a, const index_t & b){ return all_sup_equal(a,b); }
101   bool all_inf_equal (const index_t & a, const index_t & b);
102   inline bool operator <= (const index_t & a, const index_t & b){ return all_inf_equal(a,b); }
103   void index_gcd(const index_t & a,const index_t & b,index_t & res);
104   index_t index_gcd(const index_t & a,const index_t & b);
105   index_t index_lcm(const index_t & a,const index_t & b);
index_min(const index_t & a,const index_t & b)106   inline index_t index_min(const index_t & a,const index_t & b){ return index_gcd(a,b); }
index_max(const index_t & a,const index_t & b)107   inline index_t index_max(const index_t & a,const index_t & b){ return index_lcm(a,b); }
108   void dbgprint(const index_t & i);
109   void add_print_INT_(std::string & s,int i);
110   std::string print_INT_(int i);
111   std::string hexa_print_INT_(int i);
112   std::string octal_print_INT_(int i);
113   std::string binary_print_INT_(int i);
114   std::string print_INT_(const std::vector<int> & v);
115   std::string print_INT_(const std::vector<short int> & v);
116 
117   template <class T> T pow(const std::vector<T> & x, const index_t & n );
118 
119   // total degree of a std::vector
120   template <class T> T total_degree(const std::vector<T> & v1);
121 
122   // two ordering function over indices: lex ordering and total order then lex
123   template <class T>
124   bool lex_is_greater(const std::vector<T> & v1, const std::vector<T> & v2);
125   template <class T>
126   bool total_revlex_is_greater(const std::vector<T> & v1, const std::vector<T> & v2);
127   template <class T>
128   bool total_lex_is_greater(const std::vector<T> & v1, const std::vector<T> & v2);
129 
130   index_t mergeindex(const index_t & i,const index_t & j);
131   // permutation inverse
132   std::vector<int> inverse(const std::vector<int> & p);
133   // transposition
134   std::vector<int> transposition(int i,int j,int size);
135   bool has(const index_t & p,int r);
136   // zero?
137   bool is_zero(const index_t & p);
138 
pow(const std::vector<T> & x,const index_t & n)139   template <class T> T pow(const std::vector<T> & x, const index_t & n ){
140     assert(x.size()==n.size());
141     typename std::vector<T>::const_iterator itx=x.begin();
142     index_t::const_iterator itn=n.begin();
143     T res(1);
144     for (;itx!=x.end();++itx,++itn){
145       res=res*pow(*itx,*itn);
146     }
147     return res;
148   }
149 
total_degree(const std::vector<T> & v1)150   template <class T> T total_degree(const std::vector<T> & v1){
151     T i=0;
152     for (typename std::vector<T>::const_iterator it=v1.begin();it!=v1.end();++it)
153       i=i+(*it);
154     return(i);
155   }
156 
157   template <class T>
lex_is_greater(const std::vector<T> & v1,const std::vector<T> & v2)158   bool lex_is_greater(const std::vector<T> & v1, const std::vector<T> & v2){
159     assert(v1.size()==v2.size());
160     typename std::vector<T>::const_iterator it1=v1.begin(),it1end=v1.end();
161     typename std::vector<T>::const_iterator it2=v2.begin();
162     for (;it1!=it1end;++it2,++it1){
163       if ( (*it1)!=(*it2) ){
164 	if  ( (*it1)>(*it2))
165 	  return(true);
166 	else
167 	  return(false);
168       }
169     }
170     return(true);
171   }
172 
173   template <class T>
lex_is_strictly_greater(const std::vector<T> & v1,const std::vector<T> & v2)174   bool lex_is_strictly_greater(const std::vector<T> & v1, const std::vector<T> & v2){
175     assert(v1.size()==v2.size());
176     typename std::vector<T>::const_iterator it1=v1.begin(),it1end=v1.end();
177     typename std::vector<T>::const_iterator it2=v2.begin();
178     for (;it1!=it1end;++it2,++it1){
179       if ( (*it1)!=(*it2) ){
180 	if  ( (*it1)>(*it2))
181 	  return true;
182 	else
183 	  return false;
184       }
185     }
186     return false;
187   }
188 
189   bool lex_is_strictly_greater_deg_t(const std::vector<deg_t> & v1, const std::vector<deg_t> & v2);
190 
191   template <class T>
total_lex_is_greater(const std::vector<T> & v1,const std::vector<T> & v2)192   bool total_lex_is_greater(const std::vector<T> & v1, const std::vector<T> & v2){
193     T d1=total_degree(v1);
194     T d2=total_degree(v2);
195     if (d1!=d2){
196       if (d1>d2)
197 	return(true);
198       else
199 	return(false);
200     }
201     return(lex_is_greater<T>(v1,v2));
202   }
203 
204   template <class T>
total_revlex_is_greater(const std::vector<T> & v1,const std::vector<T> & v2)205   bool total_revlex_is_greater(const std::vector<T> & v1, const std::vector<T> & v2){
206     T d1=total_degree(v1);
207     T d2=total_degree(v2);
208     if (d1!=d2){
209       if (d1>d2)
210 	return(true);
211       else
212 	return(false);
213     }
214     // return(!lex_is_strictly_greater<T>(v1,v2)); but starting from end
215     typename std::vector<T>::const_iterator it1=v1.end()-1,it1end=v1.begin()-1;
216     typename std::vector<T>::const_iterator it2=v2.end()-1;
217     for (;it1!=it1end;--it2,--it1){
218       if ( *it1 != *it2 )
219 	return *it1<*it2;
220     }
221     return true;
222   }
223 
224   template <class T>
total_revlex_is_strictly_greater(const std::vector<T> & v1,const std::vector<T> & v2)225   bool total_revlex_is_strictly_greater(const std::vector<T> & v1, const std::vector<T> & v2){
226     return !total_revlex_is_greater<T>(v2,v1);
227   }
228 
229   //*****************************************
230   // class for memory efficient indices
231   //*****************************************
232 
233   class ref_index_t {
234   public:
235     ref_count_t ref_count;
236     index_t i;
ref_index_t()237     ref_index_t():ref_count(1) {}
ref_index_t(int s)238     ref_index_t(int s):ref_count(1),i(s) {}
ref_index_t(const index_t & I)239     ref_index_t(const index_t & I):ref_count(1),i(I) {}
ref_index_t(index_t::const_iterator it,index_t::const_iterator itend)240     ref_index_t(index_t::const_iterator it,index_t::const_iterator itend):ref_count(1),i(it,itend) {}
241   };
242 
243   // direct access to deg_t in index_m
244   const int POLY_VARS_DIRECT=sizeof(ref_index_t *)/sizeof(deg_t);
245   // HAS_POLY_VARS_OTHER defines the number of word (pointer size) for
246   // other deg_t directly encoded. Comment if none
247 #define HAS_POLY_VARS_OTHER 1
248 #if HAS_POLY_VARS_OTHER
249   const int POLY_VARS_OTHER=HAS_POLY_VARS_OTHER*POLY_VARS_DIRECT;
250 #else
251   const int POLY_VARS_OTHER=0;
252 #endif
253   // capacity of deg_t by direct addressing
254   const int POLY_VARS=POLY_VARS_DIRECT+POLY_VARS_OTHER-1;
255 
256 #if defined(GIAC_NO_OPTIMIZATIONS) || ((defined(VISUALC) || defined(__APPLE__)) && !defined(GIAC_VECTOR)) || defined __clang__ || defined S390X // || defined(NSPIRE) || defined FXCG
257   class index_m {
258   public:
259     ref_index_t * riptr;
260     // construct
index_m(const index_m & im)261     index_m(const index_m & im) {
262       riptr=im.riptr;
263       ++riptr->ref_count;
264     }
index_m(const index_t & i)265     index_m(const index_t & i){
266       riptr=new ref_index_t(i);
267     }
index_m()268     index_m(){ riptr=new ref_index_t; }
index_m(size_t s)269     index_m(size_t s){
270       riptr=new ref_index_t(s);
271     }
index_m(index_t::const_iterator it,index_t::const_iterator itend)272     index_m(index_t::const_iterator it,index_t::const_iterator itend){
273       riptr=new ref_index_t(it,itend);
274     }
275     // delete
~index_m()276     ~index_m(){
277       --riptr->ref_count;
278       if (!riptr->ref_count)
279 	delete riptr;
280     }
281     // copy
282     const index_m & operator = (const index_m & other){
283       --riptr->ref_count;
284       if (!riptr->ref_count)
285 	delete riptr;
286       riptr=other.riptr;
287       ++riptr->ref_count;
288       return *this;
289     }
290 
291     // members
iref()292     index_t iref() const { return riptr->i;} ;
begin()293     index_t::iterator begin() { return riptr->i.begin(); }
end()294     index_t::iterator end() { return riptr->i.end(); }
begin()295     index_t::const_iterator begin() const { return riptr->i.begin(); }
end()296     index_t::const_iterator end() const { return riptr->i.end(); }
297 #if !defined(NSPIRE) && !defined(FXCG) && !defined(OSX) && !defined(IOS) && !defined(OSXIOS)
rbegin()298     index_t::reverse_iterator rbegin() { return riptr->i.rbegin(); }
rend()299     index_t::reverse_iterator rend() { return riptr->i.rend(); }
rbegin()300     index_t::const_reverse_iterator rbegin() const { return riptr->i.rbegin(); }
rend()301     index_t::const_reverse_iterator rend() const { return riptr->i.rend(); }
302 #endif
front()303     deg_t & front() { return *begin(); }
front()304     deg_t front() const { return *begin(); }
back()305     deg_t & back() { return *(end()-1); }
back()306     deg_t back() const { return *(end()-1); }
307     deg_t & operator [] (size_t pos) { return *(begin()+pos); }
308     deg_t operator [] (size_t pos) const { return *(begin()+pos); }
clear()309     void clear() { riptr->i.clear(); }
reserve(size_t n)310     void reserve(size_t n) { riptr->i.reserve(n); }
push_back(deg_t x)311     void push_back(deg_t x) { riptr->i.push_back(x); }
size()312     size_t size() const { return riptr->i.size(); }
313     bool is_zero() const ;
314     size_t total_degree() const ;
315 #ifdef KHICAS
316     friend stdostream & operator << (stdostream & os,const index_m & m ){
317       os << ":index_m:[ " ;
318       for (index_t::const_iterator it=m.begin();it!=m.end();++it)
319 	os << *it << " ";
320       os << "] " ;
321       return(os);
322     }
323 #endif
324 #ifdef NSPIRE
325     template<class T> friend nio::ios_base<T> & operator << (nio::ios_base<T> & os,const index_m & m ){
326       os << ":index_m:[ " ;
327       for (index_t::const_iterator it=m.begin();it!=m.end();++it)
328 	os << *it << " ";
329       os << "] " ;
330       return(os);
331     }
332 #else
333     friend std::ostream & operator << (std::ostream & os, const index_m & m ){
334       os << ":index_m:[ " ;
335       for (index_t::const_iterator it=m.begin();it!=m.end();++it)
336 	os << *it << " ";
337       os << "] " ;
338       return(os);
339     }
340 #endif
dbgprint()341     void dbgprint() const {
342       COUT << *this << '\n';
343     }
344     // set first index element to 0
set_first_zero()345     index_m set_first_zero() const { index_t i(riptr->i); i[0]=0; return i; }
346   };
347 
348 #else // VISUALC
349   class index_m {
350   public:
351     union {
352       ref_index_t * riptr;
353       struct {
354 	deg_t taille;
355 	deg_t direct[POLY_VARS_DIRECT-1];
356       };
357     };
358 #ifdef HAS_POLY_VARS_OTHER
359     deg_t other[POLY_VARS_OTHER];
360 #endif
361     // construct
index_m(const index_m & im)362     index_m(const index_m & im) {
363       if ( im.taille % 2){
364 	* (size_t *) & taille = * (size_t *) &im.taille;
365 #if (HAS_POLY_VARS_OTHER==1)
366 	* (size_t *) other = * (size_t *) im.other;
367 #endif
368 #if (HAS_POLY_VARS_OTHER==2)
369 	* (size_t *) other = * (size_t *) im.other;
370 	* (((size_t *) other)+1) = * (((size_t *) im.other)+1);
371 #endif
372 #if (HAS_POLY_VARS_OTHER>2)
373 	size_t * target = (size_t *) other, * end = target + POLY_VARS_OTHER/(sizeof(size_t)/sizeof(deg_t));
374 	const size_t * source = (size_t *) im.other;
375 	for (;target!=end;++target,++source)
376 	  *target=*source;
377 #endif
378       } else {
379 	riptr=im.riptr;
380 	++riptr->ref_count;
381       }
382     }
index_m(const index_t & i)383     index_m(const index_t & i){
384       int s=int(i.size());
385       if (s<=POLY_VARS){
386 	taille=2*s+1;
387 	deg_t * target=direct,*end=direct+s;
388 	index_t::const_iterator source=i.begin();
389 	for (;target!=end;++source,++target){
390 	  *target=*source;
391 	}
392       }
393       else {
394 	// taille = 0;
395 	riptr=new ref_index_t(i);
396       }
397     }
index_m()398     index_m(){ taille =1; }
index_m(size_t s)399     index_m(size_t s){
400       if (int(s)<=POLY_VARS){
401 	riptr=0;
402 	taille=2*int(s)+1;
403 #if (HAS_POLY_VARS_OTHER==1)
404 	* (size_t *) other =0;
405 #endif
406 #if (HAS_POLY_VARS_OTHER==2)
407 	* (size_t *) other =0;
408 	* (((size_t *) other)+1) =0;
409 #endif
410 #if (HAS_POLY_VARS_OTHER>2)
411 	size_t * target = (size_t *) other ;
412 	size_t * end = target + POLY_VARS_OTHER/(sizeof(size_t)/sizeof(deg_t));
413 	for (;target!=end;++target)
414 	  *target = 0;
415 #endif
416       }
417       else {
418 	// taille=0;
419 	riptr=new ref_index_t(int(s));
420       }
421     }
index_m(index_t::const_iterator it,index_t::const_iterator itend)422     index_m(index_t::const_iterator it,index_t::const_iterator itend){
423       if (itend-it<=POLY_VARS){
424 	taille=2*int(itend-it)+1;
425 	deg_t * target = direct;
426 	for (;it!=itend;++it,++target){
427 	  *target=*it;
428 	}
429       }
430       else {
431 	// taille=0;
432 	riptr=new ref_index_t(it,itend);
433       }
434     }
435     // ptr[0] must be 2*size+1
index_m(deg_t * ptr)436     index_m(deg_t * ptr){
437       /*
438 #ifdef DEBUG_SUPPORT
439       if (ptr[0]/2>POLY_VARS)
440 	setsizeerr("Error index.h, size too large for direct access");
441 #endif
442       */
443       size_t * source = (size_t *) ptr;
444       *(size_t *) &taille = *(size_t *) source;
445 #if (HAS_POLY_VARS_OTHER==1)
446       ++source;
447       * (size_t *) other = *source;
448 #endif
449 #if (HAS_POLY_VARS_OTHER==2)
450       ++source;
451       * (size_t *) other = *source;
452       ++source;
453       * (((size_t *) other)+1) = *source;
454 #endif
455 #if (HAS_POLY_VARS_OTHER>2)
456       size_t * target = (size_t *) other ;
457       size_t * end = target + POLY_VARS_OTHER/(sizeof(size_t)/sizeof(deg_t));
458       for (++source;target!=end;++source,++target)
459 	*target = *source;
460 #endif
461     }
462     // delete
~index_m()463     ~index_m(){
464       if ( (taille % 2) == 0){
465 	--riptr->ref_count;
466 	if (!riptr->ref_count)
467 	  delete riptr;
468       }
469     }
470     // copy
471     const index_m & operator = (const index_m & other){
472       if ( (taille % 2) == 0){
473 	--riptr->ref_count;
474 	if (!riptr->ref_count)
475 	  delete riptr;
476       }
477       if ( (other.taille % 2) == 0){
478 	riptr=other.riptr;
479 	++riptr->ref_count;
480       }
481       else {
482 	* (size_t *) &taille = * (size_t *) &other.taille;
483 #if (HAS_POLY_VARS_OTHER==1)
484 	* (size_t *) this->other = * (size_t *) other.other;
485 #endif
486 #if (HAS_POLY_VARS_OTHER==2)
487 	* (size_t *) this->other = * (size_t *) other.other;
488 	* (((size_t *) this->other)+1) = * (((size_t *) other.other)+1);
489 #endif
490 #if (HAS_POLY_VARS_OTHER>2)
491 	const size_t * source = (size_t * ) other.other;
492 	size_t * target = (size_t *) this->other;
493 	size_t * end = target + POLY_VARS_OTHER/(sizeof(size_t)/sizeof(deg_t));
494 	for (;target!=end;++source,++target)
495 	  * target = * source;
496 #endif
497       }
498       return *this;
499     }
500 
501     // members
502     index_t iref() const ;
503     index_t::iterator begin() ;
504     index_t::iterator end() ;
505     index_t::const_iterator begin() const;
506     index_t::const_iterator end() const;
front()507     deg_t & front() { return *begin(); }
front()508     deg_t front() const { return *begin(); }
back()509     deg_t & back() { return *(end()-1); }
back()510     deg_t back() const { return *(end()-1); }
511     deg_t & operator [] (size_t pos) { return *(begin()+pos); }
512     deg_t operator [] (size_t pos) const { return *(begin()+pos); }
513     void clear() ;
514     void reserve(size_t n);
515     void push_back(deg_t x);
516     size_t size() const ;
517     bool is_zero() const ;
518     size_t total_degree() const ;
519 #ifdef KHICAS
520     friend stdostream & operator << (stdostream & os,const index_m & m ){
521       os << ":index_m:[ " ;
522       for (index_t::const_iterator it=m.begin();it!=m.end();++it)
523 	os << *it << " ";
524       os << "] " ;
525       return(os);
526     }
527 #endif
528 #ifdef NSPIRE
529     template<class T> friend nio::ios_base<T> & operator << (nio::ios_base<T> & os,const index_m & m ){
530       os << ":index_m:[ " ;
531       for (index_t::const_iterator it=m.begin();it!=m.end();++it)
532 	os << *it << " ";
533       os << "] " ;
534       return(os);
535     }
536 #else
537     friend std::ostream & operator << (std::ostream & os, const index_m & m ){
538       os << ":index_m:[ " ;
539       for (index_t::const_iterator it=m.begin();it!=m.end();++it)
540 	os << *it << " ";
541       os << "] " ;
542       return(os);
543     }
544 #endif
dbgprint()545     void dbgprint() const {
546       COUT << *this << '\n';
547     }
548     // set first index element to 0
549     index_m set_first_zero() const;
550   };
551 #endif // VISUALC
552 
553 #ifdef HASH_MAP_NAMESPACE
index_hash_function(const index_t & v)554   inline size_t index_hash_function(const index_t & v){
555     index_t::const_iterator it=v.begin(),itend=v.end();
556     size_t res=0;
557     if (itend-it>16)
558       itend=it+16;
559     if (itend-it>8){
560       for (;it!=itend;++it)
561 	res = (res << 2) | *it;
562     }
563     else {
564       for (;it!=itend;++it)
565 	res = (res << 4) | *it;
566     }
567     return res;
568   }
569 
570   /*
571   inline size_t index_hash_function(const vector<int> & v){
572     vector<int>::const_iterator it=v.begin(),itend=v.end();
573     if (itend-it>16)
574       itend=it+16;
575     size_t res=0,decal=32/(itend-it);
576     for (;;){
577       --itend;
578       res = (res << decal) | *itend;
579       if (itend==it)
580 	return res;
581     }
582   }
583   */
584 
585   class hash_function_object {
586   public:
operator()587     size_t operator () (const index_t & v) const { return index_hash_function(v); }
hash_function_object()588     hash_function_object() {};
589   };
590 
591   typedef HASH_MAP_NAMESPACE::hash_map< index_t,index_m,hash_function_object > hash_index ;
592 
593   // extern std::vector<hash_index> global_hash_index;
594 
595 #endif
596 
597   void add(const index_m & a, const index_m & b,index_t & res);
598   bool equal(const index_m & a,const index_t &b);
599   index_m operator + (const index_m & a, const index_m & b);
600   index_m operator - (const index_m & a, const index_m & b);
601   index_m operator * (const index_m & a, int fois);
602   inline index_m operator * (int fois,const index_m & a){ return a*fois; }
603   index_m operator / (const index_m & a, int divisepar);
604   inline int operator / (const index_m & a,const index_m & b){ return a.iref() / b.iref();}
605   bool operator == (const index_m & i1, const index_m & i2);
606   bool operator != (const index_m & i1, const index_m & i2);
607   bool operator >= (const index_m & a, const index_m & b);
608   bool operator <= (const index_m & a, const index_m & b);
609   int sum_degree(const index_m & v1);
610   int sum_degree_from(const index_m & v1,int start);
total_degree(const index_m & v1)611   inline int total_degree(const index_m & v1){ return sum_degree(v1); }
612   bool i_lex_is_greater(const index_m & v1, const index_m & v2);
613   bool i_lex_is_strictly_greater(const index_m & v1, const index_m & v2);
614   bool i_total_revlex_is_greater(const index_m & v1, const index_m & v2);
615   bool i_total_revlex_is_strictly_greater(const index_m & v1, const index_m & v2);
616   bool i_total_lex_is_greater(const index_m & v1, const index_m & v2);
617   bool i_total_lex_is_strictly_greater(const index_m & v1, const index_m & v2);
618   bool i_16var_is_greater(const index_m & v1, const index_m & v2);
619   bool i_32var_is_greater(const index_m & v1, const index_m & v2);
620   bool i_64var_is_greater(const index_m & v1, const index_m & v2);
621   bool i_11var_is_greater(const index_m & v1, const index_m & v2);
622   bool i_7var_is_greater(const index_m & v1, const index_m & v2);
623   bool i_3var_is_greater(const index_m & v1, const index_m & v2);
624   bool i_nvar_is_greater(const index_m & v1, const index_m & v2,int n,bool sametdeg);
625   int nvar_total_degree(const index_m & v1,int n);
i_16var_is_strictly_greater(const index_m & v1,const index_m & v2)626   inline bool i_16var_is_strictly_greater(const index_m & v1, const index_m & v2){ return !i_16var_is_greater(v2,v1); }
i_32var_is_strictly_greater(const index_m & v1,const index_m & v2)627   inline bool i_32var_is_strictly_greater(const index_m & v1, const index_m & v2){ return !i_32var_is_greater(v2,v1); }
i_64var_is_strictly_greater(const index_m & v1,const index_m & v2)628   inline bool i_64var_is_strictly_greater(const index_m & v1, const index_m & v2){ return !i_64var_is_greater(v2,v1); }
i_11var_is_strictly_greater(const index_m & v1,const index_m & v2)629   inline bool i_11var_is_strictly_greater(const index_m & v1, const index_m & v2){ return !i_11var_is_greater(v2,v1); }
i_7var_is_strictly_greater(const index_m & v1,const index_m & v2)630   inline bool i_7var_is_strictly_greater(const index_m & v1, const index_m & v2){ return !i_7var_is_greater(v2,v1); }
i_3var_is_strictly_greater(const index_m & v1,const index_m & v2)631   inline bool i_3var_is_strictly_greater(const index_m & v1, const index_m & v2){ return !i_3var_is_greater(v2,v1); }
632 
pow(const std::vector<T> & x,const index_m & n)633   template <class T> T pow(const std::vector<T> & x, const index_m & n ){
634     assert(x.size()==n.size());
635     typename std::vector<T>::const_iterator itx=x.begin();
636     index_t::const_iterator itn=n.begin();
637     T res(1);
638     for (;itx!=x.end();++itx,++itn){
639       res=res*pow(*itx,*itn);
640     }
641     return res;
642   }
643 
644   void index_lcm(const index_m & a,const index_m & b,index_t & res);
645   bool disjoint(const index_m & a,const index_m & b);
646 
647 #ifndef NO_NAMESPACE_GIAC
648 } // namespace giac
649 #endif // ndef NO_NAMESPACE_GIAC
650 
651 #if 0 // def NSPIRE
652 namespace std {
653   inline bool operator > (const giac::index_t & a,const giac::index_t & b){
654     if (a.size()!=b.size())
655       return a.size()>b.size();
656     return !giac::all_inf_equal(a,b);
657   }
658   inline bool operator < (const giac::index_t & a,const giac::index_t & b){
659     if (a.size()!=b.size())
660       return a.size()<b.size();
661     return !giac::all_sup_equal(a,b);
662   }
663 }
664 #endif
665 
666 #endif // ndef _GIAC_INDEX_H_
667