* Implementation of GiNaC's initially known functions. */
/*
- * GiNaC Copyright (C) 1999-2014 Johannes Gutenberg University Mainz, Germany
+ * GiNaC Copyright (C) 1999-2015 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
#include "ex.h"
#include "constant.h"
#include "lst.h"
+#include "fderivative.h"
#include "matrix.h"
#include "mul.h"
#include "power.h"
return arg;
}
+// If x is real then U.diff(x)-I*V.diff(x) represents both conjugate(U+I*V).diff(x)
+// and conjugate((U+I*V).diff(x))
+static ex conjugate_expl_derivative(const ex & arg, const symbol & s)
+{
+ if (s.info(info_flags::real))
+ return conjugate(arg.diff(s));
+ else {
+ exvector vec_arg;
+ vec_arg.push_back(arg);
+ return fderivative(ex_to<function>(conjugate(arg)).get_serial(),0,vec_arg).hold()*arg.diff(s);
+ }
+}
+
static ex conjugate_real_part(const ex & arg)
{
return arg.real_part();
REGISTER_FUNCTION(conjugate_function, eval_func(conjugate_eval).
evalf_func(conjugate_evalf).
+ expl_derivative_func(conjugate_expl_derivative).
info_func(conjugate_info).
print_func<print_latex>(conjugate_print_latex).
conjugate_func(conjugate_conjugate).
return 0;
}
+// If x is real then Re(e).diff(x) is equal to Re(e.diff(x))
+static ex real_part_expl_derivative(const ex & arg, const symbol & s)
+{
+ if (s.info(info_flags::real))
+ return real_part_function(arg.diff(s));
+ else {
+ exvector vec_arg;
+ vec_arg.push_back(arg);
+ return fderivative(ex_to<function>(real_part(arg)).get_serial(),0,vec_arg).hold()*arg.diff(s);
+ }
+}
+
REGISTER_FUNCTION(real_part_function, eval_func(real_part_eval).
evalf_func(real_part_evalf).
+ expl_derivative_func(real_part_expl_derivative).
print_func<print_latex>(real_part_print_latex).
conjugate_func(real_part_conjugate).
real_part_func(real_part_real_part).
return 0;
}
+// If x is real then Im(e).diff(x) is equal to Im(e.diff(x))
+static ex imag_part_expl_derivative(const ex & arg, const symbol & s)
+{
+ if (s.info(info_flags::real))
+ return imag_part_function(arg.diff(s));
+ else {
+ exvector vec_arg;
+ vec_arg.push_back(arg);
+ return fderivative(ex_to<function>(imag_part(arg)).get_serial(),0,vec_arg).hold()*arg.diff(s);
+ }
+}
+
REGISTER_FUNCTION(imag_part_function, eval_func(imag_part_eval).
evalf_func(imag_part_evalf).
+ expl_derivative_func(imag_part_expl_derivative).
print_func<print_latex>(imag_part_print_latex).
conjugate_func(imag_part_conjugate).
real_part_func(imag_part_real_part).
if (arg.info(info_flags::nonnegative))
return arg;
+ if (arg.info(info_flags::negative) || (-arg).info(info_flags::nonnegative))
+ return -arg;
+
if (is_ex_the_function(arg, abs))
return arg;
return abs(arg).hold();
}
+static ex abs_expl_derivative(const ex & arg, const symbol & s)
+{
+ ex diff_arg = arg.diff(s);
+ return (diff_arg*arg.conjugate()+arg*diff_arg.conjugate())/2/abs(arg);
+}
+
static void abs_print_latex(const ex & arg, const print_context & c)
{
c.s << "{|"; arg.print(c); c.s << "|}";
REGISTER_FUNCTION(abs, eval_func(abs_eval).
evalf_func(abs_evalf).
expand_func(abs_expand).
+ expl_derivative_func(abs_expl_derivative).
info_func(abs_info).
print_func<print_latex>(abs_print_latex).
print_func<print_csrc_float>(abs_print_csrc_float).
&& !(options & series_options::suppress_branchcut))
throw (std::domain_error("step_series(): on imaginary axis"));
- epvector seq;
- seq.push_back(expair(step(arg_pt), _ex0));
- return pseries(rel,seq);
+ epvector seq { expair(step(arg_pt), _ex0) };
+ return pseries(rel, std::move(seq));
}
static ex step_conjugate(const ex& arg)
&& !(options & series_options::suppress_branchcut))
throw (std::domain_error("csgn_series(): on imaginary axis"));
- epvector seq;
- seq.push_back(expair(csgn(arg_pt), _ex0));
- return pseries(rel,seq);
+ epvector seq { expair(csgn(arg_pt), _ex0) };
+ return pseries(rel, std::move(seq));
}
static ex csgn_conjugate(const ex& arg)
(y_pt.info(info_flags::numeric) && y_pt.info(info_flags::negative)) ||
((x_pt*y_pt).info(info_flags::numeric) && (x_pt*y_pt).info(info_flags::negative)))
throw (std::domain_error("eta_series(): on discontinuity"));
- epvector seq;
- seq.push_back(expair(eta(x_pt,y_pt), _ex0));
- return pseries(rel,seq);
+ epvector seq { expair(eta(x_pt,y_pt), _ex0) };
+ return pseries(rel, std::move(seq));
}
static ex eta_conjugate(const ex & x, const ex & y)
// substitute the argument's series expansion
ser = ser.subs(s==x.series(rel, order), subs_options::no_pattern);
// maybe that was terminating, so add a proper order term
- epvector nseq;
- nseq.push_back(expair(Order(_ex1), order));
- ser += pseries(rel, nseq);
+ epvector nseq { expair(Order(_ex1), order) };
+ ser += pseries(rel, std::move(nseq));
// reexpanding it will collapse the series again
return ser.series(rel, order);
// NB: Of course, this still does not allow us to compute anything
// substitute the argument's series expansion
ser = ser.subs(s==x.series(rel, order), subs_options::no_pattern);
// maybe that was terminating, so add a proper order term
- epvector nseq;
- nseq.push_back(expair(Order(_ex1), order));
- ser += pseries(rel, nseq);
+ epvector nseq { expair(Order(_ex1), order) };
+ ser += pseries(rel, std::move(nseq));
// reexpanding it will collapse the series again
return ser.series(rel, order);
}
seq.push_back(expair((replarg.op(i)/power(s-foo,i)).series(foo==point,1,options).op(0).subs(foo==s, subs_options::no_pattern),i));
// append an order term:
seq.push_back(expair(Order(_ex1), replarg.nops()-1));
- return pseries(rel, seq);
+ return pseries(rel, std::move(seq));
}
}
// all other cases should be safe, by now:
return binomial(x, y).hold();
}
-// At the moment the numeric evaluation of a binomail function always
+// At the moment the numeric evaluation of a binomial function always
// gives a real number, but if this would be implemented using the gamma
// function, also complex conjugation should be changed (or rather, deleted).
static ex binomial_conjugate(const ex & x, const ex & y)
static ex Order_series(const ex & x, const relational & r, int order, unsigned options)
{
// Just wrap the function into a pseries object
- epvector new_seq;
GINAC_ASSERT(is_a<symbol>(r.lhs()));
const symbol &s = ex_to<symbol>(r.lhs());
- new_seq.push_back(expair(Order(_ex1), numeric(std::min(x.ldegree(s), order))));
- return pseries(r, new_seq);
+ epvector new_seq { expair(Order(_ex1), numeric(std::min(x.ldegree(s), order))) };
+ return pseries(r, std::move(new_seq));
}
static ex Order_conjugate(const ex & x)
return Order(x).hold();
}
-// Differentiation is handled in function::derivative because of its special requirements
+static ex Order_expl_derivative(const ex & arg, const symbol & s)
+{
+ return Order(arg.diff(s));
+}
REGISTER_FUNCTION(Order, eval_func(Order_eval).
series_func(Order_series).
latex_name("\\mathcal{O}").
+ expl_derivative_func(Order_expl_derivative).
conjugate_func(Order_conjugate).
real_part_func(Order_real_part).
imag_part_func(Order_imag_part));