From 73d3eec8a57c920d1d2e4c304e58923910d9d12d Mon Sep 17 00:00:00 2001
From: Giovanni Bussi <giovanni.bussi@gmail.com>
Date: Tue, 28 Aug 2018 18:37:02 +0200
Subject: [PATCH] Removed repeated constants

Lepton constants are now placed in lepton. They can be
accessed with a function lepton::Constants() so as to
avoid initialization problems.

cc: @valsson
---
 src/function/Matheval.cpp       | 21 ++-------------------
 src/lepton/Lepton.h             | 10 ++++++++++
 src/lepton/Parser.cpp           | 20 ++++++++++++++++++++
 src/tools/SwitchingFunction.cpp | 20 ++------------------
 src/tools/Tools.cpp             | 18 +-----------------
 src/ves/BF_Custom.cpp           | 25 ++++---------------------
 src/ves/TD_Custom.cpp           | 19 +------------------
 7 files changed, 40 insertions(+), 93 deletions(-)

diff --git a/src/function/Matheval.cpp b/src/function/Matheval.cpp
index 431067c4b..b3a0f7b78 100644
--- a/src/function/Matheval.cpp
+++ b/src/function/Matheval.cpp
@@ -29,23 +29,6 @@ using namespace std;
 namespace PLMD {
 namespace function {
 
-const static std::map<string, double> leptonConstants= {
-  {"e", std::exp(1.0)},
-  {"log2e", 1.0/std::log(2.0)},
-  {"log10e", 1.0/std::log(10.0)},
-  {"ln2", std::log(2.0)},
-  {"ln10", std::log(10.0)},
-  {"pi", pi},
-  {"pi_2", pi*0.5},
-  {"pi_4", pi*0.25},
-//  {"1_pi", 1.0/pi},
-//  {"2_pi", 2.0/pi},
-//  {"2_sqrtpi", 2.0/std::sqrt(pi)},
-  {"sqrt2", std::sqrt(2.0)},
-  {"sqrt1_2", std::sqrt(0.5)}
-};
-
-
 //+PLUMEDOC FUNCTION MATHEVAL
 /*
 Calculate a combination of variables using a matheval expression.
@@ -253,7 +236,7 @@ Matheval::Matheval(const ActionOptions&ao):
   for(unsigned i=0; i<var.size(); i++) log.printf(" %s",var[i].c_str());
   log.printf("\n");
 
-  lepton::ParsedExpression pe=lepton::Parser::parse(func).optimize(leptonConstants);
+  lepton::ParsedExpression pe=lepton::Parser::parse(func).optimize(lepton::Constants());
   log<<"  function as parsed by lepton: "<<pe<<"\n";
   expression=pe.createCompiledExpression();
   for(auto &p: expression.getVariables()) {
@@ -263,7 +246,7 @@ Matheval::Matheval(const ActionOptions&ao):
   }
   log<<"  derivatives as computed by lepton:\n";
   for(unsigned i=0; i<getNumberOfArguments(); i++) {
-    lepton::ParsedExpression pe=lepton::Parser::parse(func).differentiate(var[i]).optimize(leptonConstants);
+    lepton::ParsedExpression pe=lepton::Parser::parse(func).differentiate(var[i]).optimize(lepton::Constants());
     log<<"    "<<pe<<"\n";
     expression_deriv[i]=pe.createCompiledExpression();
   }
diff --git a/src/lepton/Lepton.h b/src/lepton/Lepton.h
index a2ff54073..b1afd223e 100644
--- a/src/lepton/Lepton.h
+++ b/src/lepton/Lepton.h
@@ -64,6 +64,16 @@
  * USE OR OTHER DEALINGS IN THE SOFTWARE.                                     *
  * -------------------------------------------------------------------------- */
 
+#include <map>
+#include <cmath>
+#include <string>
+
+namespace PLMD {
+namespace lepton {
+const std::map<std::string, double> & Constants();
+}
+}
+
 #include "CompiledExpression.h"
 #include "CustomFunction.h"
 #include "ExpressionProgram.h"
diff --git a/src/lepton/Parser.cpp b/src/lepton/Parser.cpp
index 3096c361b..240b8857b 100644
--- a/src/lepton/Parser.cpp
+++ b/src/lepton/Parser.cpp
@@ -82,8 +82,28 @@ static const bool LeftAssociative[] = {true, true, true, true, false};
 static const int Precedence[] = {0, 0, 1, 1, 3};
 static const Operation::Id OperationId[] = {Operation::ADD, Operation::SUBTRACT, Operation::MULTIPLY, Operation::DIVIDE, Operation::POWER};
 
+const std::map<std::string, double> & Constants() {
+  static const std::map<std::string, double> constants = {
+  {"e", std::exp(1.0)},
+  {"log2e", 1.0/std::log(2.0)},
+  {"log10e", 1.0/std::log(10.0)},
+  {"ln2", std::log(2.0)},
+  {"ln10", std::log(10.0)},
+  {"pi", 3.14159265358979323844},
+  {"pi_2", 3.14159265358979323844*0.5},
+  {"pi_4", 3.14159265358979323844*0.25},
+//  {"1_pi", 1.0/pi},
+//  {"2_pi", 2.0/pi},
+//  {"2_sqrtpi", 2.0/std::sqrt(pi)},
+  {"sqrt2", std::sqrt(2.0)},
+  {"sqrt1_2", std::sqrt(0.5)}
+  };
+  return constants;
+};
+
 }
 
+
 class lepton::ParseToken {
 public:
     enum Type {Number, Operator, Variable, Function, LeftParen, RightParen, Comma, Whitespace};
diff --git a/src/tools/SwitchingFunction.cpp b/src/tools/SwitchingFunction.cpp
index 27e391972..7f37b8efe 100644
--- a/src/tools/SwitchingFunction.cpp
+++ b/src/tools/SwitchingFunction.cpp
@@ -29,22 +29,6 @@
 using namespace std;
 namespace PLMD {
 
-const static std::map<string, double> leptonConstants= {
-  {"e", std::exp(1.0)},
-  {"log2e", 1.0/std::log(2.0)},
-  {"log10e", 1.0/std::log(10.0)},
-  {"ln2", std::log(2.0)},
-  {"ln10", std::log(10.0)},
-  {"pi", pi},
-  {"pi_2", pi*0.5},
-  {"pi_4", pi*0.25},
-//  {"1_pi", 1.0/pi},
-//  {"2_pi", 2.0/pi},
-//  {"2_sqrtpi", 2.0/std::sqrt(pi)},
-  {"sqrt2", std::sqrt(2.0)},
-  {"sqrt1_2", std::sqrt(0.5)}
-};
-
 //+PLUMEDOC INTERNAL switchingfunction
 /*
 Functions that measure whether values are less than a certain quantity.
@@ -263,7 +247,7 @@ void SwitchingFunction::set(const std::string & definition,std::string& errormsg
     type=leptontype;
     std::string func;
     Tools::parse(data,"FUNC",func);
-    lepton::ParsedExpression pe=lepton::Parser::parse(func).optimize(leptonConstants);
+    lepton::ParsedExpression pe=lepton::Parser::parse(func).optimize(lepton::Constants());
     lepton_func=func;
     expression.resize(OpenMP::getNumThreads());
     for(auto & e : expression) e=pe.createCompiledExpression();
@@ -284,7 +268,7 @@ void SwitchingFunction::set(const std::string & definition,std::string& errormsg
     }
     std::string arg="x";
     if(leptonx2) arg="x2";
-    lepton::ParsedExpression ped=lepton::Parser::parse(func).differentiate(arg).optimize(leptonConstants);
+    lepton::ParsedExpression ped=lepton::Parser::parse(func).differentiate(arg).optimize(lepton::Constants());
     expression_deriv.resize(OpenMP::getNumThreads());
     for(auto & e : expression_deriv) e=ped.createCompiledExpression();
     lepton_ref_deriv.resize(expression_deriv.size());
diff --git a/src/tools/Tools.cpp b/src/tools/Tools.cpp
index b4853b41c..8114e8fbc 100644
--- a/src/tools/Tools.cpp
+++ b/src/tools/Tools.cpp
@@ -35,22 +35,6 @@
 using namespace std;
 namespace PLMD {
 
-const static std::map<string, double> leptonConstants= {
-  {"e", std::exp(1.0)},
-  {"log2e", 1.0/std::log(2.0)},
-  {"log10e", 1.0/std::log(10.0)},
-  {"ln2", std::log(2.0)},
-  {"ln10", std::log(10.0)},
-  {"pi", pi},
-  {"pi_2", pi*0.5},
-  {"pi_4", pi*0.25},
-//  {"1_pi", 1.0/pi},
-//  {"2_pi", 2.0/pi},
-//  {"2_sqrtpi", 2.0/std::sqrt(pi)},
-  {"sqrt2", std::sqrt(2.0)},
-  {"sqrt1_2", std::sqrt(0.5)}
-};
-
 template<class T>
 bool Tools::convertToAny(const string & str,T & t) {
   istringstream istr(str.c_str());
@@ -89,7 +73,7 @@ bool Tools::convertToReal(const string & str,T & t) {
     t=-pi; return true;
   }
   try {
-    t=lepton::Parser::parse(str).evaluate(leptonConstants);
+    t=lepton::Parser::parse(str).evaluate(lepton::Constants());
     return true;
   } catch(PLMD::lepton::Exception& exc) {
   }
diff --git a/src/ves/BF_Custom.cpp b/src/ves/BF_Custom.cpp
index c6d315126..19edeebf5 100644
--- a/src/ves/BF_Custom.cpp
+++ b/src/ves/BF_Custom.cpp
@@ -29,23 +29,6 @@
 namespace PLMD {
 namespace ves {
 
-const static std::map<std::string, double> leptonConstants= {
-  {"e", std::exp(1.0)},
-  {"log2e", 1.0/std::log(2.0)},
-  {"log10e", 1.0/std::log(10.0)},
-  {"ln2", std::log(2.0)},
-  {"ln10", std::log(10.0)},
-  {"pi", pi},
-  {"pi_2", pi*0.5},
-  {"pi_4", pi*0.25},
-//  {"1_pi", 1.0/pi},
-//  {"2_pi", 2.0/pi},
-//  {"2_sqrtpi", 2.0/std::sqrt(pi)},
-  {"sqrt2", std::sqrt(2.0)},
-  {"sqrt1_2", std::sqrt(0.5)}
-};
-
-
 //+PLUMEDOC VES_BASISF BF_CUSTOM
 /*
 Basis functions given by arbitrary mathematical expressions.
@@ -193,7 +176,7 @@ BF_Custom::BF_Custom(const ActionOptions&ao):
   for(unsigned int i=1; i<getNumberOfBasisFunctions(); i++) {
     std::string is; Tools::convert(i,is);
     try {
-      lepton::ParsedExpression pe_value = lepton::Parser::parse(bf_str[i]).optimize(leptonConstants);
+      lepton::ParsedExpression pe_value = lepton::Parser::parse(bf_str[i]).optimize(lepton::Constants());
       std::ostringstream tmp_stream; tmp_stream << pe_value;
       bf_values_parsed[i] = tmp_stream.str();
       bf_values_expressions_[i] = pe_value.createCompiledExpression();
@@ -214,7 +197,7 @@ BF_Custom::BF_Custom(const ActionOptions&ao):
     }
 
     try {
-      lepton::ParsedExpression pe_deriv = lepton::Parser::parse(bf_str[i]).differentiate(variable_str_).optimize(leptonConstants);
+      lepton::ParsedExpression pe_deriv = lepton::Parser::parse(bf_str[i]).differentiate(variable_str_).optimize(lepton::Constants());
       std::ostringstream tmp_stream2; tmp_stream2 << pe_deriv;
       bf_derivs_parsed[i] = tmp_stream2.str();
       bf_derivs_expressions_[i] = pe_deriv.createCompiledExpression();
@@ -242,7 +225,7 @@ BF_Custom::BF_Custom(const ActionOptions&ao):
     }
 
     try {
-      lepton::ParsedExpression pe_value = lepton::Parser::parse(transf_str).optimize(leptonConstants);;
+      lepton::ParsedExpression pe_value = lepton::Parser::parse(transf_str).optimize(lepton::Constants());;
       std::ostringstream tmp_stream; tmp_stream << pe_value;
       transf_value_parsed = tmp_stream.str();
       transf_value_expression_ = pe_value.createCompiledExpression();
@@ -263,7 +246,7 @@ BF_Custom::BF_Custom(const ActionOptions&ao):
     }
 
     try {
-      lepton::ParsedExpression pe_deriv = lepton::Parser::parse(transf_str).differentiate(transf_variable_str_).optimize(leptonConstants);;
+      lepton::ParsedExpression pe_deriv = lepton::Parser::parse(transf_str).differentiate(transf_variable_str_).optimize(lepton::Constants());;
       std::ostringstream tmp_stream2; tmp_stream2 << pe_deriv;
       transf_deriv_parsed = tmp_stream2.str();
       transf_deriv_expression_ = pe_deriv.createCompiledExpression();
diff --git a/src/ves/TD_Custom.cpp b/src/ves/TD_Custom.cpp
index c7a24eb4c..9e77b99de 100644
--- a/src/ves/TD_Custom.cpp
+++ b/src/ves/TD_Custom.cpp
@@ -32,23 +32,6 @@
 namespace PLMD {
 namespace ves {
 
-const static std::map<std::string, double> leptonConstants= {
-  {"e", std::exp(1.0)},
-  {"log2e", 1.0/std::log(2.0)},
-  {"log10e", 1.0/std::log(10.0)},
-  {"ln2", std::log(2.0)},
-  {"ln10", std::log(10.0)},
-  {"pi", pi},
-  {"pi_2", pi*0.5},
-  {"pi_4", pi*0.25},
-//  {"1_pi", 1.0/pi},
-//  {"2_pi", 2.0/pi},
-//  {"2_sqrtpi", 2.0/std::sqrt(pi)},
-  {"sqrt2", std::sqrt(2.0)},
-  {"sqrt1_2", std::sqrt(0.5)}
-};
-
-
 //+PLUMEDOC VES_TARGETDIST TD_CUSTOM
 /*
 Target distribution given by an arbitrary mathematical expression (static or dynamic).
@@ -186,7 +169,7 @@ TD_Custom::TD_Custom(const ActionOptions& ao):
   checkRead();
   //
   try {
-    lepton::ParsedExpression pe=lepton::Parser::parse(func_str).optimize(leptonConstants);
+    lepton::ParsedExpression pe=lepton::Parser::parse(func_str).optimize(lepton::Constants());
     log<<"  function as parsed by lepton: "<<pe<<"\n";
     expression=pe.createCompiledExpression();
   }
-- 
GitLab