/** * @file Slice.hpp * * A simple matrix template library. * * @author Julian Kent < julian@auterion.com > */ #pragma once #include "math.hpp" namespace matrix { template class Matrix; template class Vector; template class Slice { public: Slice(size_t x0, size_t y0, const Matrix* data) : _x0(x0), _y0(y0), _data(const_cast*>(data)) { static_assert(P <= M, "Slice rows bigger than backing matrix"); static_assert(Q <= N, "Slice cols bigger than backing matrix"); assert(x0 + P <= M); assert(y0 + Q <= N); } const Type &operator()(size_t i, size_t j) const { assert(i < P); assert(j < Q); return (*_data)(_x0 + i, _y0 + j); } Type &operator()(size_t i, size_t j) { assert(i < P); assert(j < Q); return (*_data)(_x0 + i, _y0 + j); } template Slice& operator=(const Slice& other) { Slice& self = *this; for (size_t i = 0; i < P; i++) { for (size_t j = 0; j < Q; j++) { self(i, j) = other(i, j); } } return self; } Slice& operator=(const Matrix& other) { Slice& self = *this; for (size_t i = 0; i < P; i++) { for (size_t j = 0; j < Q; j++) { self(i, j) = other(i, j); } } return self; } Slice& operator=(const Type& other) { Slice& self = *this; for (size_t i = 0; i < P; i++) { for (size_t j = 0; j < Q; j++) { self(i, j) = other; } } return self; } // allow assigning vectors to a slice that are in the axis template // make this a template function since it only exists for some instantiations Slice& operator=(const Vector& other) { Slice& self = *this; for (size_t j = 0; j < Q; j++) { self(0, j) = other(j); } return self; } template Slice& operator+=(const Slice& other) { Slice& self = *this; for (size_t i = 0; i < P; i++) { for (size_t j = 0; j < Q; j++) { self(i, j) += other(i, j); } } return self; } Slice& operator+=(const Matrix& other) { Slice& self = *this; for (size_t i = 0; i < P; i++) { for (size_t j = 0; j < Q; j++) { self(i, j) += other(i, j); } } return self; } Slice& operator+=(const Type& other) { Slice& self = *this; for (size_t i = 0; i < P; i++) { for (size_t j = 0; j < Q; j++) { self(i, j) += other; } } return self; } template Slice& operator-=(const Slice& other) { Slice& self = *this; for (size_t i = 0; i < P; i++) { for (size_t j = 0; j < Q; j++) { self(i, j) -= other(i, j); } } return self; } Slice& operator-=(const Matrix& other) { Slice& self = *this; for (size_t i = 0; i < P; i++) { for (size_t j = 0; j < Q; j++) { self(i, j) -= other(i, j); } } return self; } Slice& operator-=(const Type& other) { Slice& self = *this; for (size_t i = 0; i < P; i++) { for (size_t j = 0; j < Q; j++) { self(i, j) -= other; } } return self; } Slice& operator*=(const Type& other) { Slice& self = *this; for (size_t i = 0; i < P; i++) { for (size_t j = 0; j < Q; j++) { self(i, j) *= other; } } return self; } Slice& operator/=(const Type& other) { return operator*=(Type(1) / other); } Matrix operator*(const Type& other) const { const Slice& self = *this; Matrix res; for (size_t i = 0; i < P; i++) { for (size_t j = 0; j < Q; j++) { res(i, j) = self(i, j) * other; } } return res; } Matrix operator/(const Type& other) const { const Slice& self = *this; return self * (Type(1) / other); } template const Slice slice(size_t x0, size_t y0) const { return Slice(x0 + _x0, y0 + _y0, _data); } template Slice slice(size_t x0, size_t y0) { return Slice(x0 + _x0, y0 + _y0, _data); } void copyTo(Type dst[P*Q]) const { const Slice &self = *this; for (size_t i = 0; i < P; i++) { for (size_t j = 0; j < Q; j++) { dst[i*N+j] = self(i, j); } } } void copyToColumnMajor(Type dst[P*Q]) const { const Slice &self = *this; for (size_t i = 0; i < P; i++) { for (size_t j = 0; j < Q; j++) { dst[i+(j*M)] = self(i, j); } } } Vector diag() const { const Slice& self = *this; Vector res; for (size_t j = 0; j < (P& self = *this; Type accum(0); for (size_t i = 0; i < P; i++) { for (size_t j = 0; j < Q; j++) { accum += self(i, j)*self(i, j); } } return accum; } Type norm() const { return matrix::sqrt(norm_squared()); } bool longerThan(Type testVal) const { return norm_squared() > testVal*testVal; } private: size_t _x0, _y0; Matrix* _data; }; }