// This is core/vnl/algo/vnl_rnpoly_solve.h
#ifndef vnl_rnpoly_solve_h_
#define vnl_rnpoly_solve_h_
//:
// \file
// \brief Solves for roots of system of real polynomials
// \author Marc Pollefeys, ESAT-VISICS, K.U.Leuven
// \date   12-Aug-1997
//
// \verbatim
//  Modifications
//   Oct.1999 - Peter Vanroose - implementation simplified through "cmplx" class for doing complex arithmetic.
//   May.2002 - Peter Vanroose - added operator*=(cmplx) and operator/=(cmplx)
//   Mar.2003 - Peter Vanroose - renamed M to M_, T to T_
//   Feb.2004 - Peter Vanroose - removed hard limits on dimensionality; this gets rid of M_ and T_;
//                               now using std::vector throughout instead of C arrays of fixed size
// \endverbatim

#include <utility>
#include <vector>
#ifdef _MSC_VER
#  include <vcl_msvc_warnings.h>
#endif
#include <vnl/algo/vnl_algo_export.h>
#include <vnl/vnl_real_npolynomial.h>
#include <vnl/vnl_vector.h>

//: Solves for roots of system of real polynomials
//  Calculates all the roots of a system of N polynomials in N variables
//  through continuation.
//  Adapted from the  PARALLEL CONTINUATION algorithm, written by Darrell
//  Stam, 1991, and further improved by  Kriegman and Ponce, 1992.

class VNL_ALGO_EXPORT vnl_rnpoly_solve
{
  // Data Members--------------------------------------------------------------
  std::vector<vnl_real_npolynomial *> ps_; // the input
  std::vector<vnl_vector<double> *> r_;    // the output (real part)
  std::vector<vnl_vector<double> *> i_;    // the output (imaginary part)

public:
  // Constructor---------------------------------------------------------------

  //: The constructor already does all the calculations
  inline vnl_rnpoly_solve(std::vector<vnl_real_npolynomial *> ps)
    : ps_(std::move(ps))
  {
    compute();
  }

  // Destructor----------------------------------------------------------------

  ~vnl_rnpoly_solve();

  // Operations----------------------------------------------------------------

  //: Array of real parts of roots
  inline std::vector<vnl_vector<double> *>
  real()
  {
    return r_;
  }

  //: Array of imaginary parts of roots
  inline std::vector<vnl_vector<double> *>
  imag()
  {
    return i_;
  }

  //: Return real roots only.
  //  Roots are real if the absolute value of their imaginary part is less than
  //  the optional argument tol, which defaults to 1e-12 [untested]
  std::vector<vnl_vector<double> *>
  realroots(double tol = 1e-12);

  // Computations--------------------------------------------------------------

private:
  //: Compute roots using continuation algorithm.
  bool
  compute();

  void
  Read_Input(std::vector<unsigned int> & ideg,
             std::vector<unsigned int> & terms,
             std::vector<int> & polyn,
             std::vector<double> & coeff);
};

#endif // vnl_rnpoly_solve_h_
