From 3c6645d72d0215bf70e77f495786de961971bc45 Mon Sep 17 00:00:00 2001
From: Giovanni Bussi <giovanni.bussi@gmail.com>
Date: Wed, 6 Sep 2017 12:58:46 +0200
Subject: [PATCH] Removed libmatheval

I removed matheval everywhere in the code. Now, MATHEVAL
(and CUSTOM) keywords are automatically using lepton (see #244).

Notice that env var PLUMED_USE_LEPTON is now ignored.
---
 configure                       |  90 -------------------------
 configure.ac                    |   4 --
 src/core/CLToolMain.cpp         |   3 -
 src/function/Matheval.cpp       | 114 +++++++-------------------------
 src/tools/SwitchingFunction.cpp |  79 +---------------------
 src/tools/SwitchingFunction.h   |  10 ---
 6 files changed, 25 insertions(+), 275 deletions(-)

diff --git a/configure b/configure
index d475becad..b47ddaa92 100755
--- a/configure
+++ b/configure
@@ -714,7 +714,6 @@ enable_external_lapack
 enable_external_blas
 enable_molfile_plugins
 enable_external_molfile_plugins
-enable_matheval
 enable_zlib
 enable_readdir_r
 enable_cregex
@@ -1383,7 +1382,6 @@ Optional Features:
   --enable-external-molfile-plugins
                           enable search for external molfile_plugins, default:
                           yes
-  --enable-matheval       enable search for matheval, default: yes
   --enable-zlib           enable search for zlib, default: yes
   --enable-readdir-r      enable search for readdir_r (threadsafe), default:
                           yes
@@ -2764,24 +2762,6 @@ fi
 
 
 
-matheval=
-# Check whether --enable-matheval was given.
-if test "${enable_matheval+set}" = set; then :
-  enableval=$enable_matheval; case "${enableval}" in
-             (yes) matheval=true ;;
-             (no)  matheval=false ;;
-             (*)   as_fn_error $? "wrong argument to --enable-matheval" "$LINENO" 5 ;;
-  esac
-else
-  case "yes" in
-             (yes) matheval=true ;;
-             (no)  matheval=false ;;
-  esac
-
-fi
-
-
-
 zlib=
 # Check whether --enable-zlib was given.
 if test "${enable_zlib+set}" = set; then :
@@ -6156,76 +6136,6 @@ $as_echo "$ac_cv_prog_cxx_openmp" >&6; }
 
 
 
-if test $matheval == true ; then
-
-    found=ko
-    ac_fn_cxx_check_header_mongrel "$LINENO" "matheval.h" "ac_cv_header_matheval_h" "$ac_includes_default"
-if test "x$ac_cv_header_matheval_h" = xyes; then :
-
-      ac_fn_cxx_check_func "$LINENO" "evaluator_create" "ac_cv_func_evaluator_create"
-if test "x$ac_cv_func_evaluator_create" = xyes; then :
-  found=ok
-else
-
-          if test "${libsearch}" == true ; then
-           { $as_echo "$as_me:${as_lineno-$LINENO}: checking for evaluator_create in -lmatheval" >&5
-$as_echo_n "checking for evaluator_create in -lmatheval... " >&6; }
-if ${ac_cv_lib_matheval_evaluator_create+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lmatheval  $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char evaluator_create ();
-int
-main ()
-{
-return evaluator_create ();
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_cxx_try_link "$LINENO"; then :
-  ac_cv_lib_matheval_evaluator_create=yes
-else
-  ac_cv_lib_matheval_evaluator_create=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_matheval_evaluator_create" >&5
-$as_echo "$ac_cv_lib_matheval_evaluator_create" >&6; }
-if test "x$ac_cv_lib_matheval_evaluator_create" = xyes; then :
-  LIBS="-lmatheval $LIBS" && found=ok
-fi
-
-          fi
-
-
-fi
-
-
-fi
-
-
-    if test $found == ok ; then
-      $as_echo "#define __PLUMED_HAS_MATHEVAL 1" >>confdefs.h
-
-    else
-       { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cannot enable __PLUMED_HAS_MATHEVAL" >&5
-$as_echo "$as_me: WARNING: cannot enable __PLUMED_HAS_MATHEVAL" >&2;}
-    fi
-
-fi
 if test $readdir_r == true ; then
 
     found=ko
diff --git a/configure.ac b/configure.ac
index ee30c401e..5c8065f4b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -191,7 +191,6 @@ PLUMED_CONFIG_ENABLE([external_lapack],[external-lapack],[search for external la
 PLUMED_CONFIG_ENABLE([external_blas],[external-blas],[search for external blas],[yes])
 PLUMED_CONFIG_ENABLE([molfile_plugins],[molfile-plugins],[use molfile_plugins],[yes])
 PLUMED_CONFIG_ENABLE([external_molfile_plugins],[external-molfile-plugins],[search for external molfile_plugins],[yes])
-PLUMED_CONFIG_ENABLE([matheval],[matheval],[search for matheval],[yes])
 PLUMED_CONFIG_ENABLE([zlib],[zlib],[search for zlib],[yes])
 PLUMED_CONFIG_ENABLE([readdir_r],[readdir-r],[search for readdir_r (threadsafe)],[yes])
 PLUMED_CONFIG_ENABLE([cregex],[cregex],[search for C regular expression],[yes])
@@ -549,9 +548,6 @@ fi
 # when configuring with --disable-openmp
 AC_OPENMP
 
-if test $matheval == true ; then
-  PLUMED_CHECK_PACKAGE([matheval.h],[evaluator_create],[__PLUMED_HAS_MATHEVAL],[matheval])
-fi
 if test $readdir_r == true ; then
   PLUMED_CHECK_PACKAGE([dirent.h],[readdir_r],[__PLUMED_HAS_READDIR_R])
 fi
diff --git a/src/core/CLToolMain.cpp b/src/core/CLToolMain.cpp
index cab6dc964..607a2d8fb 100644
--- a/src/core/CLToolMain.cpp
+++ b/src/core/CLToolMain.cpp
@@ -122,8 +122,6 @@ int CLToolMain::run(int argc, char **argv,FILE*in,FILE*out,Communicator& pc) {
     } else if(a=="--has-mpi") {
       if(Communicator::initialized()) return 0;
       else return 1;
-    } else if(a=="--has-matheval") {
-      return (config::hasMatheval()?0:1);
     } else if(a=="--has-cregex") {
       return (config::hasCregex()?0:1);
     } else if(a=="--has-dlopen") {
@@ -203,7 +201,6 @@ int CLToolMain::run(int argc, char **argv,FILE*in,FILE*out,Communicator& pc) {
       "  [help|-h|--help]          : to print this help\n"
       "  [--is-installed]          : fails if plumed is not installed\n"
       "  [--has-mpi]               : fails if plumed is running without MPI\n"
-      "  [--has-matheval]          : fails if plumed is compiled without matheval\n"
       "  [--has-dlopen]            : fails if plumed is compiled without dlopen\n"
       "  [--load LIB]              : loads a shared object (typically a plugin library)\n"
       "  [--standalone-executable] : tells plumed not to look for commands implemented as scripts\n"
diff --git a/src/function/Matheval.cpp b/src/function/Matheval.cpp
index a98b6bf48..64d112e14 100644
--- a/src/function/Matheval.cpp
+++ b/src/function/Matheval.cpp
@@ -22,10 +22,6 @@
 #include "ActionRegister.h"
 #include "Function.h"
 
-#ifdef __PLUMED_HAS_MATHEVAL
-#include <matheval.h>
-#endif
-
 #include "lepton/Lepton.h"
 
 using namespace std;
@@ -188,18 +184,14 @@ progression (S) and distance (Z) variables \cite perez2015atp.
 class Matheval :
   public Function
 {
-  const bool use_lepton;
   lepton::CompiledExpression expression;
   std::vector<lepton::CompiledExpression> expression_deriv;
-  void* evaluator;
-  vector<void*> evaluator_deriv;
   vector<string> var;
   string func;
   vector<double> values;
   vector<char*> names;
 public:
   explicit Matheval(const ActionOptions&);
-  ~Matheval();
   void calculate();
   static void registerKeywords(Keywords& keys);
 };
@@ -242,10 +234,7 @@ void Matheval::registerKeywords(Keywords& keys) {
 Matheval::Matheval(const ActionOptions&ao):
   Action(ao),
   Function(ao),
-  use_lepton(std::getenv("PLUMED_USE_LEPTON")),
   expression_deriv(getNumberOfArguments()),
-  evaluator(NULL),
-  evaluator_deriv(getNumberOfArguments(),NULL),
   values(getNumberOfArguments()),
   names(getNumberOfArguments())
 {
@@ -269,97 +258,42 @@ Matheval::Matheval(const ActionOptions&ao):
   for(unsigned i=0; i<var.size(); i++) log.printf(" %s",var[i].c_str());
   log.printf("\n");
 
-  if(use_lepton) {
-    log<<"  WARNING: you are using lepton as a replacement for libmatheval\n";
-    lepton::ParsedExpression pe=lepton::Parser::parse(func).optimize(leptonConstants);
-    log<<"  function as parsed by lepton: "<<pe<<"\n";
-    expression=pe.createCompiledExpression();
-    for(auto &p: expression.getVariables()) {
-      if(std::find(var.begin(),var.end(),p)==var.end()) {
-        error("variable " + p + " is not defined");
-      }
-    }
-    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);
-      log<<"    "<<pe<<"\n";
-      expression_deriv[i]=pe.createCompiledExpression();
+  lepton::ParsedExpression pe=lepton::Parser::parse(func).optimize(leptonConstants);
+  log<<"  function as parsed by lepton: "<<pe<<"\n";
+  expression=pe.createCompiledExpression();
+  for(auto &p: expression.getVariables()) {
+    if(std::find(var.begin(),var.end(),p)==var.end()) {
+      error("variable " + p + " is not defined");
     }
-  } else {
-#ifdef __PLUMED_HAS_MATHEVAL
-    evaluator=evaluator_create(const_cast<char*>(func.c_str()));
-    if(!evaluator) error("There was some problem in parsing matheval formula "+func);
-    char **check_names;
-    int    check_count;
-    evaluator_get_variables(evaluator,&check_names,&check_count);
-    if(check_count!=int(getNumberOfArguments())) {
-      string sc;
-      Tools::convert(check_count,sc);
-      error("Your function string contains "+sc+" arguments. This should be equal to the number of ARGs");
-    }
-    for(unsigned i=0; i<getNumberOfArguments(); i++) {
-      bool found=false;
-      for(unsigned j=0; j<getNumberOfArguments(); j++) {
-        if(var[i]==check_names[j])found=true;
-      }
-      if(!found)
-        error("Variable "+var[i]+" cannot be found in your function string");
-    }
-    for(unsigned i=0; i<getNumberOfArguments(); i++)
-      evaluator_deriv[i]=evaluator_derivative(evaluator,const_cast<char*>(var[i].c_str()));
-    log.printf("  function as parsed by matheval: %s\n", evaluator_get_string(evaluator));
-    log.printf("  derivatives as computed by matheval:\n");
-    for(unsigned i=0; i<var.size(); i++) log.printf("    %s\n",evaluator_get_string(evaluator_deriv[i]));
-#else
-    error("MATHEVAL not available, please export PLUMED_USE_LEPTON=yes");
-#endif
+  }
+  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);
+    log<<"    "<<pe<<"\n";
+    expression_deriv[i]=pe.createCompiledExpression();
   }
 }
 
 void Matheval::calculate() {
-  if(use_lepton) {
-    for(unsigned i=0; i<getNumberOfArguments(); i++) {
-      try {
-        expression.getVariableReference(var[i])=getArgument(i);
-      } catch(PLMD::lepton::Exception& exc) {
+  for(unsigned i=0; i<getNumberOfArguments(); i++) {
+    try {
+      expression.getVariableReference(var[i])=getArgument(i);
+    } catch(PLMD::lepton::Exception& exc) {
 // this is necessary since in some cases lepton things a variable is not present even though it is present
 // e.g. func=0*x
-      }
     }
-    setValue(expression.evaluate());
-    for(unsigned i=0; i<getNumberOfArguments(); i++) {
-      for(unsigned j=0; j<getNumberOfArguments(); j++) {
-        try {
-          expression_deriv[i].getVariableReference(var[j])=getArgument(j);
-        } catch(PLMD::lepton::Exception& exc) {
+  }
+  setValue(expression.evaluate());
+  for(unsigned i=0; i<getNumberOfArguments(); i++) {
+    for(unsigned j=0; j<getNumberOfArguments(); j++) {
+      try {
+        expression_deriv[i].getVariableReference(var[j])=getArgument(j);
+      } catch(PLMD::lepton::Exception& exc) {
 // this is necessary since in some cases lepton things a variable is not present even though it is present
 // e.g. func=0*x
-        }
       }
-      setDerivative(i,expression_deriv[i].evaluate());
     }
-  } else {
-#ifdef __PLUMED_HAS_MATHEVAL
-    for(unsigned i=0; i<getNumberOfArguments(); i++) values[i]=getArgument(i);
-    for(unsigned i=0; i<getNumberOfArguments(); i++) names[i]=const_cast<char*>(var[i].c_str());
-    setValue(evaluator_evaluate(evaluator,names.size(),&names[0],&values[0]));
-    for(unsigned i=0; i<getNumberOfArguments(); i++) {
-      setDerivative(i,evaluator_evaluate(evaluator_deriv[i],names.size(),&names[0],&values[0]));
-    }
-#else
-    error("MATHEVAL not available, please export PLUMED_USE_LEPTON=yes");
-#endif
-  }
-}
-
-Matheval::~Matheval() {
-  if(evaluator) {
-#ifdef __PLUMED_HAS_MATHEVAL
-    evaluator_destroy(evaluator);
-    for(unsigned i=0; i<evaluator_deriv.size(); i++)evaluator_destroy(evaluator_deriv[i]);
-#else
-    error("MATHEVAL not available, please export PLUMED_USE_LEPTON=yes");
-#endif
+    setDerivative(i,expression_deriv[i].evaluate());
   }
 }
 
diff --git a/src/tools/SwitchingFunction.cpp b/src/tools/SwitchingFunction.cpp
index a7df6332e..168d8452f 100644
--- a/src/tools/SwitchingFunction.cpp
+++ b/src/tools/SwitchingFunction.cpp
@@ -26,10 +26,6 @@
 #include <vector>
 #include <limits>
 
-#ifdef __PLUMED_HAS_MATHEVAL
-#include <matheval.h>
-#endif
-
 using namespace std;
 namespace PLMD {
 
@@ -253,7 +249,7 @@ void SwitchingFunction::set(const std::string & definition,std::string& errormsg
   else if(name=="GAUSSIAN") type=gaussian;
   else if(name=="CUBIC") type=cubic;
   else if(name=="TANH") type=tanh;
-  else if((name=="MATHEVAL" || name=="CUSTOM") && std::getenv("PLUMED_USE_LEPTON")) {
+  else if((name=="MATHEVAL" || name=="CUSTOM")) {
     type=leptontype;
     std::string func;
     Tools::parse(data,"FUNC",func);
@@ -265,34 +261,6 @@ void SwitchingFunction::set(const std::string & definition,std::string& errormsg
     expression_deriv.resize(OpenMP::getNumThreads());
     for(auto & e : expression_deriv) e=ped.createCompiledExpression();
   }
-#ifdef __PLUMED_HAS_MATHEVAL
-  else if(name=="MATHEVAL" || name=="CUSTOM") {
-    type=matheval;
-    std::string func;
-    Tools::parse(data,"FUNC",func);
-    const unsigned nt=OpenMP::getNumThreads();
-    plumed_assert(nt>0);
-    evaluator.resize(nt);
-    for(unsigned i=0; i<nt; i++) {
-      evaluator[i]=evaluator_create(const_cast<char*>(func.c_str()));
-    }
-    char **check_names;
-    int    check_count;
-    evaluator_get_variables(evaluator[0],&check_names,&check_count);
-    if(check_count!=1) {
-      errormsg="wrong number of arguments in MATHEVAL switching function";
-      return;
-    }
-    if(std::string(check_names[0])!="x") {
-      errormsg ="argument should be named 'x'";
-      return;
-    }
-    evaluator_deriv.resize(nt);
-    for(unsigned i=0; i<nt; i++) {
-      evaluator_deriv[i]=evaluator_derivative(evaluator[i],const_cast<char*>("x"));
-    }
-  }
-#endif
   else errormsg="cannot understand switching function type '"+name+"'";
   if( !data.empty() ) {
     errormsg="found the following rogue keywords in switching function input : ";
@@ -327,10 +295,6 @@ std::string SwitchingFunction::description() const {
     ostr<<"tanh";
   } else if(type==leptontype) {
     ostr<<"lepton";
-#ifdef __PLUMED_HAS_MATHEVAL
-  } else if(type==matheval) {
-    ostr<<"matheval";
-#endif
   } else {
     plumed_merror("Unknown switching function type");
   }
@@ -345,10 +309,6 @@ std::string SwitchingFunction::description() const {
     ostr<<" dmax="<<dmax;
   } else if(type==leptontype) {
     ostr<<" func="<<lepton_func;
-#ifdef __PLUMED_HAS_MATHEVAL
-  } else if(type==matheval) {
-    ostr<<" func="<<evaluator_get_string(evaluator[0]);
-#endif
 
   }
   return ostr.str();
@@ -449,12 +409,6 @@ double SwitchingFunction::calculate(double distance,double&dfunc)const {
       }
       result=expression[t].evaluate();
       dfunc=expression_deriv[t].evaluate();
-#ifdef __PLUMED_HAS_MATHEVAL
-    } else if(type==matheval) {
-      const unsigned it=OpenMP::getThreadNum();
-      result=evaluator_evaluate_x(evaluator[it],rdist);
-      dfunc=evaluator_evaluate_x(evaluator_deriv[it],rdist);
-#endif
     } else plumed_merror("Unknown switching function type");
 // this is for the chain rule:
     dfunc*=invr0;
@@ -511,18 +465,6 @@ SwitchingFunction::SwitchingFunction(const SwitchingFunction&sf):
   stretch(sf.stretch),
   shift(sf.shift)
 {
-#ifdef __PLUMED_HAS_MATHEVAL
-  if(sf.evaluator.size()>0) {
-    const unsigned nt=OpenMP::getNumThreads();
-    plumed_assert(nt>0);
-    evaluator.resize(nt);
-    evaluator_deriv.resize(nt);
-    for(unsigned i=0; i<nt; i++) {
-      evaluator[i]=evaluator_create(evaluator_get_string(sf.evaluator[0]));
-      evaluator_deriv[i]=evaluator_create(evaluator_get_string(sf.evaluator_deriv[0]));
-    }
-  }
-#endif
 }
 
 SwitchingFunction & SwitchingFunction::operator=(const SwitchingFunction& sf) {
@@ -545,18 +487,6 @@ SwitchingFunction & SwitchingFunction::operator=(const SwitchingFunction& sf) {
   dmax_2=sf.dmax_2;
   stretch=sf.stretch;
   shift=sf.shift;
-#ifdef __PLUMED_HAS_MATHEVAL
-  if(sf.evaluator.size()>0) {
-    const unsigned nt=OpenMP::getNumThreads();
-    plumed_assert(nt>0);
-    evaluator.resize(nt);
-    evaluator_deriv.resize(nt);
-    for(unsigned i=0; i<nt; i++) {
-      evaluator[i]=evaluator_create(evaluator_get_string(sf.evaluator[0]));
-      evaluator_deriv[i]=evaluator_create(evaluator_get_string(sf.evaluator_deriv[0]));
-    }
-  }
-#endif
   return *this;
 }
 
@@ -596,13 +526,6 @@ double SwitchingFunction::get_dmax2() const {
   return dmax_2;
 }
 
-SwitchingFunction::~SwitchingFunction() {
-#ifdef __PLUMED_HAS_MATHEVAL
-  for(unsigned i=0; i<evaluator.size(); i++) evaluator_destroy(evaluator[i]);
-  for(unsigned i=0; i<evaluator_deriv.size(); i++) evaluator_destroy(evaluator_deriv[i]);
-#endif
-}
-
 
 }
 
diff --git a/src/tools/SwitchingFunction.h b/src/tools/SwitchingFunction.h
index 65c90e711..1536b786e 100644
--- a/src/tools/SwitchingFunction.h
+++ b/src/tools/SwitchingFunction.h
@@ -75,20 +75,10 @@ class SwitchingFunction {
 /// Lepton expression for derivative
 /// \warning Since lepton::CompiledExpression is mutable, a vector is necessary for multithreading!
   std::vector<lepton::CompiledExpression> expression_deriv;
-/// Evaluator for matheval:
-/// \warning Since evaluator is not thread safe, we should create one
-/// evaluator per thread.
-  std::vector<void*> evaluator;
-/// Evaluator for matheval:
-/// \warning Since evaluator is not thread safe, we should create one
-/// evaluator per thread.
-  std::vector<void*> evaluator_deriv;
 public:
   static void registerKeywords( Keywords& keys );
 /// Constructor
   SwitchingFunction();
-/// Destructor
-  ~SwitchingFunction();
 /// Copy constructor
   SwitchingFunction(const SwitchingFunction&);
 /// Assignment operator
-- 
GitLab