* Supplement some (now deprecated) macros by inlined template functions:
authorRichard Kreckel <Richard.Kreckel@uni-mainz.de>
Fri, 15 Jun 2001 19:20:52 +0000 (19:20 +0000)
committerRichard Kreckel <Richard.Kreckel@uni-mainz.de>
Fri, 15 Jun 2001 19:20:52 +0000 (19:20 +0000)
  - 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)

36 files changed:
NEWS
check/check_numeric.cpp
check/exam_misc.cpp
check/exam_powerlaws.cpp
ginac/add.cpp
ginac/add.h
ginac/basic.h
ginac/clifford.h
ginac/color.h
ginac/constant.cpp
ginac/constant.h
ginac/container.pl
ginac/expair.h
ginac/expairseq.h
ginac/fail.h
ginac/function.pl
ginac/idx.h
ginac/indexed.h
ginac/lst_suppl.cpp
ginac/matrix.h
ginac/mul.cpp
ginac/mul.h
ginac/ncmul.h
ginac/numeric.cpp
ginac/numeric.h
ginac/power.cpp
ginac/power.h
ginac/print.h
ginac/pseries.cpp
ginac/pseries.h
ginac/relational.h
ginac/symbol.h
ginac/symmetry.h
ginac/utils.h
ginac/wildcard.h
ginsh/ginsh_parser.yy

diff --git a/NEWS b/NEWS
index f8902a6..11a1966 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -16,6 +16,11 @@ This file records noteworthy changes.
 * 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
index 46b78d3..17bfbae 100644 (file)
@@ -75,7 +75,7 @@ static unsigned check_numeric2(void)
                        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;
index 17101bc..d703a93 100644 (file)
@@ -191,7 +191,7 @@ static unsigned exam_operator_semantics(void)
        // (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;
        }
index c269e97..b7f2815 100644 (file)
@@ -32,11 +32,11 @@ static unsigned exam_powerlaws1(void)
        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;
@@ -44,9 +44,9 @@ static unsigned exam_powerlaws1(void)
        }
        
        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;
@@ -54,11 +54,11 @@ static unsigned exam_powerlaws1(void)
        }
        
        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;
@@ -66,11 +66,11 @@ static unsigned exam_powerlaws1(void)
        }
        
        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;
@@ -78,9 +78,9 @@ static unsigned exam_powerlaws1(void)
        }
        
        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;
@@ -88,9 +88,9 @@ static unsigned exam_powerlaws1(void)
        }
        
        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;
@@ -109,12 +109,12 @@ static unsigned exam_powerlaws2(void)
        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;
@@ -122,12 +122,12 @@ static unsigned exam_powerlaws2(void)
        }
        
        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;
@@ -135,10 +135,10 @@ static unsigned exam_powerlaws2(void)
        }
        
        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;
@@ -146,12 +146,12 @@ static unsigned exam_powerlaws2(void)
        }
        
        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;
@@ -159,10 +159,10 @@ static unsigned exam_powerlaws2(void)
        }
        
        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;
@@ -171,10 +171,10 @@ static unsigned exam_powerlaws2(void)
        }
        
        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;
@@ -183,12 +183,12 @@ static unsigned exam_powerlaws2(void)
        }
        
        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;
@@ -215,7 +215,7 @@ static unsigned exam_powerlaws3(void)
        }
        
        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;
@@ -223,13 +223,13 @@ static unsigned exam_powerlaws3(void)
        }
        
        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;
        }
@@ -275,7 +275,7 @@ static unsigned exam_powerlaws5(void)
        }
        
        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;
index 17faae2..331f204 100644 (file)
@@ -116,11 +116,11 @@ void add::print(const print_context & c, unsigned level) const
 {
        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 << "(";
@@ -152,7 +152,7 @@ void add::print(const print_context & c, unsigned level) const
                
                        // 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 << "+";
                }
        
@@ -168,7 +168,7 @@ void add::print(const print_context & c, unsigned level) const
        } else {
 
                if (precedence() <= level) {
-                       if (is_of_type(c, print_latex))
+                       if (is_a<print_latex>(c))
                                c.s << "{(";
                        else
                                c.s << "(";
@@ -179,7 +179,7 @@ void add::print(const print_context & c, unsigned level) const
 
                // 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());
@@ -209,7 +209,7 @@ void add::print(const print_context & c, unsigned level) const
                                        else
                                                coeff.print(c, precedence());
                                }
-                               if (is_of_type(c, print_latex))
+                               if (is_a<print_latex>(c))
                                        c.s << ' ';
                                else
                                        c.s << '*';
@@ -219,7 +219,7 @@ void add::print(const print_context & c, unsigned level) const
                }
 
                if (precedence() <= level) {
-                       if (is_of_type(c, print_latex))
+                       if (is_a<print_latex>(c))
                                c.s << ")}";
                        else
                                c.s << ")";
@@ -427,7 +427,7 @@ expair add::split_ex_to_pair(const ex & e) const
 {
        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);
@@ -444,7 +444,7 @@ expair add::combine_ex_with_coeff_to_pair(const ex & e,
        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);
index eae0486..e04474f 100644 (file)
@@ -78,11 +78,20 @@ protected:
 };
 
 // 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__
index 4ace75f..78ceb54 100644 (file)
@@ -176,24 +176,45 @@ private:
 
 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__
index 2877b88..9d429dc 100644 (file)
@@ -101,11 +101,19 @@ public:
 
 
 // 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.
  *
index eb273c7..0916bdf 100644 (file)
@@ -115,11 +115,19 @@ public:
 
 
 // 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.
index e86a296..ba8b151 100644 (file)
@@ -140,11 +140,11 @@ void constant::print(const print_context & c, unsigned level) const
 {
        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;
index bf85b38..4c92876 100644 (file)
@@ -80,11 +80,20 @@ extern const constant Catalan;
 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__
index 5b8b59e..843421e 100755 (executable)
@@ -246,11 +246,20 @@ protected:
 };
 
 // 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);
@@ -406,7 +415,7 @@ void ${CONTAINER}::print(const print_context & c, unsigned level) const
 {
        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
@@ -494,7 +503,7 @@ ex ${CONTAINER}::subs(const lst & ls, const lst & lr, bool no_pattern) const
 
 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;
@@ -515,13 +524,12 @@ int ${CONTAINER}::compare_same_type(const basic & other) const
 
 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;
index 74744e0..91dd232 100644 (file)
@@ -41,7 +41,7 @@ public:
        ~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)
        {
@@ -55,7 +55,7 @@ public:
        /** 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. */
@@ -93,7 +93,7 @@ public:
        /** 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)));
        }
index 0bfd2ed..9865586 100644 (file)
@@ -188,11 +188,20 @@ protected:
 };
 
 // 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__
index 5b9c214..2405092 100644 (file)
@@ -39,6 +39,12 @@ protected:
        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__
index 7d45d6d..cfb9e81 100755 (executable)
@@ -224,7 +224,7 @@ const unsigned function_index_##NAME= \\
 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
 
@@ -379,11 +379,19 @@ protected:
 };
 
 // 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)
 
index 8f952b8..92c685c 100644 (file)
@@ -174,21 +174,46 @@ protected:
 
 
 // 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);
 
index 2221070..df05429 100644 (file)
@@ -233,11 +233,20 @@ private:
 
 
 // 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__
index 36b6d14..8121270 100644 (file)
@@ -27,7 +27,7 @@ namespace GiNaC {
 
 bool lst::info(unsigned inf) const
 {
-       if (inf==info_flags::list) return 1;
+       if (inf==info_flags::list) return true;
        return basic::info(inf);
 }
 
index 0cb7a71..fac033a 100644 (file)
@@ -133,11 +133,20 @@ inline matrix inverse(const matrix & m)
 { 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);
 
index 3dfe48e..10f25ec 100644 (file)
@@ -131,11 +131,11 @@ void mul::print(const print_context & c, unsigned level) const
 {
        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 << "(";
@@ -151,7 +151,7 @@ void mul::print(const print_context & c, unsigned level) const
 
                        // 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/";
@@ -181,7 +181,7 @@ void mul::print(const print_context & c, unsigned level) const
        } else {
 
                if (precedence() <= level) {
-                       if (is_of_type(c, print_latex))
+                       if (is_a<print_latex>(c))
                                c.s << "{(";
                        else
                                c.s << "(";
@@ -206,7 +206,7 @@ void mul::print(const print_context & c, unsigned level) const
                                else
                                        coeff.print(c, precedence());
                        }
-                       if (is_of_type(c, print_latex))
+                       if (is_a<print_latex>(c))
                                c.s << ' ';
                        else
                                c.s << '*';
@@ -216,7 +216,7 @@ void mul::print(const print_context & c, unsigned level) const
                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 << '*';
@@ -228,7 +228,7 @@ void mul::print(const print_context & c, unsigned level) const
                }
 
                if (precedence() <= level) {
-                       if (is_of_type(c, print_latex))
+                       if (is_a<print_latex>(c))
                                c.s << ")}";
                        else
                                c.s << ")";
@@ -655,7 +655,7 @@ ex mul::expand(unsigned options) const
        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()))) {
index 2808db9..39138c2 100644 (file)
@@ -90,11 +90,20 @@ protected:
 };
 
 // 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__
index 8620448..361deff 100644 (file)
@@ -88,11 +88,20 @@ ex nonsimplified_ncmul(const exvector & v);
 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__
index a89045b..eb9afa1 100644 (file)
@@ -370,39 +370,39 @@ void numeric::print(const print_context & c, unsigned level) const
 {
        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();
@@ -410,10 +410,10 @@ void numeric::print(const print_context & c, unsigned level) const
                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)) {
index b759d1a..d727fe3 100644 (file)
@@ -285,11 +285,20 @@ ex CatalanEvalf(void);
 
 
 // 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__
index 8996625..05b6d1c 100644 (file)
@@ -30,6 +30,7 @@
 #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"
@@ -132,21 +133,21 @@ void power::print(const print_context & c, unsigned level) const
 {
        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/(";
@@ -156,7 +157,7 @@ void power::print(const print_context & c, unsigned level) const
 
                // <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/(";
@@ -165,7 +166,7 @@ void power::print(const print_context & c, unsigned level) const
 
                // 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(";
@@ -178,31 +179,31 @@ void power::print(const print_context & c, unsigned level) const
        } 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 << ')';
index d13463a..23a7a4e 100644 (file)
@@ -92,11 +92,20 @@ protected:
 };
 
 // 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.
index c8bd9b6..e32238d 100644 (file)
@@ -88,6 +88,11 @@ public:
          : 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__
index 88f94ce..d7f7847 100644 (file)
@@ -126,7 +126,7 @@ void pseries::print(const print_context & c, unsigned level) const
 {
        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
@@ -145,8 +145,8 @@ void pseries::print(const print_context & c, unsigned level) const
                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:
@@ -168,7 +168,7 @@ void pseries::print(const print_context & c, unsigned level) const
                                }
                                // 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 << '*';
@@ -185,7 +185,7 @@ void pseries::print(const print_context & c, unsigned level) const
                                                        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 << '}';
index 72586ea..bd2db15 100644 (file)
@@ -107,19 +107,25 @@ protected:
  *
  *  @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)
 {
index c3b223b..79f3cf3 100644 (file)
@@ -82,11 +82,20 @@ protected:
 };
 
 // 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__
index aec27ae..df6a9fd 100644 (file)
@@ -115,11 +115,19 @@ private:
 
 
 // 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)
index 440ece1..405ba31 100644 (file)
@@ -167,6 +167,14 @@ inline ex symmetrize_cyclic(const ex & e, const exvector & v)
        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__
index 91d30f7..3e8e17c 100644 (file)
@@ -476,7 +476,7 @@ int classname::compare_same_type(const basic & other) const \
 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; \
@@ -486,9 +486,9 @@ void classname::print(const print_context & c, unsigned level) const \
 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; \
index 2d79cf7..6e1bf1c 100644 (file)
@@ -55,12 +55,21 @@ private:
 };
 
 
-// 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)
 {
index fcc66f4..a7872fb 100644 (file)
@@ -298,7 +298,7 @@ static ex f_sqrfree1(const exprseq &e) {return sqrfree(e[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)
 {