/*------------------------------------------------------------------------- | The software accompanies the paper | | | | Classes and Objects of Chemical Thermodynamics in Object-Oriented | | Programming. 2. A Class of Chemical Species | | | | E.B. Rudnyi | | E-mail: rudnyi@comp.chem.msu.su | | Homepages: http://www.chem.msu.su/~rudnyi/welcome.html | | | | presented at Second Electronic Computational Chemistry Conference, | | November 1995, http://hackberry.chem.niu.edu/ECCC2/ | | | | E.B. Rudnyi, Copyright (c) 1995 | | | | Permission to use, copy, modify, distribute and sell this software and | | its documentation for any purpose is hereby granted without fee, | | provided that the above copyright notice with the name of the paper and | | the conference appear in all copies and that both that copyright notice | | and this permission notice appear in supporting documentation. | | E.B. Rudnyi makes no representations about the suitability of this | | software for any purpose. It is provided "as is" without expressed or | | implied warranty. | --------------------------------------------------------------------------*/ #ifndef _FUNC_TP_H #define _FUNC_TP_H #ifndef __IOSTREAM_H #include #endif #ifndef __MATH_H #include #endif const int NFUNC = 11; const int NSYMB = 10; // ######################### class global ############################# //****************************** Purpose ****************************** //*************** Relationships with the other classes **************** // This is an auxiliary class that provides common identifiers for all // other classes. There is no need to create objects of this class, but // you may change the values of some data members. class global { public: //******************************* Data ******************************** enum derivative {dT, dp, dTp, dpT, dT2, dp2}; // Enumerates the types of derivatives which can be taken by // function df in classes func_Tp, smpl_func, function. static double T; // 0. by default static double p; // 1. by default // These two variables are utilized when a user does not give values // of temperature and pressure while estimating a value of the function // or taking derivatives. static double step1; // 10.*sqrt(DBL_EPSILON) by default static double step2; // 10.*pow(DBL_EPSILON, 1./3.) by default // step1 is a relative step made when a first derivative is // taken. step2 is for second derivatives. static int digits; // 8 by default // How many significant digits are to output for numbers in // analytical functions. }; // ##################### end of class global ########################## // ######################### class func_Tp ############################ //****************************** Purpose ****************************** // Deals with an analytical function of temperature and pressure. //****************************** Syntax ******************************* // BASIC-style expression containing T and p variables only. All white // spaces are ignored. Input opearators read a stream until the delimiters // (colon or semicolon) or the end of file (string). The colon is // extracted, the semicolon is left in the stream. // // func_Tp // expression // // expression // expression + term // expression - term // term // // term // term / factor // term * factor // factor // // factor // factor^primary // primary // // primary // NUMBER // double in C++ // T // p // -primary // acos(expession) // arc cosine // abs(expession) // asin(expession) // arc sine // atan(expession) // arc tangent // cos(expession) // cosine // exp(expession) // log(expession) // log10(expession) // sin(expession) // sqrt(expession) // tan(expession) // (expression) // //*************** Relationships with the other classes **************** // Class func_Tp is a base for class smpl_func. class func_Tp { enum func_token {ACOS, ABS, ASIN, ATAN, COS, EXP, LOG10, LOG, SIN, SQRT, TAN, PLUS, MINUS, MUL, DIV, POW, NAME_T, NAME_p, LP, RP, UMIN, NUMBER, END}; func_token *start_tok; int ntokens; double *start_val; int nvalues; static double (*func[NFUNC])(double x); static char *func_name[NFUNC]; static int func_len[NFUNC]; static char tok_name[NSYMB]; static func_token *curr_tok; static func_token *token; static double *value; void init(); func_token get_token(const char *&in, double &value); void expr(int must); void term(int must); void fact(int must); void prim(int must); void exprpr(int print) const; void termpr(int print) const; void factpr(int print) const; void primpr(int print) const; public: //**************************** Operations ***************************** func_Tp(); // Default constructor. Creates an empty function of T and p. func_Tp(const func_Tp &old); // Copy constructor. func_Tp& operator=(const func_Tp &old); // Assignment operator. func_Tp(const char *str); // Constructs the object from a string representation. In the case of // sintactics errors creates an empty object. func_Tp& operator=(const char *str); // Assigns a string representation to the object. In the case of // sintactics errors leaves an empty object. ~func_Tp(); // Destructor. void clear(); // Clears the object (result is the empty object). void copy(const func_Tp &old); // Makes the object equal to another object. const char* anal(const char *in); // Makes the object equal to that given by a string representation. // Returns a pointer to char that was not used by the function. // In the case of sintactics errors leaves an empty object. friend istream& operator>>(istream &in, func_Tp &to); // Reads stream until the delimiters (colon or semicolon) or the end of // file. The colon is extracted, the semicolon is left in the stream. char* to_str(char *buf) const; // Copies a sting representation of the object to a given string buffer. // Returns a pointer to the given buffer. friend ostream& operator<<(ostream &out, const func_Tp &old); // Writes a string representation of the object to the given stream. double est(const double &T = global::T, const double &p = global::p); // Evaluates a value of the function at given temperature and pressure. // Returns HUGE_VAL in the case of an error. double operator()(const double &T, const double &p); double operator()(const double &T); // assumes p = global::p double operator()(); // assumes T = global::T and p = global::p // Another interface for evaluating a value of the function. double df(global::derivative d, const double &T = global::T, const double &p = global::p); // Evaluates numerically a derivative of the function // at given temperature and pressure. // Returns HUGE_VAL in the case of an error. friend void oper(func_Tp &res, const func_Tp &left, const func_Tp &right, const char op); // Performs a rudimentary analytical operation // res = left op right // Argument op can be equal to '+', '-', '*', '/'. friend func_Tp operator+(const func_Tp &left, const func_Tp &right); friend func_Tp operator-(const func_Tp &left, const func_Tp &right); friend func_Tp operator*(const func_Tp &left, const func_Tp &right); friend func_Tp operator/(const func_Tp &left, const func_Tp &right); // Another interface for rudimentary analytical operations. int len() const; // Returns a number of characters necessary for string representation // of the object. operator int() const; // Returns zero if the object is empty and non-zero otherwise. //************************** Error handling *************************** enum func_err { OKAY, // everything is okay NOTERM, // there was no term NOFACT, // there was no factor NORP, // there was no right parenthesis NOLP, // there was no left parenthesis NOPRIM, // there was no primary WRTOK, // wrong token ZDIV, // division by zero NOBUF, // internal buffer is not big enough // the buffer size is controlled by BUF_TOK and BUF_DBL NOSTK, // stack size is not big enough // the stack size is controlled by STACK BAD // internal representation is corrupt }; static func_err errno; // Variable to keep the error code. It may be checked out when // something went wrong. }; // ##################### end of class func_Tp ######################### // ######################### class lim_Tp ############################# //****************************** Purpose ****************************** // Keeps an allowable rectangular range for values of temperature and // pressure. It is assumed that the following must be held // Ti <= T <= Tf // pi <= p <= pf //****************************** Syntax ******************************* // Numbers separated by commas. All white spaces are ignored. Input // opearators read a stream until the delimiters (colon or semicolon) or // the end of file (string). The colon is extracted, the semicolon is left // in the stream. // // lim_Tp // Ti, Tf, pi, pf // //*************** Relationships with the other classes **************** // Class lim_Tp is a base for class smpl_func. class lim_Tp { enum lim_token {NUMBER, COMMA, END}; void init(); lim_token get_token(const char *&in, double &value); public: //******************************* Data ******************************** double Ti; double Tf; // Minimum and maximum values allowable for the temperature. double pi; double pf; // Minimum and maximum values allowable for the pressure. enum lim_cmp { LT, // less than EQ, // equal to GT, // greater than CROSS_T, // crossing temperature intervals CROSS // crossing rectangulars }; // Possible results of the function compare (see below) //**************************** Operations ***************************** lim_Tp(); // Default constructor. Creates an object with values // Ti = 0., Tf = HUGE_VAL, pi = 0., pf = HUGE_VAL. lim_Tp(const lim_Tp &old); // Copy constructor. lim_Tp& operator=(const lim_Tp &old); // Assignment operator. lim_Tp(const char *str); // Constructs the object from a string representation. In the case of // sintactics errors creates the default object. lim_Tp& operator=(const char *str); // Assigns a string representation to the object. In the case of // sintactics errors leaves an empty object. ~lim_Tp(); // Destructor. void clear(); // Clears the object (result is the defualt object). void copy(const lim_Tp &old); // Makes the object equal to another object. const char* anal(const char *in); // Makes the object equal to that given by a string representation. // Returns a pointer to char that was not used by the function. // In the case of sintactics errors leaves the default object. friend istream& operator>>(istream &in, lim_Tp &to); // Reads stream until the delimiters (colon or semicolon) or the end of // file. The colon is extracted, the semicolon is left in the stream. char* to_str(char *buf) const; // Copies a sting representation of the object to a given string buffer. // Returns a pointer to the given buffer. For a value that is equal // to default one, writes nothing. Thus, a defualt range will be // written as ,,, friend ostream& operator<<(ostream &out, const lim_Tp &old); // Writes a string representation of the object to the given stream. int len() const; // Returns a number of characters necessary for string representation // of the object. operator int() const; // Returns zero if the object is the default one and non-zero otherwise. lim_cmp compare(const lim_Tp &second) const; // Compares two allowable ranges of temperature and pressure. // Possible results: // LT a.Tf < b.Ti or, if a.Ti = b.Ti and a.Tf = b.Tf, a.pf < b.pi, // EQ all four values are equal, // GT a.Ti > b.Tf or, if a.Ti = b.Ti and a.Tf = b.Tf, a.pi < b.pf, // CROSS_T there is an intersection between temperature intervals but // not between pressure intervals, e.g. // {100, 400, 1, 10} and {200, 500, 11, 20}, // CROSS there is an intersection between two rectangulars. // // Thus, allowable ranges can be partially ordered only. To obtain a // subset of ranges that can be completely ordered, follow a guideline: // first, divide the plane in T and p on temperature strips, and only // then cut them by pressure. int isin(const double &T, const double &p); // Returns zero if the point {T, p} does not belong to the range and // non-zero otherwise. friend int operator<(const lim_Tp &first, const lim_Tp &second); friend int operator==(const lim_Tp &first, const lim_Tp &second); friend int operator>(const lim_Tp &first, const lim_Tp &second); // Comparison of first and second ranges. If first.compare(second) // is equal to CROSS or CROSS_T, then all tree operations return // zero. friend lim_Tp cross(const lim_Tp &first, const lim_Tp &second); // Returns an intersection between first and second ranges. // If first.compare(second) is not equal to CROSS, the result is // undefined. //************************** Error handling *************************** enum lim_err { OKAY, // everything is okay WRTOK, // wrong token WRORD // wrong order (Ti > Tf or pi > pf) }; static lim_err errno; // Variable to keep the error code. It may be checked out when // something went wrong. }; // ##################### end of class lim_Tp ########################## inline func_Tp::func_Tp() { errno = OKAY; init(); } inline func_Tp::func_Tp(const func_Tp &old) { init(); copy(old); } inline func_Tp& func_Tp::operator=(const func_Tp &old) { if (this == &old) return *this; copy(old); return *this; } inline func_Tp::func_Tp(const char *str) { init(); anal(str); } inline func_Tp& func_Tp::operator=(const char *str) { anal(str); return *this; } inline func_Tp::~func_Tp() { delete [] start_tok; delete [] start_val; } inline void func_Tp::init() { nvalues = 0; ntokens = 0; start_tok = NULL; start_val = NULL; } inline void func_Tp::clear() { delete [] start_tok; delete [] start_val; init(); } inline func_Tp::operator int() const { return ntokens; } inline double func_Tp::operator()(const double &T, const double &p) { return est(T, p); } inline double func_Tp::operator()(const double &T) { return est(T, global::p); } inline double func_Tp::operator()() { return est(global::T, global::p); } inline lim_Tp::lim_Tp() { errno = OKAY; init(); } inline lim_Tp::lim_Tp(const lim_Tp &old) { copy(old); } inline lim_Tp& lim_Tp::operator=(const lim_Tp &old) { if (this == &old) return *this; copy(old); return *this; } inline lim_Tp::lim_Tp(const char *str) { anal(str); } inline lim_Tp& lim_Tp::operator=(const char *str) { anal(str); return *this; } inline lim_Tp::~lim_Tp() { } inline void lim_Tp::init() { Ti = 0.; Tf = HUGE_VAL; pi = 0.; pf = HUGE_VAL; } inline void lim_Tp::clear() { init(); } inline void lim_Tp::copy(const lim_Tp &old) { errno = OKAY; Ti = old.Ti; Tf = old.Tf; pi = old.pi; pf = old.pf; } inline lim_Tp::operator int() const { if (Ti == 0. && Tf == HUGE_VAL && pi == 0. && pf == HUGE_VAL) return 0; else return 1; } inline lim_Tp::isin(const double &T, const double &p) { if (T >= Ti && T <= Tf && p >= pi && p <= pf) return 1; else return 0; } inline int operator<(const lim_Tp &first, const lim_Tp &second) { return (first.compare(second) == lim_Tp::LT); } inline int operator==(const lim_Tp &first, const lim_Tp &second) { return (first.compare(second) == lim_Tp::EQ); } inline int operator>(const lim_Tp &first, const lim_Tp &second) { return (first.compare(second) == lim_Tp::GT); } #endif