/***************************************************************************
func.h - header file for class func, extending the GiNaC function class
*** added in 0.5
-------------------
begin : Fri Feb 13 2004
copyright : (C) 2004 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 FUNC_H
#define FUNC_H
/**
* @author Jan Rheinlaender
* @short Extends the GiNaC function class
*/
// *** modified in large parts in 0.6 for greater compatibility with GiNaC::function.h
#include <string>
#include <stdexcept>
#include <ginac/ginac.h>
/* removed in 1.4.2, changed to std::map instead
#ifdef _MSC_VER
#include <unordered_map> // *** changed in 1.4.1
#else
#include <ext/hash_map> // *** added in 1.0
#endif
*/
using namespace GiNaC;
#include "expression.h"
//#include "message.h" // *** added in 0.7
#include "utils.h"
class imathprint; // *** added in 1.4.1
/// Helper class to initialize class func
class func_init {
public:
func_init();
private:
/// A boolean used to ensure that init() is only called once in the lifetime of the class
static bool called;
static func_init func_initializer;
};
/* *** replaced by option o_difftype in 1.4.1
enum diff_t { // *** added in 0.6
dfdt, // print the differential as df(x)/dt
dot, // print the differential as \dot{f(x)}
line // print the differential as f'(x)
};
*/
/// This structure stores all the information about a user defined function
struct funcrec {
/// The serial number of the function, if it is hard-coded into GiNaC
unsigned serial;
/// dependant variables of the function (e.g. (x; y; z)
// *** changed name to vars to avoid confusion in 0.6 and changed type to exvector
exvector vars;
/// The definition of the function (e.g. for \\cubic: x^3)
expression definition;
/// True if the function is hard-coded into GiNaC
bool hard;
/// Contains hints for handling and printing of the function
unsigned hints; // *** changed in 0.6
/// Contains the (GiNaC) function options.
// Note we cannot use the options of hard-coded functions, because they are protected
// *** added in 0.6
//function_options opts;
};
/// Define a hash_map for key std::string and value funcrec*
// *** added in 1.0, changed to std::map in 1.4.2
/*
#ifdef _MSC_VER
typedef std::tr1::unordered_map<const std::string, funcrec*, std::tr1::hash<std::string>, eqstr> funcmap; // *** changed in 1.4.1
#else
typedef __gnu_cxx::hash_map<const std::string, funcrec*,
__gnu_cxx::hash<const std::string>, eqstr> funcmap;
#endif
*/
/**
* Internal GiNaC identifier for class func
*/
///const unsigned TINFO_func = 0x42420002U; *** removed in 1.2.1
/// Extends GiNaC::function by runtime definition of functions
// *** Major rewrite in 0.6, changed basic to exprseq and copied class GiNaC::function as
// *** closely as possible because of problems with the subs() method
class func : public exprseq {
GINAC_DECLARE_REGISTERED_CLASS(func, exprseq)
public:
friend class func_init;
private:
/// Helper function for the constructors
void checkargs();
void print_name(const print_context &c) const; // *** added in 1.0
public:
/**
* Construct a func with the given name
* @param n A string with the name of the function
* @param args An exvector containing the arguments of the function, e.g. (2*x; y^2)
* @param discardable Required by GiNaC
*/
// *** changed for GiNaC 1.2.1 in 0.7
func(const std::string &n, const exvector &args = exvector(), bool discardable = false);
/// Create a function from an expression
func(const std::string &n, const expression &e);
/// Create a function from an expression sequence
func(const std::string &n, const exprseq & es);
/// Create a function from an expression vector
func(const std::string &n, exvector &v, bool discardable);
/// Create a function from a pointer to an exvector
func(const std::string &n, std::auto_ptr<exvector> vp); // *** added in 0.7
/// Create a function from another function
func(const std::string &n, const function &f);
/// Print the function arguments
void printseq(const print_context & c, const std::string &openbracket, char delim,
const std::string &closebracket, unsigned this_precedence = 0, unsigned upper_precedence = 0) const;
void printseq(const imathprint & c, const std::string &openbracket, char delim,
const std::string &closebracket, unsigned this_precedence = 0, unsigned upper_precedence = 0) const;
/**
* Print the function in a GiNaC print context.
* @param c The print context (e.g., print_latex)
* @param p A power argument for the function, important for printing sin^2 x instead of (sin x)^2
* @param level Unused, for consistency with GiNaC print methods
*/
void print(const print_context &c, const ex &p, unsigned level = 0) const;
void print_imath(const imathprint &c, const ex &p, unsigned level = 0) const; // *** added in 1.4.1
/**
* Print the function in a GiNaC print context.
* @param c The print context (e.g., print_latex)
* @param level Unused, for consistency with GiNaC print methods
*/
// *** changed name to do_print in 0.8
void do_print(const print_context &c, unsigned level = 0) const;
void do_print_imath(const imathprint &c, unsigned level = 0) const; // *** added in 1.4.1
/// Print function with difftype line
// *** added in 1.4.1
void print_diff_line(const unsigned ndiff, const print_context& c) const;
// functions overriding virtual functions from base classes, see functions.h
/// Set the precedence for functions
unsigned precedence(void) const { return 70; }
/// expand the function, using its definition on the arguments
ex expand(unsigned options = 0) const;
/// symbolic integration (implemented for simple cases only)
const ex eval_integral(const symbol& sym, const ex& lbound, const ex& hbound) const;
/// Evaluate the function to a numeric value, if possible
ex eval(int level=0) const;
/// archive the function
void archive(archive_node& n) const; // *** added in 1.3.1
/// unarchive the function
void read_archive(const archive_node& n, lst& syms); // *** added in 1.3.1
/// Do unsafe evaluations of the function
// *** changed in 1.0 to use a map function
struct reduce_double_funcs : public map_function {
/// Map the expression
ex operator()(const ex &e);
};
/// Replace all GiNaC functions by EQC funcs
struct replace_function_by_func : public map_function { // *** added in 1.0
/// Map the expression
ex operator()(const ex &e);
};
/// Expand all partialdiff functions (by calculating the derivative)
struct expand_partialdiff : public map_function { // *** added in 1.0
/// Map the expression
ex operator()(const ex &e);
};
/// Expand all sum functions (by adding up)
struct expand_sum : public map_function { // *** added in 1.0
/// Map the expression
ex operator()(const ex &e);
};
/**
* Evaluate the function without arguments
@param level An argument to control the recursion depth. Use level=1 to evaluate only the
top level
@returns A GiNaC::ex with the result of the evaluation
@exception runtime_error(Max recursion level reached)
**/
ex evalf(int level = 0) const;
// *** removed evaluation with arguments in 0.6
/// Calculate the hash value of the function
unsigned calchash(void) const;
/// Return this container with v
ex thiscontainer(const exvector &v) const; // *** changed for GiNaC 1.2.1 in 0.7
/// Return this container with vp
ex thiscontainer(std::auto_ptr<exvector> vp) const; // *** changed for GiNaC 1.2.1 in 0.7
/// Create a series expansion of the function
ex series(const relational &r, int order, unsigned options = 0) const;
protected:
/// Calculate the (total) derivative of the function with respect to s
ex derivative(const symbol & s) const; // *** added in 0.6
/**
* Apply the function definition on the function arguments
* An exception is thrown if the function is not registered, or has no definition
@exception runtime_error(Function is not registered)
@exception logic_error(Function has no definition)
**/
ex expand_definition() const;
/// Equality checking functions required by GiNaC
bool is_equal_same_type(const basic & other) const; // *** added in 0.6
/// Type matching function required by GiNaC
bool match_same_type(const basic & other) const; // *** added in 0.6
/// Return type of the function
unsigned return_type(void) const; // *** added in 0.6
/// tinfo number of the function
// return_type_t return_type_tinfo(void) const; // *** added in 0.6, changed to tinfo_t in 1.2.1, changed to return_type_t in 1.3.1 and removed
/** *** added in 0.6
Calculate the partial derivative of the function with respect to the nth dependant variable
@param diff_param The number of the dependant variable
@returns An expression containing the partial derivative
@exception logic_error(Parameter does not exist)
**/
ex pderivative(unsigned diff_param) const;
// Not implemented because class GiNaC::remember_table is specific to GiNaC::function
//bool lookup_remember_table(ex & result) const;
//void store_remember_table(ex const & result) const;
// static (class) functions----------------------------------------------------
private:
static bool initialized; // *** added in 1.3.1
public:
/// Initialize the map of functions with the GiNaC hard-coded functions
static void init(); // *** made public in 1.3.1
/// Delete the function
static void remove(const std::string& fname); // *** added in 1.4.1
/// Return the function table to the state after reading 'mathconstants.tex'
static void clear();
/// Return the function table to the state after init()
static void clearall();
/// Print all the functions that have been registered
static void print_functions();
/**
* Register a user-defined function so that the scanner will be able to look it up.
@param n The Latex name of the function which the scanner finds in the input file
@param args The arguments of the function. This defines number and name of the default
arguments
@param defarg A symbol containing the default argument to use for the function if an argument
in args is invalid
@param h A flag giving hints for printing and processing the function
@exception invalid_argument(Function already exists)
**/
static void registr(const std::string &n, const lst &args, const symbol &defarg,
const unsigned h = 0); // *** added hints in 0.6
// *** added in 0.6
/// Return the number assigned to this hint
static const unsigned hint(const std::string &s);
/**
Define a user-defined function
@param n The name of the function
@param def An expression defining how to evaluate the function
@exception invalid_argument (Function does not exist)
*/
static void define(const std::string &n, const expression &def);
/**
* Check whether fname is a function
@param fname A string containing the name of the function
@returns True if the function exists
*/
static const bool is_a_func(const std::string &fname);
/// Set the notation for the tangent function to 'tg' or to 'tan'
// *** added in 1.4.3
static void set_tangent(const bool is_tg = false);
// *** replaced by option o_difftype in 1.4.1
// Return the flag characterizing the way the derivative should be printed
// static inline const diff_t get_diff_type() {
// return diff_type;
// }
// member functions-------------------------------------------
/**
* Return the name of the function
* @returns A string with the name of the function - not the Latex name!
*/
inline const std::string get_name() const { return(name); }
/// Return the number of arguments of the function
inline const unsigned get_numargs() const { return(numargs); } // *** added in 1.0
/**
* Return true if this is a trigonometric function, else false
* @exception runtime_error(Function is not registered)
**/
const bool is_trig() const;
/**
* Return true if this is a library function, else false
* @exception runtime_error(Function is not registered)
**/
const bool is_lib() const; // *** added in 0.9
/// Return true if the function has no arguments (useful for printing)
inline const bool is_pure() const { return(seq.empty()); } // *** added in 1.0
// member variables -------------------------------------------------
protected:
/// The name of the function, this is used to look it up in the map of registered functions
std::string name;
/// Number of arguments of the function
unsigned numargs; // *** added in 1.0 for efficiency purposes
// *** using seq instead of arguments in 0.6 since func is now a subclass of GiNaC::exprseq
// lst arguments;
/// The number of times this function has been differentiated in each of the dependant variables
// *** added in 0.6, removed in 1.0
//uvector diff_num;
// class variables ------------------------------------------------
/** *** moved here from ltxeqlex.ll and adapted in 0.5
* A map containing a list of function names and pointers to the corresponding func objects
**/
static std::map<const std::string, funcrec*> functions; // *** changed to funcmap in 1.0
/// A map containing the names of the functions hard-coded in GiNaC and their Latex equivalents
static std::map<const std::string, std::string> hard_names;
/// The reverse map, for fast lookup in the opposite direction
static std::map<const std::string, std::string> hard_names_rev;
/// A map containing the numbers assigned to different hints
static std::map<std::string, unsigned> hint_map;
/// A map containing functions and their inverse functions
static std::map<std::string, std::string> func_inv; // *** added in 0.9
// A flag characterizing the way the derivative should be printed
// *** added in 0.6
// *** replaced by option o_difftype in 1.4.1
// static diff_t diff_type;
};
GINAC_DECLARE_UNARCHIVER(func);
// hardcoded functions
// *** differentiation function added in 1.0, replaces diff_num functionality
DECLARE_FUNCTION_3P(partialdiff)
DECLARE_FUNCTION_3P(sum) // *** added in 1.0
DECLARE_FUNCTION_2P(round) // *** added in 1.2
DECLARE_FUNCTION_2P(ceil)
DECLARE_FUNCTION_2P(floor)
DECLARE_FUNCTION_3P(mindex) // *** added in 1.4.1
DECLARE_FUNCTION_1P(transpose) // *** added in 1.4.3
DECLARE_FUNCTION_2P(vecprod)
DECLARE_FUNCTION_2P(scalprod)
DECLARE_FUNCTION_3P(ifelse)
DECLARE_FUNCTION_1P(vmax)
DECLARE_FUNCTION_1P(vmin)
// helper functions ------------------------------------------------
/// Find derivative with respect to a (pure) function
ex diff_to_func(const ex &e, const func &s, const unsigned n = 1); // *** added in 1.0
/** *** added in 0.7
* Print a function an a message stream
* @param ms The message stream to print on
* @param f The func to print
* @returns The message stream (for concatenation of << operators)
**/
// message &operator<<(message &ms, const func &f);
// *** moved operator<<(ostream &, const exvector &) to utils.cpp in 0.7
#endif