for example (@pxref{Complex expressions}), do @emph{not} evaluate if applied
to such symbols. Likewise @code{log(exp(x))} does not evaluate to @code{x},
because of the unknown imaginary part of @code{x}.
-On the other hand, if you are sure that your symbols will hold only real values, you
-would like to have such functions evaluated. Therefore GiNaC allows you to specify
+On the other hand, if you are sure that your symbols will hold only real
+values, you would like to have such functions evaluated. Therefore GiNaC
+allows you to specify
the domain of the symbol. Instead of @code{symbol x("x");} you can write
@code{realsymbol x("x");} to tell GiNaC that @code{x} stands in for real values.
+@cindex @code{possymbol()}
+Furthermore, it is also possible to declare a symbol as positive. This will,
+for instance, enable the automatic simplification of @code{abs(x)} into
+@code{x}. This is done by declaying the symbol as @code{possymbol x("x");}.
+
@node Numbers, Constants, Symbols, Basic concepts
@c node-name, next, previous, up
domain = domain::real;
}
+// possymbol
+
+possymbol::possymbol()
+{
+ domain = domain::positive;
+}
+
//////////
// other constructors
//////////
realsymbol::realsymbol(const std::string & initname, const std::string & texname, unsigned rt, tinfo_t rtt, unsigned domain)
: symbol(initname, texname, rt, rtt, domain) { }
+// possymbol
+
+possymbol::possymbol(const std::string & initname, unsigned domain)
+ : symbol(initname, domain) { }
+
+possymbol::possymbol(const std::string & initname, const std::string & texname, unsigned domain)
+ : symbol(initname, texname, domain) { }
+
+possymbol::possymbol(const std::string & initname, unsigned rt, tinfo_t rtt, unsigned domain)
+ : symbol(initname, rt, rtt, domain) { }
+
+possymbol::possymbol(const std::string & initname, const std::string & texname, unsigned rt, tinfo_t rtt, unsigned domain)
+ : symbol(initname, texname, rt, rtt, domain) { }
+
//////////
// archiving
//////////
GINAC_DECLARE_REGISTERED_CLASS(symbol, basic)
friend class realsymbol;
+ friend class possymbol;
// types
};
+/** Specialization of symbol to real domain */
+class possymbol : public symbol
+{
+ // constructors
+public:
+ possymbol();
+ explicit possymbol(const std::string & initname, unsigned domain = domain::positive);
+ possymbol(const std::string & initname, const std::string & texname, unsigned domain = domain::positive);
+ possymbol(const std::string & initname, unsigned rt, tinfo_t rtt, unsigned domain = domain::positive);
+ possymbol(const std::string & initname, const std::string & texname, unsigned rt, tinfo_t rtt, unsigned domain = domain::positive);
+};
+
+
// utility functions
/** Specialization of is_exactly_a<realsymbol>(obj) for realsymbol objects. */
return domain==domain::real || domain==domain::positive;
}
+/** Specialization of is_exactly_a<possymbol>(obj) for possymbol objects. */
+template<> inline bool is_exactly_a<possymbol>(const basic & obj)
+{
+ if (obj.tinfo() != &symbol::tinfo_static)
+ return false;
+ unsigned domain = static_cast<const symbol &>(obj).get_domain();
+ return domain == domain::positive;
+}
+
// wrapper functions around member functions
inline void unassign(symbol & symarg)
{ symarg.unassign(); }