* Implementation of GiNaC's initially known functions. */
/*
- * GiNaC Copyright (C) 1999-2015 Johannes Gutenberg University Mainz, Germany
+ * GiNaC Copyright (C) 1999-2019 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
case info_flags::prime:
case info_flags::crational_polynomial:
case info_flags::rational_function:
- case info_flags::algebraic:
case info_flags::positive:
case info_flags::negative:
case info_flags::nonnegative:
else
prodseq.push_back(abs(*i));
}
- return (new mul(prodseq))->setflag(status_flags::dynallocated | status_flags::expanded);
+ return dynallocate<mul>(prodseq).setflag(status_flags::expanded);
}
if (options & expand_options::expand_function_args)
{
if ((is_a<numeric>(exp) && ex_to<numeric>(exp).is_even()) || exp.info(info_flags::even)) {
if (arg.info(info_flags::real) || arg.is_equal(arg.conjugate()))
- return power(arg, exp);
+ return pow(arg, exp);
else
- return power(arg, exp/2)*power(arg.conjugate(), exp/2);
+ return pow(arg, exp/2) * pow(arg.conjugate(), exp/2);
} else
return power(abs(arg), exp).hold();
}
// Solve linear system
//////////
+class symbolset {
+ exset s;
+ void insert_symbols(const ex &e)
+ {
+ if (is_a<symbol>(e)) {
+ s.insert(e);
+ } else {
+ for (const ex &sube : e) {
+ insert_symbols(sube);
+ }
+ }
+ }
+public:
+ explicit symbolset(const ex &e)
+ {
+ insert_symbols(e);
+ }
+ bool has(const ex &e) const
+ {
+ return s.find(e) != s.end();
+ }
+};
+
ex lsolve(const ex &eqns, const ex &symbols, unsigned options)
{
// solve a system of linear equations
}
// syntax checks
- if (!eqns.info(info_flags::list)) {
- throw(std::invalid_argument("lsolve(): 1st argument must be a list or an equation"));
+ if (!(eqns.info(info_flags::list) || eqns.info(info_flags::exprseq))) {
+ throw(std::invalid_argument("lsolve(): 1st argument must be a list, a sequence, or an equation"));
}
for (size_t i=0; i<eqns.nops(); i++) {
if (!eqns.op(i).info(info_flags::relation_equal)) {
throw(std::invalid_argument("lsolve(): 1st argument must be a list of equations"));
}
}
- if (!symbols.info(info_flags::list)) {
- throw(std::invalid_argument("lsolve(): 2nd argument must be a list or a symbol"));
+ if (!(symbols.info(info_flags::list) || symbols.info(info_flags::exprseq))) {
+ throw(std::invalid_argument("lsolve(): 2nd argument must be a list, a sequence, or a symbol"));
}
for (size_t i=0; i<symbols.nops(); i++) {
if (!symbols.op(i).info(info_flags::symbol)) {
- throw(std::invalid_argument("lsolve(): 2nd argument must be a list of symbols"));
+ throw(std::invalid_argument("lsolve(): 2nd argument must be a list or a sequence of symbols"));
}
}
for (size_t r=0; r<eqns.nops(); r++) {
const ex eq = eqns.op(r).op(0)-eqns.op(r).op(1); // lhs-rhs==0
+ const symbolset syms(eq);
ex linpart = eq;
for (size_t c=0; c<symbols.nops(); c++) {
+ if (!syms.has(symbols.op(c)))
+ continue;
const ex co = eq.coeff(ex_to<symbol>(symbols.op(c)),1);
linpart -= co*symbols.op(c);
sys(r,c) = co;
}
// test if system is linear and fill vars matrix
+ const symbolset sys_syms(sys);
+ const symbolset rhs_syms(rhs);
for (size_t i=0; i<symbols.nops(); i++) {
vars(i,0) = symbols.op(i);
- if (sys.has(symbols.op(i)))
+ if (sys_syms.has(symbols.op(i)))
throw(std::logic_error("lsolve: system is not linear"));
- if (rhs.has(symbols.op(i)))
+ if (rhs_syms.has(symbols.op(i)))
throw(std::logic_error("lsolve: system is not linear"));
}