From c5fc2e38c1361aef5820f91a4b1d0375e97f3af9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Villemot?= <sebastien@dynare.org>
Date: Mon, 28 Jan 2019 15:15:58 +0100
Subject: [PATCH] Simplify log(1/x) into -log(x) (and similarly for log10)

---
 src/DataTree.cc | 28 ++++++++++++++++++++--------
 1 file changed, 20 insertions(+), 8 deletions(-)

diff --git a/src/DataTree.cc b/src/DataTree.cc
index 0e3c22b7..7a60c67d 100644
--- a/src/DataTree.cc
+++ b/src/DataTree.cc
@@ -357,29 +357,41 @@ DataTree::AddExp(expr_t iArg1)
 expr_t
 DataTree::AddLog(expr_t iArg1)
 {
-  if (iArg1 != Zero && iArg1 != One)
-    return AddUnaryOp(UnaryOpcode::log, iArg1);
-  else if (iArg1 == One)
+  if (iArg1 == One)
     return Zero;
-  else
+
+  if (iArg1 == Zero)
     {
       cerr << "ERROR: log(0) not defined!" << endl;
       exit(EXIT_FAILURE);
     }
+
+  // Try to simplify log(1/x) into -log(x)
+  auto barg1 = dynamic_cast<BinaryOpNode *>(iArg1);
+  if (barg1 && barg1->op_code == BinaryOpcode::divide && barg1->arg1 == One)
+    return AddUMinus(AddLog(barg1->arg2));
+
+  return AddUnaryOp(UnaryOpcode::log, iArg1);
 }
 
 expr_t
 DataTree::AddLog10(expr_t iArg1)
 {
-  if (iArg1 != Zero && iArg1 != One)
-    return AddUnaryOp(UnaryOpcode::log10, iArg1);
-  else if (iArg1 == One)
+  if (iArg1 == One)
     return Zero;
-  else
+
+  if (iArg1 == Zero)
     {
       cerr << "ERROR: log10(0) not defined!" << endl;
       exit(EXIT_FAILURE);
     }
+
+  // Try to simplify log10(1/x) into -log10(x)
+  auto barg1 = dynamic_cast<BinaryOpNode *>(iArg1);
+  if (barg1 && barg1->op_code == BinaryOpcode::divide && barg1->arg1 == One)
+    return AddUMinus(AddLog10(barg1->arg2));
+
+  return AddUnaryOp(UnaryOpcode::log10, iArg1);
 }
 
 expr_t
-- 
GitLab