* functions. */
/*
- * GiNaC Copyright (C) 1999-2019 Johannes Gutenberg University Mainz, Germany
+ * GiNaC Copyright (C) 1999-2023 Johannes Gutenberg University Mainz, Germany
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
return exp(x.conjugate());
}
+static ex exp_power(const ex & x, const ex & a)
+{
+ /*
+ * The power law (e^x)^a=e^(x*a) is used in two cases:
+ * a) a is an integer and x may be complex;
+ * b) both x and a are reals.
+ * Negative a is excluded to keep automatic simplifications like exp(x)/exp(x)=1.
+ */
+ if (a.info(info_flags::nonnegative)
+ && (a.info(info_flags::integer) || (x.info(info_flags::real) && a.info(info_flags::real))))
+ return exp(x*a);
+ else if (a.info(info_flags::negative)
+ && (a.info(info_flags::integer) || (x.info(info_flags::real) && a.info(info_flags::real))))
+ return power(exp(-x*a), _ex_1).hold();
+
+ return power(exp(x), a).hold();
+}
+
+static bool exp_info(const ex & x, unsigned inf)
+{
+ switch (inf) {
+ case info_flags::expanded:
+ case info_flags::real:
+ return x.info(inf);
+ case info_flags::positive:
+ case info_flags::nonnegative:
+ return x.info(info_flags::real);
+ default:
+ return false;
+ }
+}
+
REGISTER_FUNCTION(exp, eval_func(exp_eval).
evalf_func(exp_evalf).
+ info_func(exp_info).
expand_func(exp_expand).
derivative_func(exp_deriv).
real_part_func(exp_real_part).
imag_part_func(exp_imag_part).
conjugate_func(exp_conjugate).
+ power_func(exp_power).
latex_name("\\exp"));
//////////
// maybe substitution of rel into arg fails because of a pole
try {
arg_pt = arg.subs(rel, subs_options::no_pattern);
- } catch (pole_error) {
+ } catch (pole_error &) {
must_expand_arg = true;
}
// or we are at the branch point anyways
return conjugate_function(log(x)).hold();
}
+static bool log_info(const ex & x, unsigned inf)
+{
+ switch (inf) {
+ case info_flags::expanded:
+ return x.info(inf);
+ case info_flags::real:
+ return x.info(info_flags::positive);
+ default:
+ return false;
+ }
+}
+
REGISTER_FUNCTION(log, eval_func(log_eval).
evalf_func(log_evalf).
+ info_func(log_info).
expand_func(log_expand).
derivative_func(log_deriv).
series_func(log_series).
return sin(x.conjugate());
}
+static bool trig_info(const ex & x, unsigned inf)
+{
+ switch (inf) {
+ case info_flags::expanded:
+ case info_flags::real:
+ return x.info(inf);
+ default:
+ return false;
+ }
+}
+
REGISTER_FUNCTION(sin, eval_func(sin_eval).
evalf_func(sin_evalf).
+ info_func(trig_info).
derivative_func(sin_deriv).
real_part_func(sin_real_part).
imag_part_func(sin_imag_part).
}
REGISTER_FUNCTION(cos, eval_func(cos_eval).
+ info_func(trig_info).
evalf_func(cos_evalf).
derivative_func(cos_deriv).
real_part_func(cos_real_part).
REGISTER_FUNCTION(tan, eval_func(tan_eval).
evalf_func(tan_evalf).
+ info_func(trig_info).
derivative_func(tan_deriv).
series_func(tan_series).
real_part_func(tan_real_part).
return conjugate_function(asin(x)).hold();
}
+static bool asin_info(const ex & x, unsigned inf)
+{
+ switch (inf) {
+ case info_flags::expanded:
+ return x.info(inf);
+ default:
+ return false;
+ }
+}
+
REGISTER_FUNCTION(asin, eval_func(asin_eval).
evalf_func(asin_evalf).
+ info_func(asin_info).
derivative_func(asin_deriv).
conjugate_func(asin_conjugate).
latex_name("\\arcsin"));
REGISTER_FUNCTION(acos, eval_func(acos_eval).
evalf_func(acos_evalf).
+ info_func(asin_info). // Flags of acos are shared with asin functions
derivative_func(acos_deriv).
conjugate_func(acos_conjugate).
latex_name("\\arccos"));
return conjugate_function(atan(x)).hold();
}
+static bool atan_info(const ex & x, unsigned inf)
+{
+ switch (inf) {
+ case info_flags::expanded:
+ case info_flags::real:
+ return x.info(inf);
+ case info_flags::positive:
+ case info_flags::negative:
+ case info_flags::nonnegative:
+ return x.info(info_flags::real) && x.info(inf);
+ default:
+ return false;
+ }
+}
+
REGISTER_FUNCTION(atan, eval_func(atan_eval).
evalf_func(atan_evalf).
+ info_func(atan_info).
derivative_func(atan_deriv).
series_func(atan_series).
conjugate_func(atan_conjugate).
return -y*power(power(x,_ex2)+power(y,_ex2),_ex_1);
}
+static bool atan2_info(const ex & y, const ex & x, unsigned inf)
+{
+ switch (inf) {
+ case info_flags::expanded:
+ case info_flags::real:
+ return y.info(inf) && x.info(inf);
+ case info_flags::positive:
+ case info_flags::negative:
+ case info_flags::nonnegative:
+ return y.info(info_flags::real) && x.info(info_flags::real)
+ && y.info(inf);
+ default:
+ return false;
+ }
+}
+
REGISTER_FUNCTION(atan2, eval_func(atan2_eval).
+ evalf_func(atan2_evalf).
+ info_func(atan2_info).
evalf_func(atan2_evalf).
derivative_func(atan2_deriv));
REGISTER_FUNCTION(sinh, eval_func(sinh_eval).
evalf_func(sinh_evalf).
+ info_func(atan_info). // Flags of sinh are shared with atan functions
derivative_func(sinh_deriv).
real_part_func(sinh_real_part).
imag_part_func(sinh_imag_part).
REGISTER_FUNCTION(cosh, eval_func(cosh_eval).
evalf_func(cosh_evalf).
+ info_func(exp_info). // Flags of cosh are shared with exp functions
derivative_func(cosh_deriv).
real_part_func(cosh_real_part).
imag_part_func(cosh_imag_part).
REGISTER_FUNCTION(tanh, eval_func(tanh_eval).
evalf_func(tanh_evalf).
+ info_func(atan_info). // Flags of tanh are shared with atan functions
derivative_func(tanh_deriv).
series_func(tanh_series).
real_part_func(tanh_real_part).
REGISTER_FUNCTION(asinh, eval_func(asinh_eval).
evalf_func(asinh_evalf).
+ info_func(atan_info). // Flags of asinh are shared with atan functions
derivative_func(asinh_deriv).
conjugate_func(asinh_conjugate));
REGISTER_FUNCTION(acosh, eval_func(acosh_eval).
evalf_func(acosh_evalf).
+ info_func(asin_info). // Flags of acosh are shared with asin functions
derivative_func(acosh_deriv).
conjugate_func(acosh_conjugate));
REGISTER_FUNCTION(atanh, eval_func(atanh_eval).
evalf_func(atanh_evalf).
+ info_func(asin_info). // Flags of atanh are shared with asin functions
derivative_func(atanh_deriv).
series_func(atanh_series).
conjugate_func(atanh_conjugate));