From 0cf43f3096cbcfc7472ff9c8927c6eb74f2eeb8c Mon Sep 17 00:00:00 2001 From: Richard Kreckel Date: Fri, 15 Jun 2001 19:20:52 +0000 Subject: [PATCH] * Supplement some (now deprecated) macros by inlined template functions: - is_of_type(foo, type) -> is_a(foo) - is_ex_of_type(foo, type) -> is_a(foo) - is_exaclty_of_type(foo, type) -> is_exaclty_a(foo) - is_ex_exaclty_of_type(foo, type) -> is_exaclty_a(foo) --- NEWS | 5 ++ check/check_numeric.cpp | 2 +- check/exam_misc.cpp | 2 +- check/exam_powerlaws.cpp | 114 +++++++++++++++++++-------------------- ginac/add.cpp | 18 +++---- ginac/add.h | 9 ++++ ginac/basic.h | 31 +++++++++-- ginac/clifford.h | 8 +++ ginac/color.h | 8 +++ ginac/constant.cpp | 4 +- ginac/constant.h | 9 ++++ ginac/container.pl | 22 +++++--- ginac/expair.h | 6 +-- ginac/expairseq.h | 9 ++++ ginac/fail.h | 6 +++ ginac/function.pl | 10 +++- ginac/idx.h | 25 +++++++++ ginac/indexed.h | 9 ++++ ginac/lst_suppl.cpp | 2 +- ginac/matrix.h | 9 ++++ ginac/mul.cpp | 16 +++--- ginac/mul.h | 9 ++++ ginac/ncmul.h | 9 ++++ ginac/numeric.cpp | 20 +++---- ginac/numeric.h | 9 ++++ ginac/power.cpp | 25 ++++----- ginac/power.h | 9 ++++ ginac/print.h | 5 ++ ginac/pseries.cpp | 10 ++-- ginac/pseries.h | 10 +++- ginac/relational.h | 9 ++++ ginac/symbol.h | 8 +++ ginac/symmetry.h | 8 +++ ginac/utils.h | 6 +-- ginac/wildcard.h | 11 +++- ginsh/ginsh_parser.yy | 2 +- 36 files changed, 345 insertions(+), 129 deletions(-) diff --git a/NEWS b/NEWS index f8902a60..11a1966a 100644 --- 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(foo) + - is_ex_of_type(foo, type) -> is_a(foo) + - is_exaclty_of_type(foo, type) -> is_exaclty_a(foo) + - is_ex_exaclty_of_type(foo, type) -> is_exaclty_a(foo) 0.9.0 (7 June 2001) * In the output and in ginsh, lists are now delimited by { } braces, and diff --git a/check/check_numeric.cpp b/check/check_numeric.cpp index 46b78d32..17bfbae3 100644 --- a/check/check_numeric.cpp +++ b/check/check_numeric.cpp @@ -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(radical)) { clog << "(" << num << "/" << den << ")^(" << nm << ") should have been a product, instead it's " << radical << endl; diff --git a/check/exam_misc.cpp b/check/exam_misc.cpp index 17101bc5..d703a93a 100644 --- a/check/exam_misc.cpp +++ b/check/exam_misc.cpp @@ -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(selfprobe)) { clog << "ex (of numeric) after self-assignment became " << selfprobe << endl; ++result; } diff --git a/check/exam_powerlaws.cpp b/check/exam_powerlaws.cpp index c269e974..b7f2815f 100644 --- a/check/exam_powerlaws.cpp +++ b/check/exam_powerlaws.cpp @@ -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(e1) && + is_exactly_a(e1.op(0)) && + is_exactly_a(e1.op(0).op(0)) && + is_exactly_a(e1.op(0).op(1)) && + is_exactly_a(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(e2) && + is_exactly_a(e2.op(0)) && + is_exactly_a(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(e3) && + is_exactly_a(e3.op(0)) && + is_exactly_a(e3.op(0).op(0)) && + is_exactly_a(e3.op(0).op(1)) && + is_exactly_a(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(e4) && + is_exactly_a(e4.op(0)) && + is_exactly_a(e4.op(0).op(0)) && + is_exactly_a(e4.op(0).op(1)) && + is_exactly_a(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(e5) && + is_exactly_a(e5.op(0)) && + is_exactly_a(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(e6) && + is_exactly_a(e6.op(0)) && + is_exactly_a(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(e1) && + is_exactly_a(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(e1.op(0).op(0)) && + is_exactly_a(e1.op(0).op(1)) && + is_exactly_a(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(e2) && + is_exactly_a(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(e2.op(0).op(0)) && + is_exactly_a(e2.op(0).op(1)) && + is_exactly_a(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(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(e3.op(0)) && + is_exactly_a(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(e4) && + is_exactly_a(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(e4.op(0).op(0)) && + is_exactly_a(e4.op(0).op(1)) && + is_exactly_a(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(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(e5.op(0)) && + is_exactly_a(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(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(e6.op(0)) && + is_exactly_a(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(e7) && + is_exactly_a(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(e7.op(0).op(0)) && + is_exactly_a(e7.op(0).op(1)) && + is_exactly_a(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(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(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(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(e2))) { clog << "0^a was evaluated to " << e2 << " though nothing is known about a." << endl; return 1; diff --git a/ginac/add.cpp b/ginac/add.cpp index 17faae2c..331f2049 100644 --- a/ginac/add.cpp +++ b/ginac/add.cpp @@ -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(c)) { inherited::print(c, level); - } else if (is_of_type(c, print_csrc)) { + } else if (is_a(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(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(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(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(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(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); diff --git a/ginac/add.h b/ginac/add.h index eae04860..e04474f2 100644 --- a/ginac/add.h +++ b/ginac/add.h @@ -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(*e.bp); } +/** Specialization of is_exactly_a(obj) for add objects. */ +template<> inline bool is_exactly_a(const basic & obj) +{ + return obj.tinfo()==TINFO_add; +} + } // namespace GiNaC #endif // ndef __GINAC_ADD_H__ diff --git a/ginac/basic.h b/ginac/basic.h index 4ace75fd..78ceb54b 100644 --- a/ginac/basic.h +++ b/ginac/basic.h @@ -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(&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((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 +inline bool is_a(const basic & obj) +{ return dynamic_cast(&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 +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 +inline bool is_a(const ex & obj) +{ return is_a(*obj.bp); } + +/** Check if ex is a handle to a T, not including base classes. */ +template +inline bool is_exactly_a(const ex & obj) +{ return is_exactly_a(*obj.bp); } + } // namespace GiNaC #endif // ndef __GINAC_BASIC_H__ diff --git a/ginac/clifford.h b/ginac/clifford.h index 2877b881..9d429dca 100644 --- a/ginac/clifford.h +++ b/ginac/clifford.h @@ -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(*e.bp); } +/** Specialization of is_exactly_a(obj) for clifford objects. */ +template<> inline bool is_exactly_a(const basic & obj) +{ + return obj.tinfo()==TINFO_clifford; +} /** Create a Clifford unity object. * diff --git a/ginac/color.h b/ginac/color.h index eb273c71..0916bdfd 100644 --- a/ginac/color.h +++ b/ginac/color.h @@ -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(*e.bp); } +/** Specialization of is_exactly_a(obj) for color objects. */ +template<> inline bool is_exactly_a(const basic & obj) +{ + return obj.tinfo()==TINFO_color; +} /** Create the su(3) unity element. This is an indexed object, although it * has no indices. diff --git a/ginac/constant.cpp b/ginac/constant.cpp index e86a2964..ba8b1514 100644 --- a/ginac/constant.cpp +++ b/ginac/constant.cpp @@ -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(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(c)) c.s << TeX_name; else c.s << name; diff --git a/ginac/constant.h b/ginac/constant.h index bf85b382..4c928765 100644 --- a/ginac/constant.h +++ b/ginac/constant.h @@ -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(*e.bp); } +/** Specialization of is_exactly_a(obj) for constant objects. */ +template<> inline bool is_exactly_a(const basic & obj) +{ + return obj.tinfo()==TINFO_constant; +} + } // namespace GiNaC #endif // ndef __GINAC_CONSTANT_H__ diff --git a/ginac/container.pl b/ginac/container.pl index 5b8b59e2..843421e9 100755 --- a/ginac/container.pl +++ b/ginac/container.pl @@ -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(*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(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(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(other)); + GINAC_ASSERT(is_a<${CONTAINER}>(other)); + ${CONTAINER} const & o = static_cast<${CONTAINER} const &>(const_cast(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; diff --git a/ginac/expair.h b/ginac/expair.h index 74744e02..91dd2323 100644 --- a/ginac/expair.h +++ b/ginac/expair.h @@ -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(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(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(coeff)); return (is_ex_exactly_of_type(rest,numeric) && (coeff.is_equal(1))); } diff --git a/ginac/expairseq.h b/ginac/expairseq.h index 0bfd2ed6..9865586c 100644 --- a/ginac/expairseq.h +++ b/ginac/expairseq.h @@ -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(*e.bp); } +/** Specialization of is_exactly_a(obj) for expairseq objects. */ +template<> inline bool is_exactly_a(const basic & obj) +{ + return obj.tinfo()==TINFO_expairseq; +} + } // namespace GiNaC #endif // ndef __GINAC_EXPAIRSEQ_H__ diff --git a/ginac/fail.h b/ginac/fail.h index 5b9c2147..24050923 100644 --- a/ginac/fail.h +++ b/ginac/fail.h @@ -39,6 +39,12 @@ protected: unsigned return_type(void) const { return return_types::noncommutative_composite; }; }; +/** Specialization of is_exactly_a(obj) for fail objects. */ +template<> inline bool is_exactly_a(const basic & obj) +{ + return obj.tinfo()==TINFO_fail; +} + } // namespace GiNaC #endif // ndef __GINAC_FAIL_H__ diff --git a/ginac/function.pl b/ginac/function.pl index 7d45d6d4..cfb9e813 100755 --- a/ginac/function.pl +++ b/ginac/function.pl @@ -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(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(*e.bp); } +/** Specialization of is_exactly_a(obj) for objects of type function. */ +template<> inline bool is_exactly_a(const basic & obj) +{ + return obj.tinfo()==TINFO_function; +} + #define is_ex_the_function(OBJ, FUNCNAME) \\ (is_ex_exactly_of_type(OBJ, function) && static_cast(OBJ.bp)->get_serial() == function_index_##FUNCNAME) diff --git a/ginac/idx.h b/ginac/idx.h index 8f952b84..92c685c4 100644 --- a/ginac/idx.h +++ b/ginac/idx.h @@ -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(*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(*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(*e.bp); } +/** Specialization of is_exactly_a(obj) for idx objects. */ +template<> inline bool is_exactly_a(const basic & obj) +{ + return obj.tinfo()==TINFO_idx; +} + +/** Specialization of is_exactly_a(obj) for varidx objects. */ +template<> inline bool is_exactly_a(const basic & obj) +{ + return obj.tinfo()==TINFO_varidx; +} + +/** Specialization of is_exactly_a(obj) for spinidx objects. */ +template<> inline bool is_exactly_a(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); diff --git a/ginac/indexed.h b/ginac/indexed.h index 22210708..df05429e 100644 --- a/ginac/indexed.h +++ b/ginac/indexed.h @@ -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(*e.bp); } +/** Specialization of is_exactly_a(obj) for indexed objects. */ +template<> inline bool is_exactly_a(const basic & obj) +{ + return obj.tinfo()==TINFO_indexed; +} + } // namespace GiNaC #endif // ndef __GINAC_INDEXED_H__ diff --git a/ginac/lst_suppl.cpp b/ginac/lst_suppl.cpp index 36b6d149..81212707 100644 --- a/ginac/lst_suppl.cpp +++ b/ginac/lst_suppl.cpp @@ -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); } diff --git a/ginac/matrix.h b/ginac/matrix.h index 0cb7a71c..fac033a9 100644 --- a/ginac/matrix.h +++ b/ginac/matrix.h @@ -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(*e.bp); } +/** Specialization of is_exactly_a(obj) for matrix objects. */ +template<> inline bool is_exactly_a(const basic & obj) +{ + return obj.tinfo()==TINFO_matrix; +} + /** Convert list of lists to matrix. */ extern ex lst_to_matrix(const lst & l); diff --git a/ginac/mul.cpp b/ginac/mul.cpp index 3dfe48eb..10f25ec7 100644 --- a/ginac/mul.cpp +++ b/ginac/mul.cpp @@ -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(c)) { inherited::print(c, level); - } else if (is_of_type(c, print_csrc)) { + } else if (is_a(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/" 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(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(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(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(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(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()))) { diff --git a/ginac/mul.h b/ginac/mul.h index 2808db99..39138c2e 100644 --- a/ginac/mul.h +++ b/ginac/mul.h @@ -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(*e.bp); } +/** Specialization of is_exactly_a(obj) for mul objects. */ +template<> inline bool is_exactly_a(const basic & obj) +{ + return obj.tinfo()==TINFO_mul; +} + } // namespace GiNaC #endif // ndef __GINAC_MUL_H__ diff --git a/ginac/ncmul.h b/ginac/ncmul.h index 86204484..361deff6 100644 --- a/ginac/ncmul.h +++ b/ginac/ncmul.h @@ -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 (*e.bp); } +/** Specialization of is_exactly_a(obj) for ncmul objects. */ +template<> inline bool is_exactly_a(const basic & obj) +{ + return obj.tinfo()==TINFO_ncmul; +} + } // namespace GiNaC #endif // ndef __GINAC_NCMUL_H__ diff --git a/ginac/numeric.cpp b/ginac/numeric.cpp index a89045bd..eb9afa19 100644 --- a/ginac/numeric.cpp +++ b/ginac/numeric.cpp @@ -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(c)) { c.s << std::string(level, ' ') << cln::the(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(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(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(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(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(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(c) ? "{(" : "("; + const std::string par_close = is_a(c) ? ")}" : ")"; + const std::string imag_sym = is_a(c) ? "i" : "I"; + const std::string mul_sym = is_a(c) ? " " : "*"; const cln::cl_R r = cln::realpart(cln::the(value)); const cln::cl_R i = cln::imagpart(cln::the(value)); if (cln::zerop(i)) { diff --git a/ginac/numeric.h b/ginac/numeric.h index b759d1af..d727fe35 100644 --- a/ginac/numeric.h +++ b/ginac/numeric.h @@ -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(*e.bp); } +/** Specialization of is_exactly_a(obj) for numeric objects. */ +template<> inline bool is_exactly_a(const basic & obj) +{ + return obj.tinfo()==TINFO_numeric; +} + } // namespace GiNaC #ifdef __MAKECINT__ diff --git a/ginac/power.cpp b/ginac/power.cpp index 8996625f..05b6d1c6 100644 --- a/ginac/power.cpp +++ b/ginac/power.cpp @@ -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(c)) { inherited::print(c, level); - } else if (is_of_type(c, print_csrc)) { + } else if (is_a(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(basis) || is_exactly_a(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(c)) c.s << "recip("; else c.s << "1.0/("; @@ -156,7 +157,7 @@ void power::print(const print_context & c, unsigned level) const // ^-1 is printed as "1.0/" 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(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(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(c)) c.s << "\\sqrt{"; else c.s << "sqrt("; basis.print(c); - if (is_of_type(c, print_latex)) + if (is_a(c)) c.s << '}'; else c.s << ')'; } else { if (precedence() <= level) { - if (is_of_type(c, print_latex)) + if (is_a(c)) c.s << "{("; else c.s << "("; } basis.print(c, precedence()); c.s << '^'; - if (is_of_type(c, print_latex)) + if (is_a(c)) c.s << '{'; exponent.print(c, precedence()); - if (is_of_type(c, print_latex)) + if (is_a(c)) c.s << '}'; if (precedence() <= level) { - if (is_of_type(c, print_latex)) + if (is_a(c)) c.s << ")}"; else c.s << ')'; diff --git a/ginac/power.h b/ginac/power.h index d13463af..23a7a4eb 100644 --- a/ginac/power.h +++ b/ginac/power.h @@ -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(*e.bp); } +/** Efficient specialization of is_exactly_a(obj) for power objects. */ +template<> inline bool is_exactly_a(const basic & obj) +{ + return obj.tinfo()==TINFO_power; +} + // wrapper functions /** Symbolic exponentiation. Returns a power-object as a new expression. diff --git a/ginac/print.h b/ginac/print.h index c8bd9b66..e32238d0 100644 --- a/ginac/print.h +++ b/ginac/print.h @@ -88,6 +88,11 @@ public: : print_csrc(os) {} }; +/** Check if obj is a T, including base classes. */ +template +inline bool is_a(const print_context & obj) +{ return dynamic_cast(&obj)!=0; } + } // namespace GiNaC #endif // ndef __GINAC_BASIC_H__ diff --git a/ginac/pseries.cpp b/ginac/pseries.cpp index 88f94ce8..d7f78476 100644 --- a/ginac/pseries.cpp +++ b/ginac/pseries.cpp @@ -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(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(c) ? "{(" : "("; + std::string par_close = is_a(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(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(c)) { c.s << '{'; i->coeff.print(c); c.s << '}'; diff --git a/ginac/pseries.h b/ginac/pseries.h index 72586eaf..bd2db158 100644 --- a/ginac/pseries.h +++ b/ginac/pseries.h @@ -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(*e.bp); } +/** Specialization of is_exactly_a(obj) for pseries objects. */ +template<> inline bool is_exactly_a(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) { diff --git a/ginac/relational.h b/ginac/relational.h index c3b223b5..79f3cf33 100644 --- a/ginac/relational.h +++ b/ginac/relational.h @@ -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(*e.bp); } +/** Specialization of is_exactly_a(obj) for relational objects. */ +template<> inline bool is_exactly_a(const basic & obj) +{ + return obj.tinfo()==TINFO_relational; +} + } // namespace GiNaC #endif // ndef __GINAC_RELATIONAL_H__ diff --git a/ginac/symbol.h b/ginac/symbol.h index aec27aee..df6a9fd4 100644 --- a/ginac/symbol.h +++ b/ginac/symbol.h @@ -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(*e.bp); } +/** Specialization of is_exactly_a(obj) for symbol objects. */ +template<> inline bool is_exactly_a(const basic & obj) +{ + return obj.tinfo()==TINFO_symbol; +} // wrapper functions around member functions inline void unassign(symbol & symarg) diff --git a/ginac/symmetry.h b/ginac/symmetry.h index 440ece18..405ba317 100644 --- a/ginac/symmetry.h +++ b/ginac/symmetry.h @@ -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(obj) for symmetry objects. */ +template<> inline bool is_exactly_a(const basic & obj) +{ + return obj.tinfo()==TINFO_symmetry; +} + } // namespace GiNaC #endif // ndef __GINAC_SYMMETRY_H__ diff --git a/ginac/utils.h b/ginac/utils.h index 91d30f7c..3e8e17ca 100644 --- a/ginac/utils.h +++ b/ginac/utils.h @@ -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(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(c)) \ inherited::print(c, level); \ - else if (is_of_type(c, print_latex)) \ + else if (is_a(c)) \ c.s << latex; \ else \ c.s << text; \ diff --git a/ginac/wildcard.h b/ginac/wildcard.h index 2d79cf7b..6e1bf1c0 100644 --- a/ginac/wildcard.h +++ b/ginac/wildcard.h @@ -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(*e.bp); } +/** Specialization of is_exactly_a(obj) for wildcard objects. */ +template<> inline bool is_exactly_a(const basic & obj) +{ + return obj.tinfo()==TINFO_wildcard; +} + /** Create a wildcard object with the specified label. */ inline ex wild(unsigned label = 0) { diff --git a/ginsh/ginsh_parser.yy b/ginsh/ginsh_parser.yy index fcc66f42..a7872fba 100644 --- a/ginsh/ginsh_parser.yy +++ b/ginsh/ginsh_parser.yy @@ -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(e[num])) throw(std::invalid_argument("argument " #num " to " #fcn "() must be a " #type)) static ex f_charpoly(const exprseq &e) { -- 2.44.0