/*------------------------------------------------------------------------- | 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. | --------------------------------------------------------------------------*/ #include #include #include "function.h" smpl_func::smpl_err smpl_func::errno; const char* smpl_func::anal(const char *in) { errno = OKAY; in = func_Tp::anal(in); if (func_Tp::errno != func_Tp::OKAY) errno = WRFUNC; in = lim_Tp::anal(in); if (lim_Tp::errno != lim_Tp::OKAY) errno = WRLIM; return in; } char* smpl_func::to_str(char *buf) const { errno = OKAY; char *str = buf; func_Tp::to_str(buf); if (func_Tp::errno != func_Tp::OKAY) errno = WRFUNC; str += strlen(buf); *str++ = ':'; lim_Tp::to_str(str); return buf; } void oper(smpl_func &res, const smpl_func &left, const smpl_func &right, const char op) { smpl_func::errno = smpl_func::OKAY; res.clear(); if (op != '+' && op != '-' && op != '*' && op != '/') return; if (left.compare(right) == lim_Tp::CROSS) res.lim_Tp::copy(cross(left, right)); else if (left.compare(right) == lim_Tp::EQ) res.lim_Tp::copy(left); else return; oper(*(func_Tp*)&res, *(func_Tp*)&left, *(func_Tp*)&right, op); } ostream& operator<<(ostream &out, const smpl_func &old) { smpl_func::errno = smpl_func::OKAY; out << *(func_Tp*)&old; if (func_Tp::errno != func_Tp::OKAY) smpl_func::errno = smpl_func::WRFUNC; out << ':'; out << *(lim_Tp*)&old; return out; } istream& operator>>(istream &in, smpl_func &to) { smpl_func::errno = smpl_func::OKAY; in >> *(func_Tp*)&to; if (func_Tp::errno != func_Tp::OKAY) smpl_func::errno = smpl_func::WRFUNC; in >> *(lim_Tp*)&to; if (lim_Tp::errno != lim_Tp::OKAY) smpl_func::errno = smpl_func::WRLIM; return in; } smpl_func operator+(const smpl_func &left, const smpl_func &right) { smpl_func res; oper(res, left, right, '+'); return res; } smpl_func operator-(const smpl_func &left, const smpl_func &right) { smpl_func res; oper(res, left, right, '-'); return res; } smpl_func operator*(const smpl_func &left, const smpl_func &right) { smpl_func res; oper(res, left, right, '*'); return res; } smpl_func operator/(const smpl_func &left, const smpl_func &right) { smpl_func res; oper(res, left, right, '/'); return res; } function::function_err function::errno; void function::clear() { node_func *tmp1 = start; node_func *tmp2; start = NULL; while (tmp1) { tmp2 = tmp1->next; delete tmp1; tmp1 = tmp2; } } void function::copy(const function &old) { errno = OKAY; clear(); node_func *tmp = NULL; node_func *tmp1; node_func *tmp2 = old.start; while (tmp2) { if ((tmp1 = new node_func) == NULL) { clear(); return; } if (tmp == NULL) tmp = start = tmp1; else tmp = tmp->next = tmp1; tmp->copy(*tmp2); tmp2 = tmp2->next; } } const char* function::anal(const char *in) { node_func *tmp; node_func *i; errno = OKAY; clear(); while (*in != '\0' && *in != ';') { if ((tmp = new node_func) == NULL) { clear(); return in; } in = tmp->anal(in); if (smpl_func::errno != smpl_func::OKAY) { errno = WRSMPL; delete tmp; break; } if (!add(tmp)) { errno = CROSS; delete tmp; break; } } if (errno != OKAY) clear(); if (*in == ';') in++; return in; } char* function::to_str(char *buf) const { node_func *i = start; char *str = buf; errno = OKAY; while (i) { i->to_str(str); if (smpl_func::errno != smpl_func::OKAY) errno = WRSMPL; str += strlen(str); *str++ = ':'; i = i->next; } *(str - 1) = ';'; *(str) = '\0'; return buf; } double function::est(const double &T, const double &p) { node_func *i = start; errno = OKAY; while (i) { if (i->isin(T, p)) return i->func_Tp::est(T, p); i = i->next; } errno = OUTRNG; return HUGE_VAL; } double function::df(global::derivative d, const double &T, const double &p) { node_func *i = start; errno = OKAY; while (i) { if (i->isin(T, p)) return i->func_Tp::df(d, T, p); i = i->next; } errno = OUTRNG; return HUGE_VAL; } void oper(function &res, const function &left, const function &right, const char op) { function::errno = function::OKAY; res.clear(); if (op != '+' && op != '-' && op != '*' && op != '/') return; if (left) { if (right) { node_func *a; node_func *b = right.start; node_func *c; node_func *d; for (a = left.start; a; a = a->next) { for (c = b; c; c = c->next) { switch (a->compare(*c)) { case lim_Tp::LT: c = NULL; break; case lim_Tp::CROSS: case lim_Tp::EQ: if ((d = new node_func) == NULL) { res.clear(); return; } oper(*d, *a, *c, op); if (!res.add(d)) { function::errno = function::BAD; res.clear(); return; } break; case lim_Tp::GT: b = c->next; break; case lim_Tp::CROSS_T: break; } if (c == NULL) break; } } } else res = left; } else if (right) res = right; } int function::len() const { if (!start) return 0; int len = 0; node_func *i = start; while (i) { len += i->len() + 1; i = i->next; } return len; } ostream& operator<<(ostream &out, const function &old) { node_func *i = old.start; function::errno = function::OKAY; while (i) { out << *i; if (smpl_func::errno != smpl_func::OKAY) function::errno = function::WRSMPL; if (i->next) { out << ':'; out << endl; } else out << ';'; i = i->next; } return out; } istream& operator>>(istream &in, function &to) { node_func *tmp; node_func *i; function::errno = function::OKAY; to.clear(); while (in >> ws, in.peek() != EOF) { if (in.peek() == ';') { in.get(); break; } if ((tmp = new node_func) == NULL) { to.clear(); return in; } in >> *tmp; if (smpl_func::errno != smpl_func::OKAY) { function::errno = function::WRSMPL; delete tmp; break; } if (!to.add(tmp)) { function::errno = function::CROSS; delete tmp; break; } } if (function::errno != function::OKAY) to.clear(); return in; } function operator+(const function &left, const function &right) { function res; oper(res, left, right, '+'); return res; } function operator-(const function &left, const function &right) { function res; oper(res, left, right, '-'); return res; } function operator*(const function &left, const function &right) { function res; oper(res, left, right, '*'); return res; } function operator/(const function &left, const function &right) { function res; oper(res, left, right, '/'); return res; } int function::nfunc() const { node_func *i = start; int n = 0; while (i) { n++; i = i->next; } return n; } int function::add(node_func *t) { if (!start) { start = t; return 1; } node_func *i = start; node_func *pri; while (i) { switch (t->compare(*i)) { case lim_Tp::LT: if (i == start) start = t; else pri->next = t; t->next = i; return 1; case lim_Tp::GT: if (i->next == NULL) { i->next = t; return 1; } break; default: return 0; } pri = i; i = i->next; } return 0; }