

#if !defined(ALIZE_DoubleSquareMatrix_h)
#define ALIZE_DoubleSquareMatrix_h

#if defined(_WIN32)
#if defined(ALIZE_EXPORTS)
#define ALIZE_API __declspec(dllexport)
#else
#define ALIZE_API __declspec(dllimport)
#endif
#else
#define ALIZE_API
#endif

#include "Object.h"
#include "RealVector.h"

namespace alize
{
  /// This class implements a symmetric matrix of real_t values.<br>
  /// Inside the object, the matrix is stored as a single-dimension
  /// array. Remember that when you call the method getArray() to
  /// access the internal array.
  ///
  /// @author Frederic Wils  frederic.wils@lia.univ-avignon.fr
  /// @version 1.0
  /// @date 2003

  class ALIZE_API DoubleSquareMatrix : public Object
  {
    friend class TestDoubleSquareMatrix;

  private:

    typedef double _type;

  public:
  
    /// Create a symmetric matrix of type double values.
    /// @param dimension of the matrix\n
    ///
    explicit DoubleSquareMatrix(unsigned long size = 0);
    const DoubleSquareMatrix& operator=(const DoubleSquareMatrix&);
    bool operator==(const DoubleSquareMatrix&) const;
    bool operator!=(const DoubleSquareMatrix&) const;
    DoubleSquareMatrix(const DoubleSquareMatrix&);
    virtual ~DoubleSquareMatrix();

    unsigned long size() const;

    /// Sets the new size of the square matrix
    /// @param size the size
    /// @param updateCapacity true = frees unused memory
    ///                       false = does not free unused memory
    ///
    void setSize(const unsigned long size,
                 const bool updateCapacity = false);

    /// Inverts the matrix and compute the determinant\n
    /// ONLY for symmetric positive definite matrix
    /// @param m to store the inverted matrix
    /// @return the determinant
    /// @exception if the matrix is not a positive definite matrix
    ///
    real_t invert(DoubleSquareMatrix& m);

    /// Sets all the values to a a particular value
    /// @param v the real_t value to set
    ///
    void setAllValues(_type v);

    /// Overloaded operator() to access an element in the matrix.<br>
    /// WARNING : contrary to class Matrix, colum index is FIRST
    /// argument and row index is SECOND argument<br>
    /// This will probably change in next release of Alize
    /// @param col column index of the element to access
    /// @param row index of the element to access
    /// @return a reference to the element
    /// @exception IndexOutOfBoundsException
    ///
    _type& operator()(unsigned long col, unsigned long row);

    /// like the other operator[] but for constant DoubleSquareMatrix object.
    ///
    _type  operator()(unsigned long col, unsigned long row) const;

    /// Use this method to access directly to the internal vector
    /// @return a pointer on the first element
    /// @warning Fast but dangerous ! Use preferably operator (col, row).
    ///
    _type* getArray() const;

    virtual String toString() const;
    virtual String getClassName() const;

    real_t upperCholesky(DoubleSquareMatrix& m);

  private:

    unsigned long _size;
    DoubleVector  _array;

    static void choleskyDecomp(real_t*, real_t*, long);
    static void choleskySolve(real_t*, real_t*, real_t*, long);
  };

} // end namespace alize

#endif  // ALIZE_DoubleSquareMatrix_h