Adafruit driver converted to mbed.

Dependents:   BNO055_Adafruit SpriteIMU

matrix.h

Committer:
simonscott
Date:
2015-09-16
Revision:
2:8092160b6a59
Parent:
0:22c544c8741a

File content as of revision 2:8092160b6a59:

/*
    Inertial Measurement Unit Maths Library
    Copyright (C) 2013-2014  Samuel Cowen
    www.camelsoftware.com

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef IMUMATH_MATRIX_HPP
#define IMUMATH_MATRIX_HPP

#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <math.h>

namespace imu
{


template <uint8_t N> class Matrix
{
public:
    Matrix()
    {
        int r = sizeof(double)*N;
        _cell = &_cell_data[0];
        memset(_cell, 0, r*r);
    }

    Matrix(const Matrix &v)
    {
        int r = sizeof(double)*N;
        _cell = &_cell_data[0];
        memset(_cell, 0, r*r);
        for (int x = 0; x < N; x++ )
        {
            for(int y = 0; y < N; y++)
            {
                _cell[x*N+y] = v._cell[x*N+y];
            }
        }
    }

    ~Matrix()
    {
    }

    void operator = (Matrix m)
    {
        for(int x = 0; x < N; x++)
        {
            for(int y = 0; y < N; y++)
            {
                cell(x, y) = m.cell(x, y);
            }
        }
    }

    Vector<N> row_to_vector(int y)
    {
        Vector<N> ret;
        for(int i = 0; i < N; i++)
        {
            ret[i] = _cell[y*N+i];
        }
        return ret;
    }

    Vector<N> col_to_vector(int x)
    {
        Vector<N> ret;
        for(int i = 0; i < N; i++)
        {
            ret[i] = _cell[i*N+x];
        }
        return ret;
    }

    void vector_to_row(Vector<N> v, int row)
    {
        for(int i = 0; i < N; i++)
        {
            cell(row, i) = v(i);
        }
    }

    void vector_to_col(Vector<N> v, int col)
    {
        for(int i = 0; i < N; i++)
        {
            cell(i, col) = v(i);
        }
    }

    double& operator ()(int x, int y)
    {
        return _cell[x*N+y];
    }

    double& cell(int x, int y)
    {
        return _cell[x*N+y];
    }


    Matrix operator + (Matrix m)
    {
        Matrix ret;
        for(int x = 0; x < N; x++)
        {
            for(int y = 0; y < N; y++)
            {
                ret._cell[x*N+y] = _cell[x*N+y] + m._cell[x*N+y];
            }
        }
        return ret;
    }

    Matrix operator - (Matrix m)
    {
        Matrix ret;
        for(int x = 0; x < N; x++)
        {
            for(int y = 0; y < N; y++)
            {
                ret._cell[x*N+y] = _cell[x*N+y] - m._cell[x*N+y];
            }
        }
        return ret;
    }

    Matrix operator * (double scalar)
    {
        Matrix ret;
        for(int x = 0; x < N; x++)
        {
            for(int y = 0; y < N; y++)
            {
                ret._cell[x*N+y] = _cell[x*N+y] * scalar;
            }
        }
        return ret;
    }

    Matrix operator * (Matrix m)
    {
        Matrix ret;
        for(int x = 0; x < N; x++)
        {
            for(int y = 0; y < N; y++)
            {
                Vector<N> row = row_to_vector(x);
                Vector<N> col = m.col_to_vector(y);
                ret.cell(x, y) = row.dot(col);
            }
        }
        return ret;
    }

    Matrix transpose()
    {
        Matrix ret;
        for(int x = 0; x < N; x++)
        {
            for(int y = 0; y < N; y++)
            {
                ret.cell(y, x) = cell(x, y);
            }
        }
        return ret;
    }

    Matrix<N-1> minor_matrix(int row, int col)
    {
        int colCount = 0, rowCount = 0;
        Matrix<N-1> ret;
        for(int i = 0; i < N; i++ )
        {
            if( i != row )
            {
                for(int j = 0; j < N; j++ )
                {
                    if( j != col )
                    {
                        ret(rowCount, colCount) = cell(i, j);
                        colCount++;
                    }
                }
                rowCount++;
            }
        }
        return ret;
    }

    double determinant()
    {
        if(N == 1)
            return cell(0, 0);

        float det = 0.0;
        for(int i = 0; i < N; i++ )
        {
            Matrix<N-1> minor = minor_matrix(0, i);
            det += (i%2==1?-1.0:1.0) * cell(0, i) * minor.determinant();
        }
        return det;
    }

    Matrix invert()
    {
        Matrix ret;
        float det = determinant();

        for(int x = 0; x < N; x++)
        {
            for(int y = 0; y < N; y++)
            {
                Matrix<N-1> minor = minor_matrix(y, x);
                ret(x, y) = det*minor.determinant();
                if( (x+y)%2 == 1)
                    ret(x, y) = -ret(x, y);
            }
        }
        return ret;
    }

private:
    double* _cell;
    double  _cell_data[N*N];
};


};

#endif