1#ifndef _FMATVEC_CHECKDERIVATIVE_H_
2#define _FMATVEC_CHECKDERIVATIVE_H_
8#include <fmatvec/linear_algebra.h>
12 #define FMATVEC_CHECKDERIVATIVE_MEMBERFUNC(func, anaDiff, value, ...) \
13 fmatvec::checkDerivative(this, std::string(__FILE__)+":"+std::to_string(__LINE__)+":"+#anaDiff, func, anaDiff, value,
__VA_ARGS__)
14 #define FMATVEC_CHECKDERIVATIVE_GLOBALFUNC(func, anaDiff, value, ...) \
15 fmatvec::checkDerivative(nullptr, std::string(__FILE__)+":"+std::to_string(__LINE__)+":"+#anaDiff, func, anaDiff, value,
__VA_ARGS__)
27 void checkDerivative(
const void *idPtr,
const std::string &idName,
const std::function<
void(
double)> &func,
const Value &anaDiff,
const Value &value,
double indep,
double eps=1e-6,
double delta=1e-8) {
29 #error "fmatvec::checkDerivative should not be active for release builds"
32 static int distributedCount = 0;
33 static std::map<std::pair<const void*, std::string>, std::pair<bool, Value>> ele;
35 auto &[disturbed, disturbedValue] = ele.emplace(std::make_pair(idPtr, idName), std::make_pair(
false, Value())).first->second;
39 if constexpr (std::is_same_v<Value, double>)
40 disturbedValue = value;
42 disturbedValue <<= value;
44 else if(distributedCount == 0) {
45 std::array<Value, 2> disturbedValueRightLeft;
53 if constexpr (std::is_same_v<Value, double>)
54 disturbedValueRightLeft[0] = disturbedValue;
56 disturbedValueRightLeft[0] <<= disturbedValue;
60 if constexpr (std::is_same_v<Value, double>)
61 disturbedValueRightLeft[1] = disturbedValue;
63 disturbedValueRightLeft[1] <<= disturbedValue;
71 std::array<double, 2> dist;
72 std::array<Value, 2> finiteDiffRightLeft;
73 for(
int i=0; i<2; ++i) {
74 if constexpr (std::is_same_v<Value, double>)
75 finiteDiffRightLeft[i] = (i==0?1.0:-1.0) * (disturbedValueRightLeft[i] - value)/delta;
77 finiteDiffRightLeft[i] <<= (i==0?1.0:-1.0) * (disturbedValueRightLeft[i] - value)/delta;
79 if constexpr (std::is_same_v<Value, double>)
80 dist[i] = std::abs(finiteDiffRightLeft[i] - anaDiff);
81 else if constexpr (Value::isVector)
82 dist[i] = fmatvec::nrmInf(finiteDiffRightLeft[i] - anaDiff);
85 for(
int c=0; c<anaDiff.cols(); c++)
86 dist[i] = std::max(dist[i], fmatvec::nrm2(finiteDiffRightLeft[i].col(c) - anaDiff.col(c)));
91 double dist0 = dist[0];
92 double dist1 = dist[1];
93 if(dist0 > eps && dist1 > eps) {
94 std::stringstream str;
95 str<<
"checkDerivative failed in "<<idPtr<<
": ID = "<<idName<<
":"<<std::endl
96 <<
"- anaDiff = "<<anaDiff<<std::endl
97 <<
"- finiteDiffRight = "<<finiteDiffRightLeft[0]<<std::endl
98 <<
"- finiteDiffLeft = "<<finiteDiffRightLeft[1]<<std::endl
99 <<
"- indep = "<<indep<<std::endl
100 <<
"- nrmInf (right/left) = "<<dist[0]<<
" "<<dist[1];
102 std::cerr<<str.str()<<std::endl;
104 throw std::runtime_error(str.str());
Namespace fmatvec.
Definition: _memory.cc:28