/************************************************************************** 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 #include #include #include #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 /// 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 equation simplify(const std::vector &s) 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 equation with the result @exception invalid_argument(Argument must be a symbol) **/ const equation 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 equation with the substitutions done @exception invalid_argument(Argument must be a relational or a list of relationals) **/ // *** changed ex to expression in 0.4 // *** added options in 0.8 const equation 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 equation csubs(const exmap &m, unsigned options = 0) const; /// Substitute a list of equations consecutively in the equation const equation 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 const equation evalf() const; // *** added in 0.7 /// 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 equation evalu() const; // *** added in 0.9 /// Normalize both sides of the equation const equation 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; // *** added in 0.6, changed return type to expression 0.9, added diff(ex, unsigned) in 1.0 /** Reverses right hand side and left hand side of the equation @returns The reversed equation **/ // *** Added in version 0.2 const equation reverse() const; }; GINAC_DECLARE_UNARCHIVER(equation); /// Collect common factors in both sides of the equation const equation 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); /** 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); /** 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); /** 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); /** 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