/** \file
 *
 *  Contains the Matrix6x6 class definition.
 *
 *  Copyright (c) 2007,2008,2009 MBARI
 *  MBARI Proprietary Information.  All Rights Reserved
 *
 */

#ifndef MATRIX6X6_H_
#define MATRIX6X6_H_

#include "I2D.h"
#include "Point6D.h"
#include "Matrix3x3.h"

/**
 * Contains a 6x6 array of double precision floating
 * point numbers, along with methods for performing
 * common operations on the array such as invert(),
 * mult(), etc.
 *
 * Matrix6x6 is not a DataValue!
 *
 * \ingroup data
 */
class Matrix6x6: public I2D<double>
{
public:
    /// Empty constructior
    Matrix6x6();

    /// Single Value constructior
    Matrix6x6( const double& init );

    /// 4x Matrix3x3 constructior
    Matrix6x6( Matrix3x3& m3x3i11, Matrix3x3& m3x3i12,
               Matrix3x3& m3x3i21, Matrix3x3& m3x3i22 );

    /// Coordinate transformation constructor
    Matrix6x6( Point6D pos );

    // as a Str
    Str toString() const;

    /// Returns true if the determinant of this matrix is zero
    bool determinantZero();

    /// Inverts this matrix
    void invert();

    /// Obtain the LU decompostion of this matrix.
    void decomposeLU();

    // Solve for x in Ax = b, where this is the LU decompostion of
    // M and b is supplied here.
    void solveLU( Point6D& b, Point6D& x ) const;

    //const Point6D operator*( const Point6D& rhs ) const;

    bool operator==( const Matrix6x6& rhs );

    Matrix6x6& operator=( const Matrix6x6& rhs );

    Matrix6x6& operator=( const double rhs );

    /// Allows one to treat this 6x6 matrix as a 2x2 matrix of 3x3 matrices.
    void set( int index1, int index2, Matrix3x3& value );

    void set( int index1, int index2, const double value );

    double& operator()( int index1, int index2 );

    /// 36 value set
    void set( const double& v00, const double& v01, const double& v02, const double& v03, const double& v04, const double& v05,
              const double& v10, const double& v11, const double& v12, const double& v13, const double& v14, const double& v15,
              const double& v20, const double& v21, const double& v22, const double& v23, const double& v24, const double& v25,
              const double& v30, const double& v31, const double& v32, const double& v33, const double& v34, const double& v35,
              const double& v40, const double& v41, const double& v42, const double& v43, const double& v44, const double& v45,
              const double& v50, const double& v51, const double& v52, const double& v53, const double& v54, const double& v55 );

    /// Implement abstract I2D method
    virtual double** getPtr2d()
    {
        return value2d_;
    }

    /// Implement abstract I2D method
    virtual double* getPtr1d()
    {
        return value_;
    }

    /// Implement abstract I2D method
    virtual int getM() const
    {
        return 6;
    }

    /// Implement abstract I2D method
    virtual int getN() const
    {
        return 6;
    }

protected:

    // The actual data
    double value_[ 36 ];

    // For I2D operations
    double* value2d_[ 6 ];

};

#endif /*MATRIX6X6_H_*/
