1 // -*- mode:C++ ; compile-command: "g++ -I.. -g -c -DHAVE_CONFIG_H -DIN_GIAC gen.cc" -*-
2 /*
3  *  Copyright (C) 2001,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_GEN_H
19 #define _GIAC_GEN_H
20 #ifdef KHICAS
21 extern size_t stackptr;
22 #endif
23 
24 /* Warning: the size of a gen depend on the architecture and of compile-time flags
25    Define -DSMARTPTR64 on 64 bit CPU if the pointers allocated by new are 48 bits
26    this will make sizeof(gen)==8 instead of 16
27    Currently the address of pointers is obtained by using the reserved and val fields
28    (48 bits) and adding 00 for the most significant bits
29    On systems that use pointers above 0x00ffffffff it might be better to use a table
30    of most significants 32 bits addresses (refered by the reserved field)
31    and use the val field for offset.
32    Define -DDOUBLEVAL if you did not define SMARTPTR64 and want full double precision
33    (53 bit mantissa). Otherwise, the 8 less significant bits will be used for the type
34    field of a gen, i.e. 0x01 for a double, hence 45 bit mantissa will be used for doubles
35    Using full double precision increases sizeof(gen) to 12 on a 32 bits CPU
36    (and 16 on a 64 bits CPU)
37  */
38 
39 // FIXME: macros defined in config.h are not welcome in a public header!
40 #ifdef HAVE_CONFIG_H
41 #include "config.h"
42 #endif
43 #include "first.h"
44 
45 // #include <gmp.h>
46 #ifdef USE_GMP_REPLACEMENTS
47 #undef HAVE_GMPXX_H
48 #undef HAVE_LIBMPFR
49 #endif
50 #ifdef HAVE_GMPXX_H
51 #include <gmpxx.h>
52 #endif
53 #ifdef HAVE_LIBMPFR
54 #include <mpfr.h>
55 // #include <mpf2mpfr.h>
56 #endif
57 #ifdef HAVE_LIBMPFI
58 #include <mpfi.h>
59 #endif
60 #include <iostream>
61 #include <string>
62 #include "vector.h"
63 #include <map>
64 #include "dispatch.h"
65 #include "vecteur.h"
66 #include "fraction.h"
67 #include "poly.h"
68 #include "giacintl.h"
69 #include <complex>
70 #include <stdlib.h>
71 #ifdef STATIC_BUILTIN_LEXER_FUNCTIONS
72 #include "static.h"
73 #endif
74 
75 #ifndef NO_NAMESPACE_GIAC
76 namespace giac {
77 #endif // ndef NO_NAMESPACE_GIAC
78 
79   int sprint_int(char * s,int r);
80   void sprint_double(char * s,double d);
81 
82 #ifdef USE_GMP_REPLACEMENTS
83 #undef HAVE_GMPXX_H
84 #undef HAVE_LIBMPFR
85 #endif
86 
87   void my_mpz_gcd(mpz_t &z,const mpz_t & A,const mpz_t & B);
88 
89   class gen ;
90   // errors
91   void settypeerr(GIAC_CONTEXT0);
92   void setsizeerr(GIAC_CONTEXT0);
93   void setdimerr(GIAC_CONTEXT0);
94   void settypeerr(const std::string & s);
95   void setsizeerr(const std::string & s);
96   void setdimerr(const std::string & s);
97   void divisionby0err(const gen &,GIAC_CONTEXT0);
98   void cksignerr(const gen &,GIAC_CONTEXT0);
99   void invalidserieserr(const std::string &,GIAC_CONTEXT0);
100   void toofewargs(const std::string & s,GIAC_CONTEXT0);
101   void toomanyargs(const std::string & s,GIAC_CONTEXT0);
102   void maxordererr(GIAC_CONTEXT0);
103   void setstabilityerr(GIAC_CONTEXT0);
104 
105   gen undeferr(const std::string & s);
106   gen gentypeerr(GIAC_CONTEXT0);
107   void gentypeerr(gen & g,GIAC_CONTEXT);
108   gen gensizeerr(GIAC_CONTEXT0);
109   void gensizeerr(gen & g,GIAC_CONTEXT);
110   gen gendimerr(GIAC_CONTEXT0);
111   void gendimerr(gen & g,GIAC_CONTEXT);
112   gen gentypeerr(const std::string & s);
113   void gentypeerr(const char * ch,gen & g);
114   gen gensizeerr(const std::string & s);
115   void gensizeerr(const char * ch,gen & g);
116   gen gendimerr(const std::string & s);
117   void gensizeerr(const char * ch,gen & g);
118   gen gendivisionby0err(const gen &,GIAC_CONTEXT0);
119   gen gencksignerr(const gen &,GIAC_CONTEXT0);
120   gen geninvalidserieserr(const std::string &,GIAC_CONTEXT0);
121   gen gentoofewargs(const std::string & s,GIAC_CONTEXT0);
122   gen gentoomanyargs(const std::string & s,GIAC_CONTEXT0);
123   gen genmaxordererr(GIAC_CONTEXT0);
124   gen genstabilityerr(GIAC_CONTEXT0);
125 
126   // short integer arithmetic
127   int absint(int a);
128   double absdouble(double a);
129   int giacmin(int a,int b);
130   int giacmax(int a,int b);
131   int invmod(int n,int modulo);
132   unsigned invmod(unsigned a,int b);
133   int invmod(longlong a,int b);
134   longlong invmodll(longlong a,longlong b);
135 #ifdef INT128
136   int invmod(int128_t a,int b);
smod(int128_t r,int m)137   inline int smod(int128_t r,int m){
138     int R=r%m;
139     return smod(R,m);
140   }
141 #endif
142   int gcd(int a,int b);
smod_adjust(int r,int m)143   inline int smod_adjust(int r,int m){ // precondition -m<r<m
144     r += (unsigned(r)>>31)*m; // make positive
145     return r-(unsigned((m>>1)-r)>>31)*m;
146   }
147   int smod(int a,int b); // where b is assumed to be positive
148   int smod(longlong a,int b);
149   longlong smodll(longlong res,longlong m);
150   int simplify(int & a,int & b);
151 
152   struct ref_mpz_t {
153     volatile ref_count_t ref_count;
154     mpz_t z;
ref_mpz_tref_mpz_t155     ref_mpz_t():ref_count(1) {mpz_init(z);}
ref_mpz_tref_mpz_t156     ref_mpz_t(size_t nbits):ref_count(1) {mpz_init2(z,int(nbits));}
ref_mpz_tref_mpz_t157     ref_mpz_t(const mpz_t & Z): ref_count(1) { mpz_init_set(z,Z); }
~ref_mpz_tref_mpz_t158     ~ref_mpz_t() { mpz_clear(z); }
159   };
160   class identificateur;
161   struct ref_identificateur; // in identificateur.h
162   struct symbolic;
163   struct ref_symbolic; // in symbolic.h
164   class unary_function_eval;
165   struct unary_function_ptr;
166   typedef const unary_function_ptr *  const_unary_function_ptr_ptr;
167   typedef const unary_function_eval *  const_unary_function_eval_ptr;
168   struct ref_unary_function_ptr; // in unary.h
169   struct eqwdata;
170   struct ref_eqwdata ; // defined below after gen
171   struct ref_complex;
172   struct ref_algext;
173   struct ref_modulo;
174   // Graphic object
175   struct grob {
176     void (* grob_draw)(void);
177     int (* grob_handle) (int);
178     void * grob_data;
179   };
180   struct ref_grob {
181     volatile ref_count_t ref_count;
182     grob g;
ref_grobref_grob183     ref_grob(const grob & G):ref_count(1),g(G) {}
184   };
185   class gen_user;
186   struct ref_gen_user ; // user defined type
187   struct ref_string {
188     volatile ref_count_t ref_count;
189     std::string s;
ref_stringref_string190     ref_string(const std::string & S):ref_count(1),s(S) {}
191   };
192   template <class T> class tensor;
193 
194   typedef tensor<gen> polynome;
195   typedef std::vector< facteur< polynome > > factorization;
196 
197   template<class T> class Tref_tensor; // in poly.h
198   typedef Tref_tensor<gen> ref_polynome;
199   typedef Tfraction<gen> fraction;
200   template<class T> class Tref_fraction;
201   typedef Tref_fraction<gen> ref_fraction;
202 
203   struct ref_vecteur;
204   void delete_ref_vecteur(ref_vecteur * ptr);
205   ref_vecteur * new_ref_vecteur(const vecteur & v);
206   ref_symbolic * new_ref_symbolic(const symbolic & s);
207 
208   template<class T> class Tref_fraction; // in fraction.h
209   struct ref_void_pointer {
210     volatile ref_count_t ref_count;
211     void * p;
ref_void_pointerref_void_pointer212     ref_void_pointer(void * P):ref_count(1),p(P) {}
213   };
214 
215 
216   struct monome;
217   // sparse polynomials: uncomment one of the 2 next lines
218 #ifdef DEBUG_SUPPORT
219   typedef dbgprint_vector<monome> sparse_poly1; // debugging support
220 #else
221   typedef std::vector<monome> sparse_poly1; // no debug. support
222 #endif
223   struct ref_sparse_poly1;
224 
225   // arbitrary precision floats hierarchy (value or interval)
226   std::string printmpf_t(const mpf_t & inf);
227   class real_object {
228   public:
229 #ifdef HAVE_LIBMPFR
230     mpfr_t inf;
231 #else
232     mpf_t inf;
233 #endif
234     real_object(double d);
235 #ifdef HAVE_LIBMPFR
236     real_object(const mpfr_t & d);
237     real_object(const mpf_t & d);
238 #else
239     real_object(const mpf_t & d);
240 #endif
241     real_object(const gen & g);
242     real_object(const gen & g,unsigned int precision);
243     real_object() ;
244     virtual std::string print(GIAC_CONTEXT) const;
dbgprint()245     const char * dbgprint() const {
246       static std::string s;
247       s=this->print(0);
248 #if 0 // ndef NSPIRE
249       CERR << s << '\n';
250 #endif
251       return s.c_str();
252     }
~real_object()253     virtual ~real_object() {
254 #ifdef HAVE_LIBMPFR
255       mpfr_clear(inf);
256 #else
257       mpf_clear(inf);
258 #endif
259     }
260     virtual real_object & operator = (const real_object & g);
261     real_object (const real_object & g) ;
262     virtual gen addition (const gen & g,GIAC_CONTEXT) const;
263     gen operator + (const gen & g) const;
264     virtual gen operator + (const real_object & g) const;
265     virtual gen multiply (const gen & g,GIAC_CONTEXT) const;
266     gen operator * (const gen & g) const;
267     virtual gen operator * (const real_object & g) const;
268     virtual gen divide (const gen & g,GIAC_CONTEXT) const;
269     gen operator / (const gen & g) const;
270     virtual gen substract (const gen & g,GIAC_CONTEXT) const;
271     virtual gen operator / (const real_object & g) const;
272     gen operator - (const gen & g) const;
273     virtual gen operator - (const real_object & g) const;
274     virtual gen operator -() const;
275     virtual gen inv() const;
276     virtual gen sqrt() const;
277     virtual gen abs() const;
278     virtual gen exp() const;
279     virtual gen log() const;
280     virtual gen sin() const;
281     virtual gen cos() const;
282     virtual gen tan() const;
283     virtual gen sinh() const;
284     virtual gen cosh() const;
285     virtual gen tanh() const;
286     virtual gen asin() const;
287     virtual gen acos() const;
288     virtual gen atan() const;
289     virtual gen asinh() const;
290     virtual gen acosh() const;
291     virtual gen atanh() const;
292     virtual bool is_zero() const;
293     virtual bool maybe_zero() const;
294     virtual bool is_inf() const;
295     virtual bool is_nan() const;
296     virtual int is_positive() const;
297     virtual double evalf_double() const;
298   };
299   struct ref_real_object {
300     volatile ref_count_t ref_count;
301     real_object r;
ref_real_objectref_real_object302     ref_real_object():ref_count(1) {}
ref_real_objectref_real_object303     ref_real_object(const real_object & R):ref_count(1),r(R) {}
304   };
305   gen real2int(const gen & g,GIAC_CONTEXT);
306   gen real2double(const gen & g);
307   class real_interval : public real_object {
308   public:
309 #ifdef HAVE_LIBMPFI
310     mpfi_t infsup;
311 #else
312 #ifdef HAVE_LIBMPFR
313     mpfr_t sup;
314 #else
315     mpf_t sup;
316 #endif
317 #endif
real_interval()318     real_interval(){
319 #ifdef HAVE_LIBMPFI
320       mpfi_init_set_fr(infsup,inf);
321 #else
322 #ifdef HAVE_LIBMPFR
323       mpfr_init_set(sup,inf,GMP_RNDN);
324 #else
325       mpf_init_set(sup,inf);
326 #endif
327 #endif
328     }
329 #ifdef HAVE_LIBMPFI
330     real_interval(const mpfi_t & interv);
331 #endif
real_interval(const real_object & r)332     real_interval(const real_object & r):real_object(r) {
333 #ifdef HAVE_LIBMPFI
334       mpfi_init2(infsup,mpfr_get_prec(r.inf));
335       mpfi_set_fr(infsup,r.inf);
336 #else
337 #ifdef HAVE_LIBMPFR
338       mpfr_init_set(sup,r.inf,GMP_RNDN);
339 #else
340       mpf_init_set(sup,r.inf);
341 #endif
342 #endif
343     }
real_interval(const real_interval & r)344     real_interval(const real_interval & r):real_object(r) {
345 #ifdef HAVE_LIBMPFI
346       mpfi_init2(infsup,mpfi_get_prec(r.infsup));
347       mpfi_set(infsup,r.infsup);
348 #else
349 #ifdef HAVE_LIBMPFR
350       mpfr_init_set(sup,r.sup,GMP_RNDN);
351 #else
352       mpf_init_set(sup,r.sup);
353 #endif
354 #endif
355     }
~real_interval()356     virtual ~real_interval() {
357 #ifdef HAVE_LIBMPFI
358       mpfi_clear(infsup);
359 #else
360 #ifdef HAVE_LIBMPFR
361       mpfr_clear(sup);
362 #else
363       mpf_clear(sup);
364 #endif
365 #endif
366     }
367     virtual real_object & operator = (const real_interval & g) ;
368     virtual real_object & operator = (const real_object & g) ;
369     virtual gen addition (const gen & g,GIAC_CONTEXT) const;
370     virtual gen operator + (const real_object & g) const;
371     virtual real_interval operator + (const real_interval & g) const;
372     virtual gen multiply (const gen & g,GIAC_CONTEXT) const;
373     virtual gen operator * (const real_object & g) const;
374     virtual real_interval operator * (const real_interval & g) const;
375     virtual gen divide (const gen & g,GIAC_CONTEXT) const;
376     virtual gen substract (const gen & g,GIAC_CONTEXT) const;
377     virtual gen operator - (const real_object & g) const;
378     virtual real_interval operator - (const real_interval & g) const ;
379     virtual gen operator -() const;
380     virtual bool is_zero () const ;
381     virtual bool maybe_zero () const ;
382     virtual int is_positive() const ;
383     virtual bool is_inf() const;
384     virtual bool is_nan() const;
385     virtual gen inv() const;
386     virtual gen sqrt() const;
387     virtual gen abs() const;
388     virtual gen exp() const;
389     virtual gen log() const;
390     virtual gen sin() const;
391     virtual gen cos() const;
392     virtual gen tan() const;
393     virtual gen sinh() const;
394     virtual gen cosh() const;
395     virtual gen tanh() const;
396     virtual gen asin() const;
397     virtual gen acos() const;
398     virtual gen atan() const;
399     virtual gen asinh() const;
400     virtual gen acosh() const;
401     virtual gen atanh() const;
402   };
403   struct ref_real_interval {
404     volatile ref_count_t ref_count;
405     real_interval r; // assumes that storage of real_object inside real_interval is first
ref_real_intervalref_real_interval406     ref_real_interval():ref_count(1) {}
ref_real_intervalref_real_interval407     ref_real_interval(const real_interval & R):ref_count(1),r(R) {}
408   };
409   std::string print_binary(const real_object & r);
410   gen read_binary(const std::string & s,unsigned int precision);
411   // Convert g to a real or complex object of precision nbits
412   gen accurate_evalf(const gen & g,int nbits);
413   vecteur accurate_evalf(const vecteur & v,int nbits);
414   std::string print_DOUBLE_(double d,GIAC_CONTEXT);
415 
416 #if 1 // def NSPIRE
417   class comparegen {
418   public:
419     bool operator () (const gen & a,const gen & b) const;
420   };
421   typedef std::map<gen,gen,comparegen> gen_map;
422 #else
423   typedef std::map<gen,gen,const std::pointer_to_binary_function < const gen &, const gen &, bool> > gen_map;
424 #endif
425   struct ref_gen_map;
426 
427   class my_mpz;
428 
429 #ifdef NO_UNARY_FUNCTION_COMPOSE
430   class unary_function_eval;
431 #else
432   class unary_function_abstract;
433 #endif
434 
435   struct alias_unary_function_eval;
436   struct unary_function_ptr {
437 #ifdef NO_UNARY_FUNCTION_COMPOSE
438     // const unary_function_eval * _ptr;
439     size_t _ptr;
440     // int quoted; // will be used to avoid evaluation of args by eval
441     // constructors
442     // lexer_register is true to add dynamically the function name
443     // to the list of functions names recognized by the lexer
unary_function_ptrunary_function_ptr444     unary_function_ptr():_ptr(0) {} ;
unary_function_ptrunary_function_ptr445     unary_function_ptr(const unary_function_eval * myptr):_ptr((size_t)myptr) {} ;
446     // unary_function_ptr(const unary_function_eval * myptr,int parser_token);
447     unary_function_ptr(const unary_function_eval * myptr,int myquoted,int parser_token);
448     // unary_function_ptr(const alias_unary_function_eval * myptr,int parser_token);
449     unary_function_ptr(const alias_unary_function_eval * myptr,int myquoted,int parser_token);
450 #else // NO_UNARY_FUNCTION_COMPOSE
451     const unary_function_abstract * _ptr;
452     // long * ref_count;
453     // int quoted; // will be used to avoid evaluation of args by eval
454     // constructors
455     // lexer_register is true to add dynamically the function name
456     // to the list of functions names recognized by the lexer
457     // unary_function_ptr(const unary_function_abstract & myptr);
458     unary_function_ptr():_ptr(0) {} ;
459     unary_function_ptr(const unary_function_abstract * myptr):_ptr(myptr) {} ;
460     // unary_function_ptr(const unary_function_abstract * myptr,int parser_token) ;
461     // unary_function_ptr(const unary_function_abstract & myptr,int myquoted,int parser_token=0);
462     unary_function_ptr(const unary_function_abstract * myptr,int myquoted,int parser_token);
463     // unary_function_ptr(const unary_function_ptr & myptr);
464     // unary_function_ptr(const alias_unary_function_eval * myptr,int parser_token);
465     unary_function_ptr(const alias_unary_function_eval * myptr,int myquoted,int parser_token);
466 #endif // NO_UNARY_FUNCTION_COMPOSE
467     // ~unary_function_ptr();
468     // unary_function_ptr & operator = (const unary_function_ptr & acopier);
469     gen operator () (const gen & arg,GIAC_CONTEXT) const;
470 #ifdef NO_UNARY_FUNCTION_COMPOSE
ptrunary_function_ptr471     inline unary_function_eval * ptr() const {
472       return (unary_function_eval *) (((size_t) _ptr) & ~(uintptr_t)3);
473 #ifdef x86_64
474       //return (unary_function_eval *) (((ulonglong ) _ptr) & 0xfffffffffffffffc);
475 #else
476       //return (unary_function_eval *) (((size_t) _ptr) & 0xfffffffc);
477 #endif
478     }
479 #else // NO_UNARY_FUNCTION_COMPOSE
ptrunary_function_ptr480     inline unary_function_abstract * ptr () const
481     {
482       return (unary_function_abstract *) (((ulonglong ) _ptr) & ~(uintptr_t)3);
483 #ifdef x86_64
484       return (unary_function_abstract *) (((ulonglong ) _ptr) & 0xfffffffffffffffc);
485 #else
486       return (unary_function_abstract *) (((size_t) _ptr) & 0xfffffffc);
487 #endif
488     }
489 #endif // NO_UNARY_FUNCTION_COMPOSE
490     bool quoted() const ;
491     inline bool operator ==(const unary_function_ptr & u) const {
492       // if (&u==this) return true;
493       return ((ulonglong)(_ptr) & ~(uintptr_t)3 )  == ((ulonglong)( u._ptr) & ~(uintptr_t)3 );
494 #ifdef x86_64
495       //return ((ulonglong)(_ptr) & 0xfffffffffffffffc)  == ((ulonglong)( u._ptr) & 0xfffffffffffffffc );
496 #else
497       //return ((size_t)(_ptr) & 0xfffffffc) == ((size_t)(u._ptr) & 0xfffffffc);
498 #endif
499     }
500     inline bool operator !=(const unary_function_ptr & u) const { return !(*this==u); }
501     inline bool operator ==(const unary_function_ptr * u) const {
502       // if (&u==this) return true;
503       return u && ( ((ulonglong)(_ptr) &  ~(uintptr_t)3 ) == ((ulonglong)(u->_ptr) &  ~(uintptr_t)3) );
504 #ifdef x86_64
505       //return u && ( ((ulonglong)(_ptr) & 0xfffffffffffffffc) == ((ulonglong)(u->_ptr) & 0xfffffffffffffffc) );
506 #else
507       //return u && ( ((size_t)(_ptr) & 0xfffffffc) == ((size_t)(u->_ptr) & 0xfffffffc ) );
508 #endif
509     }
510     inline bool operator !=(const unary_function_ptr * u) const { return !(*this==u); }
511     const char * dbgprint() const;
512   };
513 
514   void delete_ptr(signed char subtype,short int type_save,ref_mpz_t * ptr_save);
515   // FIXME: for little-endian check if type/unused/subtype order is correct!
516   class gen {
517   public:
518 #ifdef GIAC_TYPE_ON_8BITS
519     unsigned char type;  // see dispatch.h
520 #else
521     unsigned char type:5;  // 32 types is enough, keep 3 bits more for double
522     unsigned char type_unused:3;
523 #endif
524     signed char subtype;
525     unsigned short reserved; // used if SMARTPTR is defined on 64 bit CPU (16 bits for pointer val)
526     union {
527       // immediate types
528       int val; // immediate int (type _INT_)
529 #ifdef DOUBLEVAL
530       double _DOUBLE_val; // immediate float (type _DOUBLE_)
531       giac_float _FLOAT_val;
532 #endif
533 #ifndef SMARTPTR64
534       // pointer types
535       ref_mpz_t * __ZINTptr; // long int (type _ZINT)
536       ref_real_object * __REALptr; // extended double (type _REAL)
537       ref_complex * __CPLXptr ; // complex as an gen[2] array (type _CPLX)
538       ref_identificateur * __IDNTptr; // global name identifier (type _IDNT)
539       ref_symbolic * __SYMBptr; // for symbolic objects (type _SYMB)
540       ref_modulo * __MODptr;
541       ref_algext * __EXTptr; // 2 gens for alg. extension (type ext)
542       // alg ext: 1st gen is a std::vector or a fraction, 2nd gen is
543       // a/ a std::vector, the minimal monic polynomial (the roots are permutable)
544       // b/ a real_complex_rootof given by it's min poly and
545       // c/ another type meaning that the root is expressed in terms
546       //    of another rootof, in this case ext_reduce should be called
547       // For 2nd order extension, X^2=d is used if d!=1 mod 4
548       // X is the positive solution
549       // if d=1 mod 4 the equation is X^2-X=(d-1)/4
550       Tref_fraction<gen> * __FRACptr; // fraction (type _FRAC)
551       Tref_tensor<gen> * __POLYptr ; // multidim. sparse polynomials (type poly)
552       // _VECTosite types (std::vector<>)
553       ref_vecteur * __VECTptr ; // vecteur: std::vectors & dense_POLY1 (type _VECT)
554       ref_sparse_poly1 * __SPOL1ptr ; // std::vector<monome>: sparse 1-d poly (type _SPOL1)
555       ref_string * __STRNGptr;
556       size_t _FUNC_;
557       // ref_unary_function_ptr * __FUNCptr;
558       ref_gen_user * __USERptr;
559       ref_gen_map * __MAPptr;
560       ref_eqwdata * __EQWptr;
561       ref_grob * __GROBptr;
562       ref_void_pointer * __POINTERptr;
563 #endif
564     };
ref_count()565     inline volatile ref_count_t & ref_count() const {
566 #ifdef SMARTPTR64
567       return ((ref_mpz_t *) ((* (ulonglong *) (this))>>16))->ref_count;
568 #else
569       return __ZINTptr->ref_count;
570 #endif
571     }
572 #ifdef SMARTPTR64
gen()573     gen()  {
574       * ((ulonglong * ) this)=0;
575 #if defined COMPILE_FOR_STABILITY && !defined(POCKETCAS)
576       control_c();
577 #endif
578     };
579 #else
gen()580     gen(): type(_INT_),subtype(0),val(0) {
581 #if defined COMPILE_FOR_STABILITY && !defined(POCKETCAS)
582       control_c();
583 #endif
584     };
585 #endif
586 #ifdef SMARTPTR64
gen(void * ptr,short int subt)587     gen(void *ptr,short int subt)  {
588 #ifdef COMPILE_FOR_STABILITY
589       control_c();
590 #endif
591       ulonglong __POINTERptr = (ulonglong ) new ref_void_pointer(ptr);
592 #ifndef NO_STDEXCEPT
593       if (__POINTERptr & 0xffff000000000000)
594 	setsizeerr(gettext("Pointer out of range"));
595 #endif
596       * ((ulonglong *) this) = __POINTERptr << 16;
597       subtype=(signed char)subt;
598       type=_POINTER_;
599     };
600 #else
gen(void * ptr,short int subt)601     gen(void *ptr,short int subt): type(_POINTER_),subtype(char(subt)) {
602 #ifdef COMPILE_FOR_STABILITY
603       control_c();
604 #endif
605       __POINTERptr=new ref_void_pointer(ptr);
606     };
607 #endif
608 #ifdef SMARTPTR64
gen(int i)609     gen(int i) {
610       * ((ulonglong * ) this)=0;
611       val=i;
612 #ifdef COMPILE_FOR_STABILITY
613       control_c();
614 #endif
615     };
gen(size_t i)616     gen(size_t i) {
617       * ((ulonglong * ) this)=0;
618       val=int(i);
619 #ifdef COMPILE_FOR_STABILITY
620       control_c();
621 #endif
622     };
623 #else
gen(int i)624     gen(int i): type(_INT_),subtype(0),val(i) {
625 #if defined COMPILE_FOR_STABILITY && !defined(POCKETCAS)
626       control_c();
627 #endif
628     };
gen(size_t i)629     gen(size_t i): type(_INT_),subtype(0),val((int)i)  {
630 #if defined COMPILE_FOR_STABILITY && !defined(POCKETCAS)
631       control_c();
632 #endif
633     };
634 #endif
635     gen(long i);
636     gen(longlong i);
637     gen(longlong i,int nbits);
638 #ifdef INT128
639     gen(int128_t i);
640 #endif
641     gen(const mpz_t & m);
642     // WARNING coerce *mptr to an int if possible, in this case delete mptr
643     // Pls do not use this constructor unless you know exactly what you do!!
644     gen(ref_mpz_t * mptr);
645 #ifdef DOUBLEVAL
gen(double d)646     gen(double d): type(_DOUBLE_),_DOUBLE_val(d) {};
647 #else
648     // may not work on ia64 with -O2
649     gen(double d);
650 #endif
651     gen(const giac_float & f);
652 #ifdef BCD
653     gen(accurate_bcd_float * b);
654 #endif
655     // inline
656     double DOUBLE_val() const ;
657     giac_float FLOAT_val() const ;
658     gen(int a,int b);
659     gen(double a,double b);
660     gen(const gen & a,const gen & b);
661     gen(const std::complex<double> & c);
662     gen(const gen & e);
663     gen (const identificateur & s);
664     gen (ref_identificateur * sptr);
665     gen (const vecteur & v,short int s=0);
666     gen (ref_vecteur * vptr,short int s=0);
667     // vptr must be a pointer allocated by new, do not delete it explicitly
668     gen (const symbolic & s);
669     gen (ref_symbolic * sptr);
670     gen (const gen_user & g);
671     gen (ref_gen_user * sptr);
672     gen (const real_object & g);
673     gen (const real_interval & g);
674     // Pls do not use this constructor unless you know exactly what you do
675     gen (Tref_tensor<gen> * pptr);
676     gen (const polynome & p);
677     gen (const fraction & p);
678     gen (const std::string & s,GIAC_CONTEXT);
679     gen (const wchar_t * s,GIAC_CONTEXT);
gen(const char * s,GIAC_CONTEXT)680     gen (const char * s,GIAC_CONTEXT){ type=0; *this=gen(std::string(s),contextptr); };
681     gen (const sparse_poly1 & p);
682     gen (const unary_function_ptr & f,int nargs=1);
683     gen (const unary_function_ptr * f,int nargs=1);
684     gen (const gen_map & m);
685     gen (const eqwdata & );
686     gen (const grob & );
687 #ifdef HAVE_GMPXX_H
688     gen (const mpz_class &);
689 #endif
690     gen (const my_mpz &);
691     void delete_gen();
~gen()692     ~gen(){
693       if ( type>_DOUBLE_ && type!=_FLOAT_
694 #if !defined SMARTPTR64 // || defined STATIC_BUILTIN_LEXER_FUNCTIONS
695 	   && type!=_FUNC
696 #endif
697 	   ){
698 	// optimization for ref_count access must be checked in multi-thread
699 	ref_count_t * rc=(ref_count_t *) & ref_count();
700 	if (*rc!=-1 && !--*rc){
701 	  delete_gen();
702 	}
703       }
704     }
705 
706     bool in_eval(int level,gen & evaled,const context * contextptr) const;
eval(int level,const context * contextptr)707     inline gen eval(int level,const context * contextptr) const{
708       // CERR << "eval " << *this << " " << level << '\n';
709       gen res;
710       // return in_eval(level,res,contextptr)?res:*this;
711       if (in_eval(level,res,contextptr))
712 	return res;
713       else
714       return *this;
715     }
716     // inline gen eval() const { return eval(DEFAULT_EVAL_LEVEL,context0); }
717     bool in_evalf(int level,gen & evaled,const context * contextptr) const;
718     gen evalf(int level,const context * contextptr) const;
719     // inline gen evalf() const { return evalf(DEFAULT_EVAL_LEVEL,context0); }
720     gen evalf_double(int level,const context * contextptr) const ;
721     gen evalf2double(int level,const context * contextptr) const;
722 #if defined SMARTPTR64
723     gen & operator = (const gen & a){
724       ulonglong al=*((ulonglong *) &a);
725       unsigned char atype=al&0x1f;
726       ulonglong tl=*((ulonglong *) this);
727       // Copy before deleting because the target might be embedded in a
728       // with a ptr_val.ref_count of a equals to 1
729       // short int type_save=type; // short int subtype_save=subtype;
730       * ((ulonglong *) this) = al;
731       if (atype>_DOUBLE_ && atype!=_FLOAT_
732 	  && (al >> 16)	){
733 	ref_count_t * rc=(ref_count_t *)& ((ref_mpz_t *)(al>>16) )->ref_count;
734 	if (*rc!=-1)
735 	  ++(*rc); // increase ref count
736       }
737       // Now we delete the target
738       if ( (tl &0x1f)>_DOUBLE_)
739 	delete_ptr( (signed char) ((tl&0xff00)>>8),(tl &0x1f),(ref_mpz_t *) (tl >> 16));
740       return *this;
741     }
742 
743 #else // SMARTPTR64
744     gen & operator = (const gen & a){
745       register unsigned t=(type << _DECALAGE) | a.type;
746       if (!t){
747 	subtype=a.subtype;
748 	val=a.val;
749 	return *this;
750       }
751       if (a.type>_DOUBLE_ && a.type!=_FLOAT_
752 	  && a.type!=_FUNC && a.__ZINTptr
753 	  ){
754 	ref_count_t * rc=(ref_count_t *)&a.ref_count();
755 	if (*rc!=-1)
756 	  ++(*rc); // increase ref count
757       }
758       // Copy before deleting because the target might be embedded in a
759       // with a ptr_val.ref_count of a equals to 1
760       short int type_save=type; // short int subtype_save=subtype;
761       ref_mpz_t * ptr_save = __ZINTptr;
762 #ifdef DOUBLEVAL
763       _DOUBLE_val = a._DOUBLE_val;
764       subtype=a.subtype;
765 #else
766       * ((ulonglong *) this) = *((ulonglong * ) &a);
767 #endif
768       __ZINTptr=a.__ZINTptr;
769       type=a.type;
770       // Now we delete the target
771       if ( type_save>_DOUBLE_ && type_save!=_FLOAT_
772 	   && type_save!=_FUNC
773 	   )
774 	delete_ptr(subtype,type_save,ptr_save);
775       return *this;
776     }
777 #endif // SMARTPTR64
778     int to_int() const ;
779     double to_double(const context * contextptr) const;
780     bool is_vector_of_size(size_t n) const;
781     bool is_identificateur_with_name(const char * s) const;
782     bool is_real(GIAC_CONTEXT) const ;
783     bool is_cinteger() const ;
784     bool is_integer() const ;
785     bool is_constant() const;
786     std::string print(GIAC_CONTEXT) const;
787     // inline const char * printcharptr(GIAC_CONTEXT) const { return print(contextptr).c_str(); };
788     // if sptr==0, return length required, otherwise print at end of *sptr
789     int sprint(std::string * sptr,GIAC_CONTEXT) const;
790     std::string print_universal(GIAC_CONTEXT) const;
791     std::string print() const;
792     //inline const char * printcharptr() const { return print().c_str(); };
793     wchar_t * wprint(GIAC_CONTEXT) const ;
794     // print then convert to a malloc-ated wchar_t *
modify(int i)795     void modify(int i) { *this =gen(i); };
796     const char * dbgprint() const;
797     void uncoerce(size_t s=128) ;
798     gen conj(GIAC_CONTEXT) const;
799     gen re(GIAC_CONTEXT) const ;
800     gen im(GIAC_CONTEXT) const ;
801     gen inverse(GIAC_CONTEXT) const;
802     gen squarenorm(GIAC_CONTEXT) const;
803     int bindigits() const ;
804     gen operator [] (int i) const ;
805     gen operator [] (const gen & i) const;
806     gen operator_at(int i,GIAC_CONTEXT) const;
807     gen operator_at(const gen & i,GIAC_CONTEXT) const;
808     // gen & operator [] (int i) ;
809     // gen & operator [] (const gen & i) ;
810     gen operator () (const gen & i,GIAC_CONTEXT) const;
811     gen operator () (const gen & i,const gen & progname,GIAC_CONTEXT) const;
812     bool islesscomplexthan(const gen & other) const;
813     bool is_approx() const ; // true if double/real or cmplx with re/im
814     int symb_size() const;
815     gen change_subtype(int newsubtype);
816     bool is_symb_of_sommet(const unary_function_ptr & u) const ;
817     bool is_symb_of_sommet(const unary_function_ptr * u) const ;
818     gen makegen(int i) const; // make a gen of same type as this with integer i
819     // For compatibility with older versions
820     inline mpz_t * ref_ZINTptr() const ;
821     inline real_object * ref_REALptr() const ;
822     inline gen * ref_CPLXptr() const ;
823     inline identificateur * ref_IDNTptr() const ;
824     inline symbolic * ref_SYMBptr() const ;
825     inline gen * ref_MODptr () const ;
826     inline Tfraction<gen> * ref_FRACptr() const ;
827     inline gen * ref_EXTptr () const ;
828     inline polynome * ref_POLYptr() const ;
829     inline vecteur * ref_VECTptr() const ;
830     inline sparse_poly1 * ref_SPOL1ptr() const ;
831     inline std::string * ref_STRNGptr() const ;
832     inline unary_function_ptr * ref_FUNCptr() const ;
833     inline gen_user * ref_USERptr() const ;
834     inline gen_map * ref_MAPptr() const ;
835     inline eqwdata * ref_EQWptr() const ;
836     inline grob * ref_GROBptr() const ;
837     inline void * ref_POINTER_val() const ;
838   };
839 
840   bool ref_mpz_t2gen(ref_mpz_t * mptr,gen & g); // return true if mptr used in g
841   gen change_subtype(const gen &g,int newsubtype);
842   gen genfromstring(const std::string & s);
843   // pointer to an int describing display mode for complex numbers
844   int * complex_display_ptr(const gen & g);
845   // value==0 to cartesian, 1 to polar, 2 toggle, 3 count complex
846   // returns the number of complex
847   int adjust_complex_display(gen & res,int value);
848 
849 #if defined(SMARTPTR64)
850   typedef ulonglong alias_gen;
851 #else
852   struct alias_gen {
853     unsigned char type;  // see dispatch.h
854     signed char subtype;
855     unsigned short reserved; // not used
856 #ifdef DOUBLEVAL
857     longlong value;
858 #else
859     long value ;
860 #endif
861   };
862 #endif
863 
864   class vectpoly:public std::vector<polynome> {
865   public:
vectpoly()866     vectpoly():std::vector<polynome>::vector() {};
vectpoly(size_t i,const polynome & p)867     vectpoly(size_t i,const polynome & p):std::vector<polynome>::vector(i,p) {};
dbgprint()868     const char * dbgprint(){
869 #if !defined(NSPIRE) && !defined(FXCG)
870       CERR << *this << '\n';
871 #endif
872       return "Done";
873     }
874   };
875 
876   struct ref_gen_map {
877     volatile ref_count_t ref_count;
878     gen_map m;
879 #if 1 // def NSPIRE
ref_gen_mapref_gen_map880     ref_gen_map(): ref_count(1),m() {}
881 #else
ref_gen_mapref_gen_map882     ref_gen_map(const std::pointer_to_binary_function < const gen &, const gen &, bool> & p): ref_count(1),m(p) {}
883 #endif
ref_gen_mapref_gen_map884     ref_gen_map(const gen_map & M):ref_count(1),m(M) {}
885   };
886 
887   struct alias_ref_fraction { ref_count_t ref_count; alias_gen num; alias_gen den; };
888   struct alias_ref_complex {
889     ref_count_t ref_count;
890     int display;
891     alias_gen re,im;
892   };
893 
894   struct ref_vecteur {
895     volatile ref_count_t ref_count;
896     vecteur v;
ref_vecteurref_vecteur897     ref_vecteur():ref_count(1) {}
ref_vecteurref_vecteur898     ref_vecteur(unsigned s):ref_count(1),v(s) {}
ref_vecteurref_vecteur899     ref_vecteur(unsigned s,const gen & g):ref_count(1),v(s,g) {}
ref_vecteurref_vecteur900     ref_vecteur(const_iterateur it,const_iterateur itend):ref_count(1),v(it,itend) {}
ref_vecteurref_vecteur901     ref_vecteur(const vecteur & w):ref_count(1),v(w) {}
902   };
903 
904 
905 #ifdef SMARTPTR64
906 #define define_alias_gen(name,type,subtype,ptr) alias_gen name={(ulonglong(ptr) << 16) | (subtype << 8) | type };
907 #define define_alias_ref_symbolic(name,sommet,type,subtype,ptr) alias_ref_symbolic name={-1,(unary_function_eval *)sommet,(ulonglong(ptr) << 16) | (subtype << 8) | type};
908 #define define_alias_ref_fraction(name,numtype,numsubtype,numptr,dentype,densubtype,denptr) alias_ref_fraction name={-1,{(ulonglong(numptr) << 16) | (numsubtype << 8) | numtype },{(ulonglong(denptr) << 16) | (densubtype << 8) | dentype }};
909 #define define_alias_ref_complex(name,retype,resubtype,reptr,imtype,imsubtype,imptr) alias_ref_complex name={-1,0,{(ulonglong(reptr) << 16) | (resubtype << 8) | retype },{(ulonglong(imptr) << 16) | (imsubtype << 8) | imtype }};
910 #define define_tab2_alias_gen(name,retype,resubtype,reptr,imtype,imsubtype,imptr) alias_gen name[]={{(ulonglong(reptr) << 16) | (resubtype << 8) | retype },{(ulonglong(imptr) << 16) | (imsubtype << 8) | imtype }};
911 #else // SMARTPTR64
912 #ifdef DOUBLEVAL
913 #define define_alias_gen(name,type,subtype,ptr) alias_gen name={type,subtype,0,ulonglong(ptr)};
914 #define define_alias_ref_symbolic(name,sommet,type,subtype,ptr) alias_ref_symbolic name={-1,(unary_function_eval *)sommet,type,subtype,0,ulonglong(ptr)};
915 #define define_alias_ref_fraction(name,numtype,numsubtype,numptr,dentype,densubtype,denptr) alias_ref_fraction name={-1,{numtype,numsubtype,0,ulonglong(numptr)},{dentype,densubtype,0,ulonglong(denptr)}};
916 #define define_alias_ref_complex(name,retype,resubtype,reptr,imtype,imsubtype,imptr) alias_ref_complex name={-1,0,{retype,resubtype,0,ulonglong(reptr)},{imtype,imsubtype,0,ulonglong(imptr)}};
917 #define define_tab2_alias_gen(name,retype,resubtype,reptr,imtype,imsubtype,imptr) alias_gen name[]={{retype,resubtype,0,ulonglong(reptr)},{imtype,imsubtype,0,ulonglong(imptr)}};
918 #else // DOUBLEVAL
919 #define define_alias_gen(name,type,subtype,ptr) alias_gen name={type,subtype,0,long(ptr)};
920 #define define_alias_ref_symbolic(name,sommet,type,subtype,ptr) alias_ref_symbolic name={-1,(unary_function_eval *)sommet,type,subtype,0,long(ptr)};
921 #define define_alias_ref_fraction(name,numtype,numsubtype,numptr,dentype,densubtype,denptr) alias_ref_fraction name={-1,{numtype,numsubtype,0,long(numptr)},{dentype,densubtype,0,long(denptr)}};
922 #define define_alias_ref_complex(name,retype,resubtype,reptr,imtype,imsubtype,imptr) alias_ref_complex name={-1,0,{retype,resubtype,0,long(reptr)},{imtype,imsubtype,0,long(imptr)}};
923 #define define_tab2_alias_gen(name,retype,resubtype,reptr,imtype,imsubtype,imptr) alias_gen name[]={{retype,resubtype,0,long(reptr)},{imtype,imsubtype,0,long(imptr)}};
924 #endif // DOUBLEVAL
925 #endif // SMARTPTR64
926 
927   // ? #ifdef __GNUC__
928 #ifdef IMMEDIATE_VECTOR
929   struct alias_ref_vecteur { ref_count_t ref_count; const int _taille; const alias_gen * begin_immediate_vect; const alias_gen * end_immediate_vect; void * ptr; };
930 #define define_alias_ref_vecteur(name,b) alias_ref_vecteur name={-1,sizeof(b)/sizeof(gen),(const alias_gen *)b,(const alias_gen *)b+sizeof(b)/sizeof(gen),0};
931 #define define_alias_ref_vecteur2(name,b) alias_ref_vecteur name={-1,2,&b[0],&b[2],0};
932 #else
933   struct alias_ref_vecteur { ref_count_t ref_count; const alias_gen * begin; const alias_gen * end; const alias_gen * finish; void * ptr; };
934 #define define_alias_ref_vecteur(name,b) alias_ref_vecteur name={-1,(const alias_gen *)b,(const alias_gen *)b+sizeof(b)/sizeof(gen),(const alias_gen *)b+sizeof(b)/sizeof(gen),0};
935 #define define_alias_ref_vecteur2(name,b) alias_ref_vecteur name={-1,&b[0],&b[2],&b[2],0};
936 #endif
937 
938   struct ref_complex {
939     volatile ref_count_t ref_count;
940     int display;
941     gen re,im;
ref_complexref_complex942     ref_complex(const std::complex<double> & c):ref_count(1),display(0),re(real(c)),im(imag(c)) {}
ref_complexref_complex943     ref_complex(const gen & R,const gen & I):ref_count(1),display(0),re(R),im(I) {}
ref_complexref_complex944     ref_complex(const gen & R,const gen & I,int display_mode):ref_count(1),display(display_mode),re(R),im(I) {}
945   };
946   struct ref_modulo {
947     volatile ref_count_t ref_count;
948     gen n,modulo;
ref_moduloref_modulo949     ref_modulo():ref_count(1) {}
ref_moduloref_modulo950     ref_modulo(const gen &N,const gen &M):ref_count(1),n(N),modulo(M) {}
951   };
952   struct ref_algext {
953     volatile ref_count_t ref_count;
954     gen P,Pmin,additional;
ref_algextref_algext955     ref_algext():ref_count(1) {}
956   };
957 
958   bool poly_is_real(const polynome & p);
959   bool vect_is_real(const vecteur & v,GIAC_CONTEXT);
960   polynome addpoly(const polynome & p,const gen & c);
961   polynome subpoly(const polynome & p,const gen & c);
962   bool islesscomplexthanf(const gen & a,const gen & b);
963   void islesscomplexthanf_sort(iterateur it,iterateur itend);
964   void gen_sort_f(iterateur it,iterateur itend,bool (*f)(const gen &a,const gen &b));
965   void gen_sort_f_context(iterateur it,iterateur itend,bool (*f)(const gen &a,const gen &b,GIAC_CONTEXT),GIAC_CONTEXT);
966   gen makemap(); // make a new map
967   gen chartab2gen(char * s,GIAC_CONTEXT);
968 
969 
970   bool is_zero(const gen & a,GIAC_CONTEXT0);
971   bool is_exactly_zero(const gen & a);
972   bool is_one(const gen & a);
is_exactly_one(const gen & a)973   inline bool is_exactly_one(const gen & a){ return is_one(a); }
974   bool is_minus_one(const gen & a);
975   bool is_sq_minus_one(const gen & a);
976   bool is_inf(const gen & e);
977   bool is_undef(const gen & e);
978   bool is_undef(const polynome & p);
979   bool is_undef(const vecteur & v);
980   bool has_inf_or_undef(const gen & g);
981   bool is_undef(const sparse_poly1 & s);
982   bool is_zero__VECT(const vecteur & a,GIAC_CONTEXT);
983   bool has_denominator(const gen & n);
984   bool has_i(const gen & g);
985 
986   // basic arithmetic
987   gen operator && (const gen & a,const gen & b);
988   gen operator || (const gen & a,const gen & b);
989   gen operator_plus (const gen & a,const gen & b,GIAC_CONTEXT);
990   gen operator_plus (const gen & a,const gen & b,unsigned t,GIAC_CONTEXT);
991   gen operator + (const gen & a,const gen & b);
992   gen & operator_plus_eq (gen & a,const gen & b,GIAC_CONTEXT);
993   inline gen & operator += (gen & a,const gen & b){
994     return operator_plus_eq(a,b,context0);
995   }
996   Tfraction<gen> operator + (const Tfraction<gen> & a,const Tfraction<gen> & b); // specialization
997   gen sym_add (const gen & a,const gen & b,GIAC_CONTEXT);
998   gen & operator_minus_eq (gen & a,const gen & b,GIAC_CONTEXT);
999   inline gen & operator -= (gen & a,const gen & b){
1000     return operator_minus_eq(a,b,context0);
1001   }
1002   gen operator_minus (const gen & a,const gen & b,GIAC_CONTEXT);
1003   gen operator - (const gen & a,const gen & b);
1004   gen operator - (const gen & a);
1005   gen sym_sub (const gen & a,const gen & b,GIAC_CONTEXT);
1006   gen operator_times (const gen & a,const gen & b,GIAC_CONTEXT);
1007   gen operator * (const gen & a,const gen & b);
1008   inline gen operator * (int a,const gen & b){ return gen(a)*b; }
1009   inline gen operator * (double a,const gen & b){ return gen(a)*b; }
1010   gen sym_mult (const gen & a,const gen & b,GIAC_CONTEXT);
1011   gen pow(const gen & base,const gen & exponent,GIAC_CONTEXT);
1012   gen giac_pow(const gen & base,const gen & exponent,GIAC_CONTEXT);
1013   gen iquo(const gen & a,const gen & b); // same
1014   gen irem(const gen & a,const gen & b,gen & q); // same
1015   gen smod(const gen & a,const gen & b); // same
1016   void smod(const vecteur & v,const gen & g,vecteur & w);
1017   vecteur smod(const vecteur & a,const gen & b); // same
1018   gen rdiv(const gen & a,const gen & b,GIAC_CONTEXT0); // rational division
1019   inline gen operator /(const gen & a,const gen & b){ return rdiv(a,b); };
1020   gen operator %(const gen & a,const gen & b); // for int only
1021   bool is_multiple(const gen & a,const gen &b);
1022   // gen inv(const gen & a);
1023   gen inv(const gen & a,GIAC_CONTEXT);
wprint(const gen & g,GIAC_CONTEXT)1024   inline wchar_t * wprint(const gen & g,GIAC_CONTEXT){ return g.wprint(contextptr); }
1025 
swapgen(gen & a,gen & b)1026   inline void swapgen(gen & a,gen &b){
1027 #ifdef SMARTPTR64
1028     std::swap(* (ulonglong *)&a,* (ulonglong *)&b);
1029 #else
1030     gen tmp=a; a=b; b=tmp;
1031 #endif
1032   }
1033   gen algebraic_EXTension(const gen & a,const gen & v);
1034   gen ext_reduce(const gen & a, const gen & v);
1035   gen maptoarray(const gen_map & m,GIAC_CONTEXT);
1036   gen evalf_VECT(const vecteur & v,int subtype,int level,const context * contextptr);
1037   gen m_gamma(int nbits); // Euler gamma constant precision nbits
1038   gen m_gamma(GIAC_CONTEXT);
1039   gen m_pi(int nbits); // pi precision nbits
1040   gen m_pi(GIAC_CONTEXT);
1041 
1042   // a*b -> tmp, may modify tmp in place
1043   void type_operator_times(const gen & a,const gen &b,gen & tmp);
1044   // c += a*b, may modify c in place
1045   /*
1046   inline void type_operator_plus_times(const gen & a,const gen & b,gen & c){
1047     gen g;
1048     type_operator_times(a,b,g);
1049     c += g;
1050   }
1051   */
1052   void type_operator_plus_times(const gen & a,const gen & b,gen & c);
1053   void type_operator_minus_times(const gen & a,const gen & b,gen & c);
1054 
type_operator_plus_times_reduce(const gen & a,const gen & b,gen & c,int reduce)1055   inline void type_operator_plus_times_reduce(const gen & a,const gen & b,gen & c,int reduce){
1056     type_operator_plus_times(a,b,c);
1057     if (reduce)
1058       c=smod(c,reduce);
1059   }
1060 
type_operator_reduce(const gen & a,const gen & b,gen & c,int reduce)1061   inline void type_operator_reduce(const gen & a,const gen & b,gen & c,int reduce){
1062     type_operator_times(a,b,c);
1063     if (reduce)
1064       c=smod(c,reduce);
1065   }
1066 
1067   bool operator ==(const gen & a,const gen & b);
1068   bool operator ==(const gen & a,const identificateur & b);
1069   bool operator_equal(const gen & a,const gen & b,GIAC_CONTEXT);
1070   bool operator !=(const gen & a,const gen & b);
1071   inline bool operator !=(const gen & a,const identificateur & b){ return !(a==b); }
1072   gen equal(const gen & a,const gen &b,GIAC_CONTEXT);
1073   gen equal2(const gen & a,const gen &b,GIAC_CONTEXT);
1074 
1075   gen operator !(const gen & a);
1076 
1077   int fastsign(const gen & a,GIAC_CONTEXT);   // 0 if unknown, 1 if >0, -1 if <0
1078   gen sign(const gen & a,GIAC_CONTEXT);
signint(int i)1079   inline int signint(int i){ return i?(i>0?1:-1):0;}
1080 
1081   // Large tests if strictly not precised, if sign is unknown return false
1082   bool is_greater(const gen & a,const gen &b,GIAC_CONTEXT);
1083   bool is_strictly_greater(const gen & a,const gen &b,GIAC_CONTEXT);
1084   inline bool operator > (const gen & a,const gen & b){
1085     return is_strictly_greater(a,b,context0);
1086   }
1087   inline bool operator < (const gen & a, const gen & b) {
1088     return is_strictly_greater (b, a, context0);
1089   }
1090   bool is_positive(const gen & a,GIAC_CONTEXT);
1091   bool is_strictly_positive(const gen & a,GIAC_CONTEXT);
1092   // Large tests if strictly not precised, if sign is unknown make an error
1093   bool ck_is_greater(const gen & a,const gen &b,GIAC_CONTEXT);
1094   bool ck_is_strictly_greater(const gen & a,const gen &b,GIAC_CONTEXT);
1095   bool ck_is_positive(const gen & a,GIAC_CONTEXT);
1096   bool ck_is_strictly_positive(const gen & a,GIAC_CONTEXT);
1097   gen superieur_strict(const gen & a,const gen & b,GIAC_CONTEXT);
1098   gen superieur_egal(const gen & a,const gen & b,GIAC_CONTEXT);
1099   gen inferieur_strict(const gen & a,const gen & b,GIAC_CONTEXT);
1100   gen inferieur_egal(const gen & a,const gen & b,GIAC_CONTEXT);
1101   bool symb_size_less(const gen & a,const gen & b);
1102 
1103   gen min(const gen & a, const gen & b,GIAC_CONTEXT);
1104   gen max(const gen & a, const gen & b,GIAC_CONTEXT=context0);
1105   // default context0 is required for instantiation in poly.h
1106   gen factorial(unsigned long int i);
1107   gen comb(unsigned long int i,unsigned long j);
1108   gen perm(unsigned long int i,unsigned long j);
1109   gen pow(const gen & base, unsigned long int exponent);
1110   gen pow(const gen & base, int exponent);
1111   gen pow(unsigned long int base, unsigned long int exponent);
1112 
1113   // more advanced arithmetic
1114   gen gcd(const gen & A,const gen & B,GIAC_CONTEXT);
1115   gen gcd(const gen & A,const gen & B);
1116   int iegcd(int a_,int b_,int &u,int & v);
1117   gen lcm(const gen & a,const gen & b);
1118   gen simplify(gen & n, gen & d);
1119   void egcd(const gen &a,const gen &b, gen & u,gen &v,gen &d );
1120   gen ichinrem(const gen & a,const gen &b,const gen & amod, const gen & bmod);
1121   gen invmod(const gen & A,const gen & modulo);
1122   gen fracmod(const gen & a_orig,const gen & modulo); // -> p/q=a mod modulo
1123   bool fracmod(const gen & a_orig,const gen & modulo,gen & res);
1124   bool in_fracmod(const gen &m,const gen & a,mpz_t & d,mpz_t & d1,mpz_t & absd1,mpz_t &u,mpz_t & u1,mpz_t & ur,mpz_t & q,mpz_t & r,mpz_t &sqrtm,mpz_t & tmp,gen & num,gen & den);
1125   bool alloc_fracmod(const gen & a_orig,const gen & modulo,gen & res,mpz_t & d,mpz_t & d1,mpz_t & absd1,mpz_t &u,mpz_t & u1,mpz_t & ur,mpz_t & q,mpz_t & r,mpz_t &sqrtm,mpz_t & tmp);
1126   gen powmod(const gen &base,const gen & expo,const gen & modulo);
1127   gen isqrt(const gen & A);
1128   gen re(const gen & a,GIAC_CONTEXT);
1129   gen no_context_re(const gen & a);
1130   gen im(const gen & a,GIAC_CONTEXT);
1131   gen no_context_im(const gen & a);
1132   void reim(const gen & g,gen & r,gen & i,GIAC_CONTEXT);
1133   gen conj(const gen & a,GIAC_CONTEXT);
1134   gen no_context_conj(const gen & a);
1135   gen sq(const gen & a);
1136   gen abs(const gen & a,const context * contextptr=context0);
1137   // default context0 is required for instantiation in poly.h
1138   gen linfnorm(const gen & a,const context * contextptr=context0);
1139   // default context0 is required for instantiation in poly.h
1140   gen arg(const gen & a,GIAC_CONTEXT);
1141   gen arg_CPLX(const gen & a,GIAC_CONTEXT);
1142   int is_perfect_square(const gen & A);
1143   int is_probab_prime_p(const gen & A);
1144   gen nextprime(const gen & a); // more precisely next probably prime
1145   gen prevprime(const gen & a); // more precisely prev probably prime
1146   int jacobi(const gen & A, const gen &B);
1147   int legendre(const gen & A, const gen & B);
1148   vecteur pascal_next_line(const vecteur & v);
1149   vecteur pascal_nth_line(int n);
1150   // convert a __VECTOR__VECT vecteur to a normal vecteur
1151   gen vector2vecteur(const vecteur & v);
1152 
1153   // if b is a _MOD, returns a as a b _MOD
1154   gen chkmod(const gen& a,const gen & b);
1155   // make a _MOD a%b
1156   gen makemod(const gen & a,const gen & b);
1157   // same without evaluating %
1158   gen makemodquoted(const gen & a,const gen & b);
1159 
1160   // from a sum in x returns a list of [coeff monomial]
1161   // e.g. 5+2x+3*x*y -> [ [5 1] [2 x] [ 3 x*y] ]
1162   vecteur symbolique2liste(const gen & x,GIAC_CONTEXT);
1163   // v should be sorted and shrinked
1164   gen liste2symbolique(const vecteur & v);
1165 
1166   bool is_atomic(const gen & e);
1167   gen _FRAC2_SYMB(const fraction & f);
1168   gen _FRAC2_SYMB(const gen & e);
1169   gen _FRAC2_SYMB(const gen & n,const gen & d);
1170   gen string2gen(const std::string & ss,bool remove_ss_quotes=true);
1171   // by default ss is assumed to be delimited by " and "
1172   std::complex<double> gen2complex_d(const gen & e);
1173   gen eval_VECT(const vecteur & v,int subtype,int level,const context * context_ptr );
1174   // functional equivalent of gen methods
eval(const gen & e,int level,const context * contextptr)1175   inline gen eval(const gen & e,int level,const context * contextptr){ return e.eval(level,contextptr); };
eval(const gen & e,const context * contextptr)1176   inline gen eval(const gen & e,const context * contextptr){ return e.eval(eval_level(contextptr),contextptr); };
1177   gen no_context_evalf(const gen & e);
1178   gen evalf(const gen & e,int level,const context * contextptr );
1179   gen evalf2bcd_nock(const gen & g0,int level,const context * contextptr);
1180   gen evalf2bcd(const gen & g0,int level,const context * contextptr);
evalf_double(const gen & e,int level,const context * contextptr)1181   inline gen evalf_double(const gen & e,int level,const context * contextptr){ return e.evalf_double(level,contextptr); };
1182   // return true if g can be converted to a double or real or complex
1183   bool has_evalf(const gen & g,gen & res,int level,const context * contextptr);
print(const gen & e,context * contextptr)1184   inline std::string print(const gen & e,context * contextptr){ return e.print(contextptr); }
is_real(const gen & g,GIAC_CONTEXT)1185   inline bool is_real(const gen & g,GIAC_CONTEXT){ return g.is_real(contextptr); }
is_cinteger(const gen & g)1186   inline  bool is_cinteger(const gen & g){ return g.is_cinteger();}  ;
is_integer(const gen & g)1187   inline  bool is_integer(const gen & g){ return g.is_integer(); }  ;
1188   double int2double(int i);
is_constant(const gen & g)1189   inline  bool is_constant(const gen & g){ return g.is_constant(); } ;
is_approx(const gen & g)1190   inline bool is_approx(const gen & g){ return g.is_approx(); };
1191   gen aplatir_fois_plus(const gen & g);
1192   gen collect(const gen & g,GIAC_CONTEXT);
1193 
1194   class gen_user{
1195   public:
memory_alloc()1196     virtual gen_user * memory_alloc() const { gen_user * ptr = new gen_user(*this); return ptr; }
~gen_user()1197     virtual ~gen_user() {};
1198     // redefine operations if it makes sense.
1199     // You can redefine gen_user + gen_user for speed
1200     virtual gen operator + (const gen &) const { return gensizeerr(gettext("+ not redefined")); }
1201     virtual gen operator + (const gen_user & a) const { return (*this) + gen(a); }
1202     virtual gen operator - (const gen &) const { return gensizeerr(gettext("Binary - not redefined")); }
1203     virtual gen operator - (const gen_user & a) const { return (*this) - gen(a); }
1204     virtual gen operator - () const { return gensizeerr(gettext("Unary - not redefined")); }
1205     virtual gen operator * (const gen &) const { return gensizeerr(gettext("Binary * not redefined")); }
1206     virtual gen operator * (const gen_user & a) const { return (*this) * gen(a); }
1207     virtual gen operator / (const gen_user & a) const { return (*this) * a.inv(); }
1208     virtual gen operator / (const gen & a) const { return gensizeerr(gettext("Binary / not redefined")); }
is_zero()1209     virtual bool is_zero() const {
1210 #ifndef NO_STDEXCEPT
1211       setsizeerr(gettext("==0 not redefined"));
1212 #endif
1213       return false;
1214     }
is_one()1215     virtual bool is_one() const {
1216 #ifndef NO_STDEXCEPT
1217       setsizeerr(gettext("==1 not redefined"));
1218 #endif
1219       return false;
1220     }
is_minus_one()1221     virtual bool is_minus_one() const {
1222 #ifndef NO_STDEXCEPT
1223       setsizeerr(gettext("==-1 not redefined"));
1224 #endif
1225       return false;
1226     }
inv()1227     virtual gen inv() const { return gensizeerr(gettext("Inv not redefined")); }
conj(GIAC_CONTEXT)1228     virtual gen conj(GIAC_CONTEXT) const { return gensizeerr(gettext("Conj not redefined"));}
re(GIAC_CONTEXT)1229     virtual gen re(GIAC_CONTEXT) const { return gensizeerr(gettext("Real part not redefined"));}
im(GIAC_CONTEXT)1230     virtual gen im(GIAC_CONTEXT) const { return gensizeerr(gettext("Imaginary part not redefined")); }
abs(GIAC_CONTEXT)1231     virtual gen abs(GIAC_CONTEXT) const { return gensizeerr(gettext("Abs not redefined"));}
arg(GIAC_CONTEXT)1232     virtual gen arg(GIAC_CONTEXT) const { return gensizeerr(gettext("Arg not redefined")); }
sqrt(GIAC_CONTEXT)1233     virtual gen sqrt(GIAC_CONTEXT) const { return gensizeerr(gettext("Sqrt not redefined")); }
operator()1234     virtual gen operator () (const gen &,GIAC_CONTEXT) const { return gensizeerr(gettext("() not redefined")); }
1235     virtual gen operator [] (const gen &) { return gensizeerr(gettext("[] not redefined")); }
1236     virtual bool operator == (const gen &) const {
1237 #ifndef NO_STDEXCEPT
1238       setsizeerr(gettext("== not redefined"));
1239 #endif
1240       return false;
1241     }
1242     virtual bool operator == (const gen_user & a) const { return (*this) == gen(a); }
1243     // must redefine > AND <= since we do not have symetrical type arguments
1244     virtual gen operator > (const gen &) const { return gensizeerr(gettext("> not redefined")); }
1245     virtual gen operator > (const gen_user & a) const { return superieur_strict(*this, gen(a),0); }
1246     virtual gen operator <= (const gen &) const { return gensizeerr(gettext("<= not redefined")); }
1247     virtual gen operator <= (const gen_user & a) const { return inferieur_egal(*this, gen(a),0); }
polygcd(const polynome &,const polynome &,polynome &)1248     virtual gen polygcd (const polynome &,const polynome &,polynome &) const { return gensizeerr(gettext("Polynomial gcd not redefined")); }
polyfactor(const polynome & p,factorization & f)1249     virtual gen polyfactor (const polynome & p,
1250 			     factorization & f) const {
1251       return gensizeerr(gettext("Polynomial gcd not redefined"));
1252     }
gcd(const gen &)1253     virtual gen gcd (const gen &) const { return gensizeerr(gettext("gcd not redefined")); }
gcd(const gen_user & a)1254     virtual gen gcd (const gen_user & a) const { return gcd(gen(a)); }
print(GIAC_CONTEXT)1255     virtual std::string print (GIAC_CONTEXT) const { return  "Nothing_to_print";}
dbgprint()1256     const char * dbgprint () const {
1257       static std::string s;
1258       s=this->print(0);
1259 #if !defined( NSPIRE) && !defined(FXCG)
1260       CERR << s << '\n';
1261 #endif
1262       return s.c_str();
1263     }
texprint(GIAC_CONTEXT)1264     virtual std::string texprint (GIAC_CONTEXT) const { return "Nothing_to_print_tex"; }
eval(int level,const context * contextptr)1265     virtual gen eval(int level,const context * contextptr) const {return *this;};
evalf(int level,const context * contextptr)1266     virtual gen evalf(int level,const context * contextptr) const {return *this;};
makegen(int i)1267     virtual gen makegen(int i) const { return string2gen("makegen not redefined"); } ;
rand(GIAC_CONTEXT)1268     virtual gen rand(GIAC_CONTEXT) const { return string2gen("rand not redefined"); };
1269   };
1270   struct ref_gen_user {
1271     volatile ref_count_t ref_count;
1272     gen_user * u;
ref_gen_userref_gen_user1273     ref_gen_user(const gen_user & U):ref_count(1),u(U.memory_alloc()) {}
ref_gen_userref_gen_user1274     ref_gen_user(gen_user * U):ref_count(1),u(U) {}
~ref_gen_userref_gen_user1275     ~ref_gen_user() {delete u;}
1276   };
1277 
1278   std::string print_the_type(int val,GIAC_CONTEXT);
1279 
1280   // I/O
1281 #ifdef KHICAS
1282   stdostream & operator << (stdostream & os,const gen & a);
1283 #endif
1284 #ifdef NSPIRE
1285   template<class T> nio::ios_base<T> & operator<<(nio::ios_base<T> & os,const gen & a){
1286     return os << a.print(context0);
1287   }
1288   template<class T> nio::ios_base<T> & operator>>(nio::ios_base<T> & is,gen & a);
1289 #else
1290   std::ostream & operator << (std::ostream & os,const gen & a);
1291   std::istream & operator >> (std::istream & is,gen & a);
1292 #endif
1293 
1294 #if defined(GIAC_GENERIC_CONSTANTS) // || (defined(VISUALC) && !defined(RTOS_THREADX)) || defined(x86_64)
1295   extern const gen zero;
1296 #else
1297   extern const gen & zero;
1298 #endif
1299 
1300   struct monome {
1301     gen coeff;
1302     gen exponent;
monomemonome1303     monome():coeff(0),exponent(0) {};
monomemonome1304     monome(const gen & mycoeff) : coeff(mycoeff),exponent(zero) {};
monomemonome1305     monome(const gen &mycoeff,const gen &myexponent) : coeff(mycoeff),exponent(myexponent) {};
1306     // std::string print() const ;
1307     std::string print(GIAC_CONTEXT) const ;
1308     const char * dbgprint() const ;
1309   };
1310 #if 0 // def KHICAS
1311   stdostream & operator<<(stdostream & os,const monome & m){    return os << m.print() ;}
1312 #endif
1313 #ifdef NSPIRE
1314   template<class T> nio::ios_base<T> & operator<<(nio::ios_base<T> & os,const monome & m){    return os << m.print() ;}
1315 #else
1316   std::ostream & operator << (std::ostream & os,const monome & m);
1317 #endif
1318   inline bool operator == (const monome & a,const monome & b){ return a.coeff==b.coeff && a.exponent==b.exponent; }
1319   inline bool operator != (const monome & a,const monome & b){ return a.coeff!=b.coeff || a.exponent!=b.exponent; }
1320   polynome apply( const polynome & p, const context * contextptr, gen (* f) (const gen &, const context *));
1321 
1322   const char * printi(GIAC_CONTEXT);
1323   std::string hexa_print_ZINT(const mpz_t & a);
1324   std::string octal_print_ZINT(const mpz_t & a);
1325   std::string binary_print_ZINT(const mpz_t & a);
1326   std::string print_ZINT(const mpz_t & a);
1327   std::string printinner_VECT(const vecteur & v, int subtype,GIAC_CONTEXT);
1328   std::string & add_printinner_VECT(std::string & s,const vecteur &v,int subtype,GIAC_CONTEXT);
1329   std::string begin_VECT_string(int subtype,bool tex,GIAC_CONTEXT);
1330   std::string end_VECT_string(int subtype,bool tex,GIAC_CONTEXT);
1331   std::string print_VECT(const vecteur & v,int subtype,GIAC_CONTEXT); // subtype was 0 by default
1332   std::string print_SPOL1(const sparse_poly1 & p,GIAC_CONTEXT);
1333   std::string print_STRNG(const std::string & s);
1334   std::string printint32(int val,int subtype,GIAC_CONTEXT);
1335   std::string print_FLOAT_(const giac_float & f,GIAC_CONTEXT);
1336   // find closing or opening () [] {}
1337   bool matchpos(const std::string & s,int & pos);
1338   std::string cut_string(const std::string & chaine,int nchar,std::vector<int> & ligne_end) ;
1339   std::string calc_endlines_positions(const vecteur & history_in,const vecteur & history_out,int nchar,std::vector<int> & endlines,std::vector<int> & positions);
1340   bool is_operator_char(char c);
1341   void increase_selection(const std::string & s,int & pos1,int& pos2);
1342   void decrease_selection(const std::string & s,int & pos1,int& pos2);
1343   void move_selection_right(const std::string & s,int & pos1, int & pos2);
1344   void move_selection_left(const std::string & s,int & pos1, int & pos2);
1345   std::string remove_extension(const std::string & chaine);
1346 
1347 
1348   // This type collects global variables to enable threading
1349   struct environment {
1350     gen modulo; // characteristic
1351     bool moduloon; // Set to false if non modular arithmetic required
1352     bool complexe; // true if working on Z/pZ[i]
1353     gen pn; // cardinal of the field, 0 means equal to modulo
1354     gen coeff; // exemple of coeff, so that we can call coeff.makegen
environmentenvironment1355     environment(){
1356       modulo=13;
1357       moduloon=false;
1358       complexe=false;
1359       coeff=pn=0;
1360     }
1361   };
1362 
1363     struct ref_sparse_poly1 {
1364     volatile ref_count_t ref_count;
1365     sparse_poly1 s;
ref_sparse_poly1ref_sparse_poly11366     ref_sparse_poly1(const sparse_poly1 & S):ref_count(1),s(S) {}
1367   };
1368 
1369 
1370   // extern environment * env;
1371 
1372   struct attributs {
1373     short int fontsize;
1374     unsigned short int background;
1375     unsigned short int text_color;
attributsattributs1376     attributs(int f,int b,int t): fontsize(f),background(b),text_color(t) {};
attributsattributs1377     attributs():fontsize(0),background(0),text_color(0) {};
1378   };
1379 
1380   // Terminal data for EQW display
1381   struct eqwdata {
1382     gen g;
1383 #if defined KHICAS || defined FXCG
1384     short int x,y,dx,dy;
1385     short int baseline;
1386 #else
1387     int x,y,dx,dy;
1388     int baseline;
1389 #endif
1390     bool selected;
1391     bool active;
1392     bool hasbaseline;
1393     bool modifiable;
1394     attributs eqw_attributs;
eqwdataeqwdata1395     eqwdata(int dxx,int dyy,int xx, int yy,const attributs & a,const gen& gg):g(gg),eqw_attributs(a),x(xx),y(yy),dx(dxx),dy(dyy),selected(false),active(false),hasbaseline(false),modifiable(true),baseline(0) {};
eqwdataeqwdata1396     eqwdata(int dxx,int dyy,int xx, int yy,const attributs & a,const gen& gg,int mybaseline):g(gg),eqw_attributs(a),x(xx),y(yy),dx(dxx),dy(dyy),selected(false),active(false),hasbaseline(true),modifiable(true),baseline(mybaseline) {};
dbgprinteqwdata1397     const char * dbgprint(){
1398 #if !defined( NSPIRE) && !defined(FXCG)
1399       CERR << g << ":" << dx<< ","<< dy<< "+"<<x <<","<< y<< "," << baseline << "," << eqw_attributs.fontsize << "," << eqw_attributs.background << "," << eqw_attributs.text_color << '\n';
1400 #endif
1401       return "Done";
1402     }
1403   };
1404   struct ref_eqwdata {
1405     volatile ref_count_t ref_count;
1406     eqwdata e;
ref_eqwdataref_eqwdata1407     ref_eqwdata(const eqwdata & E): ref_count(1),e(E) {}
1408   };
1409 
1410 
1411   class identificateur {
1412   public:
1413     int * ref_count;
1414     gen * value;
1415     // std::string * name;
1416     const char * id_name;
1417     vecteur * localvalue;
1418     // value / localvalue might be an assumption if it's a vecteur
1419     // of subtype _ASSUME__VECT
1420     // The first gen of an assumption vecteur is the type (_FRAC for rational)
1421     // If the type is _REAL, the vecteur has 2 other elements
1422     // * an interval or a _SET_VECT of intervals
1423     //   where interval=vecteur of length 2 of subtype _LINE__VECT
1424     // * a list of excluded particular values
1425     // If the type is _DOUBLE_ the variable will be evalf-ed but not eval-ed
1426     // This is useful in geometry to make figures and get exact results
1427     // If the type is _INT_ it
1428     short int * quoted;
1429     identificateur();
1430     explicit identificateur(const std::string & s);
1431     explicit identificateur(const char * s);
1432 #ifdef GIAC_HAS_STO_38
1433     explicit identificateur(const char * s, bool StringIsNowYours); // creates identifier. if StringIsNowYours, then the string will be freed when id is destroyed...
1434 #endif
1435     explicit identificateur(const char * s,const gen & e);
1436     identificateur(const std::string & s,const gen & e);
1437     identificateur(const identificateur & s);
1438     ~identificateur();
1439     identificateur & operator =(const identificateur & s);
1440     gen eval(int level,const gen & orig,const context * context_ptr) ;
1441     bool in_eval(int level,const gen & orig,gen & evaled,const context * context_ptr, bool No38Lookup=false); // if No38Lookup, does not check if HP38 knows about this name...
1442     const char * print(const context * context_ptr) const ;
name()1443     std::string name() const { return id_name; }
dbgprint()1444     const char * dbgprint() const {
1445       static std::string s;
1446       s=this->print(context0);
1447 #if 0 // ndef NSPIRE
1448       COUT << s;
1449 #endif
1450       return s.c_str();
1451     }
1452     void unassign() ;
1453     void push(int protection,const gen & e);
1454     bool operator ==(const identificateur & i);
1455     bool operator ==(const gen & i);
1456     inline bool operator !=(const identificateur & i){ return !(*this==i); }
1457     inline bool operator !=(const gen & i){ return !(*this==i);}
1458     void MakeCopyOfNameIfNotLocal(); ///< if the name is not dynamicaly allocated, create a copy for that id.
1459   };
1460   struct ref_identificateur {
1461     volatile ref_count_t ref_count;
1462     identificateur i;
ref_identificateurref_identificateur1463     ref_identificateur(const char * s):ref_count(1),i(s){}
ref_identificateurref_identificateur1464     ref_identificateur(const std::string & s):ref_count(1),i(s){}
ref_identificateurref_identificateur1465     ref_identificateur(const identificateur & s):ref_count(1),i(s){}
1466   };
1467   struct alias_ref_identificateur {
1468     ref_count_t i;
1469     int * ref_count;
1470     gen * value;
1471     const char * id_name;
1472     vecteur * localvalue;
1473     short int * quoted;
1474   };
1475 
1476   struct ref_unary_function_ptr {
1477     volatile ref_count_t ref_count;
1478     unary_function_ptr u;
ref_unary_function_ptrref_unary_function_ptr1479     ref_unary_function_ptr(const unary_function_ptr & U):ref_count(1),u(U) {}
ref_unary_function_ptrref_unary_function_ptr1480     ref_unary_function_ptr(const unary_function_ptr * U):ref_count(1),u(*U) {}
1481   };
1482   struct symbolic {
1483     unary_function_ptr sommet;
1484     gen feuille;
symbolicsymbolic1485     symbolic(const unary_function_ptr & o,const gen & e): sommet(o),feuille(e){};
symbolicsymbolic1486     symbolic(const unary_function_ptr & o,const gen & e1,const gen &e2): sommet(o), feuille(makevecteur(e1,e2)) {};
symbolicsymbolic1487     symbolic(const unary_function_ptr & o,const gen & e1,const gen &e2,const gen & e3): sommet(o), feuille(makevecteur(e1,e2,e3)) {};
symbolicsymbolic1488     symbolic(const unary_function_ptr & o,const gen & e1,const gen &e2,const gen & e3,const gen & e4): sommet(o), feuille(makevecteur(e1,e2,e3,e4)) {};
symbolicsymbolic1489     symbolic(const unary_function_ptr * o,const gen & e): sommet(*o),feuille(e){};
symbolicsymbolic1490     symbolic(const unary_function_ptr * o,const gen & e1,const gen &e2): sommet(*o), feuille(makevecteur(e1,e2)) {};
symbolicsymbolic1491     symbolic(const unary_function_ptr * o,const gen & e1,const gen &e2,const gen & e3): sommet(*o), feuille(makevecteur(e1,e2,e3)) {};
symbolicsymbolic1492     symbolic(const unary_function_ptr * o,const gen & e1,const gen &e2,const gen & e3,const gen & e4): sommet(*o), feuille(makevecteur(e1,e2,e3,e4)) {};
symbolicsymbolic1493     symbolic(const symbolic & mys) : sommet(mys.sommet),feuille(mys.feuille) {};
1494     symbolic(const symbolic & mys,const gen & e);
1495     symbolic(const gen & a,const unary_function_ptr & o,const gen & b);
1496     symbolic(const gen & a,const unary_function_ptr * o,const gen & b);
1497     std::string print(GIAC_CONTEXT) const;
dbgprintsymbolic1498     const char * dbgprint() const {
1499       static std::string s;
1500       s=this->print(context0);
1501 #if 0 // ndef NSPIRE
1502       COUT << s << '\n';
1503 #endif
1504       return s.c_str();
1505     }
1506     gen eval(int level,const context * context_ptr) const;
1507     gen evalf(int level,const context * context_ptr) const;
1508     int size() const;
1509   };
1510 
1511   struct ref_symbolic {
1512     volatile ref_count_t ref_count;
1513     symbolic s;
ref_symbolicref_symbolic1514     ref_symbolic(const symbolic & S):ref_count(1),s(S) {}
1515   };
1516 #ifdef SMARTPTR64
1517   struct alias_ref_symbolic {
1518     ref_count_t ref_count;
1519     unary_function_eval * sommet;
1520     ulonglong feuille;
1521   };
1522 #else
1523   struct alias_ref_symbolic {
1524     ref_count_t ref_count;
1525     unary_function_eval * sommet;
1526     unsigned char type;  // see dispatch.h
1527     signed char subtype;
1528     unsigned short reserved; // not used
1529 #ifdef DOUBLEVAL
1530     longlong value;
1531 #else
1532     long value ;
1533 #endif
1534   };
1535 #endif
1536 
1537 #ifdef SMARTPTR64
ref_ZINTptr()1538   inline mpz_t * gen::ref_ZINTptr() const { return & ((ref_mpz_t *) (* (ulonglong *) this >> 16))->z ; }
ref_REALptr()1539   inline real_object * gen::ref_REALptr() const { return & ((ref_real_object *) (* (ulonglong *) this >> 16)) ->r; }
ref_CPLXptr()1540   inline gen * gen::ref_CPLXptr() const { return & ((ref_complex *)(* (ulonglong *) this >> 16))->re; }
ref_MODptr()1541   inline gen * gen::ref_MODptr () const { return & ((ref_modulo *)(* (ulonglong *) this >> 16))->n; }
ref_EXTptr()1542   inline gen * gen::ref_EXTptr () const { return & ((ref_algext *)(* (ulonglong *) this >> 16))->P; }
ref_VECTptr()1543   inline vecteur * gen::ref_VECTptr() const { return &((ref_vecteur*)(* (ulonglong *) this >> 16))->v; }
ref_SPOL1ptr()1544   inline sparse_poly1 * gen::ref_SPOL1ptr() const { return &((ref_sparse_poly1*)(* (ulonglong *) this >> 16))->s; }
ref_STRNGptr()1545   inline std::string * gen::ref_STRNGptr() const { return &((ref_string*)(* (ulonglong *) this >> 16))->s; }
ref_USERptr()1546   inline gen_user * gen::ref_USERptr() const { return ((ref_gen_user*)(* (ulonglong *) this >> 16))->u; }
ref_MAPptr()1547   inline gen_map * gen::ref_MAPptr() const { return &((ref_gen_map*)(* (ulonglong *) this >> 16))->m; }
ref_EQWptr()1548   inline eqwdata * gen::ref_EQWptr() const { return &((ref_eqwdata*)(* (ulonglong *) this >> 16))->e; }
ref_GROBptr()1549   inline grob * gen::ref_GROBptr() const { return &((ref_grob*)(* (ulonglong *) this >> 16))->g; }
ref_POINTER_val()1550   inline void * gen::ref_POINTER_val() const { return ((ref_void_pointer*)(* (ulonglong *) this >> 16))->p; }
ref_FRACptr()1551   inline Tfraction<gen> * gen::ref_FRACptr() const { return &((ref_fraction *)(* (ulonglong *) this >> 16))->f; }
ref_POLYptr()1552   inline polynome * gen::ref_POLYptr() const { return &((ref_polynome*)(* (ulonglong *) this >> 16))->t; }
ref_IDNTptr()1553   inline identificateur * gen::ref_IDNTptr() const {return &((ref_identificateur*)(* (ulonglong *) this >> 16))->i; }
ref_SYMBptr()1554   inline symbolic * gen::ref_SYMBptr() const { return &((ref_symbolic*)(* (ulonglong *) this >> 16))->s; }
ref_FUNCptr()1555   inline unary_function_ptr * gen::ref_FUNCptr() const { return &((ref_unary_function_ptr*)(* (ulonglong *) this >> 16))->u; }
1556 #else // SMARTPTR64
ref_ZINTptr()1557   inline mpz_t * gen::ref_ZINTptr() const { return &__ZINTptr->z; }
ref_REALptr()1558   inline real_object * gen::ref_REALptr() const { return &__REALptr->r; }
ref_CPLXptr()1559   inline gen * gen::ref_CPLXptr() const { return &__CPLXptr->re; }
ref_MODptr()1560   inline gen * gen::ref_MODptr () const { return &__MODptr->n; }
ref_EXTptr()1561   inline gen * gen::ref_EXTptr () const { return &__EXTptr->P; }
ref_VECTptr()1562   inline vecteur * gen::ref_VECTptr() const { return &__VECTptr->v; }
ref_SPOL1ptr()1563   inline sparse_poly1 * gen::ref_SPOL1ptr() const { return &__SPOL1ptr->s; }
ref_STRNGptr()1564   inline std::string * gen::ref_STRNGptr() const { return &__STRNGptr->s; }
ref_USERptr()1565   inline gen_user * gen::ref_USERptr() const { return __USERptr->u; }
ref_MAPptr()1566   inline gen_map * gen::ref_MAPptr() const { return &__MAPptr->m; }
ref_EQWptr()1567   inline eqwdata * gen::ref_EQWptr() const { return &__EQWptr->e; }
ref_GROBptr()1568   inline grob * gen::ref_GROBptr() const { return &__GROBptr->g; }
ref_POINTER_val()1569   inline void * gen::ref_POINTER_val() const { return __POINTERptr->p; }
ref_FRACptr()1570   inline Tfraction<gen> * gen::ref_FRACptr() const { return &__FRACptr->f; }
ref_POLYptr()1571   inline polynome * gen::ref_POLYptr() const { return &__POLYptr->t; }
ref_IDNTptr()1572   inline identificateur * gen::ref_IDNTptr() const {return &__IDNTptr->i; }
ref_SYMBptr()1573   inline symbolic * gen::ref_SYMBptr() const { return &__SYMBptr->s; }
1574   // inline unary_function_ptr * gen::ref_FUNCptr() const { return &__FUNCptr->u; }
ref_FUNCptr()1575   inline unary_function_ptr * gen::ref_FUNCptr() const { return (unary_function_ptr*) &_FUNC_; }
1576 #endif // SMARTPTR64
1577 
1578 #ifndef DOUBLEVAL
1579 #define _DOUBLE_val DOUBLE_val()
1580 #define _FLOAT_val FLOAT_val()
1581 #endif // DOUBLEVAL
1582 #define  _ZINTptr ref_ZINTptr()
1583 #define	 _REALptr ref_REALptr()
1584 #define  _CPLXptr ref_CPLXptr()
1585 #define  _IDNTptr ref_IDNTptr()
1586 #define  _SYMBptr ref_SYMBptr()
1587 #define  _MODptr ref_MODptr()
1588 #define  _FRACptr ref_FRACptr()
1589 #define  _EXTptr ref_EXTptr()
1590 #define  _POLYptr ref_POLYptr ()
1591 #define  _VECTptr  ref_VECTptr()
1592 #define  _SPOL1ptr ref_SPOL1ptr()
1593 #define  _STRNGptr ref_STRNGptr()
1594 #define  _FUNCptr ref_FUNCptr()
1595 #define  _ROOTptr ref_ROOTptr()
1596 #define  _USERptr ref_USERptr()
1597 #define  _MAPptr ref_MAPptr()
1598 #define  _EQWptr ref_EQWptr()
1599 #define  _GROBptr ref_GROBptr()
1600 #define  _POINTER_val ref_POINTER_val()
1601 
1602   // function that are indexed
1603   extern const alias_type alias_at_plus;
1604   extern const alias_type alias_at_neg;
1605   extern const alias_type alias_at_binary_minus;
1606   extern const alias_type alias_at_prod;
1607   extern const alias_type alias_at_division;
1608   extern const alias_type alias_at_inv;
1609   extern const alias_type alias_at_pow;
1610   extern const alias_type alias_at_exp;
1611   extern const alias_type alias_at_ln;
1612   extern const alias_type alias_at_abs;
1613   extern const alias_type alias_at_arg;
1614   extern const alias_type alias_at_pnt;
1615   extern const alias_type alias_at_point;
1616   extern const alias_type alias_at_segment;
1617   extern const alias_type alias_at_sto;
1618   extern const alias_type alias_at_sin;
1619   extern const alias_type alias_at_cos;
1620   extern const alias_type alias_at_tan;
1621   extern const alias_type alias_at_asin;
1622   extern const alias_type alias_at_acos;
1623   extern const alias_type alias_at_atan;
1624   extern const alias_type alias_at_sinh;
1625   extern const alias_type alias_at_cosh;
1626   extern const alias_type alias_at_tanh;
1627   extern const alias_type alias_at_asinh;
1628   extern const alias_type alias_at_acosh;
1629   extern const alias_type alias_at_atanh;
1630   extern const alias_type alias_at_interval;
1631   extern const alias_type alias_at_union;
1632   extern const alias_type alias_at_minus;
1633   extern const alias_type alias_at_intersect;
1634   extern const alias_type alias_at_not;
1635   extern const alias_type alias_at_and;
1636   extern const alias_type alias_at_ou;
1637   extern const alias_type alias_at_inferieur_strict;
1638   extern const alias_type alias_at_inferieur_egal;
1639   extern const alias_type alias_at_superieur_strict;
1640   extern const alias_type alias_at_superieur_egal;
1641   extern const alias_type alias_at_different;
1642   extern const alias_type alias_at_equal;
1643   extern const alias_type alias_at_equal2;
1644   extern const alias_type alias_at_rpn_prog;
1645   extern const alias_type alias_at_local;
1646   extern const alias_type alias_at_return;
1647   extern const alias_type alias_at_Dialog;
1648   extern const alias_type alias_at_double_deux_points;
1649   extern const alias_type alias_at_pointprod;
1650   extern const alias_type alias_at_pointdivision;
1651   extern const alias_type alias_at_pointpow;
1652   extern const alias_type alias_at_hash;
1653   extern const alias_type alias_at_pourcent;
1654   extern const alias_type alias_at_tilocal;
1655   extern const alias_type alias_at_break;
1656   extern const alias_type alias_at_continue;
1657   extern const alias_type alias_at_ampersand_times;
1658   extern const alias_type alias_at_maple_lib;
1659   extern const alias_type alias_at_unit;
1660   extern const alias_type alias_at_plot_style;
1661   extern const alias_type alias_at_xor;
1662   extern const alias_type alias_at_check_type;
1663   extern const alias_type alias_at_quote_pow;
1664   extern const alias_type alias_at_case;
1665   extern const alias_type alias_at_dollar;
1666   extern const alias_type alias_at_IFTE;
1667   extern const alias_type alias_at_RPN_CASE;
1668   extern const alias_type alias_at_RPN_LOCAL;
1669   extern const alias_type alias_at_RPN_FOR;
1670   extern const alias_type alias_at_RPN_WHILE;
1671   extern const alias_type alias_at_NOP;
1672   extern const alias_type alias_at_unit;
1673   extern const alias_type alias_at_ifte;
1674   extern const alias_type alias_at_for;
1675   extern const alias_type alias_at_bloc;
1676   extern const alias_type alias_at_program;
1677   extern const alias_type alias_at_same;
1678   extern const alias_type alias_at_increment;
1679   extern const alias_type alias_at_decrement;
1680   extern const alias_type alias_at_multcrement;
1681   extern const alias_type alias_at_divcrement;
1682   extern const alias_type alias_at_sq;
1683   extern const alias_type alias_at_display;
1684   extern const alias_type alias_at_of;
1685   extern const alias_type alias_at_at;
1686   extern const alias_type alias_at_normalmod;
1687   extern const alias_type alias_at_pointplus;
1688   extern const alias_type alias_at_pointminus;
1689   extern const alias_type alias_at_struct_dot;
1690   extern const alias_type alias_at_try_catch;
1691 
1692 #ifdef BCD
ck_gentobcd(const gen & g,accurate_bcd_float * bcdptr)1693   inline bool ck_gentobcd(const gen & g,accurate_bcd_float * bcdptr){
1694     if (g.type!=_FLOAT_)
1695       return false;
1696     fExpand(g._FLOAT_val.f,bcdptr);
1697     return true;
1698   }
gentobcd(const gen & g,accurate_bcd_float * bcdptr)1699   inline accurate_bcd_float * gentobcd(const gen & g,accurate_bcd_float * bcdptr){
1700     return fExpand(g._FLOAT_val.f,bcdptr);
1701   }
1702 #endif
1703 
1704   // should be in input_lexer.h
1705   // return true/false to tell if s is recognized. return the appropriate gen if true
1706   bool CasIsBuildInFunction(char const *s, gen &g);
1707 
1708   void sprintfdouble(char *,const char *,double d);
1709 
1710   extern "C" const char * caseval(const char *);
1711 
1712 // Alloca proposal by Cyrille to make it work on every compiler.
1713 #ifndef ALLOCA
1714   // alloca versions...
1715   #if defined(FREERTOS)
1716     // for systems that do not support alloca or s[size] syntaxes
1717     class Calloca { public:
1718       void *ram;
Calloca(size_t s)1719       Calloca(size_t s): ram(malloc(s)) { }
~Calloca()1720       ~Calloca() { free(ram); }
1721     };
1722     #define ALLOCA(type, var, size) Calloca alloca##var(size); type *var= (type*)(alloca##var.ram)
1723   #else
1724     #if defined( VISUALC ) || defined( BESTA_OS )
1725       #define ALLOCA(type, var, size) type *var= (type*)alloca(size)
1726     #else
1727       #define ALLOCA(type, var, size) type var[size]
1728     #endif
1729   #endif
1730 #endif
1731 
1732 #ifndef NO_NAMESPACE_GIAC
1733 } // namespace giac
1734 #endif // ndef NO_NAMESPACE_GIAC
1735 
1736 #endif // _GIAC_GEN_H
1737