out in one of the next releases.
- rewrote the foo_evalf() functions without TYPECHECK macros. (Since they
were not flexible enough and some functions need more flexibility than
can be provided by such macros. They are evil anyways.)
- marked the TYPECHECK macros as evil^H^H^H^Hdeprecated.
- implemented a more flexible scheme for some foo_evalf() functions, notably
zeta(3.0) eval's to a float now while zeta(3) doesn't eval, just as is
usual for all the trigonometric functions.
- this day is very hot.
extern int max_recursion_level;
-// Obsolete convenience macros. To be phased out soon!
-// Use the inlined template functions below instead of these macros.
-
-#define is_of_type(OBJ,TYPE) \
- (dynamic_cast<const TYPE *>(&OBJ)!=0)
-
-#define is_exactly_of_type(OBJ,TYPE) \
- ((OBJ).tinfo()==GiNaC::TINFO_##TYPE)
-
-#define is_ex_of_type(OBJ,TYPE) \
- (dynamic_cast<const TYPE *>((OBJ).bp)!=0)
-
-#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. */
bool is_canonical_numeric(void) const
{
GINAC_ASSERT(is_exactly_a<numeric>(coeff));
- return (is_ex_exactly_of_type(rest,numeric) &&
- (coeff.is_equal(1)));
+ return (is_exactly_a<numeric>(rest) && (coeff.is_equal(1)));
}
/** Swap contents with other expair. */
const unsigned function_index_##NAME= \\
GiNaC::function::register_new(GiNaC::function_options(#NAME).OPT);
+// The TYPECHECK-macros were used inside the _evalf() functions. They are
+// considered obsolete now: (FIXME: remove them)
+
#define BEGIN_TYPECHECK \\
bool automatic_typecheck=true;
}
#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)
+ (is_exactly_a<function>(OBJ) && static_cast<GiNaC::function *>(OBJ.bp)->get_serial() == function_index_##FUNCNAME)
} // namespace GiNaC
#define __GINAC_IDX_H__
#include "ex.h"
+#include "numeric.h"
namespace GiNaC {
ex get_value(void) const {return value;}
/** Check whether the index is numeric. */
- bool is_numeric(void) const {return is_ex_exactly_of_type(value, numeric);}
+ bool is_numeric(void) const {return is_exactly_a<numeric>(value);}
/** Check whether the index is symbolic. */
- bool is_symbolic(void) const {return !is_ex_exactly_of_type(value, numeric);}
+ bool is_symbolic(void) const {return !is_exactly_a<numeric>(value);}
/** Get dimension of index space. */
ex get_dim(void) const {return dim;}
/** Check whether the dimension is numeric. */
- bool is_dim_numeric(void) const {return is_ex_exactly_of_type(dim, numeric);}
+ bool is_dim_numeric(void) const {return is_exactly_a<numeric>(dim);}
/** Check whether the dimension is symbolic. */
- bool is_dim_symbolic(void) const {return !is_ex_exactly_of_type(dim, numeric);}
+ bool is_dim_symbolic(void) const {return !is_exactly_a<numeric>(dim);}
protected:
ex value; /**< Expression that constitutes the index (numeric or symbolic name) */
static ex abs_evalf(const ex & arg)
{
- BEGIN_TYPECHECK
- TYPECHECK(arg,numeric)
- END_TYPECHECK(abs(arg))
+ if (is_exactly_a<numeric>(arg))
+ return abs(ex_to<numeric>(arg));
- return abs(ex_to<numeric>(arg));
+ return abs(arg).hold();
}
static ex abs_eval(const ex & arg)
static ex csgn_evalf(const ex & arg)
{
- BEGIN_TYPECHECK
- TYPECHECK(arg,numeric)
- END_TYPECHECK(csgn(arg))
+ if (is_exactly_a<numeric>(arg))
+ return csgn(ex_to<numeric>(arg));
- return csgn(ex_to<numeric>(arg));
+ return csgn(arg).hold();
}
static ex csgn_eval(const ex & arg)
REGISTER_FUNCTION(eta, eval_func(eta_eval).
evalf_func(eta_evalf).
- series_func(eta_series).
+ series_func(eta_series).
latex_name("\\eta").
set_symmetry(sy_symm(0, 1)));
static ex Li2_evalf(const ex & x)
{
- BEGIN_TYPECHECK
- TYPECHECK(x,numeric)
- END_TYPECHECK(Li2(x))
+ if (is_exactly_a<numeric>(x))
+ return Li2(ex_to<numeric>(x));
- return Li2(ex_to<numeric>(x)); // -> numeric Li2(numeric)
+ return Li2(x).hold();
}
static ex Li2_eval(const ex & x)
return power(Pi,_ex2())/_ex_48() - Catalan*I;
// Li2(float)
if (!x.info(info_flags::crational))
- return Li2_evalf(x);
+ return Li2(ex_to<numeric>(x));
}
return Li2(x).hold();
GINAC_ASSERT(deriv_param==0);
// d/dx Li2(x) -> -log(1-x)/x
- return -log(1-x)/x;
+ return -log(_ex1()-x)/x;
}
static ex Li2_series(const ex &x, const relational &rel, int order, unsigned options)
// obsolete!
}
// second special case: x==1 (branch point)
- if (x_pt == _ex1()) {
+ if (x_pt.is_equal(_ex1())) {
// method:
// construct series manually in a dummy symbol s
const symbol s;
// Probably singular matrix or otherwise overdetermined system:
// It is consistent to return an empty list
return lst();
- }
+ }
GINAC_ASSERT(solution.cols()==1);
GINAC_ASSERT(solution.rows()==symbols.nops());
static ex lgamma_evalf(const ex & x)
{
- BEGIN_TYPECHECK
- TYPECHECK(x,numeric)
- END_TYPECHECK(lgamma(x))
+ if (is_exactly_a<numeric>(x)) {
+ try {
+ return lgamma(ex_to<numeric>(x));
+ } catch (const dunno &e) { }
+ }
- return lgamma(ex_to<numeric>(x));
+ return lgamma(x).hold();
}
static ex tgamma_evalf(const ex & x)
{
- BEGIN_TYPECHECK
- TYPECHECK(x,numeric)
- END_TYPECHECK(tgamma(x))
+ if (is_exactly_a<numeric>(x)) {
+ try {
+ return tgamma(ex_to<numeric>(x));
+ } catch (const dunno &e) { }
+ }
- return tgamma(ex_to<numeric>(x));
+ return tgamma(x).hold();
}
static ex beta_evalf(const ex & x, const ex & y)
{
- BEGIN_TYPECHECK
- TYPECHECK(x,numeric)
- TYPECHECK(y,numeric)
- END_TYPECHECK(beta(x,y))
+ if (is_exactly_a<numeric>(x) && is_exactly_a<numeric>(y)) {
+ try {
+ return tgamma(ex_to<numeric>(x))*tgamma(ex_to<numeric>(y))/tgamma(ex_to<numeric>(x+y));
+ } catch (const dunno &e) { }
+ }
- return tgamma(ex_to<numeric>(x))*tgamma(ex_to<numeric>(y))/tgamma(ex_to<numeric>(x+y));
+ return beta(x,y).hold();
}
}
// no problem in numerator, but denominator has pole:
if ((nx+ny).is_real() &&
- (nx+ny).is_integer() &&
- !(nx+ny).is_positive())
+ (nx+ny).is_integer() &&
+ !(nx+ny).is_positive())
return _ex0();
- // everything is ok:
- return tgamma(x)*tgamma(y)/tgamma(x+y);
+ // beta_evalf should be called here once it becomes available
}
return beta(x,y).hold();
static ex psi1_evalf(const ex & x)
{
- BEGIN_TYPECHECK
- TYPECHECK(x,numeric)
- END_TYPECHECK(psi(x))
+ if (is_exactly_a<numeric>(x)) {
+ try {
+ return psi(ex_to<numeric>(x));
+ } catch (const dunno &e) { }
+ }
- return psi(ex_to<numeric>(x));
+ return psi(x).hold();
}
/** Evaluation of digamma-function psi(x).
static ex psi2_evalf(const ex & n, const ex & x)
{
- BEGIN_TYPECHECK
- TYPECHECK(n,numeric)
- TYPECHECK(x,numeric)
- END_TYPECHECK(psi(n,x))
+ if (is_exactly_a<numeric>(n) && is_exactly_a<numeric>(x)) {
+ try {
+ return psi(ex_to<numeric>(n),ex_to<numeric>(x));
+ } catch (const dunno &e) { }
+ }
- return psi(ex_to<numeric>(n), ex_to<numeric>(x));
+ return psi(n,x).hold();
}
/** Evaluation of polygamma-function psi(n,x).
static ex exp_evalf(const ex & x)
{
- BEGIN_TYPECHECK
- TYPECHECK(x,numeric)
- END_TYPECHECK(exp(x))
+ if (is_exactly_a<numeric>(x))
+ return exp(ex_to<numeric>(x));
- return exp(ex_to<numeric>(x)); // -> numeric exp(numeric)
+ return exp(x).hold();
}
static ex exp_eval(const ex & x)
// exp(float)
if (x.info(info_flags::numeric) && !x.info(info_flags::crational))
- return exp_evalf(x);
+ return exp(ex_to<numeric>(x));
return exp(x).hold();
}
static ex log_evalf(const ex & x)
{
- BEGIN_TYPECHECK
- TYPECHECK(x,numeric)
- END_TYPECHECK(log(x))
+ if (is_exactly_a<numeric>(x))
+ return log(ex_to<numeric>(x));
- return log(ex_to<numeric>(x)); // -> numeric log(numeric)
+ return log(x).hold();
}
static ex log_eval(const ex & x)
return (Pi*I*_num_1_2());
// log(float)
if (!x.info(info_flags::crational))
- return log_evalf(x);
+ return log(ex_to<numeric>(x));
}
// log(exp(t)) -> t (if -Pi < t.imag() <= Pi):
if (is_ex_the_function(x, exp)) {
static ex sin_evalf(const ex & x)
{
- BEGIN_TYPECHECK
- TYPECHECK(x,numeric)
- END_TYPECHECK(sin(x))
+ if (is_exactly_a<numeric>(x))
+ return sin(ex_to<numeric>(x));
- return sin(ex_to<numeric>(x)); // -> numeric sin(numeric)
+ return sin(x).hold();
}
static ex sin_eval(const ex & x)
// sin(float) -> float
if (x.info(info_flags::numeric) && !x.info(info_flags::crational))
- return sin_evalf(x);
+ return sin(ex_to<numeric>(x));
return sin(x).hold();
}
static ex cos_evalf(const ex & x)
{
- BEGIN_TYPECHECK
- TYPECHECK(x,numeric)
- END_TYPECHECK(cos(x))
+ if (is_exactly_a<numeric>(x))
+ return cos(ex_to<numeric>(x));
- return cos(ex_to<numeric>(x)); // -> numeric cos(numeric)
+ return cos(x).hold();
}
static ex cos_eval(const ex & x)
// cos(float) -> float
if (x.info(info_flags::numeric) && !x.info(info_flags::crational))
- return cos_evalf(x);
+ return cos(ex_to<numeric>(x));
return cos(x).hold();
}
static ex tan_evalf(const ex & x)
{
- BEGIN_TYPECHECK
- TYPECHECK(x,numeric)
- END_TYPECHECK(tan(x)) // -> numeric tan(numeric)
+ if (is_exactly_a<numeric>(x))
+ return tan(ex_to<numeric>(x));
- return tan(ex_to<numeric>(x));
+ return tan(x).hold();
}
static ex tan_eval(const ex & x)
// tan(float) -> float
if (x.info(info_flags::numeric) && !x.info(info_flags::crational)) {
- return tan_evalf(x);
+ return tan(ex_to<numeric>(x));
}
return tan(x).hold();
static ex asin_evalf(const ex & x)
{
- BEGIN_TYPECHECK
- TYPECHECK(x,numeric)
- END_TYPECHECK(asin(x))
+ if (is_exactly_a<numeric>(x))
+ return asin(ex_to<numeric>(x));
- return asin(ex_to<numeric>(x)); // -> numeric asin(numeric)
+ return asin(x).hold();
}
static ex asin_eval(const ex & x)
return _num_1_2()*Pi;
// asin(float) -> float
if (!x.info(info_flags::crational))
- return asin_evalf(x);
+ return asin(ex_to<numeric>(x));
}
return asin(x).hold();
static ex acos_evalf(const ex & x)
{
- BEGIN_TYPECHECK
- TYPECHECK(x,numeric)
- END_TYPECHECK(acos(x))
+ if (is_exactly_a<numeric>(x))
+ return acos(ex_to<numeric>(x));
- return acos(ex_to<numeric>(x)); // -> numeric acos(numeric)
+ return acos(x).hold();
}
static ex acos_eval(const ex & x)
return Pi;
// acos(float) -> float
if (!x.info(info_flags::crational))
- return acos_evalf(x);
+ return acos(ex_to<numeric>(x));
}
return acos(x).hold();
static ex atan_evalf(const ex & x)
{
- BEGIN_TYPECHECK
- TYPECHECK(x,numeric)
- END_TYPECHECK(atan(x))
+ if (is_exactly_a<numeric>(x))
+ return atan(ex_to<numeric>(x));
- return atan(ex_to<numeric>(x)); // -> numeric atan(numeric)
+ return atan(x).hold();
}
static ex atan_eval(const ex & x)
throw (pole_error("atan_eval(): logarithmic pole",0));
// atan(float) -> float
if (!x.info(info_flags::crational))
- return atan_evalf(x);
+ return atan(ex_to<numeric>(x));
}
return atan(x).hold();
// inverse tangent (atan2(y,x))
//////////
-static ex atan2_evalf(const ex & y, const ex & x)
+static ex atan2_evalf(const ex &y, const ex &x)
{
- BEGIN_TYPECHECK
- TYPECHECK(y,numeric)
- TYPECHECK(x,numeric)
- END_TYPECHECK(atan2(y,x))
+ if (is_exactly_a<numeric>(y) && is_exactly_a<numeric>(x))
+ return atan2(ex_to<numeric>(y), ex_to<numeric>(x));
- return atan(ex_to<numeric>(y),ex_to<numeric>(x)); // -> numeric atan(numeric)
+ return atan2(y, x).hold();
}
static ex atan2_eval(const ex & y, const ex & x)
static ex sinh_evalf(const ex & x)
{
- BEGIN_TYPECHECK
- TYPECHECK(x,numeric)
- END_TYPECHECK(sinh(x))
+ if (is_exactly_a<numeric>(x))
+ return sinh(ex_to<numeric>(x));
- return sinh(ex_to<numeric>(x)); // -> numeric sinh(numeric)
+ return sinh(x).hold();
}
static ex sinh_eval(const ex & x)
if (x.is_zero()) // sinh(0) -> 0
return _ex0();
if (!x.info(info_flags::crational)) // sinh(float) -> float
- return sinh_evalf(x);
+ return sinh(ex_to<numeric>(x));
}
if ((x/Pi).info(info_flags::numeric) &&
static ex cosh_evalf(const ex & x)
{
- BEGIN_TYPECHECK
- TYPECHECK(x,numeric)
- END_TYPECHECK(cosh(x))
+ if (is_exactly_a<numeric>(x))
+ return cosh(ex_to<numeric>(x));
- return cosh(ex_to<numeric>(x)); // -> numeric cosh(numeric)
+ return cosh(x).hold();
}
static ex cosh_eval(const ex & x)
if (x.is_zero()) // cosh(0) -> 1
return _ex1();
if (!x.info(info_flags::crational)) // cosh(float) -> float
- return cosh_evalf(x);
+ return cosh(ex_to<numeric>(x));
}
if ((x/Pi).info(info_flags::numeric) &&
static ex tanh_evalf(const ex & x)
{
- BEGIN_TYPECHECK
- TYPECHECK(x,numeric)
- END_TYPECHECK(tanh(x))
+ if (is_exactly_a<numeric>(x))
+ return tanh(ex_to<numeric>(x));
- return tanh(ex_to<numeric>(x)); // -> numeric tanh(numeric)
+ return tanh(x).hold();
}
static ex tanh_eval(const ex & x)
if (x.is_zero()) // tanh(0) -> 0
return _ex0();
if (!x.info(info_flags::crational)) // tanh(float) -> float
- return tanh_evalf(x);
+ return tanh(ex_to<numeric>(x));
}
if ((x/Pi).info(info_flags::numeric) &&
static ex asinh_evalf(const ex & x)
{
- BEGIN_TYPECHECK
- TYPECHECK(x,numeric)
- END_TYPECHECK(asinh(x))
+ if (is_exactly_a<numeric>(x))
+ return asinh(ex_to<numeric>(x));
- return asinh(ex_to<numeric>(x)); // -> numeric asinh(numeric)
+ return asinh(x).hold();
}
static ex asinh_eval(const ex & x)
return _ex0();
// asinh(float) -> float
if (!x.info(info_flags::crational))
- return asinh_evalf(x);
+ return asinh(ex_to<numeric>(x));
}
return asinh(x).hold();
static ex acosh_evalf(const ex & x)
{
- BEGIN_TYPECHECK
- TYPECHECK(x,numeric)
- END_TYPECHECK(acosh(x))
+ if (is_exactly_a<numeric>(x))
+ return acosh(ex_to<numeric>(x));
- return acosh(ex_to<numeric>(x)); // -> numeric acosh(numeric)
+ return acosh(x).hold();
}
static ex acosh_eval(const ex & x)
return Pi*I;
// acosh(float) -> float
if (!x.info(info_flags::crational))
- return acosh_evalf(x);
+ return acosh(ex_to<numeric>(x));
}
return acosh(x).hold();
static ex atanh_evalf(const ex & x)
{
- BEGIN_TYPECHECK
- TYPECHECK(x,numeric)
- END_TYPECHECK(atanh(x))
+ if (is_exactly_a<numeric>(x))
+ return atanh(ex_to<numeric>(x));
- return atanh(ex_to<numeric>(x)); // -> numeric atanh(numeric)
+ return atanh(x).hold();
}
static ex atanh_eval(const ex & x)
throw (pole_error("atanh_eval(): logarithmic pole",0));
// atanh(float) -> float
if (!x.info(info_flags::crational))
- return atanh_evalf(x);
+ return atanh(ex_to<numeric>(x));
}
return atanh(x).hold();
static ex zeta1_evalf(const ex & x)
{
- BEGIN_TYPECHECK
- TYPECHECK(x,numeric)
- END_TYPECHECK(zeta(x))
-
- return zeta(ex_to<numeric>(x));
+ if (is_exactly_a<numeric>(x)) {
+ try {
+ return zeta(ex_to<numeric>(x));
+ } catch (const dunno &e) { }
+ }
+
+ return zeta(x).hold();
}
static ex zeta1_eval(const ex & x)
// trap integer arguments:
if (y.is_integer()) {
if (y.is_zero())
- return -_ex1_2();
+ return _ex_1_2();
if (x.is_equal(_ex1()))
throw(std::domain_error("zeta(1): infinity"));
if (x.info(info_flags::posint)) {
return _num0();
}
}
+ // zeta(float)
+ if (x.info(info_flags::numeric) && !x.info(info_flags::crational))
+ return zeta1_evalf(x);
}
return zeta(x).hold();
}
#include "fail.h"
#include "numeric.h"
#include "symbol.h"
+#include "lst.h"
using namespace GiNaC;
namespace GiNaC {
void set_lexer_symbols(ex l)
{
syms.clear();
- if (!is_ex_exactly_of_type(l, lst))
+ if (!is_exactly_a<lst>(l))
return;
for (unsigned i=0; i<l.nops(); i++) {
- if (is_ex_exactly_of_type(l.op(i), symbol))
- syms[ex_to_symbol(l.op(i)).get_name()] = sym_def(l.op(i), true);
+ if (is_exactly_a<symbol>(l.op(i)))
+ syms[ex_to<symbol>(l.op(i)).get_name()] = sym_def(l.op(i), true);
}
}
// Check whether symbol was predefined
bool is_lexer_symbol_predefined(const ex &s)
{
- sym_tab::const_iterator i = syms.find(ex_to_symbol(s).get_name());
+ sym_tab::const_iterator i = syms.find(ex_to<symbol>(s).get_name());
if (i == syms.end())
return false;
else
if (cln::zerop(x.to_cl_N()-aux))
return cln::zeta(aux);
}
- std::clog << "zeta(" << x
- << "): Does anybody know a good way to calculate this numerically?"
- << std::endl;
- return numeric(0);
+ throw dunno();
}
* This is only a stub! */
const numeric lgamma(const numeric &x)
{
- std::clog << "lgamma(" << x
- << "): Does anybody know a good way to calculate this numerically?"
- << std::endl;
- return numeric(0);
+ throw dunno();
}
const numeric tgamma(const numeric &x)
{
- std::clog << "tgamma(" << x
- << "): Does anybody know a good way to calculate this numerically?"
- << std::endl;
- return numeric(0);
+ throw dunno();
}
* This is only a stub! */
const numeric psi(const numeric &x)
{
- std::clog << "psi(" << x
- << "): Does anybody know a good way to calculate this numerically?"
- << std::endl;
- return numeric(0);
+ throw dunno();
}
* This is only a stub! */
const numeric psi(const numeric &n, const numeric &x)
{
- std::clog << "psi(" << n << "," << x
- << "): Does anybody know a good way to calculate this numerically?"
- << std::endl;
- return numeric(0);
+ throw dunno();
}
* to signal that ordinary Taylor expansion is safe. */
class do_taylor {};
+/** Exception class thrown by functions to signal unimplemented functionality
+ * so the expression may just be .hold() */
+class dunno {};
+
/** Exception class thrown when a singularity is encountered. */
class pole_error : public std::domain_error {
public:
c.s << text; \
}
+// Obsolete convenience macros. TO BE PHASED OUT SOON!
+// Use the inlined template functions in basic.h instead. (FIXME: remove them)
+
+#define is_of_type(OBJ,TYPE) \
+ (dynamic_cast<const TYPE *>(&OBJ)!=0)
+
+#define is_exactly_of_type(OBJ,TYPE) \
+ ((OBJ).tinfo()==GiNaC::TINFO_##TYPE)
+
+#define is_ex_of_type(OBJ,TYPE) \
+ (dynamic_cast<const TYPE *>((OBJ).bp)!=0)
+
+#define is_ex_exactly_of_type(OBJ,TYPE) \
+ ((*(OBJ).bp).tinfo()==GiNaC::TINFO_##TYPE)
+
} // namespace GiNaC
+
#endif // ndef __GINAC_UTILS_H__