Modification in output of last returned expression (for ginaccint)
[ginac.git] / ginac / ex.h
1 /** @file ex.h
2  *
3  *  Interface to GiNaC's light-weight expression handles. */
4
5 /*
6  *  GiNaC Copyright (C) 1999-2000 Johannes Gutenberg University Mainz, Germany
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 #ifndef __GINAC_EX_H__
24 #define __GINAC_EX_H__
25
26 #include <iostream>
27 #include <ginac/basic.h>
28 #include <ginac/operators.h>
29
30 #ifndef NO_GINAC_NAMESPACE
31 namespace GiNaC {
32 #endif // ndef NO_GINAC_NAMESPACE
33
34 class ex;
35 class expand_options;
36 class status_flags;
37
38 class symbol;
39 class lst;
40
41 extern ex const & _ex0(void);  /* FIXME: should this pollute headers? */
42
43 // typedef vector<ex> exvector;
44
45 #define INLINE_EX_CONSTRUCTORS
46
47 /** Lightweight wrapper for GiNaC's symbolic objects.  Basically all it does is
48  *  to hold a pointer to the other objects, manage the reference counting and
49  *  provide methods for manipulation of these objects. */
50 class ex
51 {
52     friend class basic;
53
54 // member functions
55
56     // default constructor, destructor, copy constructor assignment operator and helpers
57 public:
58     ex()
59 #ifdef INLINE_EX_CONSTRUCTORS
60     : bp(_ex0().bp)
61         {
62             GINAC_ASSERT(_ex0().bp!=0);
63             GINAC_ASSERT(_ex0().bp->flags & status_flags::dynallocated);
64             GINAC_ASSERT(bp!=0);
65             ++bp->refcount;
66 #ifdef OBSCURE_CINT_HACK
67             update_last_created_or_assigned_bp();
68 #endif // def OBSCURE_CINT_HACK
69         }
70 #else
71 ;
72 #endif // def INLINE_EX_CONSTRUCTORS
73
74     ~ex()
75 #ifdef INLINE_EX_CONSTRUCTORS
76         {
77             GINAC_ASSERT(bp!=0);
78             GINAC_ASSERT(bp->flags & status_flags::dynallocated);
79             if (--bp->refcount == 0) {
80                 delete bp;
81             }
82         }
83 #else
84 ;
85 #endif // def INLINE_EX_CONSTRUCTORS
86         
87     ex(ex const & other)
88 #ifdef INLINE_EX_CONSTRUCTORS
89     : bp(other.bp)
90         {
91             GINAC_ASSERT(bp!=0);
92             GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
93             ++bp->refcount;
94 #ifdef OBSCURE_CINT_HACK
95             update_last_created_or_assigned_bp();
96 #endif // def OBSCURE_CINT_HACK
97         }
98 #else
99 ;
100 #endif // def INLINE_EX_CONSTRUCTORS
101         
102     ex const & operator=(ex const & other)
103 #ifdef INLINE_EX_CONSTRUCTORS
104         {
105             GINAC_ASSERT(bp!=0);
106             GINAC_ASSERT(bp->flags & status_flags::dynallocated);
107             GINAC_ASSERT(other.bp!=0);
108             GINAC_ASSERT(other.bp->flags & status_flags::dynallocated);
109             ++other.bp->refcount;
110             basic * tmpbp=other.bp;
111             if (--bp->refcount==0) {
112                 delete bp;
113             }
114             bp=tmpbp;
115 #ifdef OBSCURE_CINT_HACK
116             update_last_created_or_assigned_bp();
117 #endif // def OBSCURE_CINT_HACK
118             return *this;
119         }
120 #else
121 ;
122 #endif // def INLINE_EX_CONSTRUCTORS
123
124     // other constructors
125 public:
126     ex(basic const & other)
127 #ifdef INLINE_EX_CONSTRUCTORS
128         {
129             construct_from_basic(other);
130 #ifdef OBSCURE_CINT_HACK
131             update_last_created_or_assigned_bp();
132 #endif // def OBSCURE_CINT_HACK
133         }
134 #else
135 ;
136 #endif // def INLINE_EX_CONSTRUCTORS
137     
138     ex(int const i);
139     ex(unsigned int const i);
140     ex(long const i);
141     ex(unsigned long const i);
142     ex(double const d);
143
144     // functions overriding virtual functions from bases classes
145     // none
146     
147     // new virtual functions which can be overridden by derived classes
148     // none
149
150     // non-virtual functions in this class
151 public:
152     void swap(ex & other);
153     void printraw(ostream & os) const;
154     void printtree(ostream & os, unsigned indent=0) const;
155     void print(ostream & os, unsigned upper_precedence=0) const;
156     void printcsrc(ostream & os, unsigned type, const char *var_name) const;
157     void dbgprint(void) const;
158     void dbgprinttree(void) const;
159     bool info(unsigned inf) const;
160     unsigned nops() const;
161     ex expand(unsigned options=0) const;
162     bool has(ex const & other) const;
163     int degree(symbol const & s) const;
164     int ldegree(symbol const & s) const;
165     ex coeff(symbol const & s, int const n=1) const;
166     ex lcoeff(symbol const & s) const { return coeff(s, degree(s)); }
167     ex tcoeff(symbol const & s) const { return coeff(s, ldegree(s)); }
168     ex numer(bool normalize = true) const;
169     ex denom(bool normalize = true) const;
170     ex unit(const symbol &x) const;
171     ex content(const symbol &x) const;
172     numeric integer_content(void) const;
173     ex primpart(const symbol &x) const;
174     ex primpart(const symbol &x, const ex &cont) const;
175     ex normal(int level = 0) const;
176     ex smod(const numeric &xi) const;
177     numeric max_coefficient(void) const;
178     ex collect(symbol const & s) const;
179     ex eval(int level = 0) const;
180     ex evalf(int level = 0) const;
181     ex diff(symbol const & s, unsigned nth = 1) const;
182     ex series(symbol const & s, ex const & point, int order = 6) const;
183     ex subs(lst const & ls, lst const & lr) const;
184     ex subs(ex const & e) const;
185     exvector get_indices(void) const;
186     ex simplify_ncmul(exvector const & v) const;
187     ex operator[](ex const & index) const;
188     ex operator[](int const i) const;
189     ex op(int const i) const;
190     ex & let_op(int const i);
191     int compare(ex const & other) const
192 #ifdef INLINE_EX_CONSTRUCTORS
193         {
194             GINAC_ASSERT(bp!=0);
195             GINAC_ASSERT(other.bp!=0);
196             if (bp==other.bp) {
197                 // special case: both expression point to same basic, trivially equal
198                 return 0; 
199             }
200             return bp->compare(*other.bp);
201         }
202 #else
203 ;
204 #endif // def INLINE_EX_CONSTRUCTORS
205     bool is_equal(ex const & other) const
206 #ifdef INLINE_EX_CONSTRUCTORS
207         {
208             GINAC_ASSERT(bp!=0);
209             GINAC_ASSERT(other.bp!=0);
210             if (bp==other.bp) {
211                 // special case: both expression point to same basic, trivially equal
212                 return true; 
213             }
214             return bp->is_equal(*other.bp);
215         }
216 #else
217 ;
218 #endif // def INLINE_EX_CONSTRUCTORS
219     bool is_zero(void) const {return compare(_ex0())==0;};
220         
221     unsigned return_type(void) const;
222     unsigned return_type_tinfo(void) const;
223     unsigned gethash(void) const;
224
225     ex exadd(ex const & rh) const;
226     ex exmul(ex const & rh) const;
227     ex exncmul(ex const & rh) const;
228 private:
229     void construct_from_basic(basic const & other);
230     void makewriteable();
231
232 #ifdef OBSCURE_CINT_HACK
233 public:
234     static bool last_created_or_assigned_bp_can_be_converted_to_ex(void)
235         {
236             if (last_created_or_assigned_bp==0) return false;
237             if ((last_created_or_assigned_bp->flags &
238                  status_flags::dynallocated)==0) return false;
239             if ((last_created_or_assigned_bp->flags &
240                  status_flags::evaluated)==0) return false;
241             return true;
242         }
243 protected:
244     void update_last_created_or_assigned_bp(void)
245         {
246             if (last_created_or_assigned_bp!=0) {
247                 if (--last_created_or_assigned_bp->refcount == 0) {
248                     delete last_created_or_assigned_bp;
249                 }
250             }
251             last_created_or_assigned_bp=bp;
252             ++last_created_or_assigned_bp->refcount;
253         }
254 #endif // def OBSCURE_CINT_HACK
255
256 // member variables
257
258 public:
259     basic *bp;
260 #ifdef OBSCURE_CINT_HACK
261     static basic *last_created_or_assigned_bp;
262 #endif // def OBSCURE_CINT_HACK
263 };
264
265 // utility functions
266 inline bool are_ex_trivially_equal(const ex &e1, const ex &e2)
267 {
268         return e1.bp == e2.bp;
269 }
270
271 // wrapper functions around member functions
272 inline unsigned nops(ex const & thisex)
273 { return thisex.nops(); }
274
275 inline ex expand(ex const & thisex, unsigned options = 0)
276 { return thisex.expand(options); }
277
278 inline bool has(ex const & thisex, ex const & other)
279 { return thisex.has(other); }
280
281 inline int degree(ex const & thisex, symbol const & s)
282 { return thisex.degree(s); }
283
284 inline int ldegree(ex const & thisex, symbol const & s)
285 { return thisex.ldegree(s); }
286
287 inline ex coeff(ex const & thisex, symbol const & s, int const n=1)
288 { return thisex.coeff(s, n); }
289
290 inline ex numer(ex const & thisex, bool normalize = true)
291 { return thisex.numer(normalize); }
292
293 inline ex denom(ex const & thisex, bool normalize = true)
294 { return thisex.denom(normalize); }
295
296 inline ex normal(ex const & thisex, int level=0)
297 { return thisex.normal(level); }
298
299 inline ex collect(ex const & thisex, symbol const & s)
300 { return thisex.collect(s); }
301
302 inline ex eval(ex const & thisex, int level = 0)
303 { return thisex.eval(level); }
304
305 inline ex evalf(ex const & thisex, int level = 0)
306 { return thisex.evalf(level); }
307
308 inline ex diff(ex const & thisex, symbol const & s, unsigned nth = 1)
309 { return thisex.diff(s, nth); }
310
311 inline ex subs(ex const & thisex, ex const & e)
312 { return thisex.subs(e); }
313
314 inline ex subs(ex const & thisex, lst const & ls, lst const & lr)
315 { return thisex.subs(ls, lr); }
316
317 inline void swap(ex & e1, ex & e2)
318 { e1.swap(e2); }
319
320 #ifndef NO_GINAC_NAMESPACE
321 } // namespace GiNaC
322 #endif // ndef NO_GINAC_NAMESPACE
323
324 #endif // ndef __GINAC_EX_H__
325