3 * Implementation of GiNaC's light-weight expression handles. */
6 * GiNaC Copyright (C) 1999-2000 Johannes Gutenberg University Mainz, Germany
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.
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.
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
34 #ifndef NO_GINAC_NAMESPACE
36 #endif // ndef NO_GINAC_NAMESPACE
39 // default constructor, destructor, copy constructor assignment operator and helpers
44 #ifndef INLINE_EX_CONSTRUCTORS
46 ex::ex() : bp(ex0().bp)
48 debugmsg("ex default constructor",LOGLEVEL_CONSTRUCT);
49 GINAC_ASSERT(ex0().bp!=0);
50 GINAC_ASSERT(ex0().bp->flags & status_flags::dynallocated);
57 debugmsg("ex destructor",LOGLEVEL_DESTRUCT);
59 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
60 if (--bp->refcount == 0) {
65 ex::ex(const ex & other) : bp(other.bp)
67 debugmsg("ex copy constructor",LOGLEVEL_CONSTRUCT);
69 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
73 const ex & ex::operator=(const ex & other)
75 debugmsg("ex operator=",LOGLEVEL_ASSIGNMENT);
77 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
78 GINAC_ASSERT(other.bp!=0);
79 GINAC_ASSERT(other.bp->flags & status_flags::dynallocated);
81 basic * tmpbp=other.bp;
82 if (--bp->refcount==0) {
89 #endif // ndef INLINE_EX_CONSTRUCTORS
97 #ifndef INLINE_EX_CONSTRUCTORS
98 ex::ex(const basic & other)
100 debugmsg("ex constructor from basic",LOGLEVEL_CONSTRUCT);
101 construct_from_basic(other);
107 debugmsg("ex constructor from int",LOGLEVEL_CONSTRUCT);
108 switch (i) { // some tiny efficiency-hack (FIXME: is this ok?)
122 construct_from_basic(numeric(i));
126 ex::ex(unsigned int i)
128 debugmsg("ex constructor from unsigned int",LOGLEVEL_CONSTRUCT);
129 construct_from_basic(numeric(i));
134 debugmsg("ex constructor from long",LOGLEVEL_CONSTRUCT);
135 construct_from_basic(numeric(i));
138 ex::ex(unsigned long i)
140 debugmsg("ex constructor from unsigned long",LOGLEVEL_CONSTRUCT);
141 construct_from_basic(numeric(i));
144 ex::ex(double const d)
146 debugmsg("ex constructor from double",LOGLEVEL_CONSTRUCT);
147 construct_from_basic(numeric(d));
151 // functions overriding virtual functions from bases classes
157 // new virtual functions which can be overridden by derived classes
163 // non-virtual functions in this class
168 /** Swap the contents of two expressions. */
169 void ex::swap(ex & other)
171 debugmsg("ex swap",LOGLEVEL_MEMBER_FUNCTION);
174 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
175 GINAC_ASSERT(other.bp!=0);
176 GINAC_ASSERT(other.bp->flags & status_flags::dynallocated);
183 /** Output formatted to be useful as ginsh input. */
184 void ex::print(ostream & os, unsigned upper_precedence) const
186 debugmsg("ex print",LOGLEVEL_PRINT);
188 bp->print(os,upper_precedence);
191 void ex::printraw(ostream & os) const
193 debugmsg("ex printraw",LOGLEVEL_PRINT);
200 void ex::printtree(ostream & os, unsigned indent) const
202 debugmsg("ex printtree",LOGLEVEL_PRINT);
204 // os << "refcount=" << bp->refcount << " ";
205 bp->printtree(os,indent);
208 /** Print expression as a C++ statement. The output looks like
209 * "<type> <var_name> = <expression>;". The "type" parameter has an effect
210 * on how number literals are printed.
212 * @param os output stream
213 * @param type variable type (one of the csrc_types)
214 * @param var_name variable name to be printed */
215 void ex::printcsrc(ostream & os, unsigned type, const char *var_name) const
217 debugmsg("ex print csrc", LOGLEVEL_PRINT);
220 case csrc_types::ctype_float:
223 case csrc_types::ctype_double:
226 case csrc_types::ctype_cl_N:
230 os << var_name << " = ";
231 bp->printcsrc(os, type, 0);
235 /** Little wrapper arount print to be called within a debugger. */
236 void ex::dbgprint(void) const
238 debugmsg("ex dbgprint",LOGLEVEL_PRINT);
243 /** Little wrapper arount printtree to be called within a debugger. */
244 void ex::dbgprinttree(void) const
246 debugmsg("ex dbgprinttree",LOGLEVEL_PRINT);
251 bool ex::info(unsigned inf) const
253 if (inf == info_flags::normal_form) {
255 // Polynomials are in normal form
256 if (info(info_flags::polynomial))
259 // polynomial^(-int) is in normal form
260 if (is_ex_exactly_of_type(*this, power))
261 return op(1).info(info_flags::negint);
263 // polynomial^(int) * polynomial^(int) * ... is in normal form
264 if (!is_ex_exactly_of_type(*this, mul))
266 for (unsigned i=0; i<nops(); i++) {
267 if (is_ex_exactly_of_type(op(i), power)) {
268 if (!op(i).op(1).info(info_flags::integer))
270 if (!op(i).op(0).info(info_flags::polynomial))
273 if (!op(i).info(info_flags::polynomial))
278 return bp->info(inf);
282 unsigned ex::nops() const
288 ex ex::expand(unsigned options) const
291 return bp->expand(options);
294 bool ex::has(const ex & other) const
297 return bp->has(other);
300 int ex::degree(const symbol & s) const
303 return bp->degree(s);
306 int ex::ldegree(const symbol & s) const
309 return bp->ldegree(s);
312 ex ex::coeff(const symbol & s, int n) const
315 return bp->coeff(s,n);
318 ex ex::numer(bool normalize) const
321 if (normalize && !info(info_flags::normal_form))
327 if (n.info(info_flags::polynomial))
331 if (is_ex_exactly_of_type(n, power) && n.op(1).info(info_flags::negint))
334 // something^(int) * something^(int) * ...
335 if (!is_ex_exactly_of_type(n, mul))
338 for (unsigned i=0; i<n.nops(); i++) {
339 if (!is_ex_exactly_of_type(n.op(i), power) || !n.op(i).op(1).info(info_flags::negint))
345 ex ex::denom(bool normalize) const
348 if (normalize && !info(info_flags::normal_form))
354 if (n.info(info_flags::polynomial))
358 if (is_ex_exactly_of_type(n, power) && n.op(1).info(info_flags::negint))
359 return power(n.op(0), -(n.op(1)));
361 // something^(int) * something^(int) * ...
362 if (!is_ex_exactly_of_type(n, mul))
365 for (unsigned i=0; i<n.nops(); i++) {
366 if (is_ex_exactly_of_type(n.op(i), power) && n.op(i).op(1).info(info_flags::negint))
367 res *= power(n.op(i), -1);
372 ex ex::collect(const symbol & s) const
375 return bp->collect(s);
378 ex ex::eval(int level) const
381 return bp->eval(level);
384 ex ex::evalf(int level) const
387 return bp->evalf(level);
390 ex ex::subs(const lst & ls, const lst & lr) const
393 return bp->subs(ls,lr);
396 ex ex::subs(const ex & e) const
402 exvector ex::get_indices(void) const
405 return bp->get_indices();
408 ex ex::simplify_ncmul(const exvector & v) const
411 return bp->simplify_ncmul(v);
414 ex ex::operator[](const ex & index) const
416 debugmsg("ex operator[ex]",LOGLEVEL_OPERATOR);
421 ex ex::operator[](int i) const
423 debugmsg("ex operator[int]",LOGLEVEL_OPERATOR);
428 ex ex::op(int i) const
430 debugmsg("ex op()",LOGLEVEL_MEMBER_FUNCTION);
435 ex & ex::let_op(int i)
437 debugmsg("ex let_op()",LOGLEVEL_MEMBER_FUNCTION);
440 return bp->let_op(i);
443 #ifndef INLINE_EX_CONSTRUCTORS
444 int ex::compare(const ex & other) const
447 GINAC_ASSERT(other.bp!=0);
449 // special case: both expression point to same basic, trivially equal
452 return bp->compare(*other.bp);
454 #endif // ndef INLINE_EX_CONSTRUCTORS
456 #ifndef INLINE_EX_CONSTRUCTORS
457 bool ex::is_equal(const ex & other) const
460 GINAC_ASSERT(other.bp!=0);
462 // special case: both expression point to same basic, trivially equal
465 return bp->is_equal(*other.bp);
467 #endif // ndef INLINE_EX_CONSTRUCTORS
469 unsigned ex::return_type(void) const
472 return bp->return_type();
475 unsigned ex::return_type_tinfo(void) const
478 return bp->return_type_tinfo();
481 unsigned ex::gethash(void) const
484 return bp->gethash();
487 ex ex::exadd(const ex & rh) const
489 return (new add(*this,rh))->setflag(status_flags::dynallocated);
492 ex ex::exmul(const ex & rh) const
494 return (new mul(*this,rh))->setflag(status_flags::dynallocated);
497 ex ex::exncmul(const ex & rh) const
499 return (new ncmul(*this,rh))->setflag(status_flags::dynallocated);
504 void ex::makewriteable()
506 debugmsg("ex makewriteable",LOGLEVEL_MEMBER_FUNCTION);
508 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
509 if (bp->refcount > 1) {
510 basic * bp2=bp->duplicate();
512 bp2->setflag(status_flags::dynallocated);
516 GINAC_ASSERT(bp->refcount == 1);
519 void ex::construct_from_basic(const basic & other)
521 if ((other.flags & status_flags::evaluated)==0) {
522 // cf. copy constructor
523 const ex & tmpex = other.eval(1); // evaluate only one (top) level
526 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
528 if ((other.flags & status_flags::dynallocated)&&(other.refcount==0)) {
529 delete &const_cast<basic &>(other);
532 if (other.flags & status_flags::dynallocated) {
533 bp=&const_cast<basic &>(other);
535 bp=other.duplicate();
536 bp->setflag(status_flags::dynallocated);
539 // bp->clearflag(status_flags::evaluated);
543 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
547 // static member variables
553 // functions which are not member functions
565 #ifndef NO_GINAC_NAMESPACE
567 #endif // ndef NO_GINAC_NAMESPACE