/*! @file
*  @brief This file includes standard algorithm.
*
* @author Thomas Bertram & Frank Kittmann
* @version 11.02.04
* @date 2012-08-10 11:04:58 AM
*/

/* $Header: https://svn.mpia.de/gulli/TwiceAsNice/branch/unstable/TwiceAsNice/nice/src/libNice/Nice/Alg/Alg.h 15141 2018-02-21 14:14:57Z mathar $
*/


#pragma once

#include <vector>
#include <boost/numeric/ublas/vector.hpp>
#include <boost/numeric/ublas/matrix.hpp>
//#include <Nice/Alg/Exception.h>
#include <Nice/Log.h>
#include <Nice/Util/Exception.h>
#include <Nice/Map/Circle.h>
#include <Nice/Map/Point.h>

namespace Nice
{
    struct AlgException : Exception {};

    namespace Algorithm
    {
        struct NoFitParamsException : AlgException {};
        struct GaussjSingularMatrixException : AlgException {};
    }
    
    
    class Alg
    {
    
    public:
        /*!*******************************
	* @brief exchange (swap) two values.
	* @param[in,out] a
	* @param[in,out] b
        */
        template<class T>
        inline static void SWAP ( T &a, T &b )
        {
            T tmp=a;
            a=b;
            b=tmp;
        }
    
        /*!*************************
	* @brief compute the square of a value
	* @param a The value to be squared.
	* @return The square of a.
        */
        template<class T>
        inline static const T SQR ( const T a )
        {
            return a*a;
        }
    
        static void linearFit ( boost::numeric::ublas::vector<double> &_x,
                                boost::numeric::ublas::vector<double> &_y,
                                boost::numeric::ublas::vector<double> &_sig,
                                boost::numeric::ublas::vector<double> &_a,
                                boost::numeric::ublas::vector<bool> &_ia,
                                boost::numeric::ublas::matrix<double> &_covar,
                                double &_chisq,
                                void _funcs ( const double, boost::numeric::ublas::vector<double> & ) );

        static void gaussj ( boost::numeric::ublas::matrix<double> &a,
                             boost::numeric::ublas::matrix<double> &b );

        static void covsrt ( boost::numeric::ublas::matrix<double> &_covar,
                             boost::numeric::ublas::vector<bool> &_ia,
                             const int _mfit );

        static void shinsLinearFit(boost::numeric::ublas::vector<double> &_x,
                                   boost::numeric::ublas::vector<double> &_y,
                                   boost::numeric::ublas::vector<double> &_sig,
                                   boost::numeric::ublas::vector<double> &_a,
                                   boost::numeric::ublas::vector<bool> &_ia,
                                   boost::numeric::ublas::matrix<double> &_covar,
                                   double &_chisq,
                                   void _funcs ( const double, boost::numeric::ublas::vector<double> & ) );

        static int shinsBestFitF2(const std::vector<double> & x, const std::vector<double> & y, int & AA, int & BB, int & CC, int & DD);
        static int shinsBestFitF3(const std::vector<double> & x, const std::vector<double> & y, int & AA, int & BB, int & CC, int & DD);
        static int shinsBestFitF4(const std::vector<double> & x, const std::vector<double> & y, int & AA, int & BB, int & CC, int & DD, double & maxdelta);
        static int shinsBestFitF(const std::vector<double> & x, const std::vector<double> & y, int & AA, int & BB, int & CC, int & DD, double & maxdelta);
        static int shinsFitF(const std::vector<double> & x, const std::vector<double> & y, int cc, int dd, int & AA, int & BB);
        static int shinsFit4(const std::vector<double> & x, const std::vector<double> & y, const std::vector<double> & sigmas,
                             double & AA, double & BB, double & CC, double & DD);
        static int shinsFit2(const std::vector<double> & x, const std::vector<double> & y, const std::vector<double> & sigmas,
                             double & M, double & N);
        template <typename T> static std::vector< std::vector<int> > subSets(T N, T m) ;

	static Nice::SeqPoint generateSpiral(const Nice::Circle & c, int type, double latConst) ;
    protected:
        template <typename T> static std::vector< std::vector<int> > subSets(T N, T m,
                    std::vector<int> fxd, T minm) ;


    }; /* Alg */
}
