I'm attempting to write a class that solves a system of nonlinear equations (a root finder). For this, I've written a class that encapsulates all the internal functions needed, as well as the system to solve: a function that takes an Eigen vector and returns an Eigen. The public newt
member function takes an Eigen vector (the initial guess), runs the algorithm with that initial guess, and returns the Eigen vector r
such that func(r) = {0, 0, ..., 0}
. I've written the functions as prescribed here: writing template functions that take instantiations of MatrixBase
.
The way I've handled taking an arbitrary function to solve was to implement a base class and then have the user extend it, defining func
, the function to solve. The class I have is
class Newt {
private:
template<typename TR, typename T1, typename T2, typename T3>
tuple<TR,bool> lnsrch(const MatrixBase<T1> &xold, const double fold, const MatrixBase<T2> &g, MatrixBase<T3> &p, const double stepmax);
template <typename TR, typename T1, typename T2>
TR fdjac(const MatrixBase<T1> &x, const MatrixBase<T2> &fvec);
public:
template <typename TR, typename T1>
TR func(const MatrixBase<T1>&);
template <typename TR, typename T1>
tuple<TR,bool> newt(const MatrixBase<T1> &xx);
};
The user then inherits from Newt and overrides the func
method to the desired function to solve:
struct NewtD : public Newt
{
template <typename T1, typename T2>
T1 func(const MatrixBase<T2> &z) {
// Content
}
};
Then he instantiates it and calls the newt member function. However, when I compile this with the following test case:
struct Newt3 : public Newt
{
template <typename T1, typename T2>
T1 func(const MatrixBase<T2> &x) {
return (Vectord<3>() <<
z(0),
z(1)*z(2),
pow(z(2)-1,2)
).finished();
}
};
int main() {
Newt3 solver3;
bool check;
tie(X,check) = solver3.newt<Vectord<3>>(X);
}
I get the following linker error, when compiling with g++ 6.2.0
undefined reference to `std::tuple<Eigen::Matrix<double, 3, 1, 0, 3, 1>, bool> Newt::newt<Eigen::Matrix<double, 3, 1, 0, 3, 1>, Eigen::Matrix<double, 3, 1, 0, 3, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> > const&)'
It seems it can't find newt
? I have no idea why this is, the signature in the error seems to match my code, everything seems okay. Any idea how to solve this?
PS: Oh yeah, I forgot: Vectord<N>
is a shortcut template type simply defined as
template<size_t N>
using Vectord = Matrix<double, N, 1, 0>;
PPS: The implementation is in a separate file. I didn't include it because it's quite big, but bottom-line is every function is defined there, including Newt::newt
template <typename TR, typename T1>
tuple<TR,bool> Newt::newt(const MatrixBase<T1> &xx) {
// Body
}