Upgrade Lepton library to version 2019-06-02
This commit is contained in:
@ -50,6 +50,9 @@ settings in Makefile.common should work.
|
|||||||
Note: some Colvars functions use the Lepton mathematical expression parser,
|
Note: some Colvars functions use the Lepton mathematical expression parser,
|
||||||
which is here included (no additional steps required). For more details, see:
|
which is here included (no additional steps required). For more details, see:
|
||||||
https://simtk.org/projects/lepton
|
https://simtk.org/projects/lepton
|
||||||
|
Starting from 2019-06-02, Lepton requires C++11. Please see:
|
||||||
|
https://colvars.github.io/README-c++11.html
|
||||||
|
https://lammps.sandia.gov/doc/Build_settings.html#cxx11
|
||||||
|
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
* Biological Structures at Stanford, funded under the NIH Roadmap for *
|
* Biological Structures at Stanford, funded under the NIH Roadmap for *
|
||||||
* Medical Research, grant U54 GM072970. See https://simtk.org. *
|
* Medical Research, grant U54 GM072970. See https://simtk.org. *
|
||||||
* *
|
* *
|
||||||
* Portions copyright (c) 2013-2016 Stanford University and the Authors. *
|
* Portions copyright (c) 2013-2019 Stanford University and the Authors. *
|
||||||
* Authors: Peter Eastman *
|
* Authors: Peter Eastman *
|
||||||
* Contributors: *
|
* Contributors: *
|
||||||
* *
|
* *
|
||||||
@ -99,10 +99,11 @@ private:
|
|||||||
mutable std::vector<double> workspace;
|
mutable std::vector<double> workspace;
|
||||||
mutable std::vector<double> argValues;
|
mutable std::vector<double> argValues;
|
||||||
std::map<std::string, double> dummyVariables;
|
std::map<std::string, double> dummyVariables;
|
||||||
void* jitCode;
|
double (*jitCode)();
|
||||||
#ifdef LEPTON_USE_JIT
|
#ifdef LEPTON_USE_JIT
|
||||||
void generateJitCode();
|
void generateJitCode();
|
||||||
void generateSingleArgCall(asmjit::X86Compiler& c, asmjit::X86XmmVar& dest, asmjit::X86XmmVar& arg, double (*function)(double));
|
void generateSingleArgCall(asmjit::X86Compiler& c, asmjit::X86Xmm& dest, asmjit::X86Xmm& arg, double (*function)(double));
|
||||||
|
void generateTwoArgCall(asmjit::X86Compiler& c, asmjit::X86Xmm& dest, asmjit::X86Xmm& arg1, asmjit::X86Xmm& arg2, double (*function)(double, double));
|
||||||
std::vector<double> constants;
|
std::vector<double> constants;
|
||||||
asmjit::JitRuntime runtime;
|
asmjit::JitRuntime runtime;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -72,6 +72,38 @@ public:
|
|||||||
virtual CustomFunction* clone() const = 0;
|
virtual CustomFunction* clone() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is an implementation of CustomFunction that does no computation. It just returns
|
||||||
|
* 0 for the value and derivatives. This is useful when using the parser to analyze expressions
|
||||||
|
* rather than to evaluate them. You can just create PlaceholderFunctions to represent any custom
|
||||||
|
* functions that may appear in expressions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class LEPTON_EXPORT PlaceholderFunction : public CustomFunction {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Create a Placeholder function.
|
||||||
|
*
|
||||||
|
* @param numArgs the number of arguments the function expects
|
||||||
|
*/
|
||||||
|
PlaceholderFunction(int numArgs) : numArgs(numArgs) {
|
||||||
|
}
|
||||||
|
int getNumArguments() const {
|
||||||
|
return numArgs;
|
||||||
|
}
|
||||||
|
double evaluate(const double* arguments) const {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
double evaluateDerivative(const double* arguments, const int* derivOrder) const {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
CustomFunction* clone() const {
|
||||||
|
return new PlaceholderFunction(numArgs);
|
||||||
|
};
|
||||||
|
private:
|
||||||
|
int numArgs;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace Lepton
|
} // namespace Lepton
|
||||||
|
|
||||||
#endif /*LEPTON_CUSTOM_FUNCTION_H_*/
|
#endif /*LEPTON_CUSTOM_FUNCTION_H_*/
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
* Biological Structures at Stanford, funded under the NIH Roadmap for *
|
* Biological Structures at Stanford, funded under the NIH Roadmap for *
|
||||||
* Medical Research, grant U54 GM072970. See https://simtk.org. *
|
* Medical Research, grant U54 GM072970. See https://simtk.org. *
|
||||||
* *
|
* *
|
||||||
* Portions copyright (c) 2009 Stanford University and the Authors. *
|
* Portions copyright (c) 2009-2018 Stanford University and the Authors. *
|
||||||
* Authors: Peter Eastman *
|
* Authors: Peter Eastman *
|
||||||
* Contributors: *
|
* Contributors: *
|
||||||
* *
|
* *
|
||||||
@ -65,6 +65,14 @@ public:
|
|||||||
* Get an Operation in this program.
|
* Get an Operation in this program.
|
||||||
*/
|
*/
|
||||||
const Operation& getOperation(int index) const;
|
const Operation& getOperation(int index) const;
|
||||||
|
/**
|
||||||
|
* Change an Operation in this program.
|
||||||
|
*
|
||||||
|
* The Operation must have been allocated on the heap with the "new" operator.
|
||||||
|
* The ExpressionProgram assumes ownership of it and will delete it when it
|
||||||
|
* is no longer needed.
|
||||||
|
*/
|
||||||
|
void setOperation(int index, Operation* operation);
|
||||||
/**
|
/**
|
||||||
* Get the size of the stack needed to execute this program. This is the largest number of elements present
|
* Get the size of the stack needed to execute this program. This is the largest number of elements present
|
||||||
* on the stack at any point during evaluation.
|
* on the stack at any point during evaluation.
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
* Biological Structures at Stanford, funded under the NIH Roadmap for *
|
* Biological Structures at Stanford, funded under the NIH Roadmap for *
|
||||||
* Medical Research, grant U54 GM072970. See https://simtk.org. *
|
* Medical Research, grant U54 GM072970. See https://simtk.org. *
|
||||||
* *
|
* *
|
||||||
* Portions copyright (c) 2009-2015 Stanford University and the Authors. *
|
* Portions copyright (c) 2009-2019 Stanford University and the Authors. *
|
||||||
* Authors: Peter Eastman *
|
* Authors: Peter Eastman *
|
||||||
* Contributors: *
|
* Contributors: *
|
||||||
* *
|
* *
|
||||||
@ -63,7 +63,7 @@ public:
|
|||||||
* can be used when processing or analyzing parsed expressions.
|
* can be used when processing or analyzing parsed expressions.
|
||||||
*/
|
*/
|
||||||
enum Id {CONSTANT, VARIABLE, CUSTOM, ADD, SUBTRACT, MULTIPLY, DIVIDE, POWER, NEGATE, SQRT, EXP, LOG,
|
enum Id {CONSTANT, VARIABLE, CUSTOM, ADD, SUBTRACT, MULTIPLY, DIVIDE, POWER, NEGATE, SQRT, EXP, LOG,
|
||||||
SIN, COS, SEC, CSC, TAN, COT, ASIN, ACOS, ATAN, SINH, COSH, TANH, ERF, ERFC, STEP, DELTA, SQUARE, CUBE, RECIPROCAL,
|
SIN, COS, SEC, CSC, TAN, COT, ASIN, ACOS, ATAN, ATAN2, SINH, COSH, TANH, ERF, ERFC, STEP, DELTA, SQUARE, CUBE, RECIPROCAL,
|
||||||
ADD_CONSTANT, MULTIPLY_CONSTANT, POWER_CONSTANT, MIN, MAX, ABS, FLOOR, CEIL, SELECT};
|
ADD_CONSTANT, MULTIPLY_CONSTANT, POWER_CONSTANT, MIN, MAX, ABS, FLOOR, CEIL, SELECT};
|
||||||
/**
|
/**
|
||||||
* Get the name of this Operation.
|
* Get the name of this Operation.
|
||||||
@ -137,6 +137,7 @@ public:
|
|||||||
class Asin;
|
class Asin;
|
||||||
class Acos;
|
class Acos;
|
||||||
class Atan;
|
class Atan;
|
||||||
|
class Atan2;
|
||||||
class Sinh;
|
class Sinh;
|
||||||
class Cosh;
|
class Cosh;
|
||||||
class Tanh;
|
class Tanh;
|
||||||
@ -226,6 +227,11 @@ class LEPTON_EXPORT Operation::Custom : public Operation {
|
|||||||
public:
|
public:
|
||||||
Custom(const std::string& name, CustomFunction* function) : name(name), function(function), isDerivative(false), derivOrder(function->getNumArguments(), 0) {
|
Custom(const std::string& name, CustomFunction* function) : name(name), function(function), isDerivative(false), derivOrder(function->getNumArguments(), 0) {
|
||||||
}
|
}
|
||||||
|
Custom(const std::string& name, CustomFunction* function, const std::vector<int>& derivOrder) : name(name), function(function), isDerivative(false), derivOrder(derivOrder) {
|
||||||
|
for (int order : derivOrder)
|
||||||
|
if (order != 0)
|
||||||
|
isDerivative = true;
|
||||||
|
}
|
||||||
Custom(const Custom& base, int derivIndex) : name(base.name), function(base.function->clone()), isDerivative(true), derivOrder(base.derivOrder) {
|
Custom(const Custom& base, int derivIndex) : name(base.name), function(base.function->clone()), isDerivative(true), derivOrder(base.derivOrder) {
|
||||||
derivOrder[derivIndex]++;
|
derivOrder[derivIndex]++;
|
||||||
}
|
}
|
||||||
@ -684,6 +690,28 @@ public:
|
|||||||
ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
|
ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class LEPTON_EXPORT Operation::Atan2 : public Operation {
|
||||||
|
public:
|
||||||
|
Atan2() {
|
||||||
|
}
|
||||||
|
std::string getName() const {
|
||||||
|
return "atan2";
|
||||||
|
}
|
||||||
|
Id getId() const {
|
||||||
|
return ATAN2;
|
||||||
|
}
|
||||||
|
int getNumArguments() const {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
Operation* clone() const {
|
||||||
|
return new Atan2();
|
||||||
|
}
|
||||||
|
double evaluate(double* args, const std::map<std::string, double>& variables) const {
|
||||||
|
return std::atan2(args[0], args[1]);
|
||||||
|
}
|
||||||
|
ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
|
||||||
|
};
|
||||||
|
|
||||||
class LEPTON_EXPORT Operation::Sinh : public Operation {
|
class LEPTON_EXPORT Operation::Sinh : public Operation {
|
||||||
public:
|
public:
|
||||||
Sinh() {
|
Sinh() {
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
* Biological Structures at Stanford, funded under the NIH Roadmap for *
|
* Biological Structures at Stanford, funded under the NIH Roadmap for *
|
||||||
* Medical Research, grant U54 GM072970. See https://simtk.org. *
|
* Medical Research, grant U54 GM072970. See https://simtk.org. *
|
||||||
* *
|
* *
|
||||||
* Portions copyright (c) 2013-2016 Stanford University and the Authors. *
|
* Portions copyright (c) 2013-2019 Stanford University and the Authors. *
|
||||||
* Authors: Peter Eastman *
|
* Authors: Peter Eastman *
|
||||||
* Contributors: *
|
* Contributors: *
|
||||||
* *
|
* *
|
||||||
@ -165,7 +165,7 @@ void CompiledExpression::setVariableLocations(map<string, double*>& variableLoca
|
|||||||
|
|
||||||
double CompiledExpression::evaluate() const {
|
double CompiledExpression::evaluate() const {
|
||||||
#ifdef LEPTON_USE_JIT
|
#ifdef LEPTON_USE_JIT
|
||||||
return ((double (*)()) jitCode)();
|
return jitCode();
|
||||||
#else
|
#else
|
||||||
for (int i = 0; i < variablesToCopy.size(); i++)
|
for (int i = 0; i < variablesToCopy.size(); i++)
|
||||||
*variablesToCopy[i].first = *variablesToCopy[i].second;
|
*variablesToCopy[i].first = *variablesToCopy[i].second;
|
||||||
@ -188,24 +188,26 @@ double CompiledExpression::evaluate() const {
|
|||||||
|
|
||||||
#ifdef LEPTON_USE_JIT
|
#ifdef LEPTON_USE_JIT
|
||||||
static double evaluateOperation(Operation* op, double* args) {
|
static double evaluateOperation(Operation* op, double* args) {
|
||||||
map<string, double>* dummyVariables = NULL;
|
static map<string, double> dummyVariables;
|
||||||
return op->evaluate(args, *dummyVariables);
|
return op->evaluate(args, dummyVariables);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompiledExpression::generateJitCode() {
|
void CompiledExpression::generateJitCode() {
|
||||||
X86Compiler c(&runtime);
|
CodeHolder code;
|
||||||
c.addFunc(kFuncConvHost, FuncBuilder0<double>());
|
code.init(runtime.getCodeInfo());
|
||||||
vector<X86XmmVar> workspaceVar(workspace.size());
|
X86Compiler c(&code);
|
||||||
|
c.addFunc(FuncSignature0<double>());
|
||||||
|
vector<X86Xmm> workspaceVar(workspace.size());
|
||||||
for (int i = 0; i < (int) workspaceVar.size(); i++)
|
for (int i = 0; i < (int) workspaceVar.size(); i++)
|
||||||
workspaceVar[i] = c.newXmmVar(kX86VarTypeXmmSd);
|
workspaceVar[i] = c.newXmmSd();
|
||||||
X86GpVar argsPointer(c);
|
X86Gp argsPointer = c.newIntPtr();
|
||||||
c.mov(argsPointer, imm_ptr(&argValues[0]));
|
c.mov(argsPointer, imm_ptr(&argValues[0]));
|
||||||
|
|
||||||
// Load the arguments into variables.
|
// Load the arguments into variables.
|
||||||
|
|
||||||
for (set<string>::const_iterator iter = variableNames.begin(); iter != variableNames.end(); ++iter) {
|
for (set<string>::const_iterator iter = variableNames.begin(); iter != variableNames.end(); ++iter) {
|
||||||
map<string, int>::iterator index = variableIndices.find(*iter);
|
map<string, int>::iterator index = variableIndices.find(*iter);
|
||||||
X86GpVar variablePointer(c);
|
X86Gp variablePointer = c.newIntPtr();
|
||||||
c.mov(variablePointer, imm_ptr(&getVariableReference(index->first)));
|
c.mov(variablePointer, imm_ptr(&getVariableReference(index->first)));
|
||||||
c.movsd(workspaceVar[index->second], x86::ptr(variablePointer, 0, 0));
|
c.movsd(workspaceVar[index->second], x86::ptr(variablePointer, 0, 0));
|
||||||
}
|
}
|
||||||
@ -248,12 +250,12 @@ void CompiledExpression::generateJitCode() {
|
|||||||
|
|
||||||
// Load constants into variables.
|
// Load constants into variables.
|
||||||
|
|
||||||
vector<X86XmmVar> constantVar(constants.size());
|
vector<X86Xmm> constantVar(constants.size());
|
||||||
if (constants.size() > 0) {
|
if (constants.size() > 0) {
|
||||||
X86GpVar constantsPointer(c);
|
X86Gp constantsPointer = c.newIntPtr();
|
||||||
c.mov(constantsPointer, imm_ptr(&constants[0]));
|
c.mov(constantsPointer, imm_ptr(&constants[0]));
|
||||||
for (int i = 0; i < (int) constants.size(); i++) {
|
for (int i = 0; i < (int) constants.size(); i++) {
|
||||||
constantVar[i] = c.newXmmVar(kX86VarTypeXmmSd);
|
constantVar[i] = c.newXmmSd();
|
||||||
c.movsd(constantVar[i], x86::ptr(constantsPointer, 8*i, 0));
|
c.movsd(constantVar[i], x86::ptr(constantsPointer, 8*i, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -292,6 +294,9 @@ void CompiledExpression::generateJitCode() {
|
|||||||
c.movsd(workspaceVar[target[step]], workspaceVar[args[0]]);
|
c.movsd(workspaceVar[target[step]], workspaceVar[args[0]]);
|
||||||
c.divsd(workspaceVar[target[step]], workspaceVar[args[1]]);
|
c.divsd(workspaceVar[target[step]], workspaceVar[args[1]]);
|
||||||
break;
|
break;
|
||||||
|
case Operation::POWER:
|
||||||
|
generateTwoArgCall(c, workspaceVar[target[step]], workspaceVar[args[0]], workspaceVar[args[1]], pow);
|
||||||
|
break;
|
||||||
case Operation::NEGATE:
|
case Operation::NEGATE:
|
||||||
c.xorps(workspaceVar[target[step]], workspaceVar[target[step]]);
|
c.xorps(workspaceVar[target[step]], workspaceVar[target[step]]);
|
||||||
c.subsd(workspaceVar[target[step]], workspaceVar[args[0]]);
|
c.subsd(workspaceVar[target[step]], workspaceVar[args[0]]);
|
||||||
@ -323,6 +328,9 @@ void CompiledExpression::generateJitCode() {
|
|||||||
case Operation::ATAN:
|
case Operation::ATAN:
|
||||||
generateSingleArgCall(c, workspaceVar[target[step]], workspaceVar[args[0]], atan);
|
generateSingleArgCall(c, workspaceVar[target[step]], workspaceVar[args[0]], atan);
|
||||||
break;
|
break;
|
||||||
|
case Operation::ATAN2:
|
||||||
|
generateTwoArgCall(c, workspaceVar[target[step]], workspaceVar[args[0]], workspaceVar[args[1]], atan2);
|
||||||
|
break;
|
||||||
case Operation::SINH:
|
case Operation::SINH:
|
||||||
generateSingleArgCall(c, workspaceVar[target[step]], workspaceVar[args[0]], sinh);
|
generateSingleArgCall(c, workspaceVar[target[step]], workspaceVar[args[0]], sinh);
|
||||||
break;
|
break;
|
||||||
@ -377,9 +385,9 @@ void CompiledExpression::generateJitCode() {
|
|||||||
|
|
||||||
for (int i = 0; i < (int) args.size(); i++)
|
for (int i = 0; i < (int) args.size(); i++)
|
||||||
c.movsd(x86::ptr(argsPointer, 8*i, 0), workspaceVar[args[i]]);
|
c.movsd(x86::ptr(argsPointer, 8*i, 0), workspaceVar[args[i]]);
|
||||||
X86GpVar fn(c, kVarTypeIntPtr);
|
X86Gp fn = c.newIntPtr();
|
||||||
c.mov(fn, imm_ptr((void*) evaluateOperation));
|
c.mov(fn, imm_ptr((void*) evaluateOperation));
|
||||||
X86CallNode* call = c.call(fn, kFuncConvHost, FuncBuilder2<double, Operation*, double*>());
|
CCFuncCall* call = c.call(fn, FuncSignature2<double, Operation*, double*>());
|
||||||
call->setArg(0, imm_ptr(&op));
|
call->setArg(0, imm_ptr(&op));
|
||||||
call->setArg(1, imm_ptr(&argValues[0]));
|
call->setArg(1, imm_ptr(&argValues[0]));
|
||||||
call->setRet(0, workspaceVar[target[step]]);
|
call->setRet(0, workspaceVar[target[step]]);
|
||||||
@ -387,14 +395,24 @@ void CompiledExpression::generateJitCode() {
|
|||||||
}
|
}
|
||||||
c.ret(workspaceVar[workspace.size()-1]);
|
c.ret(workspaceVar[workspace.size()-1]);
|
||||||
c.endFunc();
|
c.endFunc();
|
||||||
jitCode = c.make();
|
c.finalize();
|
||||||
|
runtime.add(&jitCode, &code);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompiledExpression::generateSingleArgCall(X86Compiler& c, X86XmmVar& dest, X86XmmVar& arg, double (*function)(double)) {
|
void CompiledExpression::generateSingleArgCall(X86Compiler& c, X86Xmm& dest, X86Xmm& arg, double (*function)(double)) {
|
||||||
X86GpVar fn(c, kVarTypeIntPtr);
|
X86Gp fn = c.newIntPtr();
|
||||||
c.mov(fn, imm_ptr((void*) function));
|
c.mov(fn, imm_ptr((void*) function));
|
||||||
X86CallNode* call = c.call(fn, kFuncConvHost, FuncBuilder1<double, double>());
|
CCFuncCall* call = c.call(fn, FuncSignature1<double, double>());
|
||||||
call->setArg(0, arg);
|
call->setArg(0, arg);
|
||||||
call->setRet(0, dest);
|
call->setRet(0, dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CompiledExpression::generateTwoArgCall(X86Compiler& c, X86Xmm& dest, X86Xmm& arg1, X86Xmm& arg2, double (*function)(double, double)) {
|
||||||
|
X86Gp fn = c.newIntPtr();
|
||||||
|
c.mov(fn, imm_ptr((void*) function));
|
||||||
|
CCFuncCall* call = c.call(fn, FuncSignature2<double, double, double>());
|
||||||
|
call->setArg(0, arg1);
|
||||||
|
call->setArg(1, arg2);
|
||||||
|
call->setRet(0, dest);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
* Biological Structures at Stanford, funded under the NIH Roadmap for *
|
* Biological Structures at Stanford, funded under the NIH Roadmap for *
|
||||||
* Medical Research, grant U54 GM072970. See https://simtk.org. *
|
* Medical Research, grant U54 GM072970. See https://simtk.org. *
|
||||||
* *
|
* *
|
||||||
* Portions copyright (c) 2009-2013 Stanford University and the Authors. *
|
* Portions copyright (c) 2009-2018 Stanford University and the Authors. *
|
||||||
* Authors: Peter Eastman *
|
* Authors: Peter Eastman *
|
||||||
* Contributors: *
|
* Contributors: *
|
||||||
* *
|
* *
|
||||||
@ -84,6 +84,11 @@ const Operation& ExpressionProgram::getOperation(int index) const {
|
|||||||
return *operations[index];
|
return *operations[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ExpressionProgram::setOperation(int index, Operation* operation) {
|
||||||
|
delete operations[index];
|
||||||
|
operations[index] = operation;
|
||||||
|
}
|
||||||
|
|
||||||
int ExpressionProgram::getStackSize() const {
|
int ExpressionProgram::getStackSize() const {
|
||||||
return stackSize;
|
return stackSize;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
* Biological Structures at Stanford, funded under the NIH Roadmap for *
|
* Biological Structures at Stanford, funded under the NIH Roadmap for *
|
||||||
* Medical Research, grant U54 GM072970. See https://simtk.org. *
|
* Medical Research, grant U54 GM072970. See https://simtk.org. *
|
||||||
* *
|
* *
|
||||||
* Portions copyright (c) 2009-2015 Stanford University and the Authors. *
|
* Portions copyright (c) 2009-2019 Stanford University and the Authors. *
|
||||||
* Authors: Peter Eastman *
|
* Authors: Peter Eastman *
|
||||||
* Contributors: *
|
* Contributors: *
|
||||||
* *
|
* *
|
||||||
@ -202,6 +202,16 @@ ExpressionTreeNode Operation::Atan::differentiate(const std::vector<ExpressionTr
|
|||||||
childDerivs[0]);
|
childDerivs[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExpressionTreeNode Operation::Atan2::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
|
||||||
|
return ExpressionTreeNode(new Operation::Divide(),
|
||||||
|
ExpressionTreeNode(new Operation::Subtract(),
|
||||||
|
ExpressionTreeNode(new Operation::Multiply(), children[1], childDerivs[0]),
|
||||||
|
ExpressionTreeNode(new Operation::Multiply(), children[0], childDerivs[1])),
|
||||||
|
ExpressionTreeNode(new Operation::Add(),
|
||||||
|
ExpressionTreeNode(new Operation::Square(), children[0]),
|
||||||
|
ExpressionTreeNode(new Operation::Square(), children[1])));
|
||||||
|
}
|
||||||
|
|
||||||
ExpressionTreeNode Operation::Sinh::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
|
ExpressionTreeNode Operation::Sinh::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
|
||||||
return ExpressionTreeNode(new Operation::Multiply(),
|
return ExpressionTreeNode(new Operation::Multiply(),
|
||||||
ExpressionTreeNode(new Operation::Cosh(),
|
ExpressionTreeNode(new Operation::Cosh(),
|
||||||
|
|||||||
@ -271,6 +271,16 @@ ExpressionTreeNode ParsedExpression::substituteSimplerExpression(const Expressio
|
|||||||
return ExpressionTreeNode(new Operation::MultiplyConstant(-dynamic_cast<const Operation::MultiplyConstant*>(&node.getOperation())->getValue()), children[0].getChildren()[0]);
|
return ExpressionTreeNode(new Operation::MultiplyConstant(-dynamic_cast<const Operation::MultiplyConstant*>(&node.getOperation())->getValue()), children[0].getChildren()[0]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case Operation::SQRT:
|
||||||
|
{
|
||||||
|
if (children[0].getOperation().getId() == Operation::SQUARE) // sqrt(square(x)) = abs(x)
|
||||||
|
return ExpressionTreeNode(new Operation::Abs(), children[0].getChildren()[0]);
|
||||||
|
}
|
||||||
|
case Operation::SQUARE:
|
||||||
|
{
|
||||||
|
if (children[0].getOperation().getId() == Operation::SQRT) // square(sqrt(x)) = x
|
||||||
|
return children[0].getChildren()[0];
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
// If operation ID is not one of the above,
|
// If operation ID is not one of the above,
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
* Biological Structures at Stanford, funded under the NIH Roadmap for *
|
* Biological Structures at Stanford, funded under the NIH Roadmap for *
|
||||||
* Medical Research, grant U54 GM072970. See https://simtk.org. *
|
* Medical Research, grant U54 GM072970. See https://simtk.org. *
|
||||||
* *
|
* *
|
||||||
* Portions copyright (c) 2009-2015 Stanford University and the Authors. *
|
* Portions copyright (c) 2009-2019 Stanford University and the Authors. *
|
||||||
* Authors: Peter Eastman *
|
* Authors: Peter Eastman *
|
||||||
* Contributors: *
|
* Contributors: *
|
||||||
* *
|
* *
|
||||||
@ -313,6 +313,7 @@ Operation* Parser::getFunctionOperation(const std::string& name, const map<strin
|
|||||||
opMap["asin"] = Operation::ASIN;
|
opMap["asin"] = Operation::ASIN;
|
||||||
opMap["acos"] = Operation::ACOS;
|
opMap["acos"] = Operation::ACOS;
|
||||||
opMap["atan"] = Operation::ATAN;
|
opMap["atan"] = Operation::ATAN;
|
||||||
|
opMap["atan2"] = Operation::ATAN2;
|
||||||
opMap["sinh"] = Operation::SINH;
|
opMap["sinh"] = Operation::SINH;
|
||||||
opMap["cosh"] = Operation::COSH;
|
opMap["cosh"] = Operation::COSH;
|
||||||
opMap["tanh"] = Operation::TANH;
|
opMap["tanh"] = Operation::TANH;
|
||||||
@ -368,6 +369,8 @@ Operation* Parser::getFunctionOperation(const std::string& name, const map<strin
|
|||||||
return new Operation::Acos();
|
return new Operation::Acos();
|
||||||
case Operation::ATAN:
|
case Operation::ATAN:
|
||||||
return new Operation::Atan();
|
return new Operation::Atan();
|
||||||
|
case Operation::ATAN2:
|
||||||
|
return new Operation::Atan2();
|
||||||
case Operation::SINH:
|
case Operation::SINH:
|
||||||
return new Operation::Sinh();
|
return new Operation::Sinh();
|
||||||
case Operation::COSH:
|
case Operation::COSH:
|
||||||
|
|||||||
Reference in New Issue
Block a user