#ifndef __GAUSSIANMODEL_H__
#define __GAUSSIANMODEL_H__

#include "matrix.h"
#include <pthread.h>

///a gaussian model
class gaussianmodel
{
 public:
  gaussianmodel();
  ~gaussianmodel();
  int init( int d);
  int setmean( matrix &m );
  int setvariance(matrix &v);
  int getmean(matrix &m);
  int getvariance(matrix &v);
  long double prob( matrix &m );

  /// threaded probability calculator
  long double prob_t( matrix &m, long double *tmparray );

  long double prob( double *m );
  int zero();
  int size();

  int split( gaussianmodel &o );

  gaussianmodel &operator=(const gaussianmodel &);
  int copy( gaussianmodel &g );

  int fixcovariance();

  int getserializedsize();
  int serialize(char *buffer);
  int deserialize(char *buffer);

  /// returns 0 if there is a not a value
  int isgood();

  /// cache the covariance cholesky matrix
  int cachecholesky();

 private:

  int wigglecovariance();

  matrix mean;         ///< mean of the distribution
  matrix covariance;   ///< covariance of the distribution

  int cacheflag;       ///< flag to tell if the cached values are good
  matrix chol;         ///< cholesky factorization of covariance
  matrix ichol;        ///< inverse of the chol
  long double gc;      ///< constant factor in the gaussian
  int dsize;

  long double *calcb;  ///< calculation buffer used to calculate probability
#ifdef __THREADING__
  pthread_mutex_t lock;
#endif
};

std::ostream& operator <<(std::ostream &o, gaussianmodel &m);

#endif
