#include <complex>
#include <cmath>
#include <iostream>

#include "zerosolver.hpp"  // definitions of the solver functions

/********************************************************************/
// The definition of the function: f(z) = exp(3*z) + 2*z*cos(z) - 1

template <typename T> std::complex<T> f (const std::complex<T> & z, void * p)
{
return std::exp(3.0*z) + 2.0 * z * std::cos(z) - 1.0;
}

/********************************************************************/
// The definition of the function derivative: f'(z) = 3*exp(3*z) + 2*cos(z) - 2*z*sin(z)

template <typename T> std::complex<T> df (const std::complex<T> & z, void * p)
{
return 3.0 * std::exp(3.0*z) + 2.0 * std::cos(z) - 2.0 * z * std::sin(z);
}

/********************************************************************/

int main (int argc, char ** argv)
{
type::Function<double> F(f, df);            // define the complex function object (with double precision)

type::Box<double> B(-2.0, 2.0, -2.0, 3.0);  // define the rectangular region (box) in the complex plane (xmin, xmax, ymin, ymax)

alg::zersol::Settings<double> S;            // define the default solver setings

alg::zersol::ZeroSolver<double> solver(F, B, S);  // define the solver with the specified F, B, S

int max_n_zeros = 32, n_zeros = 0;                // specify maximum and current number of wanted zeros

std::complex<double> Z[max_n_zeros], V[max_n_zeros];  // allocate arrays for zeros and values of the function

solver.FindZeros(max_n_zeros, Z, V, n_zeros);  // the solver sets Z, V, n_zeros and returns 0 if successful

solver.print_status();       // the solver prints information about the search status

return 0;
}

/********************************************************************/