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

#ifndef MATRIX3X3_H_
#define MATRIX3X3_H_

#include "I2D.h"
#include "Point3D.h"
#include "Point6D.h"

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

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

    /// Nine value constructor
    Matrix3x3( const double value11, const double value12, const double value13,
               const double value21, const double value22, const double value23,
               const double value31, const double value32, const double value33 );

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

    /// as a Str
    Str toString() const;

    /// Transpose the matrix.
    void transpose();

    /// Invert the 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( Point3D& b,  Point3D& x ) const;

    /// Cross-Multiplies two Point3D values and stores the value here.
    const void mult( Point3D& lhs, Point3D& rhs ) const;

    bool operator==( const Matrix3x3& rhs );

    Matrix3x3& operator=( const Matrix3x3& rhs );

    Matrix3x3& operator=( const double rhs );

    Matrix3x3& operator+=( const Matrix3x3& rhs );

    Matrix3x3& operator-=( const Matrix3x3& rhs );

    Matrix3x3& operator*=( const double rhs );

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

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

    /// 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 3;
    }

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

protected:

    // The actual data
    double value_[9];
    double* value2d_[3];
};

#endif /*MATRIX3X3_H_*/
