/**
 * @file
 * @brief Globally used functions
 * @author Kai Lingemann. Institute of Computer Science, University of Osnabrueck, Germany.
 * @author Andreas Nuechter. Institute of Computer Science, University of Osnabrueck, Germany.
 */

#ifndef __GLOBALS_ICC__
#define __GLOBALS_ICC__

#ifdef _MSC_VER
#include <windows.h>
#define  _USE_MATH_DEFINES
#include <math.h>

inline int gettimeofday (struct timeval* tp, void* tzp) 
{
  unsigned long t;
  t = timeGetTime();
  tp->tv_sec = t / 1000;
  tp->tv_usec = t % 1000;
  return 0;      /* 0 indicates success. */
}
#else
#include <sys/time.h>
#endif

#define  _USE_MATH_DEFINES
#include <math.h>

#if defined(__CYGWIN__)
# ifndef M_PI
#  define M_PI		3.14159265358979323846
#  define M_PI_2	1.57079632679489661923
#  define M_PI_4	0.78539816339744830962
#  define M_1_PI	0.31830988618379067154
#  define M_2_PI	0.63661977236758134308
#  define M_SQRT2	1.41421356237309504880
#  define M_SQRT1_2	0.70710678118654752440
# endif
#endif

#include <algorithm>
using std::min;
using std::max;
#include <cmath>
#include <sstream>
using std::stringstream;
#include <fstream>
using std::ostream;
using std::istream;
#include <iostream>
using std::cout;
using std::endl;
#include <iomanip>
#include <stdexcept>
using std::runtime_error;

/**
 * Set bits count
 *
 * @param unsigned char x 
 *
 * @return char 
 *
 */
inline unsigned char _my_popcount_3(unsigned char x) {
  x -= (x >> 1) & 0x55;                //put count of each 2 bits into those 2 bits
  x = (x & 0x33) + ((x >> 2) & 0x33);  //put count of each 4 bits into those 4 bits 
  x = (x + (x >> 4)) & 0x0f;           //put count of each 8 bits into those 8 bits 
  return x;
}

/**
 * Converts a class T to a string of width with padding 0
 *
 * @param t output
 * @param width length
 *
 * @return string of t
 *
 */
template <class T>
inline std::string to_string(const T& t, int width)
{
  stringstream ss;
  ss << std::setfill('0') << std::setw(width) << t;
  return ss.str();
}

/**
 * Converts a class T to a string of width with padding 0
 *
 * @param t output
 * @return string of t
 *
 */
template <class T>
inline std::string to_string(const T& t)
{
  stringstream ss;
  ss << t;
  return ss.str();
}


/**
 * Overridden "<<" operator for sending a (4x4)-matrix to a stream
 *
 * @param os      stream
 * @param matrix  4x4 matrix sent to stream
 * @return stream
 */
inline ostream& operator<<(ostream& os, const double matrix[16])
{
  for (int i = 0; i < 16; os << matrix[i++] << " ");
  return os;
}

/**
 * Overridden ">>" operator for reading a (4x4)-matrix from a stream.<br>
 * Throws a runtime error if not enough data in the stream.
 *
 * @param is      stream
 * @param matrix  4x4 matrix sent to stream
 * @return stream
*/
inline istream& operator>>(istream& is, double matrix[16])
{
  for (int i = 0; i < 16; i++) {
    if (!is.good()) throw runtime_error("Not enough elements to read for >>(istream&, double[16])");
    is >> matrix[i];
  }
  return is;
}


/**
 * Converts an angle (given in deg) to rad
 *
 * @param deg integer indicating, whether the figure to be drawn to show
 * the clusters should be circles (0) or rectangles(1)
 *
 * @return the clustered image, with the clusters marked by colored figures
 *
 */
template <class T>
inline T rad(const T deg)
{
  return ( (2 * M_PI * deg) / 360 );
}

/**
 * Converts an angle (given in rad) to deg
 *
 * @param rad  angle in rad
 * @return     angle in deg
 */
template <class T>
inline T deg(const T rad)
{
  return ( (rad * 360) / (2 * M_PI) ); 
}


/**
 *  Calculates x^2
 *
 * @param   x  input scalar value
 * @return  squared value
 */
template <class T>
static inline T sqr(const T &x)
{
  return x*x;
}


/**
 * Computes the <i>squared</i> length of a 3-vector
 *
 * @param x   input 3-vector
 * @return    length^2 of vector 
 */
template <class T>
inline T Len2(const T *x)
{
  return sqr(x[0]) + sqr(x[1]) + sqr(x[2]);
}


/**
 * Computes the length of a 3-vector
 *
 * @param x   input 3-vector
 * @return    length of vector
 */
template <class T>
inline T Len(const T *x)
{
  return sqrt(Len2(x));
}


/**
 * Computes the <i>squared</i> Eucledian distance between two points
 * in 3-space
 *
 * @param x1   first input vector
 * @param x2   decond input vecotr
 * @return  Eucledian distance^2 between the two locations
 */
template <class T, class F>
inline T Dist2(const T *x1, const F *x2)
{
  T dx = x2[0] - x1[0];
  T dy = x2[1] - x1[1];
  T dz = x2[2] - x1[2];

  return sqr(dx) + sqr(dy) + sqr(dz);
}

/*
 * Normalization of the input 3-vector
 *
 * @param x  input/output 3-vector
 */
template <class T>
static inline void Normalize3(T *x)
{
  T norm = sqrt(x[0]*x[0] + x[1]*x[1] + x[2]*x[2]);
  x[0] /= norm;
  x[1] /= norm;
  x[2] /= norm;
}

/*
 * Normalization of the input 4-vector
 *
 * @param x  input/output 4-vector
 */
template <class T>
static inline void Normalize4(T *x)
{
  T norm = sqrt((x[0]*x[0] + x[1]*x[1] + x[2]*x[2] + x[3]*x[3]));
  
  x[0] /= norm;
  x[1] /= norm;
  x[2] /= norm;
  x[3] /= norm;
}

/**
 * Sets a 4x4 matrix to identity
 *
 * @param M 4x4 matrix
 */
template <class T>
inline void M4identity( T *M )
{
  M[0] = M[5] = M[10] = M[15] = 1.0;
  M[1] = M[2] = M[3] = M[4] = M[6] = M[7] = M[8] = M[9] = M[11] = M[12] = M[13] = M[14] = 0.0;
}

/**
 *   Multiplies a 4x4 matrices in OpenGL
 *   (column-major) order
 *
 *  @param M1   first input matrix 
 *  @param M2   second input matrix
 *  @param Mout output matrix
 *
 */
template <class T>
inline void MMult(const T *M1,
			   const T *M2,
			   T *Mout)
{
  Mout[ 0] = M1[ 0]*M2[ 0]+M1[ 4]*M2[ 1]+M1[ 8]*M2[ 2]+M1[12]*M2[ 3];
  Mout[ 1] = M1[ 1]*M2[ 0]+M1[ 5]*M2[ 1]+M1[ 9]*M2[ 2]+M1[13]*M2[ 3];
  Mout[ 2] = M1[ 2]*M2[ 0]+M1[ 6]*M2[ 1]+M1[10]*M2[ 2]+M1[14]*M2[ 3];
  Mout[ 3] = M1[ 3]*M2[ 0]+M1[ 7]*M2[ 1]+M1[11]*M2[ 2]+M1[15]*M2[ 3];
  Mout[ 4] = M1[ 0]*M2[ 4]+M1[ 4]*M2[ 5]+M1[ 8]*M2[ 6]+M1[12]*M2[ 7];
  Mout[ 5] = M1[ 1]*M2[ 4]+M1[ 5]*M2[ 5]+M1[ 9]*M2[ 6]+M1[13]*M2[ 7];
  Mout[ 6] = M1[ 2]*M2[ 4]+M1[ 6]*M2[ 5]+M1[10]*M2[ 6]+M1[14]*M2[ 7];
  Mout[ 7] = M1[ 3]*M2[ 4]+M1[ 7]*M2[ 5]+M1[11]*M2[ 6]+M1[15]*M2[ 7];
  Mout[ 8] = M1[ 0]*M2[ 8]+M1[ 4]*M2[ 9]+M1[ 8]*M2[10]+M1[12]*M2[11];
  Mout[ 9] = M1[ 1]*M2[ 8]+M1[ 5]*M2[ 9]+M1[ 9]*M2[10]+M1[13]*M2[11];
  Mout[10] = M1[ 2]*M2[ 8]+M1[ 6]*M2[ 9]+M1[10]*M2[10]+M1[14]*M2[11];
  Mout[11] = M1[ 3]*M2[ 8]+M1[ 7]*M2[ 9]+M1[11]*M2[10]+M1[15]*M2[11];
  Mout[12] = M1[ 0]*M2[12]+M1[ 4]*M2[13]+M1[ 8]*M2[14]+M1[12]*M2[15];
  Mout[13] = M1[ 1]*M2[12]+M1[ 5]*M2[13]+M1[ 9]*M2[14]+M1[13]*M2[15];
  Mout[14] = M1[ 2]*M2[12]+M1[ 6]*M2[13]+M1[10]*M2[14]+M1[14]*M2[15];
  Mout[15] = M1[ 3]*M2[12]+M1[ 7]*M2[13]+M1[11]*M2[14]+M1[15]*M2[15];
}

template <class T>
inline void MMult(const T *M1,
			   const T *M2,
			   float *Mout)
{
  Mout[ 0] = M1[ 0]*M2[ 0]+M1[ 4]*M2[ 1]+M1[ 8]*M2[ 2]+M1[12]*M2[ 3];
  Mout[ 1] = M1[ 1]*M2[ 0]+M1[ 5]*M2[ 1]+M1[ 9]*M2[ 2]+M1[13]*M2[ 3];
  Mout[ 2] = M1[ 2]*M2[ 0]+M1[ 6]*M2[ 1]+M1[10]*M2[ 2]+M1[14]*M2[ 3];
  Mout[ 3] = M1[ 3]*M2[ 0]+M1[ 7]*M2[ 1]+M1[11]*M2[ 2]+M1[15]*M2[ 3];
  Mout[ 4] = M1[ 0]*M2[ 4]+M1[ 4]*M2[ 5]+M1[ 8]*M2[ 6]+M1[12]*M2[ 7];
  Mout[ 5] = M1[ 1]*M2[ 4]+M1[ 5]*M2[ 5]+M1[ 9]*M2[ 6]+M1[13]*M2[ 7];
  Mout[ 6] = M1[ 2]*M2[ 4]+M1[ 6]*M2[ 5]+M1[10]*M2[ 6]+M1[14]*M2[ 7];
  Mout[ 7] = M1[ 3]*M2[ 4]+M1[ 7]*M2[ 5]+M1[11]*M2[ 6]+M1[15]*M2[ 7];
  Mout[ 8] = M1[ 0]*M2[ 8]+M1[ 4]*M2[ 9]+M1[ 8]*M2[10]+M1[12]*M2[11];
  Mout[ 9] = M1[ 1]*M2[ 8]+M1[ 5]*M2[ 9]+M1[ 9]*M2[10]+M1[13]*M2[11];
  Mout[10] = M1[ 2]*M2[ 8]+M1[ 6]*M2[ 9]+M1[10]*M2[10]+M1[14]*M2[11];
  Mout[11] = M1[ 3]*M2[ 8]+M1[ 7]*M2[ 9]+M1[11]*M2[10]+M1[15]*M2[11];
  Mout[12] = M1[ 0]*M2[12]+M1[ 4]*M2[13]+M1[ 8]*M2[14]+M1[12]*M2[15];
  Mout[13] = M1[ 1]*M2[12]+M1[ 5]*M2[13]+M1[ 9]*M2[14]+M1[13]*M2[15];
  Mout[14] = M1[ 2]*M2[12]+M1[ 6]*M2[13]+M1[10]*M2[14]+M1[14]*M2[15];
  Mout[15] = M1[ 3]*M2[12]+M1[ 7]*M2[13]+M1[11]*M2[14]+M1[15]*M2[15];
}

/**
 * Transforms a vector with a matrix (P = M * V)
 * @param M the transformation matrix
 * @param v the initial vector
 * @param p the transformt vector
 */
template <class T>
inline void VTrans(const T *M, const T *V, T *P)
{
    P[0] = M[0] * V[0] + M[4] * V[1] + M[8] * V[2] + M[12];
    P[1] = M[1] * V[0] + M[5] * V[1] + M[9] * V[2] + M[13];
    P[2] = M[2] * V[0] + M[6] * V[1] + M[10] * V[2] + M[14];
}

/**
 * Converts an Euler angle to a 3x3 matrix
 *
 * @param rPosTheta  vector of Euler angles
 * @param alignxf    3x3 matrix corresponding to the Euler angles
 */
inline void EulerToMatrix3(const double *rPosTheta, double *alignxf)
{
  double sx = sin(rPosTheta[0]);
  double cx = cos(rPosTheta[0]);
  double sy = sin(rPosTheta[1]);
  double cy = cos(rPosTheta[1]);
  double sz = sin(rPosTheta[2]);
  double cz = cos(rPosTheta[2]);

  alignxf[0]  = cy*cz;
  alignxf[1]  = sx*sy*cz + cx*sz;
  alignxf[2]  = -cx*sy*cz + sx*sz;
  alignxf[3]  = -cy*sz;
  alignxf[4]  = -sx*sy*sz + cx*cz;
  alignxf[5]  = cx*sy*sz + sx*cz;
  alignxf[6]  = sy;
  alignxf[7]  = -sx*cy;
  alignxf[8] = cx*cy;
}

/**
 * Calculates the determinant of a 3x3 matrix
 *
 * @param M  input 3x3 matrix
 * @return   determinant of input matrix
 */
template <class T>
inline double M3det( const T *M )
{
  double det;
  det = (double)(M[0] * ( M[4]*M[8] - M[7]*M[5] )
			  - M[1] * ( M[3]*M[8] - M[6]*M[5] )
			  + M[2] * ( M[3]*M[7] - M[6]*M[4] ));
  return ( det );
}

/**
 * Inverts a 3x3 matrix
 *
 * @param Min   input 3x3 matrix
 * @param Mout  output 3x3 matrix
 */
template <class T>
inline void M3inv( const T *Min, T *Mout )
{
  double det = M3det( Min );

  if ( fabs( det ) < 0.0005 ) {
    M3identity( Mout );
    return;
  }
  
  Mout[0] =  (double)( Min[4]*Min[8] - Min[5]*Min[7] ) / det;
  Mout[1] =  (double)(-( Min[1]*Min[8] - Min[7]*Min[2] )) / det;
  Mout[2] =  (double)( Min[1]*Min[5] - Min[4]*Min[2] ) / det;

  Mout[3] = (double)(-( Min[3]*Min[8] - Min[5]*Min[6] )) / det;
  Mout[4] = (double)( Min[0]*Min[8] - Min[6]*Min[2] ) / det;
  Mout[5] = (double)(-( Min[0]*Min[5] - Min[3]*Min[2] )) / det;

  Mout[6] = (double) ( Min[3]*Min[7] - Min[6]*Min[4] ) / det;
  Mout[7] = (double)(-( Min[0]*Min[7] - Min[6]*Min[1] )) / det;
  Mout[8] = (double) ( Min[0]*Min[4] - Min[1]*Min[3] ) / det;
}


/**
 * Converts a pose into a RT matrix
 * @param *rPos Pointer to the position (double[3])
 * @param *rPosTheta Pointer to the angles (double[3])
 * @param *alignxf The calculated matrix
 */
inline void EulerToMatrix4(const double *rPos, const double *rPosTheta, double *alignxf)
{
  double sx = sin(rPosTheta[0]);
  double cx = cos(rPosTheta[0]);
  double sy = sin(rPosTheta[1]);
  double cy = cos(rPosTheta[1]);
  double sz = sin(rPosTheta[2]);
  double cz = cos(rPosTheta[2]);

  alignxf[0]  = cy*cz;
  alignxf[1]  = sx*sy*cz + cx*sz;
  alignxf[2]  = -cx*sy*cz + sx*sz;
  alignxf[3]  = 0.0;
  alignxf[4]  = -cy*sz;
  alignxf[5]  = -sx*sy*sz + cx*cz;
  alignxf[6]  = cx*sy*sz + sx*cz;
  alignxf[7]  = 0.0;
  alignxf[8]  = sy;
  alignxf[9]  = -sx*cy;
  alignxf[10] = cx*cy;
  
  alignxf[11] = 0.0;

  alignxf[12] = rPos[0];
  alignxf[13] = rPos[1];
  alignxf[14] = rPos[2];
  alignxf[15] = 1;
}

/**
 * Converts a 4x4 matrix to Euler angles.
 *
 * @param alignxf    input 4x4 matrix
 * @param rPosTheta  output 3-vector of Euler angles
 * @param rPos       output vector of trnaslation (position) if set
 *
 */
static inline void Matrix4ToEuler(const double *alignxf, double *rPosTheta, double *rPos = 0)
{
  
  double _trX, _trY;
  
  if(alignxf[0] > 0.0) {
    rPosTheta[1] = asin(alignxf[8]);
  } else {
    rPosTheta[1] = M_PI - asin(alignxf[8]);
  }
  // rPosTheta[1] =  asin( alignxf[8]);           // Calculate Y-axis angle 
                  
  double  C    =  cos( rPosTheta[1] );
  if ( fabs( C ) > 0.005 )  {                 // Gimball lock? 
    _trX      =  alignxf[10] / C;             // No, so get X-axis angle 
    _trY      =  -alignxf[9] / C;
    rPosTheta[0]  = atan2( _trY, _trX );
    _trX      =  alignxf[0] / C;              // Get Z-axis angle 
    _trY      = -alignxf[4] / C;
    rPosTheta[2]  = atan2( _trY, _trX );
  } else {                                    // Gimball lock has occurred 
    rPosTheta[0] = 0.0;                       // Set X-axis angle to zero 
    _trX      =  alignxf[5];  //1                // And calculate Z-axis angle 
    _trY      =  alignxf[1];  //2
    rPosTheta[2]  = atan2( _trY, _trX );
  }
  
  rPosTheta[0] = rPosTheta[0];
  rPosTheta[1] = rPosTheta[1];
  rPosTheta[2] = rPosTheta[2];
     
  if (rPos != 0) {
    rPos[0] = alignxf[12];
    rPos[1] = alignxf[13];
    rPos[2] = alignxf[14];
  }
}


/**
 * Sets a 3x3 matrix to the identity matrix
 *
 * @param M  input 3x3 matrix
 */
template <class T>
static inline void M3identity( T *M )
{
  M[0] = M[4] = M[8] = 1.0;
  M[1] = M[2] = M[3] = M[5] = M[6] = M[7] = 0.0;
}

/**
 * Gets the current time (in ms)
 *
 * @return current time (in ms)
 */
static inline unsigned long GetCurrentTimeInMilliSec()
{
  static unsigned long milliseconds;
#ifdef _MSC_VER
  SYSTEMTIME stime;
  GetSystemTime(&stime);
  milliseconds = ((stime.wHour * 60 + stime.wMinute) * 60 +  stime.wSecond) * 1000 + stime.wMilliseconds;
#else
  static struct timeval tv;
  gettimeofday(&tv, NULL);
  milliseconds = tv.tv_sec * 1000 + tv.tv_usec / 1000;
#endif   
  return milliseconds;
}

/**
 * generates random numbers in [0..rnd]
 *
 * @param rnd  maximum number
 * @return random number between 0 and rnd
 */
inline int rand(int rnd)
{
  return (int) ((double)rnd * (double)std::rand() / (RAND_MAX + 1.0));
}

/**
 * generates unsigned character random numbers in [0..rnd]
 *
 * @param rnd  maximum number
 * @return random number between 0 and rnd
 */
inline unsigned char randUC(unsigned char rnd)
{
  return (unsigned char) ((float)rnd * std::rand() / (RAND_MAX + 1.0));
}

/**
 * Computes the angle between 2 points in polar coordinates
 */
inline double polardist(double* p, double *p2) {
  double stheta = sin(p[0]) * sin(p2[0]);
  double myd2 = acos( stheta * cos(p[1]) * cos(p2[1]) 
                    + stheta * sin(p[1]) * sin(p2[1]) 
                    + cos(p[0]) * cos(p2[0])); 
  return myd2;
}

                        

inline void toKartesian(double *polar, double *kart) {
  kart[0] = polar[2] * cos( polar[1] ) * sin( polar[0] );
  kart[1] = polar[2] * sin( polar[1] ) * sin( polar[0] );
  kart[2] = polar[2] * cos( polar[0] );

}

/**
  * Transforms a point in cartesian coordinates into polar 
  * coordinates 
  */

inline void toPolar(double *n, double *polar) {
  double phi, theta, rho;
  rho = Len(n);
  Normalize3(n);

 // if(fabs(1 - fabs(n[1])) < 0.001)  {
 // cout << "Y " << n[0] << " " << n[1] << " " << n[2] << endl;

  phi = acos(n[2]);
  //if ( fabs(phi) < 0.0001) phi = 0.0001;
  //if ( fabs(M_PI - phi) < 0.0001) phi = 0.0001;

  double theta0;

  if(fabs(phi) < 0.0001) {
    theta = 0.0;
  } else if(fabs(M_PI - phi) < 0.0001) {
    theta = 0.0;
  } else {
    if(fabs(n[0]/sin(phi)) > 1.0) {
      if(n[0]/sin(phi) < 0) {
        theta0 = M_PI;
      } else {
        theta0 = 0.0;
      }
    } else {
      theta0 = acos(n[0]/sin(phi));
    
    }
  
    
    double sintheta = n[1]/sin(phi);

    double EPS = 0.0001;

    if(fabs(sin(theta0) - sintheta) < EPS) {
      theta = theta0;
    } else if(fabs( sin( 2*M_PI - theta0 ) - sintheta ) < EPS) {
      theta = 2*M_PI - theta0;
    } else {
      theta = 0;
      cout << "Fehler" << endl;
    }

  }
 /* } else {
    theta = 0.0;
    phi = 0.0;
  }*/
  polar[0] = phi;
  polar[1] = theta;
  polar[2] = rho;

}

/*
 *   Computes the submatrix without
 *   row i and column j
 *
 * @param Min   input 4x4 matrix
 * @param Mout  output 3x3 matrix
 * @param i     row index i 
 * @param j     column index j
 */
template <class T>
static inline void	M4_submat(const T *Min, T *Mout, int i, int j ) {
  int di, dj, si, sj;
  // loop through 3x3 submatrix
  for( di = 0; di < 3; di ++ ) {
    for( dj = 0; dj < 3; dj ++ ) {
	 // map 3x3 element (destination) to 4x4 element (source)
	 si = di + ( ( di >= i ) ? 1 : 0 );
	 sj = dj + ( ( dj >= j ) ? 1 : 0 );
	 // copy element
	 Mout[di * 3 + dj] = Min[si * 4 + sj];
    }
  }
}

/*
 *  Computes the determinant of a 4x4 matrix
 *
 * @param 4x4 matrix
 * @return determinant
 */
template <class T>
static inline double M4det(const T *M )
{
  T det, result = 0, i = 1.0;
  T Msub3[9];
  int    n;
  for ( n = 0; n < 4; n++, i *= -1.0 ) {
    M4_submat( M, Msub3, 0, n );
    det     = M3det( Msub3 );
    result += M[n] * det * i;
  }
  return( result );
}


/* 
 * invert a 4x4 Matrix
 *
 * @param Min input 4x4 matrix
 * @param Mout output matrix
 * @return 1 if successful
 */
template <class T>
static inline int M4inv(const T *Min, T *Mout )
{
  T  mdet = M4det( Min );
  if ( fabs( mdet ) < 0.0005 ) {
    cout << "Error matrix inverting!" << endl;
    M4identity( Mout );
    return( 0 );
  }
  T  mtemp[9];
  int     i, j, sign;
  for ( i = 0; i < 4; i++ ) {
    for ( j = 0; j < 4; j++ ) {
	 sign = 1 - ( (i +j) % 2 ) * 2;
	 M4_submat( Min, mtemp, i, j );
	 Mout[i+j*4] = ( M3det( mtemp ) * sign ) / mdet;
    }
  }
  return( 1 );
}

/*
 * transposes a 4x4 matrix
 * 
 * @param Min  input 4x4 matrix
 * @param Mout output 4x4 matrix
 */
template <class T>
static inline int M4transpose(const T *Min, T *Mout )
{
  Mout[0]  = Min[0]; 
  Mout[4]  = Min[1]; 
  Mout[8]  = Min[2]; 
  Mout[12] = Min[3]; 
  Mout[1]  = Min[4]; 
  Mout[5]  = Min[5]; 
  Mout[9]  = Min[6]; 
  Mout[13] = Min[7]; 
  Mout[2]  = Min[8]; 
  Mout[6]  = Min[9]; 
  Mout[10] = Min[10]; 
  Mout[14] = Min[11]; 
  Mout[3]  = Min[12]; 
  Mout[7]  = Min[13]; 
  Mout[11] = Min[14]; 
  Mout[15] = Min[15]; 
  return( 1 );
}

/* +++++++++-------------++++++++++++
 * NAME
 *   choldc
 * DESCRIPTION
 *   Cholesky Decomposition of a symmetric
 *    positive definite matrix
 *   Overwrites lower triangle of matrix
 *   Numerical Recipes, but has a bit of
 *    the fancy C++ template thing happening
 * +++++++++-------------++++++++++++ */ 
static inline bool choldc(double A[3][3], double diag[3])
{
  for (unsigned int i = 0; i < 3; i++) {
    for (unsigned int j = i; j < 3; j++) {
      double sum = A[i][j];
      for (int k=i-1; k >= 0; k--)
        sum -= A[i][k] * A[j][k];
      if (i == j) {
        if (sum < 1.0e-7)
          return false;
        diag[i] = sqrt(sum);
      } else {
        A[j][i] = sum / diag[i];
      }
    }
  }
  return true;
}


/* +++++++++-------------++++++++++++
 * NAME
 *   choldc
 * DESCRIPTION
 *   Cholesky Decomposition of a symmetric
 *    positive definite matrix
 *   Overwrites lower triangle of matrix
 *   Numerical Recipes, but has a bit of
 *    the fancy C++ template thing happening
 * +++++++++-------------++++++++++++ */
static inline bool choldc(unsigned int n, double **A, double *diag)
{
  for (unsigned int i = 0; i < n; i++) {
    for (unsigned int j = i; j < n; j++) {
      double sum = A[i][j];
      for (int k=i-1; k >= 0; k--)
        sum -= A[i][k] * A[j][k];
      if (i == j) {
        if (sum < 1.0e-7)
          return false;
        diag[i] = sqrt(sum);
      } else {
        A[j][i] = sum / diag[i];
      }
    }
  }
  return true;
}


/* +++++++++-------------++++++++++++
 * NAME
 *   cholsl
 * DESCRIPTION
 *   Solve Ax=B after choldc
 * +++++++++-------------++++++++++++ */  
static inline void cholsl(double A[3][3],
					 double diag[3],
					 double B[3],
					 double x[3])
{
  for (int i=0; i < 3; i++) {
    double sum = B[i];
    for (int k=i-1; k >= 0; k--)
      sum -= A[i][k] * x[k];
    x[i] = sum / diag[i];
  }
  for (int i=2; i >= 0; i--) {
    double sum = x[i];
    for (int k=i+1; k < 3; k++)
      sum -= A[k][i] * x[k];
    x[i] = sum / diag[i];
  }
}


/* +++++++++-------------++++++++++++
 * NAME
 *   cholsl
 * DESCRIPTION
 *   Solve Ax=B after choldc
 * +++++++++-------------++++++++++++ */
static inline void cholsl(unsigned int n,
					 double **A,
					 double *diag,
					 double *B,
					 double *x)
{
  for (unsigned int i=0; i < n; i++) {
    double sum = B[i];
    for (int k=(int)i-1; k >= 0; k--)
      sum -= A[i][k] * x[k];
    x[i] = sum / diag[i];
  }
  for (int i=(int)n-1; i >= 0; i--) {
    double sum = x[i];
    for (unsigned int k=i+1; k < n; k++)
      sum -= A[k][i] * x[k];
    x[i] = sum / diag[i];
  }
}


/**
 * Transforms a a quaternion and a translation vector into a 4x4
 * Matrix
 *
 * @param quat  input quaternion
 * @param t     input translation
 * @param mat   output matrix
 */
static inline void QuatToMatrix4(const double *quat, const double *t, double *mat)
{
  //  double q00 = quat[0]*quat[0];
  double q11 = quat[1]*quat[1];
  double q22 = quat[2]*quat[2];
  double q33 = quat[3]*quat[3];
  double q03 = quat[0]*quat[3];
  double q13 = quat[1]*quat[3];
  double q23 = quat[2]*quat[3];
  double q02 = quat[0]*quat[2];
  double q12 = quat[1]*quat[2];
  double q01 = quat[0]*quat[1];
  mat[0] = 1 - 2 * (q22 + q33);
  mat[5] = 1 - 2 * (q11 + q33);
  mat[10] = 1 - 2 * (q11 + q22);
  mat[4] = 2.0*(q12-q03);
  mat[1] = 2.0*(q12+q03);
  mat[8] = 2.0*(q13+q02);
  mat[2] = 2.0*(q13-q02);
  mat[9] = 2.0*(q23-q01);
  mat[6] = 2.0*(q23+q01);

  mat[3] = mat[7] = mat[11] = 0.0;

  if (t == 0) {
    mat[12] = mat[13] = mat[14] = 0.0;
  } else {
    mat[12] = t[0];
    mat[13] = t[1];
    mat[14] = t[2];
  }
  mat[15] = 1.0;
}


/**
 * Transforms a 4x4 Transformation Matrix into a quaternion
 *
 * @param mat     matrix to be converted
 * @param quat    resulting quaternion
 * @param t       resulting translation
 */
static inline void Matrix4ToQuat(const double *mat, double *quat, double *t = 0)
{
  
  double T, S, X, Y, Z, W;
  T = 1 + mat[0] + mat[5] + mat[10];
  if ( T > 0.00000001 ) { // to avoid large distortions!

    S = sqrt(T) * 2;
    X = ( mat[9] - mat[6] ) / S;
    Y = ( mat[2] - mat[8] ) / S;
    Z = ( mat[4] - mat[1] ) / S;
    W = 0.25 * S;
  } else if ( mat[0] > mat[5] && mat[0] > mat[10] )  { // Column 0: 
    S  = sqrt( 1.0 + mat[0] - mat[5] - mat[10] ) * 2;
    X = 0.25 * S;
    Y = (mat[4] + mat[1] ) / S;
    Z = (mat[2] + mat[8] ) / S;
    W = (mat[9] - mat[6] ) / S;
  } else if ( mat[5] > mat[10] ) {                    // Column 1: 
    S  = sqrt( 1.0 + mat[5] - mat[0] - mat[10] ) * 2;
    X = (mat[4] + mat[1] ) / S;
    Y = 0.25 * S;
    Z = (mat[9] + mat[6] ) / S;
    W = (mat[2] - mat[8] ) / S;
  } else {                                            // Column 2:
    S  = sqrt( 1.0 + mat[10] - mat[0] - mat[5] ) * 2;
    X = (mat[2] + mat[8] ) / S;
    Y = (mat[9] + mat[6] ) / S;
    Z = 0.25 * S;
    W = (mat[4] - mat[1] ) / S;
  }
  quat[0] = W;
  quat[1] = -X;
  quat[2] = -Y;
  quat[3] = -Z;
  
  Normalize4(quat);
  if (t != 0) {
    t[0] = mat[12];
    t[1] = mat[13];
    t[2] = mat[14];
  }
}

/**
 *  Transforms a Quaternion to the corresponding Axis-Angle representation
 *
 * @param quat   4-vector of quaternion
 *               gets overridden by the axis/angle representation
 */
static inline void QuatToAA(double *quat){
  //double x, y, z, w;
  double sum = 0.0;
  
  double cos_a, angle, x, y, z, sin_a;

  for(int i = 0; i < 4; i++){
    sum += quat[i]*quat[i];
  }
  sum = sqrt(sum);

  //quaternion_normalise( |W,X,Y,Z| );
  cos_a = quat[0]/sum;
  angle = acos( cos_a ) * 2;
  sin_a = sqrt( 1.0 - cos_a * cos_a );
  if ( fabs( sin_a ) < 0.0005 ) sin_a = 1;
  x = quat[1] / sin_a;
  y = quat[2] / sin_a;
  z = quat[3] / sin_a;
  
  quat[0] = angle;
  quat[1] = x;
  quat[2] = y;
  quat[3] = z;
}

/**
 * Quaternion Multiplication q1 * q2 = q3
 */
static inline void QMult(const double *q1, const double *q2, double *q3) {
  q3[0] = q1[0] * q2[0] - q1[1] * q2[1] - q1[2] * q2[2] - q1[3] * q2[3];
  q3[1] = q1[0] * q2[1] + q1[1] * q2[0] + q1[2] * q2[3] - q1[3] * q2[2];
  q3[2] = q1[0] * q2[2] - q1[1] * q2[3] + q1[2] * q2[0] + q1[3] * q2[1];
  q3[3] = q1[0] * q2[3] + q1[1] * q2[2] - q1[2] * q2[1] + q1[3] * q2[0];
}

/**
 * Quaternion SLERP
 * http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/
 */
static inline void slerp(const double *qa, const double *qb, const double t, double *qm) {
  // Calculate angle between them.
  double cosHalfTheta = qa[0] * qb[0] + qa[1] * qb[1] + qa[2] * qb[2] + qa[3] * qb[3];
  // if qa=qb or qa=-qb then theta = 0 and we can return qa
  if (fabs(cosHalfTheta) >= 1.0) {
    qm[0] = qa[0];
    qm[1] = qa[1];
    qm[2] = qa[2];
    qm[3] = qa[3];
    return;
  }
  // Calculate temporary values.
  double halfTheta = acos(cosHalfTheta);
  double sinHalfTheta = sqrt(1.0 - cosHalfTheta * cosHalfTheta);
  // if theta = 180 degrees then result is not fully defined
  // we could rotate around any axis normal to qa or qb
  if (fabs(sinHalfTheta) < 0.001){
    qm[0] = (qa[0] * 0.5 + qb[0] * 0.5);
    qm[1] = (qa[1] * 0.5 + qb[1] * 0.5);
    qm[2] = (qa[2] * 0.5 + qb[2] * 0.5);
    qm[3] = (qa[3] * 0.5 + qb[3] * 0.5);
    Normalize4(qm);
    return;
  }
  double ratioA = sin((1 - t) * halfTheta) / sinHalfTheta;
  double ratioB = sin(t * halfTheta) / sinHalfTheta; 
  //calculate Quaternion.
  qm[0] = (qa[0] * ratioA + qb[0] * ratioB);
  qm[1] = (qa[1] * ratioA + qb[1] * ratioB);
  qm[2] = (qa[2] * ratioA + qb[2] * ratioB);
  qm[3] = (qa[3] * ratioA + qb[3] * ratioB);
  Normalize4(qm);
}

/* taken from ROOT (CERN)
 * as well in:
 * Effective Sampling and Distance Metrics for 3D Rigid Body Path Planning
 * James J. Kuffner
 *
 * Distance between two rotations in Quaternion form
 * Note:  The rotation group is isomorphic to a 3-sphere
 * with diametrically opposite points identified.
 * The (rotation group-invariant) is the smaller
 * of the two possible angles between the images of
 * the two rotations on that sphere.  Thus the distance
 * is never greater than pi/2.
 */
inline double quat_dist(double quat1[4], double quat2[4]) {
  double chordLength = std::fabs(quat1[0]*quat2[0] + quat1[1]*quat2[1] + quat1[2]*quat2[2] + quat1[3]*quat2[3]);
  if (chordLength > 1) chordLength = 1; // in case roundoff fouls us up
  return acos(chordLength) / M_PI * 180.0;
}



/**
 *  Converts a Rotation given by Axis-Angle and a Translation into a
 *  4x4 Transformation matrix
 *
 * @param aa         axis and angle aa[0] is the angle
 * @param trans      vector containing the translation
 * @param matrix     matrix to be computed
 */
inline void AAToMatrix(double *aa, double *trans, double *matrix ){
  double rcos = cos(aa[0]);
  double rsin = sin(aa[0]);
  double u = aa[1];
  double v = aa[2];
  double w = aa[3];

  matrix[0]    =      rcos + u*u*(1-rcos);
  matrix[1]    =  w * rsin + v*u*(1-rcos);
  matrix[2]    = -v * rsin + w*u*(1-rcos);
  matrix[3]    = 0.0;
  matrix[4]    = -w * rsin + u*v*(1-rcos);
  matrix[5]    =      rcos + v*v*(1-rcos);
  matrix[6]    =  u * rsin + w*v*(1-rcos);
  matrix[7]    = 0.0;
  matrix[8]    =  v * rsin + u*w*(1-rcos);
  matrix[9]    = -u * rsin + v*w*(1-rcos);
  matrix[10]    =     rcos + w*w*(1-rcos);
  matrix[11]   = 0.0;
  matrix[12]   = trans[0];
  matrix[13]   = trans[1];
  matrix[14]   = trans[2];
  matrix[15]   = 1.0;

}


/**
 * Factors matrix A into lower and upper triangular matrices 
 *   (L and U respectively) in solving the linear equation Ax=b.  
 *
 * @param A        (input/output) Matrix(1:n, 1:n)  In input, matrix to be
 *                  factored.  On output, overwritten with lower and 
 *                  upper triangular factors.
 *
 * @param indx     (output) Vector(1:n)    Pivot vector. Describes how
 *                  the rows of A were reordered to increase
 *                  numerical stability.
 *
 * @return return int(0 if successful, 1 otherwise)
 */
inline int LU_factor( double A[4][4], int indx[4])
{
  int M = 4;
  int N = 4;

  int  i=0,j=0,k=0;
  int  jp=0;

  double t;

  int minMN = 4;

  for (j = 0; j < minMN; j++)
    {

	 // find pivot in column j and  test for singularity.

	 jp = j;
	 t = fabs(A[j][j]);
	 for (i = j+1; i < M; i++)
	   if ( fabs(A[i][j]) > t)
		{
		  jp = i;
		  t = fabs(A[i][j]);
		}

	 indx[j] = jp;

	 // jp now has the index of maximum element 
	 // of column j, below the diagonal

	 if ( A[jp][j] == 0 )                 
	   return 1;       // factorization failed because of zero pivot


	 if (jp != j)            // swap rows j and jp
	   for (k = 0; k < N; k++)
		{
		  t = A[j][k];
		  A[j][k] = A[jp][k];
		  A[jp][k] =t;
		}

	 if (j < M)                // compute elements j+1:M of jth column
        {
		// note A(j,j), was A(jp,p) previously which was
		// guarranteed not to be zero (Label #1)
		//
		double recp =  1.0 / A[j][j];

		for (k = j+1; k < M; k++)
		  A[k][j] *= recp;
        }

	 if (j < minMN)
        {
		// rank-1 update to trailing submatrix:   E = E - x*y;
		//
		// E is the region A(j+1:M, j+1:N)
		// x is the column vector A(j+1:M,j)
		// y is row vector A(j,j+1:N)

		int ii,jj;

		for (ii = j+1; ii < M; ii++)
		  for (jj = j+1; jj < N; jj++)
		    A[ii][jj] -= A[ii][j]*A[j][jj];
        }
    }

  return 0;
}   

/**
 * Solves a linear system via LU after LU factor
 *
 * @param A 4x4 matrix
 * @param indx indices
 * @param b 4 vectort
 *
 * @return 0
 *
 */
inline int LU_solve(const double A[4][4], const int indx[4], double b[4])
{
  int i,ii=0,ip,j;
  int n = 4;
  double sum = 0.0;

  for (i = 0; i < n; i++) 
    {
	 ip=indx[i];
	 sum=b[ip];
	 b[ip]=b[i];
	 if (ii)
	   for (j = ii;j <= i-1; j++) 
		sum -= A[i][j]*b[j];
	 else if (sum) ii=i;
	 b[i]=sum;
    }
  for (i = n-1; i >= 0; i--) 
    {
	 sum=b[i];
	 for (j = i+1; j < n; j++) 
	   sum -= A[i][j]*b[j];
	 b[i]=sum/A[i][i];
    }

  return 0;
}

/**
 * Calculates the <i>cross</i> product of two 4-vectors
 *
 * @param x input 1
 * @param y input 2
 * @param T output
 *
 */
template <class T>
static inline void Cross(const T *x, const T *y, T *result)
{
  result[0] = x[1] * y[2] - x[2] * y[1];
  result[1] = x[2] * y[0] - x[0] * y[2];
  result[2] = x[0] * y[1] - x[1] * y[0];
  return;
}

/**
 * Computes the <i>dot</i> product of two 3-vector
 *
 * @param x   input 3-vector
 * @param y   input 3-vector
 * @return    dot product of x and y
 */
template <class T>
inline T Dot(const T *x, const T *y)
{
  return x[0] * y[0] + x[1] * y[1] + x[2] * y[2];
}

/**
 * converts a quaternion to Euler angels in the roll pitch yaw system
 */
static inline void QuatRPYEuler(const double *quat, double *euler)
{
	double n = sqrt(quat[0]*quat[0] + quat[1]*quat[1] + quat[2]*quat[2] + quat[3]*quat[3]);
	double s = n > 0?2./(n*n):0.;

	double m00, m10, m20, m21, m22;


	double xs = quat[1]*s;
	double ys = quat[2]*s;
	double zs = quat[3]*s;

	double wx = quat[0]*xs;
	double wy = quat[0]*ys;
	double wz = quat[0]*zs;

	double xx = quat[1]*xs;
	double xy = quat[1]*ys;
	double xz = quat[1]*zs;

	double yy = quat[2]*ys;
	double yz = quat[2]*zs;

	double zz = quat[3]*zs;

	m00 = 1.0 - (yy + zz);
	m22 = 1.0 - (xx + yy);


	m10 = xy + wz;

	m20 = xz - wy;
	m21 = yz + wx;

	euler[0] = atan2(m21,m22);
	euler[1] = atan2(-m20,sqrt(m21*m21 + m22*m22));
	euler[2] = atan2(m10,m00);
}

/**
 * converts from Euler angels in the roll pitch yaw system to a quaternion
 */
static inline void RPYEulerQuat(const double *euler, double *quat)
{
	double sphi   = sin(euler[0]);
	double stheta = sin(euler[1]);
	double spsi   = sin(euler[2]);
	double cphi   = cos(euler[0]);
	double ctheta = cos(euler[1]);
	double cpsi   = cos(euler[2]);

	double _r[3][3] = { //create rotational Matrix
		{cpsi*ctheta, cpsi*stheta*sphi - spsi*cphi, cpsi*stheta*cphi + spsi*sphi},
		{spsi*ctheta, spsi*stheta*sphi + cpsi*cphi, spsi*stheta*cphi - cpsi*sphi},
		{    -stheta,                  ctheta*sphi,                  ctheta*cphi}
	};

#define MY_MAX(a,b) (((a)>(b))?(a):(b))
	double _w = sqrt(MY_MAX(0, 1 + _r[0][0] + _r[1][1] + _r[2][2]))/2.0;
	double _x = sqrt(MY_MAX(0, 1 + _r[0][0] - _r[1][1] - _r[2][2]))/2.0;
	double _y = sqrt(MY_MAX(0, 1 - _r[0][0] + _r[1][1] - _r[2][2]))/2.0;
	double _z = sqrt(MY_MAX(0, 1 - _r[0][0] - _r[1][1] + _r[2][2]))/2.0;
	quat[0] = _w;
	quat[1] = (_r[2][1] - _r[1][2])>=0?fabs(_x):-fabs(_x);
	quat[2] = (_r[0][2] - _r[2][0])>=0?fabs(_y):-fabs(_y);
	quat[3] = (_r[1][0] - _r[0][1])>=0?fabs(_z):-fabs(_z);
}


inline void transform3(const double *alignxf, double *point)
{
  double x_neu, y_neu, z_neu;
  x_neu = point[0] * alignxf[0] + point[1] * alignxf[4] + point[2] * alignxf[8];
  y_neu = point[0] * alignxf[1] + point[1] * alignxf[5] + point[2] * alignxf[9];
  z_neu = point[0] * alignxf[2] + point[1] * alignxf[6] + point[2] * alignxf[10];
  point[0] = x_neu + alignxf[12];
  point[1] = y_neu + alignxf[13];
  point[2] = z_neu + alignxf[14];
}

inline void transform3(const double *alignxf, const double *point, double *tpoint)
{
  tpoint[0] = point[0] * alignxf[0] + point[1] * alignxf[4] + point[2] * alignxf[8]  + alignxf[12];
  tpoint[1] = point[0] * alignxf[1] + point[1] * alignxf[5] + point[2] * alignxf[9]  + alignxf[13];
  tpoint[2] = point[0] * alignxf[2] + point[1] * alignxf[6] + point[2] * alignxf[10] + alignxf[14];
}

inline std::string trim(const std::string& source)
{
  unsigned int start = 0, end = source.size() - 1;
  while(source[start] == ' ') start++;
  while(source[end] == ' ') end--;
  return source.substr(start, end - start + 1);
}

#endif
