f2c0a03e5133cec2457e67630e73f53968bbe9c9
[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 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 // typedef vector<ex> exvector;
42
43 // enum definitions
44
45 ex const & exZERO(void);
46 ex const & exONE(void);
47 ex const & exTWO(void);
48 ex const & exTHREE(void);
49 ex const & exMINUSONE(void);
50 ex const & exHALF(void);
51 ex const & exMINUSHALF(void);
52
53 #define INLINE_EX_CONSTRUCTORS
54
55 /** Lightweight interface to GiNaC's symbolic objects. Basically all it does is
56  *  to hold a pointer to the other objects, manage the reference counting and
57  *  provide methods for manipulation of these objects. */
58 class ex
59 {
60     friend class basic;
61
62 // member functions
63
64     // default constructor, destructor, copy constructor assignment operator and helpers
65 public:
66     ex()
67 #ifdef INLINE_EX_CONSTRUCTORS
68     : bp(exZERO().bp)
69         {
70             GINAC_ASSERT(exZERO().bp!=0);
71             GINAC_ASSERT(exZERO().bp->flags & status_flags::dynallocated);
72             GINAC_ASSERT(bp!=0);
73             ++bp->refcount;
74 #ifdef OBSCURE_CINT_HACK
75             update_last_created_or_assigned_bp();
76 #endif // def OBSCURE_CINT_HACK
77         }
78 #else
79 ;
80 #endif // def INLINE_EX_CONSTRUCTORS
81
82     ~ex()
83 #ifdef INLINE_EX_CONSTRUCTORS
84         {
85             GINAC_ASSERT(bp!=0);
86             GINAC_ASSERT(bp->flags & status_flags::dynallocated);
87             if (--bp->refcount == 0) {
88                 delete bp;
89             }
90         }
91 #else
92 ;
93 #endif // def INLINE_EX_CONSTRUCTORS
94         
95     ex(ex const & other)
96 #ifdef INLINE_EX_CONSTRUCTORS
97     : bp(other.bp)
98         {
99             GINAC_ASSERT(bp!=0);
100             GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
101             ++bp->refcount;
102 #ifdef OBSCURE_CINT_HACK
103             update_last_created_or_assigned_bp();
104 #endif // def OBSCURE_CINT_HACK
105         }
106 #else
107 ;
108 #endif // def INLINE_EX_CONSTRUCTORS
109         
110     ex const & operator=(ex const & other)
111 #ifdef INLINE_EX_CONSTRUCTORS
112         {
113             GINAC_ASSERT(bp!=0);
114             GINAC_ASSERT(bp->flags & status_flags::dynallocated);
115             GINAC_ASSERT(other.bp!=0);
116             GINAC_ASSERT(other.bp->flags & status_flags::dynallocated);
117             ++other.bp->refcount;
118             basic * tmpbp=other.bp;
119             if (--bp->refcount==0) {
120                 delete bp;
121             }
122             bp=tmpbp;
123 #ifdef OBSCURE_CINT_HACK
124             update_last_created_or_assigned_bp();
125 #endif // def OBSCURE_CINT_HACK
126             return *this;
127         }
128 #else
129 ;
130 #endif // def INLINE_EX_CONSTRUCTORS
131
132     // other constructors
133 public:
134     ex(basic const & other)
135 #ifdef INLINE_EX_CONSTRUCTORS
136         {
137             construct_from_basic(other);
138 #ifdef OBSCURE_CINT_HACK
139             update_last_created_or_assigned_bp();
140 #endif // def OBSCURE_CINT_HACK
141         }
142 #else
143 ;
144 #endif // def INLINE_EX_CONSTRUCTORS
145     
146     ex(int const i);
147     ex(unsigned int const i);
148     ex(long const i);
149     ex(unsigned long const i);
150     ex(double const d);
151
152     // functions overriding virtual functions from bases classes
153     // none
154     
155     // new virtual functions which can be overridden by derived classes
156     // none
157
158     // non-virtual functions in this class
159 public:
160     void swap(ex & other);
161     void printraw(ostream & os) const;
162     void printtree(ostream & os, unsigned indent=0) const;
163     void print(ostream & os, unsigned upper_precedence=0) const;
164     void printcsrc(ostream & os, unsigned type, const char *var_name) const;
165     void dbgprint(void) const;
166     void dbgprinttree(void) const;
167     bool info(unsigned inf) const;
168     int nops() const;
169     ex expand(unsigned options=0) const;
170     bool has(ex const & other) const;
171     int degree(symbol const & s) const;
172     int ldegree(symbol const & s) const;
173     ex coeff(symbol const & s, int const n=1) const;
174     ex lcoeff(symbol const & s) const { return coeff(s, degree(s)); }
175     ex tcoeff(symbol const & s) const { return coeff(s, ldegree(s)); }
176     ex numer(bool normalize = true) const;
177     ex denom(bool normalize = true) const;
178     ex unit(const symbol &x) const;
179     ex content(const symbol &x) const;
180     numeric integer_content(void) const;
181     ex primpart(const symbol &x) const;
182     ex primpart(const symbol &x, const ex &cont) const;
183     ex normal(int level = 0) const;
184     ex smod(const numeric &xi) const;
185     numeric max_coefficient(void) const;
186     ex collect(symbol const & s) const;
187     ex eval(int level = 0) const;
188     ex evalf(int level = 0) const;
189     ex diff(symbol const & s, unsigned nth = 1) const;
190     ex series(symbol const & s, ex const & point, int order = 6) const;
191     ex subs(lst const & ls, lst const & lr) const;
192     ex subs(ex const & e) const;
193     exvector get_indices(void) const;
194     ex simplify_ncmul(exvector const & v) const;
195     ex operator[](ex const & index) const;
196     ex operator[](int const i) const;
197     ex op(int const i) const;
198     ex & let_op(int const i);
199     int compare(ex const & other) const
200 #ifdef INLINE_EX_CONSTRUCTORS
201         {
202             GINAC_ASSERT(bp!=0);
203             GINAC_ASSERT(other.bp!=0);
204             if (bp==other.bp) {
205                 // special case: both expression point to same basic, trivially equal
206                 return 0; 
207             }
208             return bp->compare(*other.bp);
209         }
210 #else
211 ;
212 #endif // def INLINE_EX_CONSTRUCTORS
213     bool is_equal(ex const & other) const
214 #ifdef INLINE_EX_CONSTRUCTORS
215         {
216             GINAC_ASSERT(bp!=0);
217             GINAC_ASSERT(other.bp!=0);
218             if (bp==other.bp) {
219                 // special case: both expression point to same basic, trivially equal
220                 return true; 
221             }
222             return bp->is_equal(*other.bp);
223         }
224 #else
225 ;
226 #endif // def INLINE_EX_CONSTRUCTORS
227     bool is_zero(void) const {return compare(exZERO()) == 0;};
228         
229     unsigned return_type(void) const;
230     unsigned return_type_tinfo(void) const;
231     unsigned gethash(void) const;
232
233     ex exadd(ex const & rh) const;
234     ex exmul(ex const & rh) const;
235     ex exncmul(ex const & rh) const;
236 private:
237     void construct_from_basic(basic const & other);
238     void makewriteable();
239
240 #ifdef OBSCURE_CINT_HACK
241 public:
242     static bool last_created_or_assigned_bp_can_be_converted_to_ex(void)
243         {
244             if (last_created_or_assigned_bp==0) return false;
245             if ((last_created_or_assigned_bp->flags &
246                  status_flags::dynallocated)==0) return false;
247             if ((last_created_or_assigned_bp->flags &
248                  status_flags::evaluated)==0) return false;
249             return true;
250         }
251 protected:
252     void update_last_created_or_assigned_bp(void)
253         {
254             if (last_created_or_assigned_bp!=0) {
255                 if (--last_created_or_assigned_bp->refcount == 0) {
256                     delete last_created_or_assigned_bp;
257                 }
258             }
259             last_created_or_assigned_bp=bp;
260             ++last_created_or_assigned_bp->refcount;
261             last_created_or_assigned_bp_modified=true;
262         }
263 #endif // def OBSCURE_CINT_HACK
264
265 // member variables
266
267 public:
268     basic *bp;
269 #ifdef OBSCURE_CINT_HACK
270     static basic *last_created_or_assigned_bp;
271     static bool last_created_or_assigned_bp_modified;
272 #endif // def OBSCURE_CINT_HACK
273 };
274
275 // utility functions
276 inline bool are_ex_trivially_equal(const ex &e1, const ex &e2)
277 {
278         return e1.bp == e2.bp;
279 }
280
281 // wrapper functions around member functions
282 inline int nops(ex const & thisex)
283 { return thisex.nops(); }
284
285 inline ex expand(ex const & thisex, unsigned options = 0)
286 { return thisex.expand(options); }
287
288 inline bool has(ex const & thisex, ex const & other)
289 { return thisex.has(other); }
290
291 inline int degree(ex const & thisex, symbol const & s)
292 { return thisex.degree(s); }
293
294 inline int ldegree(ex const & thisex, symbol const & s)
295 { return thisex.ldegree(s); }
296
297 inline ex coeff(ex const & thisex, symbol const & s, int const n=1)
298 { return thisex.coeff(s, n); }
299
300 inline ex numer(ex const & thisex, bool normalize = true)
301 { return thisex.numer(normalize); }
302
303 inline ex denom(ex const & thisex, bool normalize = true)
304 { return thisex.denom(normalize); }
305
306 inline ex normal(ex const & thisex, int level=0)
307 { return thisex.normal(level); }
308
309 inline ex collect(ex const & thisex, symbol const & s)
310 { return thisex.collect(s); }
311
312 inline ex eval(ex const & thisex, int level = 0)
313 { return thisex.eval(level); }
314
315 inline ex evalf(ex const & thisex, int level = 0)
316 { return thisex.evalf(level); }
317
318 inline ex diff(ex const & thisex, symbol const & s, unsigned nth = 1)
319 { return thisex.diff(s, nth); }
320
321 inline ex subs(ex const & thisex, ex const & e)
322 { return thisex.subs(e); }
323
324 inline ex subs(ex const & thisex, lst const & ls, lst const & lr)
325 { return thisex.subs(ls, lr); }
326
327 inline void swap(ex & e1, ex & e2)
328 { e1.swap(e2); }
329
330 #ifndef NO_GINAC_NAMESPACE
331 } // namespace GiNaC
332 #endif // ndef NO_GINAC_NAMESPACE
333
334 #endif // ndef __GINAC_EX_H__
335