AbaKus – a complex calculator
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

420 lines
9.5KB

  1. /*
  2. * node.cpp - part of abakus
  3. * Copyright (C) 2004, 2005 Michael Pyne <michael.pyne@kdemail.net>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  18. */
  19. #include <kdebug.h>
  20. #include <math.h>
  21. #include "node.h"
  22. #include "valuemanager.h"
  23. #include "function.h"
  24. void Node::deleteNode(Node *node)
  25. {
  26. if(dynamic_cast<BaseFunction *>(node) != 0)
  27. delete node;
  28. }
  29. BaseFunction::BaseFunction(const char *name) :
  30. m_name(name)
  31. {
  32. }
  33. const Function *BaseFunction::function() const
  34. {
  35. return FunctionManager::instance()->function(m_name);
  36. }
  37. UnaryFunction::UnaryFunction(const char *name, Node *operand) :
  38. BaseFunction(name), m_node(operand)
  39. {
  40. }
  41. UnaryFunction::~UnaryFunction()
  42. {
  43. deleteNode(m_node);
  44. m_node = 0;
  45. }
  46. void UnaryFunction::setOperand(Node *operand)
  47. {
  48. m_node = operand;
  49. }
  50. void UnaryFunction::applyMap(NodeFunctor &fn) const
  51. {
  52. fn(operand());
  53. fn(this);
  54. }
  55. TQString UnaryFunction::infixString() const
  56. {
  57. return TQString("%1(%2)").arg(name(), operand()->infixString());
  58. }
  59. BuiltinFunction::BuiltinFunction(const char *name, Node *operand) :
  60. UnaryFunction(name, operand)
  61. {
  62. }
  63. Abakus::number_t BuiltinFunction::value() const
  64. {
  65. if(function() && operand()) {
  66. Abakus::number_t fnValue = operand()->value();
  67. return evaluateFunction(function(), fnValue);
  68. }
  69. return Abakus::number_t(0);
  70. }
  71. Abakus::number_t BuiltinFunction::derivative() const
  72. {
  73. Abakus::number_t du = operand()->derivative();
  74. Abakus::number_t value = operand()->value();
  75. Abakus::number_t one(1), zero(0);
  76. if(du == zero)
  77. return du;
  78. // In case these functions get added later, these derivatives may
  79. // be useful:
  80. // d/dx(asinh u) = (du/dx * 1 / sqrt(x^2 + 1))
  81. // d/dx(acosh u) = (du/dx * 1 / sqrt(x^2 - 1))
  82. // d/dx(atanh u) = (du/dx * 1 / (1 - x^2))
  83. // This is very unfortunate duplication.
  84. if(name() == "sin")
  85. return value.cos() * du;
  86. else if(name() == "cos")
  87. return -value.sin() * du;
  88. else if(name() == "tan") {
  89. Abakus::number_t cosResult;
  90. cosResult = value.cos();
  91. cosResult = cosResult * cosResult;
  92. return one / cosResult;
  93. }
  94. else if(name() == "asinh") {
  95. value = value * value + one;
  96. return du / value.sqrt();
  97. }
  98. else if(name() == "acosh") {
  99. value = value * value - one;
  100. return du / value.sqrt();
  101. }
  102. else if(name() == "atanh") {
  103. value = one - value * value;
  104. return du / value;
  105. }
  106. else if(name() == "sinh") {
  107. return du * value.cosh();
  108. }
  109. else if(name() == "cosh") {
  110. return du * value.sinh(); // Yes the sign is correct.
  111. }
  112. else if(name() == "tanh") {
  113. Abakus::number_t tanh = value.tanh();
  114. return du * (one - tanh * tanh);
  115. }
  116. else if(name() == "atan") {
  117. return one * du / (one + value * value);
  118. }
  119. else if(name() == "acos") {
  120. // Same as asin but with inverted sign.
  121. return -(one / (value * value - one).sqrt() * du);
  122. }
  123. else if(name() == "asin") {
  124. return one / (value * value - one).sqrt() * du;
  125. }
  126. else if(name() == "ln") {
  127. return du / value;
  128. }
  129. else if(name() == "exp") {
  130. return du * value.exp();
  131. }
  132. else if(name() == "log") {
  133. return du / value / Abakus::number_t(10).ln();
  134. }
  135. else if(name() == "sqrt") {
  136. Abakus::number_t half("0.5");
  137. return half * value.pow(-half) * du;
  138. }
  139. else if(name() == "abs") {
  140. return (value / value.abs()) * du;
  141. }
  142. // Approximate it.
  143. Abakus::number_t epsilon("1e-15");
  144. Abakus::number_t fxh = evaluateFunction(function(), value + epsilon);
  145. Abakus::number_t fx = evaluateFunction(function(), value);
  146. return (fxh - fx) / epsilon;
  147. }
  148. DerivativeFunction::~DerivativeFunction()
  149. {
  150. deleteNode(m_operand);
  151. m_operand = 0;
  152. }
  153. Abakus::number_t DerivativeFunction::value() const
  154. {
  155. ValueManager *vm = ValueManager::instance();
  156. Abakus::number_t result;
  157. if(vm->isValueSet("x")) {
  158. Abakus::number_t oldValue = vm->value("x");
  159. vm->setValue("x", m_where->value());
  160. result = m_operand->derivative();
  161. vm->setValue("x", oldValue);
  162. }
  163. else {
  164. vm->setValue("x", m_where->value());
  165. result = m_operand->derivative();
  166. vm->removeValue("x");
  167. }
  168. return result;
  169. }
  170. Abakus::number_t DerivativeFunction::derivative() const
  171. {
  172. kdError() << k_funcinfo << endl;
  173. kdError() << "This function is never supposed to be called!\n";
  174. return m_operand->derivative();
  175. }
  176. void DerivativeFunction::applyMap(NodeFunctor &fn) const
  177. {
  178. fn(m_operand);
  179. fn(this);
  180. }
  181. TQString DerivativeFunction::infixString() const
  182. {
  183. return TQString("deriv(%1, %2)").arg(m_operand->infixString(), m_where->infixString());
  184. }
  185. UnaryOperator::UnaryOperator(Type type, Node *operand)
  186. : m_type(type), m_node(operand)
  187. {
  188. }
  189. UnaryOperator::~UnaryOperator()
  190. {
  191. deleteNode(m_node);
  192. m_node = 0;
  193. }
  194. void UnaryOperator::applyMap(NodeFunctor &fn) const
  195. {
  196. fn(operand());
  197. fn(this);
  198. }
  199. TQString UnaryOperator::infixString() const
  200. {
  201. if(dynamic_cast<BinaryOperator *>(operand()))
  202. return TQString("-(%1)").arg(operand()->infixString());
  203. return TQString("-%1").arg(operand()->infixString());
  204. }
  205. Abakus::number_t UnaryOperator::derivative() const
  206. {
  207. switch(type()) {
  208. case Negation:
  209. return -(operand()->derivative());
  210. default:
  211. kdError() << "Impossible case encountered for UnaryOperator!\n";
  212. return Abakus::number_t(0);
  213. }
  214. }
  215. Abakus::number_t UnaryOperator::value() const
  216. {
  217. switch(type()) {
  218. case Negation:
  219. return -(operand()->value());
  220. default:
  221. kdError() << "Impossible case encountered for UnaryOperator!\n";
  222. return Abakus::number_t(0);
  223. }
  224. }
  225. BinaryOperator::BinaryOperator(Type type, Node *left, Node *right) :
  226. m_type(type), m_left(left), m_right(right)
  227. {
  228. }
  229. BinaryOperator::~BinaryOperator()
  230. {
  231. deleteNode(m_left);
  232. m_left = 0;
  233. deleteNode(m_right);
  234. m_right = 0;
  235. }
  236. void BinaryOperator::applyMap(NodeFunctor &fn) const
  237. {
  238. fn(leftNode());
  239. fn(rightNode());
  240. fn(this);
  241. }
  242. TQString BinaryOperator::infixString() const
  243. {
  244. TQString op;
  245. switch(type()) {
  246. case Addition:
  247. op = "+";
  248. break;
  249. case Subtraction:
  250. op = "-";
  251. break;
  252. case Multiplication:
  253. op = "*";
  254. break;
  255. case Division:
  256. op = "/";
  257. break;
  258. case Exponentiation:
  259. op = "^";
  260. break;
  261. default:
  262. op = "Error";
  263. }
  264. TQString left = TQString(isSimpleNode(leftNode()) ? "%1" : "(%1)").arg(leftNode()->infixString());
  265. TQString right = TQString(isSimpleNode(rightNode()) ? "%1" : "(%1)").arg(rightNode()->infixString());
  266. return TQString("%1 %2 %3").arg(left, op, right);
  267. }
  268. Abakus::number_t BinaryOperator::derivative() const
  269. {
  270. if(!leftNode() || !rightNode()) {
  271. kdError() << "Can't evaluate binary operator!\n";
  272. return Abakus::number_t(0);
  273. }
  274. Abakus::number_t f = leftNode()->value();
  275. Abakus::number_t fPrime = leftNode()->derivative();
  276. Abakus::number_t g = rightNode()->value();
  277. Abakus::number_t gPrime = rightNode()->derivative();
  278. switch(type()) {
  279. case Addition:
  280. return fPrime + gPrime;
  281. case Subtraction:
  282. return fPrime - gPrime;
  283. case Multiplication:
  284. return f * gPrime + fPrime * g;
  285. case Division:
  286. return (g * fPrime - f * gPrime) / (g * g);
  287. case Exponentiation:
  288. return f.pow(g) * ((g / f) * fPrime + gPrime * f.ln());
  289. default:
  290. kdError() << "Impossible case encountered evaluating binary operator!\n";
  291. return Abakus::number_t(0);
  292. }
  293. }
  294. Abakus::number_t BinaryOperator::value() const
  295. {
  296. if(!leftNode() || !rightNode()) {
  297. kdError() << "Can't evaluate binary operator!\n";
  298. return Abakus::number_t(0);
  299. }
  300. Abakus::number_t lValue = leftNode()->value();
  301. Abakus::number_t rValue = rightNode()->value();
  302. switch(type()) {
  303. case Addition:
  304. return lValue + rValue;
  305. case Subtraction:
  306. return lValue - rValue;
  307. case Multiplication:
  308. return lValue * rValue;
  309. case Division:
  310. return lValue / rValue;
  311. case Exponentiation:
  312. return lValue.pow(rValue);
  313. default:
  314. kdError() << "Impossible case encountered evaluating binary operator!\n";
  315. return Abakus::number_t(0);
  316. }
  317. }
  318. bool BinaryOperator::isSimpleNode(Node *node) const
  319. {
  320. if(dynamic_cast<Identifier *>(node) ||
  321. dynamic_cast<NumericValue *>(node) ||
  322. dynamic_cast<UnaryOperator *>(node) ||
  323. dynamic_cast<BaseFunction *>(node))
  324. {
  325. return true;
  326. }
  327. return false;
  328. }
  329. Identifier::Identifier(const char *name) : m_name(name)
  330. {
  331. }
  332. Abakus::number_t Identifier::value() const
  333. {
  334. return ValueManager::instance()->value(name());
  335. }
  336. void Identifier::applyMap(NodeFunctor &fn) const
  337. {
  338. fn(this);
  339. }
  340. TQString NumericValue::infixString() const
  341. {
  342. return value().toString();
  343. }
  344. // vim: set et ts=8 sw=4: