* Generalized map() to take a function object instead of a function pointer.
This allows passing an arbitrary number of additional state to the
function being called.
+* Supplement some (now deprecated) macros by inlined template functions:
+ - is_of_type(foo, type) -> is_a<type>(foo)
+ - is_ex_of_type(foo, type) -> is_a<type>(foo)
+ - is_exaclty_of_type(foo, type) -> is_exaclty_a<type>(foo)
+ - is_ex_exaclty_of_type(foo, type) -> is_exaclty_a<type>(foo)
0.9.0 (7 June 2001)
* In the output and in ginsh, lists are now delimited by { } braces, and
ex radical = pow(ex(num)/ex(den),ex(nm));
numeric floating = pow(num/den,nm);
// test the result:
- if (is_ex_of_type(radical,numeric)) {
+ if (is_a<numeric>(radical)) {
clog << "(" << num << "/" << den << ")^(" << nm
<< ") should have been a product, instead it's "
<< radical << endl;
// (which incidentally was severely broken from version 0.7.3 to 0.8.2).
ex selfprobe = numeric("65536");
selfprobe = selfprobe;
- if (!is_ex_exactly_of_type(selfprobe, numeric)) {
+ if (!is_exactly_a<numeric>(selfprobe)) {
clog << "ex (of numeric) after self-assignment became " << selfprobe << endl;
++result;
}
symbol b("b");
ex e1 = power(power(x,a), b);
- if (!(is_ex_exactly_of_type(e1,power) &&
- is_ex_exactly_of_type(e1.op(0),power) &&
- is_ex_exactly_of_type(e1.op(0).op(0),symbol) &&
- is_ex_exactly_of_type(e1.op(0).op(1),symbol) &&
- is_ex_exactly_of_type(e1.op(1),symbol) &&
+ if (!(is_exactly_a<power>(e1) &&
+ is_exactly_a<power>(e1.op(0)) &&
+ is_exactly_a<symbol>(e1.op(0).op(0)) &&
+ is_exactly_a<symbol>(e1.op(0).op(1)) &&
+ is_exactly_a<symbol>(e1.op(1)) &&
e1.is_equal(power(power(x,a),b)) )) {
clog << "(x^a)^b, x,a,b symbolic wrong" << endl;
clog << "returned: " << e1 << endl;
}
ex e2 = e1.subs(a==1);
- if (!(is_ex_exactly_of_type(e2,power) &&
- is_ex_exactly_of_type(e2.op(0),symbol) &&
- is_ex_exactly_of_type(e2.op(1),symbol) &&
+ if (!(is_exactly_a<power>(e2) &&
+ is_exactly_a<symbol>(e2.op(0)) &&
+ is_exactly_a<symbol>(e2.op(1)) &&
e2.is_equal(power(x,b)) )) {
clog << "(x^a)^b, x,b symbolic, a==1 wrong" << endl;
clog << "returned: " << e2 << endl;
}
ex e3 = e1.subs(a==-1);
- if (!(is_ex_exactly_of_type(e3,power) &&
- is_ex_exactly_of_type(e3.op(0),power) &&
- is_ex_exactly_of_type(e3.op(0).op(0),symbol) &&
- is_ex_exactly_of_type(e3.op(0).op(1),numeric) &&
- is_ex_exactly_of_type(e3.op(1),symbol) &&
+ if (!(is_exactly_a<power>(e3) &&
+ is_exactly_a<power>(e3.op(0)) &&
+ is_exactly_a<symbol>(e3.op(0).op(0)) &&
+ is_exactly_a<numeric>(e3.op(0).op(1)) &&
+ is_exactly_a<symbol>(e3.op(1)) &&
e3.is_equal(power(power(x,-1),b)) )) {
clog << "(x^a)^b, x,b symbolic, a==-1 wrong" << endl;
clog << "returned: " << e3 << endl;
}
ex e4 = e1.subs(lst(a==-1, b==2.5));
- if (!(is_ex_exactly_of_type(e4,power) &&
- is_ex_exactly_of_type(e4.op(0),power) &&
- is_ex_exactly_of_type(e4.op(0).op(0),symbol) &&
- is_ex_exactly_of_type(e4.op(0).op(1),numeric) &&
- is_ex_exactly_of_type(e4.op(1),numeric) &&
+ if (!(is_exactly_a<power>(e4) &&
+ is_exactly_a<power>(e4.op(0)) &&
+ is_exactly_a<symbol>(e4.op(0).op(0)) &&
+ is_exactly_a<numeric>(e4.op(0).op(1)) &&
+ is_exactly_a<numeric>(e4.op(1)) &&
e4.is_equal(power(power(x,-1),2.5)) )) {
clog << "(x^a)^b, x symbolic, a==-1, b==2.5 wrong" << endl;
clog << "returned: " << e4 << endl;
}
ex e5 = e1.subs(lst(a==-0.9, b==2.5));
- if (!(is_ex_exactly_of_type(e5,power) &&
- is_ex_exactly_of_type(e5.op(0),symbol) &&
- is_ex_exactly_of_type(e5.op(1),numeric) &&
+ if (!(is_exactly_a<power>(e5) &&
+ is_exactly_a<symbol>(e5.op(0)) &&
+ is_exactly_a<numeric>(e5.op(1)) &&
e5.is_equal(power(x,numeric(-0.9)*numeric(2.5))) )) {
clog << "(x^a)^b, x symbolic, a==-0.9, b==2.5 wrong" << endl;
clog << "returned: " << e5 << endl;
}
ex e6 = e1.subs(lst(a==numeric(3)+numeric(5.3)*I, b==-5));
- if (!(is_ex_exactly_of_type(e6,power) &&
- is_ex_exactly_of_type(e6.op(0),symbol) &&
- is_ex_exactly_of_type(e6.op(1),numeric) &&
+ if (!(is_exactly_a<power>(e6) &&
+ is_exactly_a<symbol>(e6.op(0)) &&
+ is_exactly_a<numeric>(e6.op(1)) &&
e6.is_equal(power(x,numeric(-15)+numeric(5.3)*numeric(-5)*I)) )) {
clog << "(x^a)^b, x symbolic, a==3+5.3*I, b==-5 wrong" << endl;
clog << "returned: " << e6 << endl;
symbol b("b");
ex e1 = power(a*x,b);
- if (!(is_ex_exactly_of_type(e1,power) &&
- is_ex_exactly_of_type(e1.op(0),mul) &&
+ if (!(is_exactly_a<power>(e1) &&
+ is_exactly_a<mul>(e1.op(0)) &&
(e1.op(0).nops()==2) &&
- is_ex_exactly_of_type(e1.op(0).op(0),symbol) &&
- is_ex_exactly_of_type(e1.op(0).op(1),symbol) &&
- is_ex_exactly_of_type(e1.op(1),symbol) &&
+ is_exactly_a<symbol>(e1.op(0).op(0)) &&
+ is_exactly_a<symbol>(e1.op(0).op(1)) &&
+ is_exactly_a<symbol>(e1.op(1)) &&
e1.is_equal(power(a*x,b)) )) {
clog << "(a*x)^b, x,a,b symbolic wrong" << endl;
clog << "returned: " << e1 << endl;
}
ex e2 = e1.subs(a==3);
- if (!(is_ex_exactly_of_type(e2,power) &&
- is_ex_exactly_of_type(e2.op(0),mul) &&
+ if (!(is_exactly_a<power>(e2) &&
+ is_exactly_a<mul>(e2.op(0)) &&
(e2.op(0).nops()==2) &&
- is_ex_exactly_of_type(e2.op(0).op(0),symbol) &&
- is_ex_exactly_of_type(e2.op(0).op(1),numeric) &&
- is_ex_exactly_of_type(e2.op(1),symbol) &&
+ is_exactly_a<symbol>(e2.op(0).op(0)) &&
+ is_exactly_a<numeric>(e2.op(0).op(1)) &&
+ is_exactly_a<symbol>(e2.op(1)) &&
e2.is_equal(power(3*x,b)) )) {
clog << "(a*x)^b, x,b symbolic, a==3 wrong" << endl;
clog << "returned: " << e2 << endl;
}
ex e3 = e1.subs(b==-3);
- if (!(is_ex_exactly_of_type(e3,mul) &&
+ if (!(is_exactly_a<mul>(e3) &&
(e3.nops()==2) &&
- is_ex_exactly_of_type(e3.op(0),power) &&
- is_ex_exactly_of_type(e3.op(1),power) &&
+ is_exactly_a<power>(e3.op(0)) &&
+ is_exactly_a<power>(e3.op(1)) &&
e3.is_equal(power(a,-3)*power(x,-3)) )) {
clog << "(a*x)^b, x,a symbolic, b==-3 wrong" << endl;
clog << "returned: " << e3 << endl;
}
ex e4 = e1.subs(b==4.5);
- if (!(is_ex_exactly_of_type(e4,power) &&
- is_ex_exactly_of_type(e4.op(0),mul) &&
+ if (!(is_exactly_a<power>(e4) &&
+ is_exactly_a<mul>(e4.op(0)) &&
(e4.op(0).nops()==2) &&
- is_ex_exactly_of_type(e4.op(0).op(0),symbol) &&
- is_ex_exactly_of_type(e4.op(0).op(1),symbol) &&
- is_ex_exactly_of_type(e4.op(1),numeric) &&
+ is_exactly_a<symbol>(e4.op(0).op(0)) &&
+ is_exactly_a<symbol>(e4.op(0).op(1)) &&
+ is_exactly_a<numeric>(e4.op(1)) &&
e4.is_equal(power(a*x,4.5)) )) {
clog << "(a*x)^b, x,a symbolic, b==4.5 wrong" << endl;
clog << "returned: " << e4 << endl;
}
ex e5 = e1.subs(lst(a==3.2, b==3+numeric(5)*I));
- if (!(is_ex_exactly_of_type(e5,mul) &&
+ if (!(is_exactly_a<mul>(e5) &&
(e5.nops()==2) &&
- is_ex_exactly_of_type(e5.op(0),power) &&
- is_ex_exactly_of_type(e5.op(1),numeric) &&
+ is_exactly_a<power>(e5.op(0)) &&
+ is_exactly_a<numeric>(e5.op(1)) &&
e5.is_equal(power(x,3+numeric(5)*I)*
power(numeric(3.2),3+numeric(5)*I)) )) {
clog << "(a*x)^b, x symbolic, a==3.2, b==3+5*I wrong" << endl;
}
ex e6 = e1.subs(lst(a==-3.2, b==3+numeric(5)*I));
- if (!(is_ex_exactly_of_type(e6,mul) &&
+ if (!(is_exactly_a<mul>(e6) &&
(e6.nops()==2) &&
- is_ex_exactly_of_type(e6.op(0),power) &&
- is_ex_exactly_of_type(e6.op(1),numeric) &&
+ is_exactly_a<power>(e6.op(0)) &&
+ is_exactly_a<numeric>(e6.op(1)) &&
e6.is_equal(power(-x,3+numeric(5)*I)*
power(numeric(3.2),3+numeric(5)*I)) )) {
clog << "(a*x)^b, x symbolic, a==-3.2, b==3+5*I wrong" << endl;
}
ex e7 = e1.subs(lst(a==3+numeric(5)*I, b==3.2));
- if (!(is_ex_exactly_of_type(e7,power) &&
- is_ex_exactly_of_type(e7.op(0),mul) &&
+ if (!(is_exactly_a<power>(e7) &&
+ is_exactly_a<mul>(e7.op(0)) &&
(e7.op(0).nops()==2) &&
- is_ex_exactly_of_type(e7.op(0).op(0),symbol) &&
- is_ex_exactly_of_type(e7.op(0).op(1),numeric) &&
- is_ex_exactly_of_type(e7.op(1),numeric) &&
+ is_exactly_a<symbol>(e7.op(0).op(0)) &&
+ is_exactly_a<numeric>(e7.op(0).op(1)) &&
+ is_exactly_a<numeric>(e7.op(1)) &&
e7.is_equal(power((3+numeric(5)*I)*x,3.2)) )) {
clog << "(a*x)^b, x symbolic, a==3+5*I, b==3.2 wrong" << endl;
clog << "returned: " << e7 << endl;
}
ex e3 = power(numeric(5),numeric(1,2));
- if (!(is_ex_exactly_of_type(e3,power) &&
+ if (!(is_exactly_a<power>(e3) &&
e3.op(0).is_equal(numeric(5)) &&
e3.op(1).is_equal(numeric(1,2)))) {
clog << "5^(1/2) wrongly returned " << e3 << endl;
}
ex e4 = power(numeric(5),evalf(numeric(1,2)));
- if (!(is_ex_exactly_of_type(e4,numeric))) {
+ if (!(is_exactly_a<numeric>(e4))) {
clog << "5^(0.5) wrongly returned " << e4 << endl;
return 1;
}
ex e5 = power(evalf(numeric(5)),numeric(1,2));
- if (!(is_ex_exactly_of_type(e5,numeric))) {
+ if (!(is_exactly_a<numeric>(e5))) {
clog << "5.0^(1/2) wrongly returned " << e5 << endl;
return 1;
}
}
ex e2 = pow(0,a);
- if (!(is_ex_exactly_of_type(e2,power))) {
+ if (!(is_exactly_a<power>(e2))) {
clog << "0^a was evaluated to " << e2
<< " though nothing is known about a." << endl;
return 1;
{
debugmsg("add 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)) {
if (precedence() <= level)
c.s << "(";
// Separator is "+", except if the following expression would have a leading minus sign
it++;
- if (it != itend && !(it->coeff.compare(_num0()) < 0 || (it->coeff.compare(_num1()) == 0 && is_ex_exactly_of_type(it->rest, numeric) && it->rest.compare(_num0()) < 0)))
+ if (it != itend && !(it->coeff.compare(_num0()) < 0 || (it->coeff.compare(_num1()) == 0 && is_exactly_a<numeric>(it->rest) && it->rest.compare(_num0()) < 0)))
c.s << "+";
}
} else {
if (precedence() <= level) {
- if (is_of_type(c, print_latex))
+ if (is_a<print_latex>(c))
c.s << "{(";
else
c.s << "(";
// First print the overall numeric coefficient, if present
if (!overall_coeff.is_zero()) {
- if (!is_of_type(c, print_tree))
+ if (!is_a<print_tree>(c))
overall_coeff.print(c, 0);
else
overall_coeff.print(c, precedence());
else
coeff.print(c, precedence());
}
- if (is_of_type(c, print_latex))
+ if (is_a<print_latex>(c))
c.s << ' ';
else
c.s << '*';
}
if (precedence() <= level) {
- if (is_of_type(c, print_latex))
+ if (is_a<print_latex>(c))
c.s << ")}";
else
c.s << ")";
{
if (is_ex_exactly_of_type(e,mul)) {
const mul &mulref = ex_to_mul(e);
- ex numfactor = mulref.overall_coeff;
+ ex numfactor(mulref.overall_coeff);
mul *mulcopyp = new mul(mulref);
mulcopyp->overall_coeff = _ex1();
mulcopyp->clearflag(status_flags::evaluated);
GINAC_ASSERT(is_ex_exactly_of_type(c, numeric));
if (is_ex_exactly_of_type(e, mul)) {
const mul &mulref = ex_to_mul(e);
- ex numfactor = mulref.overall_coeff;
+ ex numfactor(mulref.overall_coeff);
mul *mulcopyp = new mul(mulref);
mulcopyp->overall_coeff = _ex1();
mulcopyp->clearflag(status_flags::evaluated);
};
// utility functions
+
+/** Return the add object handled by an ex.
+ * 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)
+{
+ return obj.tinfo()==TINFO_add;
+}
+
} // namespace GiNaC
#endif // ndef __GINAC_ADD_H__
extern int max_recursion_level;
-// convenience macros
+// Obsolete convenience macros. To be phased out soon!
+// Use the inlined template functions below instead of these macros.
-/** Check if OBJ is a TYPE, including base classes. */
#define is_of_type(OBJ,TYPE) \
(dynamic_cast<const TYPE *>(&OBJ)!=0)
-/** Check if OBJ is a TYPE, not including base classes. */
#define is_exactly_of_type(OBJ,TYPE) \
((OBJ).tinfo()==GiNaC::TINFO_##TYPE)
-/** Check if ex is a handle to a TYPE, including base classes. */
#define is_ex_of_type(OBJ,TYPE) \
(dynamic_cast<const TYPE *>((OBJ).bp)!=0)
-/** Check if ex is a handle to a TYPE, not including base classes. */
#define is_ex_exactly_of_type(OBJ,TYPE) \
((*(OBJ).bp).tinfo()==GiNaC::TINFO_##TYPE)
+// convenience type checker template functions
+
+/** Check if obj is a T, including base classes. */
+template <class T>
+inline bool is_a(const basic & obj)
+{ return dynamic_cast<const T *>(&obj)!=0; }
+
+/** Check if obj is a T, not including base classes. This one is just an
+ * 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)
+{ 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)
+{ 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)
+{ return is_exactly_a<T>(*obj.bp); }
+
} // namespace GiNaC
#endif // ndef __GINAC_BASIC_H__
// global functions
+
+/** Return the clifford object handled by an ex.
+ * 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)
+{
+ return obj.tinfo()==TINFO_clifford;
+}
/** Create a Clifford unity object.
*
// global functions
+
+/** Return the color object handled by an ex.
+ * 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)
+{
+ return obj.tinfo()==TINFO_color;
+}
/** Create the su(3) unity element. This is an indexed object, although it
* has no indices.
{
debugmsg("constant print", LOGLEVEL_PRINT);
- if (is_of_type(c, print_tree)) {
+ if (is_a<print_tree>(c)) {
c.s << std::string(level, ' ') << name << " (" << class_name() << ")"
<< 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;
extern const constant Euler;
// utility functions
+
+/** Return the constant object handled by an ex.
+ * 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)
+{
+ return obj.tinfo()==TINFO_constant;
+}
+
} // namespace GiNaC
#endif // ndef __GINAC_CONSTANT_H__
};
// utility functions
+
+/** Return the ${CONTAINER} object handled by an ex.
+ * 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);
{
debugmsg("${CONTAINER} 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
int ${CONTAINER}::compare_same_type(const basic & other) const
{
- GINAC_ASSERT(is_of_type(other,${CONTAINER}));
+ GINAC_ASSERT(is_a<${CONTAINER}>(other));
${CONTAINER} const & o=static_cast<${CONTAINER} const &>
(const_cast<basic &>(other));
int cmpval;
bool ${CONTAINER}::is_equal_same_type(const basic & other) const
{
- GINAC_ASSERT(is_of_type(other,${CONTAINER}));
- ${CONTAINER} const & o=static_cast<${CONTAINER} const &>
- (const_cast<basic &>(other));
+ GINAC_ASSERT(is_a<${CONTAINER}>(other));
+ ${CONTAINER} const & o = static_cast<${CONTAINER} const &>(const_cast<basic &>(other));
if (seq.size()!=o.seq.size()) return false;
- ${STLT}::const_iterator it1=seq.begin();
- ${STLT}::const_iterator it2=o.seq.begin();
+ ${STLT}::const_iterator it1 = seq.begin();
+ ${STLT}::const_iterator it2 = o.seq.begin();
for (; it1!=seq.end(); ++it1, ++it2) {
if (!(*it1).is_equal(*it2)) return false;
~expair() { }
expair(const expair & other) : rest(other.rest), coeff(other.coeff)
{
- GINAC_ASSERT(is_ex_exactly_of_type(coeff,numeric));
+ GINAC_ASSERT(is_exactly_a<numeric>(coeff));
}
const expair & operator=(const expair & other)
{
/** Construct an expair from two ex. */
expair(const ex & r, const ex & c) : rest(r), coeff(c)
{
- GINAC_ASSERT(is_ex_exactly_of_type(coeff,numeric));
+ GINAC_ASSERT(is_exactly_a<numeric>(coeff));
}
/** Member-wise check for canonical ordering equality. */
/** True if this is of the form (numeric,ex(1)). */
bool is_canonical_numeric(void) const
{
- GINAC_ASSERT(is_ex_exactly_of_type(coeff,numeric));
+ GINAC_ASSERT(is_exactly_a<numeric>(coeff));
return (is_ex_exactly_of_type(rest,numeric) &&
(coeff.is_equal(1)));
}
};
// utility functions
+
+/** Return the expairseq object handled by an ex.
+ * 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)
+{
+ return obj.tinfo()==TINFO_expairseq;
+}
+
} // namespace GiNaC
#endif // ndef __GINAC_EXPAIRSEQ_H__
unsigned return_type(void) const { return return_types::noncommutative_composite; };
};
+/** Specialization of is_exactly_a<fail>(obj) for fail objects. */
+template<> inline bool is_exactly_a<fail>(const basic & obj)
+{
+ return obj.tinfo()==TINFO_fail;
+}
+
} // namespace GiNaC
#endif // ndef __GINAC_FAIL_H__
bool automatic_typecheck=true;
#define TYPECHECK(VAR,TYPE) \\
-if (!is_ex_exactly_of_type(VAR,TYPE)) { \\
+if (!is_exactly_a<TYPE>(VAR)) { \\
automatic_typecheck=false; \\
} else
};
// 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)
+{
+ return obj.tinfo()==TINFO_function;
+}
+
#define is_ex_the_function(OBJ, FUNCNAME) \\
(is_ex_exactly_of_type(OBJ, function) && static_cast<GiNaC::function *>(OBJ.bp)->get_serial() == function_index_##FUNCNAME)
// utility functions
+
+/** Return the idx object handled by an ex.
+ * 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.
+ * 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.
+ * 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)
+{
+ return obj.tinfo()==TINFO_idx;
+}
+
+/** Specialization of is_exactly_a<varidx>(obj) for varidx objects. */
+template<> inline bool is_exactly_a<varidx>(const basic & obj)
+{
+ return obj.tinfo()==TINFO_varidx;
+}
+
+/** Specialization of is_exactly_a<spinidx>(obj) for spinidx objects. */
+template<> inline bool is_exactly_a<spinidx>(const basic & obj)
+{
+ return obj.tinfo()==TINFO_spinidx;
+}
+
/** Check whether two indices form a dummy pair. */
bool is_dummy_pair(const idx & i1, const idx & i2);
// utility functions
+
+/** Return the indexed object handled by an ex.
+ * 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)
+{
+ return obj.tinfo()==TINFO_indexed;
+}
+
} // namespace GiNaC
#endif // ndef __GINAC_INDEXED_H__
bool lst::info(unsigned inf) const
{
- if (inf==info_flags::list) return 1;
+ if (inf==info_flags::list) return true;
return basic::info(inf);
}
{ return m.inverse(); }
// utility functions
+
+/** Return the matrix object handled by an ex.
+ * 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)
+{
+ return obj.tinfo()==TINFO_matrix;
+}
+
/** Convert list of lists to matrix. */
extern ex lst_to_matrix(const lst & l);
{
debugmsg("mul 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)) {
if (precedence() <= level)
c.s << "(";
// If the first argument is a negative integer power, it gets printed as "1.0/<expr>"
if (it == seq.begin() && ex_to_numeric(it->coeff).is_integer() && it->coeff.compare(_num0()) < 0) {
- if (is_of_type(c, print_csrc_cl_N))
+ if (is_a<print_csrc_cl_N>(c))
c.s << "recip(";
else
c.s << "1.0/";
} else {
if (precedence() <= level) {
- if (is_of_type(c, print_latex))
+ if (is_a<print_latex>(c))
c.s << "{(";
else
c.s << "(";
else
coeff.print(c, precedence());
}
- if (is_of_type(c, print_latex))
+ if (is_a<print_latex>(c))
c.s << ' ';
else
c.s << '*';
epvector::const_iterator it = seq.begin(), itend = seq.end();
while (it != itend) {
if (!first) {
- if (is_of_type(c, print_latex))
+ if (is_a<print_latex>(c))
c.s << ' ';
else
c.s << '*';
}
if (precedence() <= level) {
- if (is_of_type(c, print_latex))
+ if (is_a<print_latex>(c))
c.s << ")}";
else
c.s << ")";
non_adds.reserve(expanded_seq.size());
epvector::const_iterator cit = expanded_seq.begin();
epvector::const_iterator last = expanded_seq.end();
- ex last_expanded = _ex1();
+ ex last_expanded(_ex1());
while (cit!=last) {
if (is_ex_exactly_of_type((*cit).rest,add) &&
((*cit).coeff.is_equal(_ex1()))) {
};
// utility functions
+
+/** Return the mul object handled by an ex.
+ * 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)
+{
+ return obj.tinfo()==TINFO_mul;
+}
+
} // namespace GiNaC
#endif // ndef __GINAC_MUL_H__
ex simplified_ncmul(const exvector & v);
// utility functions
+
+/** Return the ncmul object handled by an ex.
+ * 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)
+{
+ return obj.tinfo()==TINFO_ncmul;
+}
+
} // namespace GiNaC
#endif // ndef __GINAC_NCMUL_H__
{
debugmsg("numeric print", LOGLEVEL_PRINT);
- if (is_of_type(c, print_tree)) {
+ if (is_a<print_tree>(c)) {
c.s << std::string(level, ' ') << cln::the<cln::cl_N>(value)
<< " (" << class_name() << ")"
<< std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec
<< std::endl;
- } else if (is_of_type(c, print_csrc)) {
+ } else if (is_a<print_csrc>(c)) {
std::ios::fmtflags oldflags = c.s.flags();
c.s.setf(std::ios::scientific);
if (this->is_rational() && !this->is_integer()) {
if (compare(_num0()) > 0) {
c.s << "(";
- if (is_of_type(c, print_csrc_cl_N))
+ if (is_a<print_csrc_cl_N>(c))
c.s << "cln::cl_F(\"" << numer().evalf() << "\")";
else
c.s << numer().to_double();
} else {
c.s << "-(";
- if (is_of_type(c, print_csrc_cl_N))
+ if (is_a<print_csrc_cl_N>(c))
c.s << "cln::cl_F(\"" << -numer().evalf() << "\")";
else
c.s << -numer().to_double();
}
c.s << "/";
- if (is_of_type(c, print_csrc_cl_N))
+ if (is_a<print_csrc_cl_N>(c))
c.s << "cln::cl_F(\"" << denom().evalf() << "\")";
else
c.s << denom().to_double();
c.s << ")";
} else {
- if (is_of_type(c, print_csrc_cl_N))
+ if (is_a<print_csrc_cl_N>(c))
c.s << "cln::cl_F(\"" << evalf() << "\")";
else
c.s << to_double();
c.s.flags(oldflags);
} else {
- const std::string par_open = is_of_type(c, print_latex) ? "{(" : "(";
- const std::string par_close = is_of_type(c, print_latex) ? ")}" : ")";
- const std::string imag_sym = is_of_type(c, print_latex) ? "i" : "I";
- const std::string mul_sym = is_of_type(c, print_latex) ? " " : "*";
+ const std::string par_open = is_a<print_latex>(c) ? "{(" : "(";
+ const std::string par_close = is_a<print_latex>(c) ? ")}" : ")";
+ const std::string imag_sym = is_a<print_latex>(c) ? "i" : "I";
+ const std::string mul_sym = is_a<print_latex>(c) ? " " : "*";
const cln::cl_R r = cln::realpart(cln::the<cln::cl_N>(value));
const cln::cl_R i = cln::imagpart(cln::the<cln::cl_N>(value));
if (cln::zerop(i)) {
// utility functions
+
+/** Return the numeric object handled by an ex.
+ * 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)
+{
+ return obj.tinfo()==TINFO_numeric;
+}
+
} // namespace GiNaC
#ifdef __MAKECINT__
#include "mul.h"
#include "ncmul.h"
#include "numeric.h"
+#include "constant.h"
#include "inifcns.h" // for log() in power::derivative()
#include "matrix.h"
#include "symbol.h"
{
debugmsg("power 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)) {
// Integer powers of symbols are printed in a special, optimized way
if (exponent.info(info_flags::integer)
- && (is_ex_exactly_of_type(basis, symbol) || is_ex_exactly_of_type(basis, constant))) {
+ && (is_exactly_a<symbol>(basis) || is_exactly_a<constant>(basis))) {
int exp = ex_to_numeric(exponent).to_int();
if (exp > 0)
c.s << '(';
else {
exp = -exp;
- if (is_of_type(c, print_csrc_cl_N))
+ if (is_a<print_csrc_cl_N>(c))
c.s << "recip(";
else
c.s << "1.0/(";
// <expr>^-1 is printed as "1.0/<expr>" or with the recip() function of CLN
} else if (exponent.compare(_num_1()) == 0) {
- if (is_of_type(c, print_csrc_cl_N))
+ if (is_a<print_csrc_cl_N>(c))
c.s << "recip(";
else
c.s << "1.0/(";
// Otherwise, use the pow() or expt() (CLN) functions
} else {
- if (is_of_type(c, print_csrc_cl_N))
+ if (is_a<print_csrc_cl_N>(c))
c.s << "expt(";
else
c.s << "pow(";
} else {
if (exponent.is_equal(_ex1_2())) {
- if (is_of_type(c, print_latex))
+ if (is_a<print_latex>(c))
c.s << "\\sqrt{";
else
c.s << "sqrt(";
basis.print(c);
- if (is_of_type(c, print_latex))
+ if (is_a<print_latex>(c))
c.s << '}';
else
c.s << ')';
} else {
if (precedence() <= level) {
- if (is_of_type(c, print_latex))
+ if (is_a<print_latex>(c))
c.s << "{(";
else
c.s << "(";
}
basis.print(c, precedence());
c.s << '^';
- if (is_of_type(c, print_latex))
+ if (is_a<print_latex>(c))
c.s << '{';
exponent.print(c, precedence());
- if (is_of_type(c, print_latex))
+ if (is_a<print_latex>(c))
c.s << '}';
if (precedence() <= level) {
- if (is_of_type(c, print_latex))
+ if (is_a<print_latex>(c))
c.s << ")}";
else
c.s << ')';
};
// utility functions
+
+/** Return the power object handled by an ex.
+ * 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)
+{
+ return obj.tinfo()==TINFO_power;
+}
+
// wrapper functions
/** Symbolic exponentiation. Returns a power-object as a new expression.
: print_csrc(os) {}
};
+/** Check if obj is a T, including base classes. */
+template <class T>
+inline bool is_a(const print_context & obj)
+{ return dynamic_cast<const T *>(&obj)!=0; }
+
} // namespace GiNaC
#endif // ndef __GINAC_BASIC_H__
{
debugmsg("pseries 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
if (precedence() <= level)
c.s << "(";
- std::string par_open = is_of_type(c, print_latex) ? "{(" : "(";
- std::string par_close = is_of_type(c, print_latex) ? ")}" : ")";
+ std::string par_open = is_a<print_latex>(c) ? "{(" : "(";
+ std::string par_close = is_a<print_latex>(c) ? ")}" : ")";
// objects of type pseries must not have any zero entries, so the
// trivial (zero) pseries needs a special treatment here:
}
// print 'coeff', something like (x-1)^42
if (!i->coeff.is_zero()) {
- if (is_of_type(c, print_latex))
+ if (is_a<print_latex>(c))
c.s << ' ';
else
c.s << '*';
i->coeff.print(c);
c.s << par_close;
} else {
- if (is_of_type(c, print_latex)) {
+ if (is_a<print_latex>(c)) {
c.s << '{';
i->coeff.print(c);
c.s << '}';
*
* @param e expression
* @return reference to pseries object
- * @see is_ex_of_type */
+ * @see is_a<> */
inline const pseries &ex_to_pseries(const ex &e)
{
return static_cast<const pseries &>(*e.bp);
}
+/** Specialization of is_exactly_a<pseries>(obj) for pseries objects. */
+template<> inline bool is_exactly_a<pseries>(const basic & obj)
+{
+ return obj.tinfo()==TINFO_pseries;
+}
+
/** Convert the pseries object embedded in an expression to an ordinary
* polynomial in the expansion variable. The result is undefined if the
* expression does not contain a pseries object at its top level.
*
* @param e expression
* @return polynomial expression
- * @see is_ex_of_type
+ * @see is_a<>
* @see pseries::convert_to_poly */
inline ex series_to_poly(const ex &e)
{
};
// utility functions
+
+/** Return the relational object handled by an ex.
+ * 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)
+{
+ return obj.tinfo()==TINFO_relational;
+}
+
} // namespace GiNaC
#endif // ndef __GINAC_RELATIONAL_H__
// utility functions
+
+/** Return the symbol object handled by an ex.
+ * 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);
}
+/** Specialization of is_exactly_a<symbol>(obj) for symbol objects. */
+template<> inline bool is_exactly_a<symbol>(const basic & obj)
+{
+ return obj.tinfo()==TINFO_symbol;
+}
// wrapper functions around member functions
inline void unassign(symbol & symarg)
return symmetrize(e, v.begin(), v.end());
}
+// utility functions
+
+/** Specialization of is_exactly_a<symmetry>(obj) for symmetry objects. */
+template<> inline bool is_exactly_a<symmetry>(const basic & obj)
+{
+ return obj.tinfo()==TINFO_symmetry;
+}
+
} // namespace GiNaC
#endif // ndef __GINAC_SYMMETRY_H__
void classname::print(const print_context & c, unsigned level) const \
{ \
debugmsg(#classname " print", LOGLEVEL_PRINT); \
- if (is_of_type(c, print_tree)) \
+ if (is_a<print_tree>(c)) \
inherited::print(c, level); \
else \
c.s << text; \
void classname::print(const print_context & c, unsigned level) const \
{ \
debugmsg(#classname " 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_latex)) \
+ else if (is_a<print_latex>(c)) \
c.s << latex; \
else \
c.s << text; \
};
-// global functions
+// utility functions
+
+/** Return the wildcard object handled by an ex.
+ * 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)
+{
+ return obj.tinfo()==TINFO_wildcard;
+}
+
/** Create a wildcard object with the specified label. */
inline ex wild(unsigned label = 0)
{
static ex f_subs2(const exprseq &e) {return e[0].subs(e[1]);}
static ex f_tcoeff(const exprseq &e) {return e[0].tcoeff(e[1]);}
-#define CHECK_ARG(num, type, fcn) if (!is_ex_of_type(e[num], type)) throw(std::invalid_argument("argument " #num " to " #fcn "() must be a " #type))
+#define CHECK_ARG(num, type, fcn) if (!is_a<type>(e[num])) throw(std::invalid_argument("argument " #num " to " #fcn "() must be a " #type))
static ex f_charpoly(const exprseq &e)
{