//#####################################################################
// Copyright 2013.
// This file is part of PhysBAM whose distribution is governed by the license contained in the accompanying file PHYSBAM_COPYRIGHT.txt.
//#####################################################################
// Class GENERAL_MATRIX_BASE
//#####################################################################
#ifndef __GENERAL_MATRIX_BASE__
#define __GENERAL_MATRIX_BASE__
#include <Core/Matrices/MATRIX_OPERATIONS.h>
namespace PhysBAM{

template<class T,class T_MATRIX>
class GENERAL_MATRIX_BASE
{
public:
    T_MATRIX& Derived()
    {return static_cast<T_MATRIX&>(*this);}

    const T_MATRIX& Derived() const
    {return static_cast<const T_MATRIX&>(*this);}

    T_MATRIX Componentwise_Min(const T_MATRIX& m) const
    {return ::PhysBAM::Componentwise_Min(Derived(),m);}

    T_MATRIX Componentwise_Max(const T_MATRIX& m) const
    {return ::PhysBAM::Componentwise_Max(Derived(),m);}

    template<class A>
    auto Transpose_Times(const A& a) const
    {return ::PhysBAM::Transpose_Times(Derived(),a);}

    template<class A>
    auto Times_Transpose(const A& a) const
    {return ::PhysBAM::Times_Transpose(Derived(),a);}

    auto Transposed() const
    {return ::PhysBAM::Transposed(Derived());}

    auto Symmetric_Part() const
    {return ::PhysBAM::Symmetric_Part(Derived());}

    auto Twice_Symmetric_Part() const
    {return ::PhysBAM::Twice_Symmetric_Part(Derived());}

    T Trace() const
    {return ::PhysBAM::Trace(Derived());}

    T Max_Abs() const
    {return ::PhysBAM::Max_Abs(Derived());}

    template<class T_MATRIX1>
    T Double_Contract(const T_MATRIX1& A) const
    {return ::PhysBAM::Double_Contract(Derived(),A);}

    T Frobenius_Norm_Squared() const
    {return Double_Contract(Derived());}

    T Frobenius_Norm() const
    {return sqrt(Frobenius_Norm_Squared());}

    static T_MATRIX Identity_Matrix()
    {return T_MATRIX()+1;}

    auto Diagonal_Part() const
    {return ::PhysBAM::Diagonal_Part(Derived());}

    auto Outer_Product_Matrix() const
    {return Times_Transpose_With_Symmetric_Result(Derived(),Derived());}

    auto Normal_Equations_Matrix() const
    {return Transpose_Times_With_Symmetric_Result(Derived(),Derived());}
};
}
#endif
