/**************************************************************************
equation.h - header file for class equation
-------------------
begin : Sun Oct 21 2001
copyright : (C) 2001 by Jan Rheinlaender
email : jrheinlaender@users.sourceforge.net
***************************************************************************/
/**************************************************************************
* *
* 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 *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
/**
@short Used to store, print and evaluate equations
@author Jan Rheinlaender
Class equation is used to store, print and evaluate equations
**/
#ifndef EQUATION_H
#define EQUATION_H
#include <iostream>
#include <string>
#include <stdexcept>
#include <ginac/ginac.h>
#include "expression.h" // *** added in 0.4
//#include "message.h" // *** added in 0.7
#include "optstack.h" // *** added in 1.1, defines alignment types
#include "printing.h"
using namespace GiNaC;
/// Defines the possible equation types
enum eqtype { // *** added in 0.6
original, // The equation was given by the user
derived, // The equation was derived from another equation
empty, // The equation is empty
unknown // The type has not been set yet
};
// Moved enum aligntype to optstack.h in 1.1
/// Helper class
class equation_init {
public:
equation_init();
private:
/// A boolean used to ensure that init() is only called once in the lifetime of the class
static bool called;
static equation_init equation_initializer;
};
/// Internal GiNaC identifier for class equation
//const unsigned TINFO_equation = 0x42420003U; // *** added in 0.9, removed in 1.2.1
/// Used to store, print and evaluate equations
class equation : public relational { // *** made subclass of GiNaC::relational in 0.9
GINAC_DECLARE_REGISTERED_CLASS(equation, relational)
/**
A string containing an optional name for identifying the equation. This can be a number, too,
in the case of numbered equations.
**/
std::string label;
// *** removed number in 0.7
// *** removed left and right in 0.9, provided by class relational
/// Defines the alignment type of the operator
aligntype al; // *** replaces equal_sign together with operator in superclass in 0.9
/// Identifies the type of equation
eqtype type;
/// Contains the ltxrepr of the equation, or an empty string if there is none
std::string ltxrepr; // *** added in 0.9
private:
/// Contains the next number to be given to an equation if no label is supplied.
static int nextlabel;
static bool initialized; // *** added in 1.3.1
public:
/// Initialize the class
static void init(); // *** made public in 1.3.1
friend class equation_init; // *** added in 0.6
/// Reset the equation label number
static void clear(); // *** added in 0.8
/// Set a boolean option (printing flag)
// *** added in 0.9, changed in 1.1, moved to class optstack in 1.2
/**
Constructs an equation from two expressions representing the left and the right hand side.
@param le The left hand side of the equation
@param ri The right hand side of the equation
@param op The operator of the equation, e.g. equals, less
@param align The alignment type of the equation, e.g., for equations inside
Latex equationarray environments. It only has an effect on pretty-printing of the equation.
@param l The equation label
@param t The equation type
**/
equation(const expression &le, const expression &ri,
const operators op = equal, const aligntype align = none,
const eqtype t = unknown, const std::string &l = "");
/**
Constructs an equation from another equation.
@param eq The equation that is used to construct the new object
**/
equation(const equation &eq); // *** Removed parameter in_array in version 0.2
/**
Constructs an equation from a relational.
@param eq The equation that is used to construct the new object
@param align The alignment type of the equation, e.g., for equations inside
Latex equationarray environments. It only has an effect on pretty-printing of the equation.
@param l The equation label
@param t The equation type
**/
equation(const relational &r, const aligntype align = none, const eqtype t = unknown, const std::string &l = "");
/// Assigns an equation to another equation
equation &operator=(const equation &other); // *** added in 0.9
/// Return type. Returns non_commutative if either side is non-commutative
// Note that this is different from the behaviour of relational, which asserts that both sides
// have the same return_type. But an equation could have a scalar product of two vectors on one side
// (non-commutative) which after evaluation results in a scalar (commutative)
unsigned return_type() const;
/**
Return the operator sign of the equation
@returns The operator of the equation
**/
inline const operators getop() const { return o; }
/**
Set the operator sign of the equation
@param op An operator type, e.g. relational::equal
@returns The equation with the changed operator sign
**/
inline const equation &setop(const operators op) { o = op; return *this; }
// *** added in 0.8, changed in 0.9
/**
Return the alignment type of the equation. This may differ
depending on whether the equation appears inside a Latex equationarray environment or not
@returns The alignment type of the equation
**/
inline const aligntype getalign() const { return al; } // *** added in 0.9
/**
Set the alignment type
@param align The alignment type (none, onlyleft, onlyright, both)
@returns The equation with the alignment type changed
**/
// *** added in 0.8, changed and made inline in 0.9
inline const equation &setalign(const aligntype &align) { al = align; return *this; }
/// Add an alignment (valid types are only left and right) to an equation
const equation &addalign(const aligntype &align); // *** added in 0.9
/// Return the equation label
inline const std::string getlabel() const { return(label); }
/// Set the equation label
inline const equation &setlabel(const std::string &l) { label = l; return *this; }
/// Set the equation label to a temporary label
const equation &settemplabel();
/// Return the equation type
inline const eqtype gettype() const { return(type); }
/// Set the equation type
inline const equation &settype(const eqtype t) { type = t; return *this; }
/**
Checks whether the equation is an assignment. This is considered to be the case when the left hand side is a
symbol and the right hand side is a quantity.
@returns A boolean indicating whether the equation is an assignment.
**/
const bool is_assignment() const;
/// Returns true if the equation has a temporary label or no label at all
const bool is_temporary() const;
/// Print the operator and alignment characters on a print context
void print_oper(const print_context &c) const; // *** added in 0.9
/// Print the operator and alignment characters in latex format
void print_oper_ltx(const print_context &c) const; // *** added in 0.9
void print_oper_imath(const imathprint &c) const; // *** added in 0.9
// *** removed print(std::ostream &) and print(message &) in 0.9
/**
Prints the equation on a GiNac print context. The output format depends on the print context type
@param c The print context
@param level Required for compatibility with GiNaC
**/
void do_print(const print_context &c, unsigned level = 0) const;
/// Print the equation on a print context in Latex format
void do_print_ltx(const print_context &c, unsigned level = 0) const;
/// Print the equation on a print context in iMath format
void do_print_imath(const imathprint &c, unsigned level = 0) const;
/** *** Added in 0.4, made inline in 0.9
* Return the Latex representation of the equation (identical to the user input)
* @returns The Latex representation
*/
inline const std::string getltxrepr() const { return ltxrepr; }
/// Set the Latex representation of the equation
inline equation &setltxrepr(const std::string& s) { ltxrepr = s; return *this; } // *** added in 0.9
/** *** added in 0.6, changed argument to vector in 0.9
Simplifies both sides of the equation according to the list of simplifications given
@param s A vector of simplifications that are to be performed
@returns The simplified equation
**/
const expression simplify(const std::vector<std::string> &s) const;
/**
Orders both sides as a polynomial in the given expression
@param e An expression that is to be the base of the polynomial
@returns The modified equation
**/
const expression collect(const expression &e = numeric(0)) const;
/** *** added in 0.8
Solve the equation for the given variable
@param e The variable to solve for
@param n The number of the solution to return (in case there is more than one solution)
@returns An expression with the resulting equation
@exception invalid_argument(Argument must be a symbol)
**/
const expression solve(const expression &e, const expression &n = numeric(1)) const;
/**
Substitute a list of equations in the equation.
Note that GiNaC does not do intelligent substitution yet, i.e. in x+y+z it is not possible to
substitute x+y==4 because GiNaC only substitutes objects, in this case the whole "add" object.
@param e An expression containing a list of substitutions
@param options A flag of options, e.g. subs_options::algebraic
@returns An expression with the substitutions done
@exception invalid_argument(Argument must be a relational or a list of relationals)
**/
ex subs(const ex & e, unsigned options = 0) const;
/// Substitute a map of expressions in the object
// *** added in 1.0, this cannot be const equation because GiNaC defines it thus
ex subs(const exmap &m, unsigned options = 0) const;
/** *** added in 0.9
Same as subs, but the substitutions are done consecutively.
@param m A GiNaC exmap of substitutions
@param options A flag of options, e.g. subs_options::algebraic
@returns An equation with the substitutions done
**/
const expression csubs(const exmap &m, unsigned options = 0) const;
/// Substitute a list of equations consecutively in the equation
const expression csubs(const ex &e, unsigned options = 0) const; // *** added in 0.9
/// Expand both sides of the equation
ex expand(unsigned options = 0) const;
// *** added in 0.7, changed return type to ex in 0.9
/// Evaluate both sides of the equation
#if ((GINACLIB_MAJOR_VERSION == 1) && (GINACLIB_MINOR_VERSION >= 7))
ex evalf() const override;
#else
ex evalf(int level=0) const;
#endif
/// Evaluate matrices on both sides of the equation
ex evalm() const; // *** added in 1.0
/// Perform unsafe simplifications on both sides of the equation
const expression evalu() const; // *** added in 0.9
/// Normalize both sides of the equation
const expression normal() const; // *** added in 0.9
/// archive the equation
void archive(archive_node& n) const; // *** added in 1.3.1
/// unarchive the equation
void read_archive(const archive_node& n, lst& syms); // *** added in 1.3.1
/// Add an expression or equation to the equation
const equation &eqadd(const expression &add);
// *** added in 0.9
/// Multiply the equation with an expression
const equation &eqmul(const expression &mul);
// *** added in 0.9
/** *** added in 0.9
Applies a function to both sides of the equation. Beware: The user must handle any
mathematical problems resulting from this, for example, if the function is \\sqrt.
@param e An expression containing the function
@returns An equation containing the result of the operation
**/
const expression apply_func(const expression &e) const;
const expression apply_func(const std::string& fname) const; // *** added in 1.4.1
/// Raises both sides to the power of e
// *** added in 1.4.1
const expression apply_power(const expression &e) const;
/**
Differentiates both sides of the equation with respect to the dependant variable given
@param var The dependant variable as a GiNaC::symbol or (pure) function
@param nth Calculates the nth derivative
@returns An equation containing the result of the differentation
@exception logic_error(Can only differentiate with respect to a symbol or pure function)
**/
const expression diff(const ex &var, unsigned nth = 1) const;
/// Same, but only for dependant variables given as GiNaC::symbol
const expression diff(const symbol &var, unsigned nth = 1) const;
/**
Differentiates partially both sides of the equation with respect to the dependant variable given.
All other symbols and functions are considered constant.
@param var The dependant variable as a GiNaC::symbol or (pure) function
@param nth Calculates the nth derivative
@returns An equation containing the result of the differentation
@exception logic_error(Can only differentiate with respect to a symbol or pure function)
**/
const expression pdiff(const ex &var, unsigned nth = 1) const;
/**
Integrates both sides of the equation with respect to the dependant variable given.
The integral is not evaluated at all. Use simplify for that
@param var The dependant variable as a symbol or function
@param integration_constant The symbol to use as integration constant
@returns An equation containing the result of the integration
@exception logic_error(Can only integrate with respect to a symbol)
**/
const expression integrate(const ex &var, const symbol& integration_constant) const;
const expression integrate(const ex &var, const ex& lowerbound, const ex& upperbound) const;
const expression integrate(const ex &lvar, const symbol& l_integration_constant, const ex &rvar, const symbol& r_integration_constant) const;
const expression integrate(const ex &lvar, const ex& l_lowerbound, const ex& l_upperbound, const ex &rvar, const ex& r_lowerbound, const ex& r_upperbound) const;
/**
Reverses right hand side and left hand side of the equation
@returns The reversed equation
**/
// *** Added in version 0.2
const expression reverse() const;
};
GINAC_DECLARE_UNARCHIVER(equation);
/// Collect common factors in both sides of the equation
const expression collect_common_factors(const equation &eq); // *** added in 0.9
/// These operators are defined in analogy to operators.h. They take care of equations
// *** changed in 0.9. They cannot be defined in expression.h because class equation is not known there
/**
Adds two expressions.
@param e The first expression
@param add The second expression
@returns An ex containing the result of the addition
@exception invalid_argument
**/
const ex operator+(const expression &e, const expression &add);
const ex operator+(const equation &e, const equation &add);
const ex operator+(const expression &e, const equation &add);
const ex operator+(const equation &e, const expression &add);
/**
Subtracts an expression from another expression.
@param e The expression
@param sub The expression that should be subtracted
@returns An ex containing the result of the subtraction
@exception invalid_argument
**/
const ex operator-(const expression &e, const expression &sub);
const ex operator-(const equation &e, const equation &sub);
const ex operator-(const expression &e, const equation &sub);
const ex operator-(const equation &e, const expression &sub);
/**
Multiplies two expressions. Throws an exception if the multiplicator is zero.
@param e The first expression
@param mul The second expression
@returns An ex containing the result of the multiplication
@exception invalid_argument(Multiplication with zero)
@exception invalid_argument(Cannot multiply two equations)
**/
const ex operator*(const expression &e, const expression &mul);
const ex operator*(const equation &e, const equation &mul);
const ex operator*(const expression &e, const equation &mul);
const ex operator*(const equation &e, const expression &mul);
/**
Divides an expression by an expression. Throws an exception if the divisor is zero.
@param e The first expression
@param divisor The expression by which e should be divided
@returns An expression containing the result of the division
@exception invalid_argument(Division by zero)
**/
const ex operator/(const expression &e, const expression &divisor);
const ex operator/(const equation &e, const equation &divisor);
const ex operator/(const expression &e, const equation &divisor);
const ex operator/(const equation &e, const expression &divisor);
/**
Takes the expression to the power of another expression, taking care of equations.
Beware: This does NOT handle
the ambiguity if, for example, taking the square root of x^2 (could be +x or -x)!
@param e The expression
@param exponent The exponent
@returns An expression containing the result of the operation
@exception invalid_argument(Cannot calculate power to exponent that is an equation)
**/
// *** changed in 0.9
const ex pow(const expression &e, const expression &exponent);
/**
Negate an expression.
@param e The expression
@returns The negated expression
**/
const ex operator-(const expression &e); // *** added in 0.9
/** *** added in 0.7
New output method for printing an equation on a message stream. The GiNaC representation is printed
@param ms The message stream.
@param eq The equation to be printed
@returns The messaage stream (to enable concatenation of output operators)
**/
//message &operator<<(message &ms, const equation &eq);
#endif