This file records noteworthy changes.
+0.9.4 (<date>)
+* interface cleanups and bugfixes.
+
0.9.3 (16 August 2001)
* series expansion now much more consistent for small order expansion.
* lsolve() accepts algorithmic hint as parameter.
#ifdef DO_GINAC_ASSERT
epvector::const_iterator i = seq.begin(), end = seq.end();
while (i != end) {
- GINAC_ASSERT(!is_ex_exactly_of_type(i->rest,add));
+ GINAC_ASSERT(!is_exactly_a<add>(i->rest));
if (is_ex_exactly_of_type(i->rest,numeric))
dbgprint();
- GINAC_ASSERT(!is_ex_exactly_of_type(i->rest,numeric));
+ GINAC_ASSERT(!is_exactly_a<numeric>(i->rest));
++i;
}
#endif // def DO_GINAC_ASSERT
expair add::combine_ex_with_coeff_to_pair(const ex & e,
const ex & c) const
{
- GINAC_ASSERT(is_ex_exactly_of_type(c, numeric));
+ GINAC_ASSERT(is_exactly_a<numeric>(c));
if (is_ex_exactly_of_type(e, mul)) {
const mul &mulref(ex_to<mul>(e));
ex numfactor = mulref.overall_coeff;
expair add::combine_pair_with_coeff_to_pair(const expair & p,
const ex & c) const
{
- GINAC_ASSERT(is_ex_exactly_of_type(p.coeff,numeric));
- GINAC_ASSERT(is_ex_exactly_of_type(c,numeric));
+ GINAC_ASSERT(is_exactly_a<numeric>(p.coeff));
+ GINAC_ASSERT(is_exactly_a<numeric>(c));
if (is_ex_exactly_of_type(p.rest,numeric)) {
GINAC_ASSERT(ex_to<numeric>(p.coeff).is_equal(_num1())); // should be normalized
// utility functions
-/** Return the add object handled by an ex. Deprecated: use ex_to<add>().
- * This is unsafe: you need to check the type first. */
-inline const add &ex_to_add(const ex &e)
-{
- return static_cast<const add &>(*e.bp);
-}
-
/** Specialization of is_exactly_a<add>(obj) for add objects. */
template<> inline bool is_exactly_a<add>(const basic & obj)
{
#include "lst.h"
#include "ncmul.h"
#include "relational.h"
+#include "wildcard.h"
#include "print.h"
#include "archive.h"
#include "utils.h"
* but e.has(x+y) is false. */
bool basic::has(const ex & pattern) const
{
- GINAC_ASSERT(pattern.bp!=0);
lst repl_lst;
- if (match(*pattern.bp, repl_lst))
+ if (match(pattern, repl_lst))
return true;
for (unsigned i=0; i<nops(); i++)
if (op(i).has(pattern))
// be the same expression)
for (unsigned i=0; i<repl_lst.nops(); i++) {
if (repl_lst.op(i).op(0).is_equal(pattern))
- return is_equal(*repl_lst.op(i).op(1).bp);
+ return is_equal(ex_to<basic>(repl_lst.op(i).op(1)));
}
repl_lst.append(pattern == *this);
return true;
} else {
// Expression must be of the same type as the pattern
- if (tinfo() != pattern.bp->tinfo())
+ if (tinfo() != ex_to<basic>(pattern).tinfo())
return false;
// Number of subexpressions must match
// No subexpressions? Then just compare the objects (there can't be
// wildcards in the pattern)
if (nops() == 0)
- return is_equal_same_type(*pattern.bp);
+ return is_equal_same_type(ex_to<basic>(pattern));
// Check whether attributes that are not subexpressions match
- if (!match_same_type(*pattern.bp))
+ if (!match_same_type(ex_to<basic>(pattern)))
return false;
// Otherwise the subexpressions must match one-to-one
if (no_pattern) {
for (unsigned i=0; i<ls.nops(); i++) {
- if (is_equal(*ls.op(i).bp))
+ if (is_equal(ex_to<basic>(ls.op(i))))
return lr.op(i);
}
} else {
for (unsigned i=0; i<ls.nops(); i++) {
lst repl_lst;
- if (match(*ls.op(i).bp, repl_lst))
- return lr.op(i).bp->subs(repl_lst, true); // avoid infinite recursion when re-substituting the wildcards
+ if (match(ex_to<basic>(ls.op(i)), repl_lst))
+ return lr.op(i).subs(repl_lst, true); // avoid infinite recursion when re-substituting the wildcards
}
}
return (options == 0) ? setflag(status_flags::expanded) : *this;
else {
expand_map_function map_expand(options);
- return map(map_expand).bp->setflag(options == 0 ? status_flags::expanded : 0);
+ return ex_to<basic>(map(map_expand)).setflag(options == 0 ? status_flags::expanded : 0);
}
}
/** Check if obj is a T, including base classes. */
template <class T>
-inline bool is_a(const basic & obj)
+inline bool is_a(const basic &obj)
{
return dynamic_cast<const T *>(&obj)!=0;
}
* inefficient default. It should in all time-critical cases be overridden
* by template specializations that don't create a temporary. */
template <class T>
-inline bool is_exactly_a(const class basic & obj)
+inline bool is_exactly_a(const class basic &obj)
{
const T foo; return foo.tinfo()==obj.tinfo();
}
/** Check if ex is a handle to a T, including base classes. */
template <class T>
-inline bool is_a(const ex & obj)
+inline bool is_a(const ex &obj)
{
return is_a<T>(*obj.bp);
}
/** Check if ex is a handle to a T, not including base classes. */
template <class T>
-inline bool is_exactly_a(const ex & obj)
+inline bool is_exactly_a(const ex &obj)
{
return is_exactly_a<T>(*obj.bp);
}
/** Return a reference to the basic-derived class T object embedded in an
* expression. This is fast but unsafe: the result is undefined if the
- * expression does not contain a T object at its top level.
+ * expression does not contain a T object at its top level. Hence, you
+ * should generally check the type of e first.
*
* @param e expression
* @return reference to pseries object
int clifford::compare_same_type(const basic & other) const
{
- GINAC_ASSERT(is_of_type(other, clifford));
+ GINAC_ASSERT(is_a<clifford>(other));
const clifford &o = static_cast<const clifford &>(other);
if (representation_label != o.representation_label) {
bool clifford::match_same_type(const basic & other) const
{
- GINAC_ASSERT(is_of_type(other, clifford));
+ GINAC_ASSERT(is_a<clifford>(other));
const clifford &o = static_cast<const clifford &>(other);
return representation_label == o.representation_label;
// global functions
-/** Return the clifford object handled by an ex. Deprecated: use ex_to<clifford>().
- * This is unsafe: you need to check the type first. */
-inline const clifford &ex_to_clifford(const ex &e)
-{
- return static_cast<const clifford &>(*e.bp);
-}
-
/** Specialization of is_exactly_a<clifford>(obj) for clifford objects. */
template<> inline bool is_exactly_a<clifford>(const basic & obj)
{
#include "ncmul.h"
#include "symmetry.h"
#include "numeric.h"
+#include "mul.h"
#include "power.h" // for sqrt()
#include "symbol.h"
#include "print.h"
int color::compare_same_type(const basic & other) const
{
- GINAC_ASSERT(is_of_type(other, color));
+ GINAC_ASSERT(is_a<color>(other));
const color &o = static_cast<const color &>(other);
if (representation_label != o.representation_label) {
bool color::match_same_type(const basic & other) const
{
- GINAC_ASSERT(is_of_type(other, color));
+ GINAC_ASSERT(is_a<color>(other));
const color &o = static_cast<const color &>(other);
return representation_label == o.representation_label;
/** Automatic symbolic evaluation of indexed symmetric structure constant. */
ex su3d::eval_indexed(const basic & i) const
{
- GINAC_ASSERT(is_of_type(i, indexed));
+ GINAC_ASSERT(is_a<indexed>(i));
GINAC_ASSERT(i.nops() == 4);
- GINAC_ASSERT(is_ex_of_type(i.op(0), su3d));
+ GINAC_ASSERT(is_a<su3d>(i.op(0)));
// Convolutions are zero
if (!(static_cast<const indexed &>(i).get_dummy_indices().empty()))
/** Automatic symbolic evaluation of indexed antisymmetric structure constant. */
ex su3f::eval_indexed(const basic & i) const
{
- GINAC_ASSERT(is_of_type(i, indexed));
+ GINAC_ASSERT(is_a<indexed>(i));
GINAC_ASSERT(i.nops() == 4);
- GINAC_ASSERT(is_ex_of_type(i.op(0), su3f));
+ GINAC_ASSERT(is_a<su3f>(i.op(0)));
// Numeric evaluation
if (static_cast<const indexed &>(i).all_index_values_are(info_flags::nonnegint)) {
/** Contraction of generator with something else. */
bool su3t::contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const
{
- GINAC_ASSERT(is_ex_of_type(*self, indexed));
- GINAC_ASSERT(is_ex_of_type(*other, indexed));
+ GINAC_ASSERT(is_a<indexed>(*self));
+ GINAC_ASSERT(is_a<indexed>(*other));
GINAC_ASSERT(self->nops() == 2);
- GINAC_ASSERT(is_ex_of_type(self->op(0), su3t));
+ GINAC_ASSERT(is_a<su3t>(self->op(0)));
unsigned char rl = ex_to<color>(*self).get_representation_label();
if (is_ex_exactly_of_type(other->op(0), su3t)) {
/** Contraction of an indexed symmetric structure constant with something else. */
bool su3d::contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const
{
- GINAC_ASSERT(is_ex_of_type(*self, indexed));
- GINAC_ASSERT(is_ex_of_type(*other, indexed));
+ GINAC_ASSERT(is_a<indexed>(*self));
+ GINAC_ASSERT(is_a<indexed>(*other));
GINAC_ASSERT(self->nops() == 4);
- GINAC_ASSERT(is_ex_of_type(self->op(0), su3d));
+ GINAC_ASSERT(is_a<su3d>(self->op(0)));
if (is_ex_exactly_of_type(other->op(0), su3d)) {
/** Contraction of an indexed antisymmetric structure constant with something else. */
bool su3f::contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const
{
- GINAC_ASSERT(is_ex_of_type(*self, indexed));
- GINAC_ASSERT(is_ex_of_type(*other, indexed));
+ GINAC_ASSERT(is_a<indexed>(*self));
+ GINAC_ASSERT(is_a<indexed>(*other));
GINAC_ASSERT(self->nops() == 4);
- GINAC_ASSERT(is_ex_of_type(self->op(0), su3f));
+ GINAC_ASSERT(is_a<su3f>(self->op(0)));
if (is_ex_exactly_of_type(other->op(0), su3f)) { // f*d is handled by su3d class
// global functions
-/** Return the color object handled by an ex. Deprecated: use ex_to<color>().
- * This is unsafe: you need to check the type first. */
-inline const color &ex_to_color(const ex &e)
-{
- return static_cast<const color &>(*e.bp);
-}
-
/** Specialization of is_exactly_a<color>(obj) for color objects. */
template<> inline bool is_exactly_a<color>(const basic & obj)
{
int constant::compare_same_type(const basic & other) const
{
- GINAC_ASSERT(is_exactly_of_type(other, constant));
+ GINAC_ASSERT(is_exactly_a<constant>(other));
const constant &o = static_cast<const constant &>(other);
if (serial == o.serial)
bool constant::is_equal_same_type(const basic & other) const
{
- GINAC_ASSERT(is_exactly_of_type(other, constant));
+ GINAC_ASSERT(is_exactly_a<constant>(other));
const constant &o = static_cast<const constant &>(other);
return serial == o.serial;
// utility functions
-/** Return the constant object handled by an ex. Deprecated: use ex_to<constant>().
- * This is unsafe: you need to check the type first. */
-inline const constant &ex_to_constant(const ex &e)
-{
- return static_cast<const constant &>(*e.bp);
-}
-
/** Specialization of is_exactly_a<constant>(obj) for constant objects. */
template<> inline bool is_exactly_a<constant>(const basic & obj)
{
// utility functions
-/** Return the ${CONTAINER} object handled by an ex. Deprecated: use ex_to<${CONTAINER}>().
- * This is unsafe: you need to check the type first. */
-inline const ${CONTAINER} &ex_to_${CONTAINER}(const ex &e)
-{
- return static_cast<const ${CONTAINER} &>(*e.bp);
-}
-
/** Specialization of is_exactly_a<${CONTAINER}>(obj) for ${CONTAINER} objects. */
template<> inline bool is_exactly_a<${CONTAINER}>(const basic & obj)
{
return obj.tinfo()==TINFO_${CONTAINER};
}
-inline ${CONTAINER} &ex_to_nonconst_${CONTAINER}(const ex &e)
-{
- return static_cast<${CONTAINER} &>(*e.bp);
-}
-
} // namespace GiNaC
#endif // ndef __GINAC_${CONTAINER_UC}_H__
{
${STLT} *vp = subschildren(ls, lr, no_pattern);
if (vp)
- return this${CONTAINER}(vp).bp->basic::subs(ls, lr, no_pattern);
+ return ex_to<basic>(this${CONTAINER}(vp)).basic::subs(ls, lr, no_pattern);
else
return basic::subs(ls, lr, no_pattern);
}
void ex::construct_from_basic(const basic & other)
{
if (!(other.flags & status_flags::evaluated)) {
- const ex & tmpex(other.eval(1)); // evaluate only one (top) level
+ const ex & tmpex = other.eval(1); // evaluate only one (top) level
bp = tmpex.bp;
GINAC_ASSERT(bp->flags & status_flags::dynallocated);
++bp->refcount;
* a thing a proxy class.) */
class ex
{
- friend class basic;
+ friend class archive_node;
+ friend bool are_ex_trivially_equal(const ex &, const ex &);
+ template<class T> friend const T &ex_to(const ex &);
+ template<class T> friend bool is_a(const ex &);
+ template<class T> friend bool is_exactly_a(const ex &);
// member functions
// member variables
public:
- basic *bp; ///< pointer to basic object managed by this
+ basic *bp; ///< pointer to basic object managed by this, direct manipulation deprecated
#ifdef OBSCURE_CINT_HACK
static basic * last_created_or_assigned_bp;
static basic * dummy_bp;
#include "expairseq.h"
#include "lst.h"
+#include "mul.h"
+#include "power.h"
#include "relational.h"
+#include "wildcard.h"
#include "print.h"
#include "archive.h"
#include "debugmsg.h"
namespace GiNaC {
+
GINAC_IMPLEMENT_REGISTERED_CLASS_NO_CTORS(expairseq, basic)
//////////
return new expairseq(*this);
}
-void expairseq::print(const print_context & c, unsigned level) const
+void expairseq::print(const print_context &c, unsigned level) const
{
debugmsg("expairseq print",LOGLEVEL_PRINT);
throw(std::logic_error("let_op not defined for expairseq and derived classes (add,mul,...)"));
}
-ex expairseq::map(map_function & f) const
+ex expairseq::map(map_function &f) const
{
epvector *v = new epvector;
v->reserve(seq.size());
// This differs from basic::match() because we want "a+b+c+d" to
// match "d+*+b" with "*" being "a+c", and we want to honor commutativity
- if (tinfo() == pattern.bp->tinfo()) {
+ if (this->tinfo() == ex_to<basic>(pattern).tinfo()) {
// Check whether global wildcard (one that matches the "rest of the
// expression", like "*" above) is present
ex rest = thisexpairseq(vp, default_overall_coeff());
for (unsigned i=0; i<repl_lst.nops(); i++) {
if (repl_lst.op(i).op(0).is_equal(global_wildcard))
- return rest.is_equal(*repl_lst.op(i).op(1).bp);
+ return rest.is_equal(repl_lst.op(i).op(1));
}
repl_lst.append(global_wildcard == rest);
return true;
{
epvector *vp = subschildren(ls, lr, no_pattern);
if (vp)
- return thisexpairseq(vp, overall_coeff).bp->basic::subs(ls, lr, no_pattern);
+ return ex_to<basic>(thisexpairseq(vp, overall_coeff)).basic::subs(ls, lr, no_pattern);
else
return basic::subs(ls, lr, no_pattern);
}
int expairseq::compare_same_type(const basic &other) const
{
- GINAC_ASSERT(is_of_type(other, expairseq));
+ GINAC_ASSERT(is_a<expairseq>(other));
const expairseq &o = static_cast<const expairseq &>(other);
int cmpval;
unsigned expairseq::calchash(void) const
{
- unsigned v = golden_ratio_hash(tinfo());
+ unsigned v = golden_ratio_hash(this->tinfo());
epvector::const_iterator i = seq.begin(), end = seq.end();
while (i != end) {
#if !EXPAIRSEQ_USE_HASHTAB
void expairseq::printpair(const print_context & c, const expair & p, unsigned upper_precedence) const
{
c.s << "[[";
- p.rest.bp->print(c, precedence());
+ p.rest.print(c, precedence());
c.s << ",";
- p.coeff.bp->print(c, precedence());
+ p.coeff.print(c, precedence());
c.s << "]]";
}
expair expairseq::combine_ex_with_coeff_to_pair(const ex &e,
const ex &c) const
{
- GINAC_ASSERT(is_ex_exactly_of_type(c,numeric));
+ GINAC_ASSERT(is_exactly_a<numeric>(c));
return expair(e,c);
}
expair expairseq::combine_pair_with_coeff_to_pair(const expair &p,
const ex &c) const
{
- GINAC_ASSERT(is_ex_exactly_of_type(p.coeff,numeric));
- GINAC_ASSERT(is_ex_exactly_of_type(c,numeric));
+ GINAC_ASSERT(is_exactly_a<numeric>(p.coeff));
+ GINAC_ASSERT(is_exactly_a<numeric>(c));
return expair(p.rest,ex_to<numeric>(p.coeff).mul_dyn(ex_to<numeric>(c)));
}
void expairseq::combine_overall_coeff(const ex &c)
{
- GINAC_ASSERT(is_ex_exactly_of_type(overall_coeff,numeric));
- GINAC_ASSERT(is_ex_exactly_of_type(c,numeric));
+ GINAC_ASSERT(is_exactly_a<numeric>(overall_coeff));
+ GINAC_ASSERT(is_exactly_a<numeric>(c));
overall_coeff = ex_to<numeric>(overall_coeff).add_dyn(ex_to<numeric>(c));
}
void expairseq::combine_overall_coeff(const ex &c1, const ex &c2)
{
- GINAC_ASSERT(is_ex_exactly_of_type(overall_coeff,numeric));
- GINAC_ASSERT(is_ex_exactly_of_type(c1,numeric));
- GINAC_ASSERT(is_ex_exactly_of_type(c2,numeric));
+ GINAC_ASSERT(is_exactly_a<numeric>(overall_coeff));
+ GINAC_ASSERT(is_exactly_a<numeric>(c1));
+ GINAC_ASSERT(is_exactly_a<numeric>(c2));
overall_coeff = ex_to<numeric>(overall_coeff).
add_dyn(ex_to<numeric>(c1).mul(ex_to<numeric>(c2)));
}
void expairseq::construct_from_2_ex(const ex &lh, const ex &rh)
{
- if (lh.bp->tinfo()==tinfo()) {
- if (rh.bp->tinfo()==tinfo()) {
+ if (ex_to<basic>(lh).tinfo()==this->tinfo()) {
+ if (ex_to<basic>(rh).tinfo()==this->tinfo()) {
#if EXPAIRSEQ_USE_HASHTAB
unsigned totalsize = ex_to<expairseq>(lh).seq.size() +
ex_to<expairseq>(rh).seq.size();
#endif // EXPAIRSEQ_USE_HASHTAB
return;
}
- } else if (rh.bp->tinfo()==tinfo()) {
+ } else if (ex_to<basic>(rh).tinfo()==this->tinfo()) {
#if EXPAIRSEQ_USE_HASHTAB
unsigned totalsize=ex_to<expairseq>(rh).seq.size()+1;
if (calc_hashtabsize(totalsize)!=0) {
int cmpval = p1.rest.compare(p2.rest);
if (cmpval==0) {
- p1.coeff=ex_to<numeric>(p1.coeff).add_dyn(ex_to<numeric>(p2.coeff));
+ p1.coeff = ex_to<numeric>(p1.coeff).add_dyn(ex_to<numeric>(p2.coeff));
if (!ex_to<numeric>(p1.coeff).is_zero()) {
// no further processing is necessary, since this
// one element will usually be recombined in eval()
int cmpval = (*first1).rest.compare((*first2).rest);
if (cmpval==0) {
// combine terms
- const numeric &newcoeff = ex_to<numeric>((*first1).coeff).
- add(ex_to<numeric>((*first2).coeff));
+ const numeric &newcoeff = ex_to<numeric>(first1->coeff).
+ add(ex_to<numeric>(first2->coeff));
if (!newcoeff.is_zero()) {
- seq.push_back(expair((*first1).rest,newcoeff));
+ seq.push_back(expair(first1->rest,newcoeff));
if (expair_needs_further_processing(seq.end()-1)) {
needs_further_processing = true;
}
cit = v.begin();
while (cit!=v.end()) {
- if (cit->bp->tinfo()==this->tinfo()) {
+ if (ex_to<basic>(*cit).tinfo()==this->tinfo()) {
++nexpairseqs;
noperands += ex_to<expairseq>(*cit).seq.size();
}
// copy elements and split off numerical part
cit = v.begin();
while (cit!=v.end()) {
- if (cit->bp->tinfo()==this->tinfo()) {
+ if (ex_to<basic>(*cit).tinfo()==this->tinfo()) {
const expairseq &subseqref = ex_to<expairseq>(*cit);
combine_overall_coeff(subseqref.overall_coeff);
epvector::const_iterator cit_s = subseqref.seq.begin();
cit = v.begin();
while (cit!=v.end()) {
- if (cit->rest.bp->tinfo()==this->tinfo()) {
+ if (ex_to<basic>(cit->rest).tinfo()==this->tinfo()) {
++nexpairseqs;
noperands += ex_to<expairseq>(cit->rest).seq.size();
}
// copy elements and split off numerical part
cit = v.begin();
while (cit!=v.end()) {
- if (cit->rest.bp->tinfo()==this->tinfo() &&
+ if (ex_to<basic>(cit->rest).tinfo()==this->tinfo() &&
this->can_make_flat(*cit)) {
const expairseq &subseqref = ex_to<expairseq>(cit->rest);
combine_overall_coeff(ex_to<numeric>(subseqref.overall_coeff),
// utility functions
-/** Return the expairseq object handled by an ex. Deprecated: use ex_to<expairseq>().
- * This is unsafe: you need to check the type first. */
-inline const expairseq &ex_to_expairseq(const ex &e)
-{
- return static_cast<const expairseq &>(*e.bp);
-}
-
/** Specialization of is_exactly_a<expairseq>(obj) for expairseq objects. */
template<> inline bool is_exactly_a<expairseq>(const basic & obj)
{
int fderivative::compare_same_type(const basic & other) const
{
- GINAC_ASSERT(is_of_type(other, fderivative));
+ GINAC_ASSERT(is_a<fderivative>(other));
const fderivative & o = static_cast<const fderivative &>(other);
if (parameter_set != o.parameter_set)
bool fderivative::is_equal_same_type(const basic & other) const
{
- GINAC_ASSERT(is_of_type(other, fderivative));
+ GINAC_ASSERT(is_a<fderivative>(other));
const fderivative & o = static_cast<const fderivative &>(other);
if (parameter_set != o.parameter_set)
bool fderivative::match_same_type(const basic & other) const
{
- GINAC_ASSERT(is_of_type(other, fderivative));
+ GINAC_ASSERT(is_a<fderivative>(other));
const fderivative & o = static_cast<const fderivative &>(other);
return parameter_set == o.parameter_set;
};
// utility functions/macros
-/** Return the object of type function handled by an ex.
- * This is unsafe: you need to check the type first. */
-inline const function &ex_to_function(const ex &e)
-{
- return static_cast<const function &>(*e.bp);
-}
/** Specialization of is_exactly_a<function>(obj) for objects of type function. */
template<> inline bool is_exactly_a<function>(const basic & obj)
}
#define is_ex_the_function(OBJ, FUNCNAME) \\
- (is_exactly_a<function>(OBJ) && static_cast<GiNaC::function *>(OBJ.bp)->get_serial() == function_index_##FUNCNAME)
+ (is_exactly_a<GiNaC::function>(OBJ) && ex_to<GiNaC::function>(OBJ).get_serial() == function_index_##FUNCNAME)
} // namespace GiNaC
int function::degree(const ex & s) const
{
- return is_equal(*s.bp) ? 1 : 0;
+ return is_equal(ex_to<basic>(s)) ? 1 : 0;
}
int function::ldegree(const ex & s) const
{
- return is_equal(*s.bp) ? 1 : 0;
+ return is_equal(ex_to<basic>(s)) ? 1 : 0;
}
ex function::coeff(const ex & s, int n) const
{
- if (is_equal(*s.bp))
+ if (is_equal(ex_to<basic>(s)))
return n==1 ? _ex1() : _ex0();
else
return n==0 ? ex(*this) : _ex0();
* must be such that dummy indices lie next to each other. */
int idx::compare_same_type(const basic & other) const
{
- GINAC_ASSERT(is_of_type(other, idx));
+ GINAC_ASSERT(is_a<idx>(other));
const idx &o = static_cast<const idx &>(other);
int cmpval = value.compare(o.value);
bool idx::match_same_type(const basic & other) const
{
- GINAC_ASSERT(is_of_type(other, idx));
+ GINAC_ASSERT(is_a<idx>(other));
const idx &o = static_cast<const idx &>(other);
return dim.is_equal(o.dim);
int varidx::compare_same_type(const basic & other) const
{
- GINAC_ASSERT(is_of_type(other, varidx));
+ GINAC_ASSERT(is_a<varidx>(other));
const varidx &o = static_cast<const varidx &>(other);
int cmpval = inherited::compare_same_type(other);
bool varidx::match_same_type(const basic & other) const
{
- GINAC_ASSERT(is_of_type(other, varidx));
+ GINAC_ASSERT(is_a<varidx>(other));
const varidx &o = static_cast<const varidx &>(other);
if (covariant != o.covariant)
int spinidx::compare_same_type(const basic & other) const
{
- GINAC_ASSERT(is_of_type(other, spinidx));
+ GINAC_ASSERT(is_a<spinidx>(other));
const spinidx &o = static_cast<const spinidx &>(other);
// Check dottedness first so dummy indices will end up next to each other
bool spinidx::match_same_type(const basic & other) const
{
- GINAC_ASSERT(is_of_type(other, spinidx));
+ GINAC_ASSERT(is_a<spinidx>(other));
const spinidx &o = static_cast<const spinidx &>(other);
if (dotted != o.dotted)
// First look for index substitutions
for (unsigned i=0; i<ls.nops(); i++) {
- if (is_equal(*(ls.op(i)).bp)) {
+ if (is_equal(ex_to<basic>(ls.op(i)))) {
// Substitution index->index
if (is_ex_of_type(lr.op(i), idx))
// utility functions
-/** Return the idx object handled by an ex. Deprecated: use ex_to<idx>().
- * This is unsafe: you need to check the type first. */
-inline const idx &ex_to_idx(const ex & e)
-{
- return static_cast<const idx &>(*e.bp);
-}
-
-/** Return the varidx object handled by an ex. Deprecated: use ex_to<varidx>().
- * This is unsafe: you need to check the type first. */
-inline const varidx &ex_to_varidx(const ex & e)
-{
- return static_cast<const varidx &>(*e.bp);
-}
-
-/** Return the spinidx object handled by an ex. Deprecated: use ex_to<spinidx>().
- * This is unsafe: you need to check the type first. */
-inline const spinidx &ex_to_spinidx(const ex & e)
-{
- return static_cast<const spinidx &>(*e.bp);
-}
-
/** Specialization of is_exactly_a<idx>(obj) for idx objects. */
template<> inline bool is_exactly_a<idx>(const basic & obj)
{
symtree = sy_none();
break;
}
- ex_to_nonconst_symmetry(symtree).validate(seq.size() - 1);
+ const_cast<symmetry &>(ex_to<symmetry>(symtree)).validate(seq.size() - 1);
}
}
int indexed::compare_same_type(const basic & other) const
{
- GINAC_ASSERT(is_of_type(other, indexed));
+ GINAC_ASSERT(is_a<indexed>(other));
return inherited::compare_same_type(other);
}
// Canonicalize indices according to the symmetry properties
if (seq.size() > 2) {
exvector v = seq;
- GINAC_ASSERT(is_ex_exactly_of_type(symtree, symmetry));
+ GINAC_ASSERT(is_exactly_a<symmetry>(symtree));
int sig = canonicalize(v.begin() + 1, ex_to<symmetry>(symtree));
if (sig != INT_MAX) {
// Something has changed while sorting indices, more evaluations later
}
// Let the class of the base object perform additional evaluations
- return base.bp->eval_indexed(*this);
+ return ex_to<basic>(base).eval_indexed(*this);
}
int indexed::degree(const ex & s) const
{
- return is_equal(*s.bp) ? 1 : 0;
+ return is_equal(ex_to<basic>(s)) ? 1 : 0;
}
int indexed::ldegree(const ex & s) const
{
- return is_equal(*s.bp) ? 1 : 0;
+ return is_equal(ex_to<basic>(s)) ? 1 : 0;
}
ex indexed::coeff(const ex & s, int n) const
{
- if (is_equal(*s.bp))
+ if (is_equal(ex_to<basic>(s)))
return n==1 ? _ex1() : _ex0();
else
return n==0 ? ex(*this) : _ex0();
if (!symtree.is_zero()) {
if (!is_ex_exactly_of_type(symtree, symmetry))
throw(std::invalid_argument("symmetry of indexed object must be of type symmetry"));
- ex_to_nonconst_symmetry(symtree).validate(seq.size() - 1);
+ const_cast<symmetry &>(ex_to<symmetry>(symtree)).validate(seq.size() - 1);
}
}
}
// Try to contract the first one with the second one
- contracted = it1->op(0).bp->contract_with(it1, it2, v);
+ contracted = ex_to<basic>(it1->op(0)).contract_with(it1, it2, v);
if (!contracted) {
// That didn't work; maybe the second object knows how to
// contract itself with the first one
- contracted = it2->op(0).bp->contract_with(it2, it1, v);
+ contracted = ex_to<basic>(it2->op(0)).contract_with(it2, it1, v);
}
if (contracted) {
contraction_done:
// Product of indexed object with a scalar?
if (is_ex_exactly_of_type(r, mul) && r.nops() == 2
&& is_ex_exactly_of_type(r.op(1), numeric) && is_ex_of_type(r.op(0), indexed))
- return r.op(0).op(0).bp->scalar_mul_indexed(r.op(0), ex_to<numeric>(r.op(1)));
+ return ex_to<basic>(r.op(0).op(0)).scalar_mul_indexed(r.op(0), ex_to<numeric>(r.op(1)));
else
return r;
}
if (!indices_consistent(free_indices, free_indices_of_term))
throw (std::runtime_error("simplify_indexed: inconsistent indices in sum"));
if (is_ex_of_type(sum, indexed) && is_ex_of_type(term, indexed))
- sum = sum.op(0).bp->add_indexed(sum, term);
+ sum = ex_to<basic>(sum.op(0)).add_indexed(sum, term);
else
sum += term;
}
// utility functions
-/** Return the indexed object handled by an ex. Deprecated: use ex_to<indexed>().
- * This is unsafe: you need to check the type first. */
-inline const indexed &ex_to_indexed(const ex &e)
-{
- return static_cast<const indexed &>(*e.bp);
-}
-
/** Specialization of is_exactly_a<indexed>(obj) for indexed objects. */
template<> inline bool is_exactly_a<indexed>(const basic & obj)
{
else
return _ex0();
} else if (is_ex_exactly_of_type(x, mul)) {
- mul *m = static_cast<mul *>(x.bp);
+ const mul &m = ex_to<mul>(x);
// O(c*expr) -> O(expr)
- if (is_ex_exactly_of_type(m->op(m->nops() - 1), numeric))
- return Order(x / m->op(m->nops() - 1)).hold();
+ if (is_ex_exactly_of_type(m.op(m.nops() - 1), numeric))
+ return Order(x / m.op(m.nops() - 1)).hold();
}
return Order(x).hold();
}
{
// Just wrap the function into a pseries object
epvector new_seq;
- GINAC_ASSERT(is_ex_exactly_of_type(r.lhs(),symbol));
+ GINAC_ASSERT(is_exactly_a<symbol>(r.lhs()));
const symbol &s = ex_to<symbol>(r.lhs());
new_seq.push_back(expair(Order(_ex1()), numeric(std::min(x.ldegree(s), order))));
return pseries(r, new_seq);
const ex sol = lsolve(lst(eqns),lst(symbols));
GINAC_ASSERT(sol.nops()==1);
- GINAC_ASSERT(is_ex_exactly_of_type(sol.op(0),relational));
+ GINAC_ASSERT(is_exactly_a<relational>(sol.op(0)));
return sol.op(0).op(1); // return rhs of first solution
}
// tgamma series directly.
const ex arg1_pt = arg1.subs(rel);
const ex arg2_pt = arg2.subs(rel);
- GINAC_ASSERT(is_ex_exactly_of_type(rel.lhs(),symbol));
+ GINAC_ASSERT(is_exactly_a<symbol>(rel.lhs()));
const symbol &s = ex_to<symbol>(rel.lhs());
ex arg1_ser, arg2_ser, arg1arg2_ser;
if ((!arg1_pt.info(info_flags::integer) || arg1_pt.info(info_flags::positive)) &&
int order,
unsigned options)
{
- GINAC_ASSERT(is_ex_exactly_of_type(rel.lhs(),symbol));
+ GINAC_ASSERT(is_exactly_a<symbol>(rel.lhs()));
ex arg_pt;
bool must_expand_arg = false;
// maybe substitution of rel into arg fails because of a pole
int order,
unsigned options)
{
- GINAC_ASSERT(is_ex_exactly_of_type(rel.lhs(),symbol));
+ GINAC_ASSERT(is_exactly_a<symbol>(rel.lhs()));
// method:
// Taylor series where there is no pole falls back to tan_deriv.
// On a pole simply expand sin(x)/cos(x).
int order,
unsigned options)
{
- GINAC_ASSERT(is_ex_exactly_of_type(rel.lhs(),symbol));
+ GINAC_ASSERT(is_exactly_a<symbol>(rel.lhs()));
// method:
// Taylor series where there is no pole or cut falls back to atan_deriv.
// There are two branch cuts, one runnig from I up the imaginary axis and
int order,
unsigned options)
{
- GINAC_ASSERT(is_ex_exactly_of_type(rel.lhs(),symbol));
+ GINAC_ASSERT(is_exactly_a<symbol>(rel.lhs()));
// method:
// Taylor series where there is no pole falls back to tanh_deriv.
// On a pole simply expand sinh(x)/cosh(x).
int order,
unsigned options)
{
- GINAC_ASSERT(is_ex_exactly_of_type(rel.lhs(),symbol));
+ GINAC_ASSERT(is_exactly_a<symbol>(rel.lhs()));
// method:
// Taylor series where there is no pole or cut falls back to atanh_deriv.
// There are two branch cuts, one runnig from 1 up the real axis and one
if (is_lexer_symbol_predefined($1))
$$ = $1.eval();
else
- throw (std::runtime_error("unknown symbol '" + ex_to_symbol($1).get_name() + "'"));
+ throw (std::runtime_error("unknown symbol '" + ex_to<symbol>($1).get_name() + "'"));
}
| T_LITERAL {$$ = $1;}
| T_DIGITS {$$ = $1;}
| T_SYMBOL '(' exprseq ')' {
- unsigned i = function::find_function(ex_to_symbol($1).get_name(), $3.nops());
- $$ = function(i, static_cast<const exprseq &>(*($3.bp))).eval(1);
+ unsigned i = function::find_function(ex_to<symbol>($1).get_name(), $3.nops());
+ $$ = function(i, ex_to<exprseq>($3)).eval(1);
}
| exp T_EQUAL exp {$$ = $1 == $3;}
| exp T_NOTEQ exp {$$ = $1 != $3;}
| exp '!' {$$ = factorial($1);}
| '(' exp ')' {$$ = $2;}
| '{' list_or_empty '}' {$$ = $2;}
- | '[' matrix ']' {$$ = lst_to_matrix(ex_to_lst($2));}
+ | '[' matrix ']' {$$ = lst_to_matrix(ex_to<lst>($2));}
;
exprseq : exp {$$ = exprseq($1);}
- | exprseq ',' exp {exprseq es(static_cast<exprseq &>(*($1.bp))); $$ = es.append($3);}
+ | exprseq ',' exp {exprseq es(ex_to<exprseq>($1)); $$ = es.append($3);}
;
list_or_empty: /* empty */ {$$ = *new lst;}
;
list : exp {$$ = lst($1);}
- | list ',' exp {lst l(static_cast<lst &>(*($1.bp))); $$ = l.append($3);}
+ | list ',' exp {lst l(ex_to<lst>($1)); $$ = l.append($3);}
;
matrix : '[' row ']' {$$ = lst($2);}
- | matrix ',' '[' row ']' {lst l(static_cast<lst &>(*($1.bp))); $$ = l.append($4);}
+ | matrix ',' '[' row ']' {lst l(ex_to<lst>($1)); $$ = l.append($4);}
;
row : exp {$$ = lst($1);}
- | row ',' exp {lst l(static_cast<lst &>(*($1.bp))); $$ = l.append($3);}
+ | row ',' exp {lst l(ex_to<lst>($1)); $$ = l.append($3);}
;
{
debugmsg("matrix print", LOGLEVEL_PRINT);
- if (is_of_type(c, print_tree)) {
+ if (is_a<print_tree>(c)) {
inherited::print(c, level);
int matrix::compare_same_type(const basic & other) const
{
- GINAC_ASSERT(is_exactly_of_type(other, matrix));
- const matrix & o = static_cast<const matrix &>(other);
+ GINAC_ASSERT(is_exactly_a<matrix>(other));
+ const matrix &o = static_cast<const matrix &>(other);
// compare number of rows
if (row != o.rows())
bool matrix::match_same_type(const basic & other) const
{
- GINAC_ASSERT(is_exactly_of_type(other, matrix));
+ GINAC_ASSERT(is_exactly_a<matrix>(other));
const matrix & o = static_cast<const matrix &>(other);
// The number of rows and columns must be the same. This is necessary to
/** Automatic symbolic evaluation of an indexed matrix. */
ex matrix::eval_indexed(const basic & i) const
{
- GINAC_ASSERT(is_of_type(i, indexed));
- GINAC_ASSERT(is_ex_of_type(i.op(0), matrix));
+ GINAC_ASSERT(is_a<indexed>(i));
+ GINAC_ASSERT(is_a<matrix>(i.op(0)));
bool all_indices_unsigned = static_cast<const indexed &>(i).all_index_values_are(info_flags::nonnegint);
/** Sum of two indexed matrices. */
ex matrix::add_indexed(const ex & self, const ex & other) const
{
- GINAC_ASSERT(is_ex_of_type(self, indexed));
- GINAC_ASSERT(is_ex_of_type(self.op(0), matrix));
- GINAC_ASSERT(is_ex_of_type(other, indexed));
+ GINAC_ASSERT(is_a<indexed>(self));
+ GINAC_ASSERT(is_a<matrix>(self.op(0)));
+ GINAC_ASSERT(is_a<indexed>(other));
GINAC_ASSERT(self.nops() == 2 || self.nops() == 3);
// Only add two matrices
/** Product of an indexed matrix with a number. */
ex matrix::scalar_mul_indexed(const ex & self, const numeric & other) const
{
- GINAC_ASSERT(is_ex_of_type(self, indexed));
- GINAC_ASSERT(is_ex_of_type(self.op(0), matrix));
+ GINAC_ASSERT(is_a<indexed>(self));
+ GINAC_ASSERT(is_a<matrix>(self.op(0)));
GINAC_ASSERT(self.nops() == 2 || self.nops() == 3);
const matrix &self_matrix = ex_to<matrix>(self.op(0));
/** Contraction of an indexed matrix with something else. */
bool matrix::contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const
{
- GINAC_ASSERT(is_ex_of_type(*self, indexed));
- GINAC_ASSERT(is_ex_of_type(*other, indexed));
+ GINAC_ASSERT(is_a<indexed>(*self));
+ GINAC_ASSERT(is_a<indexed>(*other));
GINAC_ASSERT(self->nops() == 2 || self->nops() == 3);
- GINAC_ASSERT(is_ex_of_type(self->op(0), matrix));
+ GINAC_ASSERT(is_a<matrix>(self->op(0)));
// Only contract with other matrices
if (!is_ex_of_type(other->op(0), matrix))
++k;
} else {
// search largest element in column co beginning at row ro
- GINAC_ASSERT(is_ex_of_type(this->m[k*col+co],numeric));
+ GINAC_ASSERT(is_a<numeric>(this->m[k*col+co]));
unsigned kmax = k+1;
numeric mmax = abs(ex_to<numeric>(m[kmax*col+co]));
while (kmax<row) {
- GINAC_ASSERT(is_ex_of_type(this->m[kmax*col+co],numeric));
+ GINAC_ASSERT(is_a<numeric>(this->m[kmax*col+co]));
numeric tmp = ex_to<numeric>(this->m[kmax*col+co]);
if (abs(tmp) > mmax) {
mmax = tmp;
// utility functions
-/** Return the matrix object handled by an ex. Deprecated: use ex_to<matrix>().
- * This is unsafe: you need to check the type first. */
-inline const matrix &ex_to_matrix(const ex &e)
-{
- return static_cast<const matrix &>(*e.bp);
-}
-
/** Specialization of is_exactly_a<matrix>(obj) for matrix objects. */
template<> inline bool is_exactly_a<matrix>(const basic & obj)
{
#ifdef DO_GINAC_ASSERT
epvector::const_iterator i = seq.begin(), end = seq.end();
while (i != end) {
- GINAC_ASSERT((!is_ex_exactly_of_type(i->rest, mul)) ||
+ GINAC_ASSERT((!is_exactly_a<mul>(i->rest)) ||
(!(ex_to<numeric>(i->coeff).is_integer())));
GINAC_ASSERT(!(i->is_canonical_numeric()));
if (is_ex_exactly_of_type(recombine_pair_to_ex(*i), numeric))
print(print_tree(std::cerr));
- GINAC_ASSERT(!is_ex_exactly_of_type(recombine_pair_to_ex(*i), numeric));
+ GINAC_ASSERT(!is_exactly_a<numeric>(recombine_pair_to_ex(*i)));
/* for paranoia */
expair p = split_ex_to_pair(recombine_pair_to_ex(*i));
GINAC_ASSERT(p.rest.is_equal(i->rest));
void mul::combine_overall_coeff(const ex & c)
{
- GINAC_ASSERT(is_ex_exactly_of_type(overall_coeff,numeric));
- GINAC_ASSERT(is_ex_exactly_of_type(c,numeric));
+ GINAC_ASSERT(is_exactly_a<numeric>(overall_coeff));
+ GINAC_ASSERT(is_exactly_a<numeric>(c));
overall_coeff = ex_to<numeric>(overall_coeff).mul_dyn(ex_to<numeric>(c));
}
void mul::combine_overall_coeff(const ex & c1, const ex & c2)
{
- GINAC_ASSERT(is_ex_exactly_of_type(overall_coeff,numeric));
- GINAC_ASSERT(is_ex_exactly_of_type(c1,numeric));
- GINAC_ASSERT(is_ex_exactly_of_type(c2,numeric));
+ GINAC_ASSERT(is_exactly_a<numeric>(overall_coeff));
+ GINAC_ASSERT(is_exactly_a<numeric>(c1));
+ GINAC_ASSERT(is_exactly_a<numeric>(c2));
overall_coeff = ex_to<numeric>(overall_coeff).mul_dyn(ex_to<numeric>(c1).power(ex_to<numeric>(c2)));
}
bool mul::can_make_flat(const expair & p) const
{
- GINAC_ASSERT(is_ex_exactly_of_type(p.coeff,numeric));
+ GINAC_ASSERT(is_exactly_a<numeric>(p.coeff));
// this assertion will probably fail somewhere
// it would require a more careful make_flat, obeying the power laws
// probably should return true only if p.coeff is integer
// utility functions
-/** Return the mul object handled by an ex. Deprecated: use ex_to<mul>().
- * This is unsafe: you need to check the type first. */
-inline const mul &ex_to_mul(const ex &e)
-{
- return static_cast<const mul &>(*e.bp);
-}
-
/** Specialization of is_exactly_a<mul>(obj) for mul objects. */
template<> inline bool is_exactly_a<mul>(const basic & obj)
{
{
debugmsg("ncmul print", LOGLEVEL_PRINT);
- if (is_of_type(c, print_tree)) {
+ if (is_a<print_tree>(c)) {
inherited::print(c, level);
- } else if (is_of_type(c, print_csrc)) {
+ } else if (is_a<print_csrc>(c)) {
c.s << "ncmul(";
exvector::const_iterator it = seq.begin(), itend = seq.end()-1;
// utility functions
-/** Return the ncmul object handled by an ex. Deprecated: use ex_to<ncmul>().
- * This is unsafe: you need to check the type first. */
-inline const ncmul &ex_to_ncmul(const ex &e)
-{
- return static_cast <const ncmul &>(*e.bp);
-}
-
/** Specialization of is_exactly_a<ncmul>(obj) for ncmul objects. */
template<> inline bool is_exactly_a<ncmul>(const basic & obj)
{
epvector::const_iterator itend = seq.end();
numeric c = _num0();
while (it != itend) {
- GINAC_ASSERT(!is_ex_exactly_of_type(it->rest,numeric));
- GINAC_ASSERT(is_ex_exactly_of_type(it->coeff,numeric));
+ GINAC_ASSERT(!is_exactly_a<numeric>(it->rest));
+ GINAC_ASSERT(is_exactly_a<numeric>(it->coeff));
c = gcd(ex_to<numeric>(it->coeff), c);
it++;
}
- GINAC_ASSERT(is_ex_exactly_of_type(overall_coeff,numeric));
+ GINAC_ASSERT(is_exactly_a<numeric>(overall_coeff));
c = gcd(ex_to<numeric>(overall_coeff),c);
return c;
}
epvector::const_iterator it = seq.begin();
epvector::const_iterator itend = seq.end();
while (it != itend) {
- GINAC_ASSERT(!is_ex_exactly_of_type(recombine_pair_to_ex(*it),numeric));
+ GINAC_ASSERT(!is_exactly_a<numeric>(recombine_pair_to_ex(*it)));
++it;
}
#endif // def DO_GINAC_ASSERT
- GINAC_ASSERT(is_ex_exactly_of_type(overall_coeff,numeric));
+ GINAC_ASSERT(is_exactly_a<numeric>(overall_coeff));
return abs(ex_to<numeric>(overall_coeff));
}
{
epvector::const_iterator it = seq.begin();
epvector::const_iterator itend = seq.end();
- GINAC_ASSERT(is_ex_exactly_of_type(overall_coeff,numeric));
+ GINAC_ASSERT(is_exactly_a<numeric>(overall_coeff));
numeric cur_max = abs(ex_to<numeric>(overall_coeff));
while (it != itend) {
numeric a;
- GINAC_ASSERT(!is_ex_exactly_of_type(it->rest,numeric));
+ GINAC_ASSERT(!is_exactly_a<numeric>(it->rest));
a = abs(ex_to<numeric>(it->coeff));
if (a > cur_max)
cur_max = a;
epvector::const_iterator it = seq.begin();
epvector::const_iterator itend = seq.end();
while (it != itend) {
- GINAC_ASSERT(!is_ex_exactly_of_type(recombine_pair_to_ex(*it),numeric));
+ GINAC_ASSERT(!is_exactly_a<numeric>(recombine_pair_to_ex(*it)));
it++;
}
#endif // def DO_GINAC_ASSERT
- GINAC_ASSERT(is_ex_exactly_of_type(overall_coeff,numeric));
+ GINAC_ASSERT(is_exactly_a<numeric>(overall_coeff));
return abs(ex_to<numeric>(overall_coeff));
}
epvector::const_iterator it = seq.begin();
epvector::const_iterator itend = seq.end();
while (it != itend) {
- GINAC_ASSERT(!is_ex_exactly_of_type(it->rest,numeric));
+ GINAC_ASSERT(!is_exactly_a<numeric>(it->rest));
numeric coeff = GiNaC::smod(ex_to<numeric>(it->coeff), xi);
if (!coeff.is_zero())
newseq.push_back(expair(it->rest, coeff));
it++;
}
- GINAC_ASSERT(is_ex_exactly_of_type(overall_coeff,numeric));
+ GINAC_ASSERT(is_exactly_a<numeric>(overall_coeff));
numeric coeff = GiNaC::smod(ex_to<numeric>(overall_coeff), xi);
return (new add(newseq,coeff))->setflag(status_flags::dynallocated);
}
epvector::const_iterator it = seq.begin();
epvector::const_iterator itend = seq.end();
while (it != itend) {
- GINAC_ASSERT(!is_ex_exactly_of_type(recombine_pair_to_ex(*it),numeric));
+ GINAC_ASSERT(!is_exactly_a<numeric>(recombine_pair_to_ex(*it)));
it++;
}
#endif // def DO_GINAC_ASSERT
mul * mulcopyp = new mul(*this);
- GINAC_ASSERT(is_ex_exactly_of_type(overall_coeff,numeric));
+ GINAC_ASSERT(is_exactly_a<numeric>(overall_coeff));
mulcopyp->overall_coeff = GiNaC::smod(ex_to<numeric>(overall_coeff),xi);
mulcopyp->clearflag(status_flags::evaluated);
mulcopyp->clearflag(status_flags::hash_calculated);
// as defined by get_first_symbol() is made positive)
const symbol *x;
if (get_first_symbol(den, x)) {
- GINAC_ASSERT(is_ex_exactly_of_type(den.unit(*x),numeric));
+ GINAC_ASSERT(is_exactly_a<numeric>(den.unit(*x)));
if (ex_to<numeric>(den.unit(*x)).is_negative()) {
num *= _ex_1();
den *= _ex_1();
lst sym_lst, repl_lst;
ex e = bp->normal(sym_lst, repl_lst, level);
- GINAC_ASSERT(is_ex_of_type(e, lst));
+ GINAC_ASSERT(is_a<lst>(e));
// Re-insert replaced symbols
if (sym_lst.nops() > 0)
lst sym_lst, repl_lst;
ex e = bp->normal(sym_lst, repl_lst, 0);
- GINAC_ASSERT(is_ex_of_type(e, lst));
+ GINAC_ASSERT(is_a<lst>(e));
// Re-insert replaced symbols
if (sym_lst.nops() > 0)
lst sym_lst, repl_lst;
ex e = bp->normal(sym_lst, repl_lst, 0);
- GINAC_ASSERT(is_ex_of_type(e, lst));
+ GINAC_ASSERT(is_a<lst>(e));
// Re-insert replaced symbols
if (sym_lst.nops() > 0)
lst sym_lst, repl_lst;
ex e = bp->normal(sym_lst, repl_lst, 0);
- GINAC_ASSERT(is_ex_of_type(e, lst));
+ GINAC_ASSERT(is_a<lst>(e));
// Re-insert replaced symbols
if (sym_lst.nops() > 0)
int numeric::compare_same_type(const basic &other) const
{
- GINAC_ASSERT(is_exactly_of_type(other, numeric));
+ GINAC_ASSERT(is_exactly_a<numeric>(other));
const numeric &o = static_cast<const numeric &>(other);
return this->compare(o);
bool numeric::is_equal_same_type(const basic &other) const
{
- GINAC_ASSERT(is_exactly_of_type(other,numeric));
+ GINAC_ASSERT(is_exactly_a<numeric>(other));
const numeric &o = static_cast<const numeric &>(other);
return this->is_equal(o);
// utility functions
-/** Return the numeric object handled by an ex. Deprecated: use ex_to<numeric>().
- * This is unsafe: you need to check the type first. */
-inline const numeric &ex_to_numeric(const ex &e)
-{
- return static_cast<const numeric &>(*e.bp);
-}
-
/** Specialization of is_exactly_a<numeric>(obj) for numeric objects. */
template<> inline bool is_exactly_a<numeric>(const basic & obj)
{
int power::compare_same_type(const basic & other) const
{
- GINAC_ASSERT(is_exactly_of_type(other, power));
+ GINAC_ASSERT(is_exactly_a<power>(other));
const power &o = static_cast<const power &>(other);
int cmpval = basis.compare(o.basis);
term.reserve(m+1);
for (l=0; l<m-1; l++) {
const ex & b = a.op(l);
- GINAC_ASSERT(!is_ex_exactly_of_type(b,add));
- GINAC_ASSERT(!is_ex_exactly_of_type(b,power) ||
- !is_ex_exactly_of_type(ex_to<power>(b).exponent,numeric) ||
+ GINAC_ASSERT(!is_exactly_a<add>(b));
+ GINAC_ASSERT(!is_exactly_a<power>(b) ||
+ !is_exactly_a<numeric>(ex_to<power>(b).exponent) ||
!ex_to<numeric>(ex_to<power>(b).exponent).is_pos_integer() ||
- !is_ex_exactly_of_type(ex_to<power>(b).basis,add) ||
- !is_ex_exactly_of_type(ex_to<power>(b).basis,mul) ||
- !is_ex_exactly_of_type(ex_to<power>(b).basis,power));
+ !is_exactly_a<add>(ex_to<power>(b).basis) ||
+ !is_exactly_a<mul>(ex_to<power>(b).basis) ||
+ !is_exactly_a<power>(ex_to<power>(b).basis));
if (is_ex_exactly_of_type(b,mul))
term.push_back(expand_mul(ex_to<mul>(b),numeric(k[l])));
else
}
const ex & b = a.op(l);
- GINAC_ASSERT(!is_ex_exactly_of_type(b,add));
- GINAC_ASSERT(!is_ex_exactly_of_type(b,power) ||
- !is_ex_exactly_of_type(ex_to<power>(b).exponent,numeric) ||
+ GINAC_ASSERT(!is_exactly_a<add>(b));
+ GINAC_ASSERT(!is_exactly_a<power>(b) ||
+ !is_exactly_a<numeric>(ex_to<power>(b).exponent) ||
!ex_to<numeric>(ex_to<power>(b).exponent).is_pos_integer() ||
- !is_ex_exactly_of_type(ex_to<power>(b).basis,add) ||
- !is_ex_exactly_of_type(ex_to<power>(b).basis,mul) ||
- !is_ex_exactly_of_type(ex_to<power>(b).basis,power));
+ !is_exactly_a<add>(ex_to<power>(b).basis) ||
+ !is_exactly_a<mul>(ex_to<power>(b).basis) ||
+ !is_exactly_a<power>(ex_to<power>(b).basis));
if (is_ex_exactly_of_type(b,mul))
term.push_back(expand_mul(ex_to<mul>(b),numeric(n-k_cum[m-2])));
else
const ex & r = cit0->rest;
const ex & c = cit0->coeff;
- GINAC_ASSERT(!is_ex_exactly_of_type(r,add));
- GINAC_ASSERT(!is_ex_exactly_of_type(r,power) ||
- !is_ex_exactly_of_type(ex_to<power>(r).exponent,numeric) ||
+ GINAC_ASSERT(!is_exactly_a<add>(r));
+ GINAC_ASSERT(!is_exactly_a<power>(r) ||
+ !is_exactly_a<numeric>(ex_to<power>(r).exponent) ||
!ex_to<numeric>(ex_to<power>(r).exponent).is_pos_integer() ||
- !is_ex_exactly_of_type(ex_to<power>(r).basis,add) ||
- !is_ex_exactly_of_type(ex_to<power>(r).basis,mul) ||
- !is_ex_exactly_of_type(ex_to<power>(r).basis,power));
+ !is_exactly_a<add>(ex_to<power>(r).basis) ||
+ !is_exactly_a<mul>(ex_to<power>(r).basis) ||
+ !is_exactly_a<power>(ex_to<power>(r).basis));
if (are_ex_trivially_equal(c,_ex1())) {
if (is_ex_exactly_of_type(r,mul)) {
// utility functions
-/** Return the power object handled by an ex. Deprecated: use ex_to<power>().
- * This is unsafe: you need to check the type first. */
-inline const power &ex_to_power(const ex &e)
-{
- return static_cast<const power &>(*e.bp);
-}
-
/** Efficient specialization of is_exactly_a<power>(obj) for power objects. */
template<> inline bool is_exactly_a<power>(const basic & obj)
{
int pseries::compare_same_type(const basic & other) const
{
- GINAC_ASSERT(is_of_type(other, pseries));
+ GINAC_ASSERT(is_a<pseries>(other));
const pseries &o = static_cast<const pseries &>(other);
// first compare the lengths of the series...
ex point;
};
-/** Return a reference to the pseries object embedded in an expression.
- * The result is undefined if the expression does not contain a pseries
- * object at its top level.
- *
- * @param e expression
- * @return reference to pseries object
- * @see is_a<> */
-inline const pseries &ex_to_pseries(const ex &e)
-{
- return static_cast<const pseries &>(*e.bp);
-}
+
+// utility functions
/** Specialization of is_exactly_a<pseries>(obj) for pseries objects. */
template<> inline bool is_exactly_a<pseries>(const basic & obj)
* @see pseries::convert_to_poly */
inline ex series_to_poly(const ex &e)
{
- return (static_cast<const pseries &>(*e.bp).convert_to_poly(true));
+ return (ex_to<pseries>(e).convert_to_poly(true));
}
inline bool is_terminating(const pseries & s)
{
debugmsg("relational print",LOGLEVEL_PRINT);
- if (is_of_type(c, print_tree)) {
+ if (is_a<print_tree>(c)) {
inherited::print(c, level);
int relational::compare_same_type(const basic & other) const
{
- GINAC_ASSERT(is_exactly_of_type(other, relational));
+ GINAC_ASSERT(is_exactly_a<relational>(other));
const relational &oth = static_cast<const relational &>(other);
if (o == oth.o) {
bool relational::match_same_type(const basic & other) const
{
- GINAC_ASSERT(is_exactly_of_type(other, relational));
+ GINAC_ASSERT(is_exactly_a<relational>(other));
const relational &oth = static_cast<const relational &>(other);
return o == oth.o;
// utility functions
-/** Return the relational object handled by an ex. Deprecated: use ex_to<relational>().
- * This is unsafe: you need to check the type first. */
-inline const relational &ex_to_relational(const ex &e)
-{
- return static_cast<const relational &>(*e.bp);
-}
-
/** Specialization of is_exactly_a<relational>(obj) for relational objects. */
template<> inline bool is_exactly_a<relational>(const basic & obj)
{
{
debugmsg("structure print",LOGLEVEL_PRINT);
- if (is_of_type(c, print_tree)) {
+ if (is_a<print_tree>(c)) {
c.s << std::string(level, ' ') << class_name()
<< std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec
bool structure::is_equal_same_type(const basic & other) const
{
- GINAC_ASSERT(is_of_type(other, structure));
+ GINAC_ASSERT(is_a<structure>(other));
return true; // all structures are the same
}
{
debugmsg("symbol print", LOGLEVEL_PRINT);
- if (is_of_type(c, print_tree)) {
+ if (is_a<print_tree>(c)) {
c.s << std::string(level, ' ') << name << " (" << class_name() << ")"
<< ", serial=" << serial
<< std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec
<< std::endl;
- } else if (is_of_type(c, print_latex))
+ } else if (is_a<print_latex>(c))
c.s << TeX_name;
else
c.s << name;
int symbol::compare_same_type(const basic & other) const
{
- GINAC_ASSERT(is_of_type(other,symbol));
+ GINAC_ASSERT(is_a<symbol>(other));
const symbol *o = static_cast<const symbol *>(&other);
if (serial==o->serial) return 0;
return serial < o->serial ? -1 : 1;
bool symbol::is_equal_same_type(const basic & other) const
{
- GINAC_ASSERT(is_of_type(other,symbol));
+ GINAC_ASSERT(is_a<symbol>(other));
const symbol *o = static_cast<const symbol *>(&other);
return serial==o->serial;
}
// utility functions
-/** Return the symbol object handled by an ex. Deprecated: use ex_to<symbol>().
- * This is unsafe: you need to check the type first. */
-inline const symbol &ex_to_symbol(const ex &e)
-{
- return static_cast<const symbol &>(*e.bp);
-}
-
-inline symbol &ex_to_nonconst_symbol(const ex &e)
-{
- return static_cast<symbol &>(*e.bp);
-}
-
/** Specialization of is_exactly_a<symbol>(obj) for symbol objects. */
template<> inline bool is_exactly_a<symbol>(const basic & obj)
{
int symmetry::compare_same_type(const basic & other) const
{
- GINAC_ASSERT(is_of_type(other, symmetry));
+ GINAC_ASSERT(is_a<symmetry>(other));
// All symmetry trees are equal. They are not supposed to appear in
// ordinary expressions anyway...
{
debugmsg("symmetry print", LOGLEVEL_PRINT);
- if (is_of_type(c, print_tree)) {
+ if (is_a<print_tree>(c)) {
c.s << std::string(level, ' ') << class_name()
<< std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec
{
// All children must have the same number of indices
if (type != none && !children.empty()) {
- GINAC_ASSERT(is_ex_exactly_of_type(children[0], symmetry));
+ GINAC_ASSERT(is_exactly_a<symmetry>(children[0]));
if (ex_to<symmetry>(children[0]).indices.size() != c.indices.size())
throw (std::logic_error("symmetry:add(): children must have same number of indices"));
}
bool operator() (const ex &lh, const ex &rh) const
{
- GINAC_ASSERT(is_ex_exactly_of_type(lh, symmetry));
- GINAC_ASSERT(is_ex_exactly_of_type(rh, symmetry));
+ GINAC_ASSERT(is_exactly_a<symmetry>(lh));
+ GINAC_ASSERT(is_exactly_a<symmetry>(rh));
GINAC_ASSERT(ex_to<symmetry>(lh).indices.size() == ex_to<symmetry>(rh).indices.size());
std::set<unsigned>::const_iterator ait = ex_to<symmetry>(lh).indices.begin(), aitend = ex_to<symmetry>(lh).indices.end(), bit = ex_to<symmetry>(rh).indices.begin();
while (ait != aitend) {
void operator() (const ex &lh, const ex &rh)
{
- GINAC_ASSERT(is_ex_exactly_of_type(lh, symmetry));
- GINAC_ASSERT(is_ex_exactly_of_type(rh, symmetry));
+ GINAC_ASSERT(is_exactly_a<symmetry>(lh));
+ GINAC_ASSERT(is_exactly_a<symmetry>(rh));
GINAC_ASSERT(ex_to<symmetry>(lh).indices.size() == ex_to<symmetry>(rh).indices.size());
std::set<unsigned>::const_iterator ait = ex_to<symmetry>(lh).indices.begin(), aitend = ex_to<symmetry>(lh).indices.end(), bit = ex_to<symmetry>(rh).indices.begin();
while (ait != aitend) {
int sign = 1;
exvector::const_iterator first = symm.children.begin(), last = symm.children.end();
while (first != last) {
- GINAC_ASSERT(is_ex_exactly_of_type(*first, symmetry));
+ GINAC_ASSERT(is_exactly_a<symmetry>(*first));
int child_sign = canonicalize(v, ex_to<symmetry>(*first));
if (child_sign == 0)
return 0;
// global functions
-inline symmetry &ex_to_nonconst_symmetry(const ex &e)
-{
- return static_cast<symmetry &>(*e.bp);
-}
inline symmetry sy_none(void) { return symmetry(); }
inline symmetry sy_none(const symmetry &c1, const symmetry &c2) { return symmetry(symmetry::none, c1, c2); }
int minkmetric::compare_same_type(const basic & other) const
{
- GINAC_ASSERT(is_of_type(other, minkmetric));
+ GINAC_ASSERT(is_a<minkmetric>(other));
const minkmetric &o = static_cast<const minkmetric &>(other);
if (pos_sig != o.pos_sig)
int tensepsilon::compare_same_type(const basic & other) const
{
- GINAC_ASSERT(is_of_type(other, tensepsilon));
+ GINAC_ASSERT(is_a<tensepsilon>(other));
const tensepsilon &o = static_cast<const tensepsilon &>(other);
if (minkowski != o.minkowski)
/** Automatic symbolic evaluation of an indexed delta tensor. */
ex tensdelta::eval_indexed(const basic & i) const
{
- GINAC_ASSERT(is_of_type(i, indexed));
+ GINAC_ASSERT(is_a<indexed>(i));
GINAC_ASSERT(i.nops() == 3);
- GINAC_ASSERT(is_ex_of_type(i.op(0), tensdelta));
+ GINAC_ASSERT(is_a<tensdelta>(i.op(0)));
const idx & i1 = ex_to<idx>(i.op(1));
const idx & i2 = ex_to<idx>(i.op(2));
/** Automatic symbolic evaluation of an indexed metric tensor. */
ex tensmetric::eval_indexed(const basic & i) const
{
- GINAC_ASSERT(is_of_type(i, indexed));
+ GINAC_ASSERT(is_a<indexed>(i));
GINAC_ASSERT(i.nops() == 3);
- GINAC_ASSERT(is_ex_of_type(i.op(0), tensmetric));
- GINAC_ASSERT(is_ex_of_type(i.op(1), varidx));
- GINAC_ASSERT(is_ex_of_type(i.op(2), varidx));
+ GINAC_ASSERT(is_a<tensmetric>(i.op(0)));
+ GINAC_ASSERT(is_a<varidx>(i.op(1)));
+ GINAC_ASSERT(is_a<varidx>(i.op(2)));
const varidx & i1 = ex_to<varidx>(i.op(1));
const varidx & i2 = ex_to<varidx>(i.op(2));
/** Automatic symbolic evaluation of an indexed Lorentz metric tensor. */
ex minkmetric::eval_indexed(const basic & i) const
{
- GINAC_ASSERT(is_of_type(i, indexed));
+ GINAC_ASSERT(is_a<indexed>(i));
GINAC_ASSERT(i.nops() == 3);
- GINAC_ASSERT(is_ex_of_type(i.op(0), minkmetric));
- GINAC_ASSERT(is_ex_of_type(i.op(1), varidx));
- GINAC_ASSERT(is_ex_of_type(i.op(2), varidx));
+ GINAC_ASSERT(is_a<minkmetric>(i.op(0)));
+ GINAC_ASSERT(is_a<varidx>(i.op(1)));
+ GINAC_ASSERT(is_a<varidx>(i.op(2)));
const varidx & i1 = ex_to<varidx>(i.op(1));
const varidx & i2 = ex_to<varidx>(i.op(2));
/** Automatic symbolic evaluation of an indexed metric tensor. */
ex spinmetric::eval_indexed(const basic & i) const
{
- GINAC_ASSERT(is_of_type(i, indexed));
+ GINAC_ASSERT(is_a<indexed>(i));
GINAC_ASSERT(i.nops() == 3);
- GINAC_ASSERT(is_ex_of_type(i.op(0), spinmetric));
- GINAC_ASSERT(is_ex_of_type(i.op(1), spinidx));
- GINAC_ASSERT(is_ex_of_type(i.op(2), spinidx));
+ GINAC_ASSERT(is_a<spinmetric>(i.op(0)));
+ GINAC_ASSERT(is_a<spinidx>(i.op(1)));
+ GINAC_ASSERT(is_a<spinidx>(i.op(2)));
const spinidx & i1 = ex_to<spinidx>(i.op(1));
const spinidx & i2 = ex_to<spinidx>(i.op(2));
/** Automatic symbolic evaluation of an indexed epsilon tensor. */
ex tensepsilon::eval_indexed(const basic & i) const
{
- GINAC_ASSERT(is_of_type(i, indexed));
+ GINAC_ASSERT(is_a<indexed>(i));
GINAC_ASSERT(i.nops() > 1);
- GINAC_ASSERT(is_ex_of_type(i.op(0), tensepsilon));
+ GINAC_ASSERT(is_a<tensepsilon>(i.op(0)));
// Convolutions are zero
if (!(static_cast<const indexed &>(i).get_dummy_indices().empty()))
/** Contraction of an indexed delta tensor with something else. */
bool tensdelta::contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const
{
- GINAC_ASSERT(is_ex_of_type(*self, indexed));
- GINAC_ASSERT(is_ex_of_type(*other, indexed));
+ GINAC_ASSERT(is_a<indexed>(*self));
+ GINAC_ASSERT(is_a<indexed>(*other));
GINAC_ASSERT(self->nops() == 3);
- GINAC_ASSERT(is_ex_of_type(self->op(0), tensdelta));
+ GINAC_ASSERT(is_a<tensdelta>(self->op(0)));
// Try to contract first index
const idx *self_idx = &ex_to<idx>(self->op(1));
/** Contraction of an indexed metric tensor with something else. */
bool tensmetric::contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const
{
- GINAC_ASSERT(is_ex_of_type(*self, indexed));
- GINAC_ASSERT(is_ex_of_type(*other, indexed));
+ GINAC_ASSERT(is_a<indexed>(*self));
+ GINAC_ASSERT(is_a<indexed>(*other));
GINAC_ASSERT(self->nops() == 3);
- GINAC_ASSERT(is_ex_of_type(self->op(0), tensmetric));
+ GINAC_ASSERT(is_a<tensmetric>(self->op(0)));
// If contracting with the delta tensor, let the delta do it
// (don't raise/lower delta indices)
/** Contraction of an indexed spinor metric with something else. */
bool spinmetric::contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const
{
- GINAC_ASSERT(is_ex_of_type(*self, indexed));
- GINAC_ASSERT(is_ex_of_type(*other, indexed));
+ GINAC_ASSERT(is_a<indexed>(*self));
+ GINAC_ASSERT(is_a<indexed>(*other));
GINAC_ASSERT(self->nops() == 3);
- GINAC_ASSERT(is_ex_of_type(self->op(0), spinmetric));
+ GINAC_ASSERT(is_a<spinmetric>(self->op(0)));
// Contractions between spinor metrics
if (is_ex_of_type(other->op(0), spinmetric)) {
/** Contraction of epsilon tensor with something else. */
bool tensepsilon::contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const
{
- GINAC_ASSERT(is_ex_of_type(*self, indexed));
- GINAC_ASSERT(is_ex_of_type(*other, indexed));
- GINAC_ASSERT(is_ex_of_type(self->op(0), tensepsilon));
+ GINAC_ASSERT(is_a<indexed>(*self));
+ GINAC_ASSERT(is_a<indexed>(*other));
+ GINAC_ASSERT(is_a<tensepsilon>(self->op(0)));
unsigned num = self->nops() - 1;
if (is_ex_exactly_of_type(other->op(0), tensepsilon) && num+1 == other->nops()) {
// utility functions
-/** Return the tensor object handled by an ex. Deprecated: use ex_to<tensor>().
- * This is unsafe: you need to check the type first. */
-inline const tensor &ex_to_tensor(const ex &e)
-{
- return static_cast<const tensor &>(*e.bp);
-}
-
/** Create a delta tensor with specified indices. The indices must be of class
* idx or a subclass. The delta tensor is always symmetric and its trace is
* the dimension of the index space.
int wildcard::compare_same_type(const basic & other) const
{
- GINAC_ASSERT(is_of_type(other, wildcard));
+ GINAC_ASSERT(is_a<wildcard>(other));
const wildcard &o = static_cast<const wildcard &>(other);
if (label == o.label)
{
debugmsg("wildcard print", LOGLEVEL_PRINT);
- if (is_of_type(c, print_tree)) {
+ if (is_a<print_tree>(c)) {
c.s << std::string(level, ' ') << class_name() << " (" << label << ")"
<< std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec
<< std::endl;
// utility functions
-/** Return the wildcard object handled by an ex. Deprecated: use ex_to<wildcard>().
- * This is unsafe: you need to check the type first. */
-inline const wildcard &ex_to_wildcard(const ex &e)
-{
- return static_cast<const wildcard &>(*e.bp);
-}
-
/** Specialization of is_exactly_a<wildcard>(obj) for wildcard objects. */
template<> inline bool is_exactly_a<wildcard>(const basic & obj)
{
}
}
| T_DIGITS '=' T_NUMBER {$$ = $3; Digits = ex_to<numeric>($3).to_int();}
- | T_SYMBOL '=' exp {$$ = $3; ex_to_nonconst_symbol($1).assign($3);}
+ | T_SYMBOL '=' exp {$$ = $3; const_cast<symbol&>(ex_to<symbol>($1)).assign($3);}
| exp T_EQUAL exp {$$ = $1 == $3;}
| exp T_NOTEQ exp {$$ = $1 != $3;}
| exp '<' exp {$$ = $1 < $3;}
static ex f_unassign(const exprseq &e)
{
CHECK_ARG(0, symbol, unassign);
- ex_to_nonconst_symbol(e[0]).unassign();
+ const_cast<symbol&>(ex_to<symbol>(e[0])).unassign();
return e[0];
}