/***************************************************************************
operands.h - Header file for class operands
-------------------
begin : Wed Jun 26 2002
copyright : (C) 2002 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. *
* *
***************************************************************************/
#ifndef OPERANDS_H
#define OPERANDS_H
/**
@short A helper class for the Latex printing routines. With the methods of this class, all elements of a
GiNaC expression can be stored separately (i.e., functions, numerics, symbols etc.) Class operands assumes that
any expression is either an add or a mul. The class offers functions for checking whether an operand is a quantity,
a numeric etc., and for pretty-printing in Latex syntax.
@author Jan Rheinlaender
**/
#include <stdexcept>
#include <ginac/ginac.h>
using namespace GiNaC;
#include "expression.h"
// Possible value for ops_type
#define GINAC_ADD 0
#define GINAC_MUL 1
/// A helper class for the Latex printing routines
class operands {
/**
Definition of the function used to connect the operands (addition or multiplication)
**/
typedef ex (*op_func)(const ex&, const ex&);
/**
An integer defining the type of the operands (GiNaC::add or GiNaC::mul)
**/
int type;
/**
An expression containing all the functions.
This includes GiNaC's functions and our functions
**/
ex functions;
/// An expression containing all the integrals
ex integrals; // *** added in 1.3.1
/**
An expression containing all the symbols.
**/
ex symbols;
/// An expression containing all the constants.
ex constants; // *** added in 1.2
/**
An expression containing all the units.
**/
ex units;
/**
An expression containing all the adds. This is empty if the oper_func is &add_ops.
**/
ex adds;
/**
An expression containing all the muls. This is empty if the oper_func is &mul_ops.
**/
ex muls;
/**
An expression containing all the powers.
**/
ex powers;
/**
An expression containing the numeric coefficient.
**/
numeric coefficient;
/// An expression containing the matrices
ex matrices; // *** added in 1.0
/**
An expression containing all the GiNaC types that might occur.
**/
// TODO: Implement them and get rid of others.
ex others;
/**
A pointer to the function (either add_ops() or mul_ops()) that is to be used to connect the operands.
**/
op_func oper;
public:
/**
Create a new instance of class operands. Throws an argument if ops_type is neither GINAC_ADD nor
GINAC_MUL. All operand types (functions, powers, etc.) are initialized to the value of ops_type.
@param ops_type An integer indicating whether the operands are part of an add or a mul
@exception invalid_argument
**/
operands(const int ops_type) throw(std::invalid_argument);
/**
Destroys the instance.
**/
~operands();
/**
* This is a kind of constructor, too. It takes an expression and splits it into operands. If any
* unknown GiNaC types are encountered, the method throws an exception.
* -# If the expression is an add, it is split into positive and negative operands
* -# If the expression is a mul, it is split into positive and negative powers
@param e The GiNaC expression that is to be split into operands
@param o1 The positive operands or positive powers
@param o2 The negative operands or negative powers
@exception runtime_error
*/
static void split_ex(const expression &e, operands &o1, operands &o2)
throw(std::runtime_error);
// *** changed ex& to expression& in 0.9
/**
@returns The numeric coefficient of the operands.
**/
inline const numeric &get_coefficient() const { return coefficient; }
/**
@returns The symbols of the operand.
**/
inline const ex &get_symbols() const { return symbols; }
/**
@returns The constants of the operand.
**/
inline const ex &get_constants() const { return constants; }
/**
@returns The units of the operand.
**/
inline const ex &get_units() const { return units; }
/**
@returns The functions of the operand.
**/
inline const ex &get_functions() const { return functions; }
/**
@returns The integrals of the operand
**/
inline const ex &get_integrals() const { return integrals; } // *** added in 1.3.1
/**
@returns The adds of the operand. If the receiver is of type GINAC_ADD, this returns 0.
**/
inline const ex &get_adds() const { return adds; }
/**
@returns The muls of the operand. If the receiver is of type GINAC_MUL, this returns 1.
**/
inline const ex &get_muls() const { return muls; }
/**
@returns The matrices of the operand.
**/
inline const ex &get_matrices() const { return matrices; } // *** added in 1.0
/// Checks if there are any matrices stored in the operand
const bool check_matrices(const unsigned type) const; // *** added in 1.4.3
/// Checks if there are any symbols stored in the operand
const bool check_symbols(const unsigned type) const; // *** added in 1.4.3
/**
@returns The powers of the operand.
**/
inline const ex &get_powers() const { return powers; }
/**
@returns Any other GiNaC data types.
**/
inline const ex &get_others() const { return others; }
/**
Includes an expression in the receiver. Note that any complex expressions (adds or muls) that are
passed to this method will just be added to the adds or muls field respectively. They are not split
into their subparts and included according to type.
@param what The expression to include
**/
void include(const ex &what);
/**
Excludes an expression from the receiver by multiplying the contents of the field corresponding to
its type with 1 / what. Note that this is NOT possible with include(1/what) because the type of this
is always a power!
@param what The expression to exclude
**/
void exclude(const ex &what); // *** added in 1.2
/// Same as exclude, but the argument can be an add/mul, then every part of it is excluded separately
void exclude_all(const ex &what); // *** added in 1.2
/**
@returns True if the receiver is a quantity.
**/
const bool is_quantity() const;
/**
@returns True if the receiver is a numeric.
**/
const bool is_number() const;
/**
@returns True if the receiver is trivial (0 or 1, depending on the op_type).
**/
const bool is_trivial() const;
/**
@returns True if the receiver consists of only one symbol
**/
const bool is_symbol() const; // *** added in 1.2
/**
@returns True if the receiver is of type GINAC_ADD.
**/
const bool is_add() const;
/**
@returns True if the receiver is of type GINAC_MUL.
**/
const bool is_mul() const;
/**
Pretty-prints the receiver on a stream in Latex syntax. The different GiNaC data types are printed
in order, i.e., numerics first, then symbols, etc. Throws an exception if the receiver is not of
type GINAC_MUL.
@param os The stream to print on
@param toplevel True if the expression is being printed at top level (equation splitting is only allowed here)
@param opnum Counts the number of operands that have already been printed
@exception invalid_argument
**/
void print_ltx_mul(std::ostream &os, const bool toplevel, const int ops) const throw(std::invalid_argument);
/**
Pretty-prints the receiver on a stream in Latex syntax. The different GiNaC data types are printed
in order, i.e., numerics first, then symbols, etc. Throws an exception if the receiver is not of
type GINAC_ADD.
@param neg An operands object containing the negative parts of the expression to be printed
@param os The stream to print on
@param toplevel True if the expression is being printed at top level (equation splitting is only allowed here)
@param opnum An operand count for the purpose of splitting the equation across several lines
@exception invalid_argument
**/
void print_ltx_add(const operands &neg, std::ostream &os, const bool toplevel, const int ops) const throw(std::invalid_argument);
/// Print the receiver onto a stream
void print(std::ostream &os) const;
/// Print the receiver onto a message stream
// void print(message &ms) const; // *** added in 0.7, changed in 1.3.1
};
/// Helper structure for use in remember_split
struct exrec { // *** added in 1.0
/// The expression
expression e;
/// The first operands
operands o1;
/// The second operands
operands o2;
/// Just for statistical purposes...
unsigned hits;
/// Create a new instance
exrec(const expression &exp, const operands &op1, const operands &op2);
~exrec();
};
/// Stores the result of previous split_ex() calls for faster execution
static std::map<unsigned, exrec*> remember_split; // *** added in 1.0
/// Split the equation at this position if requested by the user
void checksplit(const bool toplevel, const int opnum, std::ostream &os); // *** added in 1.2
#endif