a

Dependencies:   mbed mbed-rtos

include/Linalg/linalg.h

Committer:
alexpirciu
Date:
2019-03-28
Revision:
1:ceee5a608e7c

File content as of revision 1:ceee5a608e7c:

#ifndef LINALG_H
#define LINALG_H

// #include <mbed.h>
#include <stdint.h>
#include <array>

namespace linalg
{
    template <class T, uint32_t M, uint32_t N>
    class CMatrix
    {
    public:
        using CThisType = CMatrix<T,M,N>;
        using CTransposeType = CMatrix<T,N,M>;
        using CContainerType = std::array<std::array<T,N>,M>;
        using CDataType =T;

        template <uint32_t P>
        using CLeftMultipliableType = CMatrix<T,P,M>;

        template <uint32_t P>
        using CRightMultipliableType = CMatrix<T,N,P>;

        template <uint32_t P>
        using CLeftMultiplicationResultType = CMatrix<T,P,N>;

        template <uint32_t P>
        using CRightMultiplicationResultType = CMatrix<T,M,P>;

        friend class CMatrix<T,N,M>; 

        CMatrix() : m_data() {}
        CMatrix(const CThisType& f_matrix) : m_data(f_matrix.m_data) {}
        CMatrix(const CThisType&& f_matrix) : m_data(f_matrix.m_data) {}
        CMatrix(const CContainerType& f_data) : m_data(f_data) {}
        CMatrix(const CContainerType&& f_data) : m_data(f_data) {}

        CThisType& operator=(const CThisType& f_matrix)
        {
            for (uint32_t l_row = 0; l_row < M; ++l_row)
            {
                for (uint32_t l_col = 0; l_col < N; ++l_col)
                {
                    this->m_data[l_row][l_col] = f_matrix.m_data[l_row][l_col];
                }
            }
            return *this;
        }
        CThisType& operator=(const CThisType&& f_matrix)
        {
            for (uint32_t l_row = 0; l_row < M; ++l_row)
            {
                for (uint32_t l_col = 0; l_col < N; ++l_col)
                {
                    this->m_data[l_row][l_col] = f_matrix.m_data[l_row][l_col];
                }
            }
            return *this;
        }

        std::array<T,N>& operator[](uint32_t f_row)
        {
            return m_data[f_row];
        }

        CDataType& operator()(uint32_t f_row, uint32_t f_col)
        {
            return m_data[f_row][f_col];
        }

        const std::array<T,N>& operator[](uint32_t f_row) const
        {
            return m_data[f_row];
        }

        const CDataType& operator()(uint32_t f_row, uint32_t f_col) const
        {
            return m_data[f_row][f_col];
        }

        // template<>
        // CMatrix<T,1,1>::operator CDataType()
        // {
        //     return m_data[0][0];
        // }

        CThisType& operator+() {return *this;}
        CThisType operator-()
        {
            CThisType l_matrix;
            for (uint32_t l_row = 0; l_row < M; ++l_row)
            {
                for (uint32_t l_col = 0; l_col < N; ++l_col)
                {
                    l_matrix.m_data[l_row][l_col] = -this->m_data[l_row][l_col];
                }
            }
            return l_matrix;
        }
        CThisType operator+(const CThisType& f_matrix)
        {
            CThisType l_matrix;
            for (uint32_t l_row = 0; l_row < M; ++l_row)
            {
                for (uint32_t l_col = 0; l_col < N; ++l_col)
                {
                    l_matrix.m_data[l_row][l_col] = this->m_data[l_row][l_col] + f_matrix.m_data[l_row][l_col];
                }
            }
            return l_matrix;
        }
        CThisType operator-(const CThisType& f_matrix)
        {
            CThisType l_matrix;
            for (uint32_t l_row = 0; l_row < M; ++l_row)
            {
                for (uint32_t l_col = 0; l_col < N; ++l_col)
                {
                    l_matrix.m_data[l_row][l_col] = this->m_data[l_row][l_col] - f_matrix.m_data[l_row][l_col];
                }
            }
            return l_matrix;
        }
        CThisType& operator+=(const CThisType& f_matrix)
        {
            for (uint32_t l_row = 0; l_row < M; ++l_row)
            {
                for (uint32_t l_col = 0; l_col < N; ++l_col)
                {
                    this->m_data[l_row][l_col] += f_matrix.m_data[l_row][l_col];
                }
            }
            return *this;
        }
        CThisType& operator-=(const CThisType& f_matrix)
        {
            for (uint32_t l_row = 0; l_row < M; ++l_row)
            {
                for (uint32_t l_col = 0; l_col < N; ++l_col)
                {
                    this->m_data[l_row][l_col] -= f_matrix.m_data[l_row][l_col];
                }
            }
            return *this;
        }

        CThisType operator+(const CDataType& f_val)
        {
            CThisType l_matrix;
            for (uint32_t l_row = 0; l_row < M; ++l_row)
            {
                for (uint32_t l_col = 0; l_col < N; ++l_col)
                {
                    l_matrix.m_data[l_row][l_col] = this->m_data[l_row][l_col] + f_val;
                }
            }
            return l_matrix;
        }
        CThisType operator-(const CDataType& f_val)
        {
            CThisType l_matrix;
            for (uint32_t l_row = 0; l_row < M; ++l_row)
            {
                for (uint32_t l_col = 0; l_col < N; ++l_col)
                {
                    l_matrix.m_data[l_row][l_col] = this->m_data[l_row][l_col] - f_val;
                }
            }
            return l_matrix;
        }
        CThisType& operator+=(const CDataType& f_val)
        {
            for (uint32_t l_row = 0; l_row < M; ++l_row)
            {
                for (uint32_t l_col = 0; l_col < N; ++l_col)
                {
                    this->m_data[l_row][l_col] += f_val;
                }
            }
            return *this;
        }
        CThisType& operator-=(const CDataType& f_val)
        {
            for (uint32_t l_row = 0; l_row < M; ++l_row)
            {
                for (uint32_t l_col = 0; l_col < N; ++l_col)
                {
                    this->m_data[l_row][l_col] -= f_val;
                }
            }
            return *this;
        }
        CThisType& operator*=(const CDataType& f_val)
        {
            for (uint32_t l_row = 0; l_row < M; ++l_row)
            {
                for (uint32_t l_col = 0; l_col < N; ++l_col)
                {
                    this->m_data[l_row][l_col] *= f_val;
                }
            }
            return *this;
        }
        CThisType& operator*=(const CThisType& f_val)
        {
            CThisType& l_thisRef(*this);
            l_thisRef = l_thisRef * f_val;
            return l_thisRef;
        }
        CThisType& operator/=(const CDataType& f_val)
        {
            for (uint32_t l_row = 0; l_row < M; ++l_row)
            {
                for (uint32_t l_col = 0; l_col < N; ++l_col)
                {
                    this->m_data[l_row][l_col] /= f_val;
                }
            }
            return *this;
        }
        CThisType operator*(const CDataType& f_val)
        {
            CThisType l_matrix;
            for (uint32_t l_row = 0; l_row < M; ++l_row)
            {
                for (uint32_t l_col = 0; l_col < N; ++l_col)
                {
                    l_matrix.m_data[l_row][l_col] = this->m_data[l_row][l_col] * f_val;
                }
            }
            return l_matrix;
        }
        template <uint32_t P>
        CRightMultiplicationResultType<P> operator*(const CRightMultipliableType<P>& f_matrix)
        {
            CRightMultiplicationResultType<P> l_matrix;
            for (uint32_t l_row = 0; l_row < M; ++l_row)
            {
                for (uint32_t l_col = 0; l_col < P; ++l_col)
                {
                    l_matrix[l_row][l_col] = 0;
                    for (uint32_t l_idx = 0; l_idx < N; ++l_idx)
                    {
                        l_matrix[l_row][l_col] += this->m_data[l_row][l_idx] * f_matrix[l_idx][l_col];
                    }
                }
            }
            return l_matrix;
        }
        CThisType inv();

        CTransposeType transpose()
        {
            CTransposeType l_trsp;

            for (uint32_t l_row = 0; l_row < M; ++l_row)
            {
                for (uint32_t l_col = 0; l_col < N; ++l_col)
                {
                    l_trsp.m_data[l_col][l_row] = this->m_data[l_row][l_col];
                }
            }

            return l_trsp;
        }

        template <uint32_t P>
        CRightMultiplicationResultType<P> solve(const CRightMultipliableType<P>& f_B)
        {
            return CLUDecomposition(*this).solve();
        }

        static CThisType zeros()
        {
            CThisType l_res;

            for (uint32_t l_row = 0; l_row < M; ++l_row)
            {
                for (uint32_t l_col = 0; l_col < N; ++l_col)
                {
                    l_res[l_row][l_col] = 0;
                }
            }

            return l_res;
        }

        static CThisType ones()
        {
            CThisType l_res;

            for (uint32_t l_row = 0; l_row < M; ++l_row)
            {
                for (uint32_t l_col = 0; l_col < N; ++l_col)
                {
                    l_res[l_row][l_col] = 1;
                }
            }

            return l_res;
        }

        static CThisType eye()
        {
            CThisType l_res(CThisType::zeros());
            uint32_t l_minDim = std::min(M,N);

            for (uint32_t l_row = 0; l_row < l_minDim; ++l_row)
            {
                l_res[l_row][l_row] = 1;
            }

            return l_res;
        }

    protected:
        std::array<std::array<T,N>,M> m_data;
    };

    template<class T, uint32_t N>
    class CLUDecomposition
    {
    public:
        using CThisType = CLUDecomposition<T,N>;
        using COriginalType = CMatrix<T,N,N>;
        using CDataType =T;

        template <uint32_t P>
        using CLeftMultipliableType = CMatrix<T,P,N>;

        template <uint32_t P>
        using CRightMultipliableType = CMatrix<T,N,P>;

        template <uint32_t P>
        using CLeftMultiplicationResultType = CMatrix<T,P,N>;

        template <uint32_t P>
        using CRightMultiplicationResultType = CMatrix<T,N,P>;

        CLUDecomposition(const CThisType& f_decomposition) : m_L(f_decomposition.m_L), m_U(f_decomposition.m_U), m_P(f_decomposition.m_P) {}
        CLUDecomposition(const CThisType&& f_decomposition) : m_L(f_decomposition.m_L), m_U(f_decomposition.m_U), m_P(f_decomposition.m_P) {}
        CLUDecomposition(const COriginalType& f_matrix) : m_L(), m_U(), m_P() {decompose(f_matrix);}
        CLUDecomposition(const COriginalType&& f_matrix) : m_L(), m_U(), m_P() {decompose(f_matrix);}

        operator COriginalType()
        {
            return m_L * m_U;
        }

        COriginalType inv()
        {
            return triUInv() * triLInv();
        }

        COriginalType triLInv()
        {
            COriginalType l_invL(m_L);

            for (uint32_t l_jdx = 0; l_jdx < N; ++l_jdx)
            {
                l_invL[l_jdx][l_jdx] = 1/l_invL[l_jdx][l_jdx];

                for (uint32_t l_idx = l_jdx+1; l_idx < N; ++l_idx)
                {
                    l_invL[l_idx][l_jdx] = 0;

                    for (uint32_t l_kdx = l_jdx; l_kdx < l_idx; ++l_kdx)
                    {
                        l_invL[l_idx][l_jdx] -= m_L[l_idx][l_kdx]*l_invL[l_kdx][l_jdx];
                    }

                    l_invL[l_idx][l_jdx] /= l_invL[l_idx][l_idx];
                }
            }

            return l_invL;
        }

        COriginalType triUInv()
        {
            COriginalType l_invU(m_U);

            for (int32_t l_jdx = (N-1); l_jdx >= 0; --l_jdx)
            {
                l_invU[l_jdx][l_jdx] = 1/l_invU[l_jdx][l_jdx];

                for (int32_t l_idx = (l_jdx-1); l_idx >= 0; --l_idx)
                {
                    l_invU[l_idx][l_jdx] = 0;

                    for (int32_t l_kdx = (l_idx+1); l_kdx < (l_jdx+1); ++l_kdx)
                    {
                        l_invU[l_idx][l_jdx] -= m_U[l_idx][l_kdx]*l_invU[l_kdx][l_jdx];
                    }

                    l_invU[l_idx][l_jdx] /= l_invU[l_idx][l_idx];
                }
            }

            return l_invU;
        }

        template <uint32_t P>
        CRightMultiplicationResultType<P> solve(const CRightMultipliableType<P>& f_B)
        {
            CRightMultipliableType<P> l_B;

            for (uint32_t l_idx = 0; l_idx < N; ++l_idx)
            {
                for (uint32_t l_jdx = 0; l_jdx < P; ++l_jdx)
                {
                    l_B[l_idx][l_jdx] = f_B[m_P[l_idx]][l_jdx];
                }
            }

            return sTriL(sTriU(l_B));
        }

        template <uint32_t P>
        CRightMultiplicationResultType<P> sTriU(const CRightMultipliableType<P>& f_B)
        {
            return triUInv()*f_B;
        }

        template <uint32_t P>
        CRightMultiplicationResultType<P> sTriL(const CRightMultipliableType<P>& f_B)
        {
            // return triLInv()*f_B;
        }


    // private:
        void decompose(const CMatrix<T,N,N>& f_matrix)
                {
            m_U = f_matrix;
            for (uint32_t l_kdx = 0; l_kdx < (N-1); ++l_kdx)
            {
                m_L[l_kdx][l_kdx] = 1;
                m_P[l_kdx] = l_kdx;

                for(uint32_t l_idx = l_kdx+1; l_idx < N; ++l_idx)
                {
                    m_L[l_idx][l_kdx] = m_U[l_idx][l_kdx]/m_U[l_kdx][l_kdx];
                    m_U[l_idx][l_kdx] = 0;
                    for(uint32_t l_jdx = l_kdx+1; l_jdx < N; ++l_jdx)
                    {
                        m_U[l_idx][l_jdx] = m_U[l_idx][l_jdx] - m_L[l_idx][l_kdx]*m_U[l_kdx][l_jdx];
                    }
                }
            }
            m_L[N-1][N-1] = 1;
            m_P[N-1] = N-1;
        }
        CMatrix<T,N,N> m_L;
        CMatrix<T,N,N> m_U;
        std::array<uint32_t,N> m_P;
    };

    template <class T, uint32_t N>
    using CColVector = CMatrix<T,N,1>;

    template <class T, uint32_t N>
    using CVector = CColVector<T,N>;

    template <class T, uint32_t N>
    using CRowVector = CMatrix<T,1,N>;
};

#include "linalg.inl"

#endif // LINALG_H