commit 76e86cf937c586e19f300b7aafc95fb2b8121847 Author: jgoppert Date: Tue Nov 3 14:46:54 2015 -0500 Initial commit. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..a5309e6b90 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +build*/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000..6cb01964c6 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 2.8) + +project(matrix CXX) + +list(APPEND CMAKE_CXX_FLAGS + -Wall + -Weffc++ + -Wfatal-errors + ) + +string(REPLACE ";" " " CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + +enable_testing() + +include_directories(matrix) + +add_subdirectory(test) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000..1d5f729548 --- /dev/null +++ b/LICENSE @@ -0,0 +1,28 @@ +Copyright (c) 2015, James Goppert +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of ocr nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/matrix/Dcm.hpp b/matrix/Dcm.hpp new file mode 100644 index 0000000000..8222e356d2 --- /dev/null +++ b/matrix/Dcm.hpp @@ -0,0 +1,64 @@ +/** + * @file Dcm.hpp + * + * A direction cosine matrix class. + * + * @author James Goppert + */ + +#pragma once + +#include +#include +#include + +namespace matrix +{ + +template +class Quaternion; + +template +class Dcm : public Matrix +{ +public: + virtual ~Dcm() {}; + + typedef Matrix Vector3; + + Dcm() : Matrix() + { + } + + Dcm(const Quaternion & q) { + // TODO + Dcm &c = *this; + c(0, 0) = 0; + c(0, 1) = 0; + c(0, 2) = 0; + c(1, 0) = 0; + c(1, 1) = 0; + c(1, 2) = 0; + c(2, 0) = 0; + c(2, 1) = 0; + c(2, 2) = 0; + } + + Dcm(const Euler & e) { + // TODO + Dcm &c = *this; + c(0, 0) = 0; + c(0, 1) = 0; + c(0, 2) = 0; + c(1, 0) = 0; + c(1, 1) = 0; + c(1, 2) = 0; + c(2, 0) = 0; + c(2, 1) = 0; + c(2, 2) = 0; + } +}; + +typedef Dcm Dcmf; + +}; // namespace matrix diff --git a/matrix/Euler.hpp b/matrix/Euler.hpp new file mode 100644 index 0000000000..d6a7178f89 --- /dev/null +++ b/matrix/Euler.hpp @@ -0,0 +1,61 @@ +/** + * @file Euler.hpp + * + * Euler angle tait-bryan body 3-2-1 + * + * @author James Goppert + */ + +#pragma once +#include +#include +#include + +namespace matrix +{ + +template +class Dcm; + +template +class Quaternion; + +template +class Euler : public Vector +{ +public: + virtual ~Euler() {}; + + Euler() : Vector() + { + } + + Euler(Type roll, Type pitch, Type yaw) : Vector() + { + Euler &v(*this); + v(0) = roll; + v(1) = pitch; + v(2) = yaw; + } + + Euler(const Dcm & dcm) { + // TODO + Euler &e = *this; + e(0) = 0; + e(1) = 0; + e(2) = 0; + } + + Euler(const Quaternion & q) { + // TODO + Euler &e = *this; + e(0) = 0; + e(1) = 0; + e(2) = 0; + } + +}; + +typedef Euler Eulerf; + +}; // namespace matrix diff --git a/matrix/Matrix.hpp b/matrix/Matrix.hpp new file mode 100644 index 0000000000..ee94b6020a --- /dev/null +++ b/matrix/Matrix.hpp @@ -0,0 +1,472 @@ +/** + * @file Matrix.hpp + * + * A simple matrix template library. + * + * @author James Goppert + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace matrix +{ + +template +class Matrix +{ + +protected: + Type _data[M][N]; + size_t _rows; + size_t _cols; + +public: + + virtual ~Matrix() {}; + + Matrix() : + _data(), + _rows(M), + _cols(N) + { + } + + Matrix(const Type *data) : + _data(), + _rows(M), + _cols(N) + { + memcpy(_data, data, sizeof(_data)); + } + + Matrix(const Matrix &other) : + _data(), + _rows(M), + _cols(N) + { + memcpy(_data, other._data, sizeof(_data)); + } + + /** + * Accessors/ Assignment etc. + */ + + Type *data() + { + return _data[0]; + } + + inline size_t rows() const + { + return _rows; + } + + inline size_t cols() const + { + return _rows; + } + + inline Type operator()(size_t i, size_t j) const + { + return _data[i][j]; + } + + inline Type &operator()(size_t i, size_t j) + { + return _data[i][j]; + } + + /** + * Matrix Operations + */ + + // this might use a lot of programming memory + // since it instantiates a class for every + // required mult pair, but it provides + // compile time size_t checking + template + Matrix operator*(const Matrix &other) const + { + const Matrix &self = *this; + Matrix res; + res.setZero(); + + for (size_t i = 0; i < M; i++) { + for (size_t k = 0; k < P; k++) { + for (size_t j = 0; j < N; j++) { + res(i, k) += self(i, j) * other(j, k); + } + } + } + + return res; + } + + Matrix operator+(const Matrix &other) const + { + Matrix res; + const Matrix &self = *this; + + for (size_t i = 0; i < M; i++) { + for (size_t j = 0; j < N; j++) { + res(i , j) = self(i, j) + other(i, j); + } + } + + return res; + } + + bool operator==(const Matrix &other) const + { + Matrix res; + const Matrix &self = *this; + + for (size_t i = 0; i < M; i++) { + for (size_t j = 0; j < N; j++) { + if (self(i , j) != other(i, j)) { + return false; + } + } + } + + return true; + } + + operator Type(); + + Matrix operator-(const Matrix &other) const + { + Matrix res; + const Matrix &self = *this; + + for (size_t i = 0; i < M; i++) { + for (size_t j = 0; j < N; j++) { + res(i , j) = self(i, j) - other(i, j); + } + } + + return res; + } + + void operator+=(const Matrix &other) + { + Matrix &self = *this; + self = self + other; + } + + void operator-=(const Matrix &other) + { + Matrix &self = *this; + self = self - other; + } + + void operator*=(const Matrix &other) + { + Matrix &self = *this; + self = self * other; + } + + /** + * Scalar Operations + */ + + Matrix operator*(Type scalar) const + { + Matrix res; + const Matrix &self = *this; + + for (size_t i = 0; i < M; i++) { + for (size_t j = 0; j < N; j++) { + res(i , j) = self(i, j) * scalar; + } + } + + return res; + } + + Matrix operator+(Type scalar) const + { + Matrix res; + Matrix &self = *this; + + for (size_t i = 0; i < M; i++) { + for (size_t j = 0; j < N; j++) { + res(i , j) = self(i, j) + scalar; + } + } + + return res; + } + + void operator*=(Type scalar) + { + Matrix &self = *this; + + for (size_t i = 0; i < M; i++) { + for (size_t j = 0; j < N; j++) { + self(i, j) = self(i, j) * scalar; + } + } + } + + void operator/=(Type scalar) + { + Matrix &self = *this; + self = self * (1.0f / scalar); + } + + /** + * Misc. Functions + */ + + void print() + { + Matrix &self = *this; + printf("\n"); + + for (size_t i = 0; i < M; i++) { + printf("["); + + for (size_t j = 0; j < N; j++) { + printf("%10g\t", double(self(i, j))); + } + + printf("]\n"); + } + } + + Matrix transpose() const + { + Matrix res; + const Matrix &self = *this; + + for (size_t i = 0; i < M; i++) { + for (size_t j = 0; j < N; j++) { + res(j, i) = self(i, j); + } + } + + return res; + } + + + // tranpose alias + inline Matrix T() const + { + return transpose(); + } + + Matrix expm(float dt, size_t n) const + { + Matrix res; + res.setIdentity(); + Matrix A_pow = *this; + float k_fact = 1; + size_t k = 1; + + while (k < n) { + res += A_pow * (float(pow(dt, k)) / k_fact); + + if (k == n) { break; } + + A_pow *= A_pow; + k_fact *= k; + k++; + } + + return res; + } + + Matrix diagonal() const + { + Matrix res; + // force square for now + const Matrix &self = *this; + + for (size_t i = 0; i < M; i++) { + res(i) = self(i, i); + } + + return res; + } + + void setZero() + { + memset(_data, 0, sizeof(_data)); + } + + void setIdentity() + { + setZero(); + Matrix &self = *this; + + for (size_t i = 0; i < M and i < N; i++) { + self(i, i) = 1; + } + } + + inline void swapRows(size_t a, size_t b) + { + if (a == b) { return; } + + Matrix &self = *this; + + for (size_t j = 0; j < cols(); j++) { + Type tmp = self(a, j); + self(a, j) = self(b, j); + self(b, j) = tmp; + } + } + + inline void swapCols(size_t a, size_t b) + { + if (a == b) { return; } + + Matrix &self = *this; + + for (size_t i = 0; i < rows(); i++) { + Type tmp = self(i, a); + self(i, a) = self(i, b); + self(i, b) = tmp; + } + } + + /** + * inverse based on LU factorization with partial pivotting + */ + Matrix inverse() const + { + Matrix L; + L.setIdentity(); + const Matrix &A = (*this); + Matrix U = A; + Matrix P; + P.setIdentity(); + + //printf("A:\n"); A.print(); + + // for all diagonal elements + for (size_t n = 0; n < N; n++) { + + // if diagonal is zero, swap with row below + if (fabsf(U(n, n)) < 1e-8f) { + //printf("trying pivot for row %d\n",n); + for (size_t i = 0; i < N; i++) { + if (i == n) { continue; } + + //printf("\ttrying row %d\n",i); + if (fabsf(U(i, n)) > 1e-8f) { + //printf("swapped %d\n",i); + U.swapRows(i, n); + P.swapRows(i, n); + } + } + } + +#ifdef MATRIX_ASSERT + //printf("A:\n"); A.print(); + //printf("U:\n"); U.print(); + //printf("P:\n"); P.print(); + //fflush(stdout); + ASSERT(fabsf(U(n, n)) > 1e-8f); +#endif + + // failsafe, return zero matrix + if (fabsf(U(n, n)) < 1e-8f) { + Matrix zero; + zero.setZero(); + return zero; + } + + // for all rows below diagonal + for (size_t i = (n + 1); i < N; i++) { + L(i, n) = U(i, n) / U(n, n); + + // add i-th row and n-th row + // multiplied by: -a(i,n)/a(n,n) + for (size_t k = n; k < N; k++) { + U(i, k) -= L(i, n) * U(n, k); + } + } + } + + //printf("L:\n"); L.print(); + //printf("U:\n"); U.print(); + + // solve LY=P*I for Y by forward subst + Matrix Y = P; + + // for all columns of Y + for (size_t c = 0; c < N; c++) { + // for all rows of L + for (size_t i = 0; i < N; i++) { + // for all columns of L + for (size_t j = 0; j < i; j++) { + // for all existing y + // subtract the component they + // contribute to the solution + Y(i, c) -= L(i, j) * Y(j, c); + } + + // divide by the factor + // on current + // term to be solved + // Y(i,c) /= L(i,i); + // but L(i,i) = 1.0 + } + } + + //printf("Y:\n"); Y.print(); + + // solve Ux=y for x by back subst + Matrix X = Y; + + // for all columns of X + for (size_t c = 0; c < N; c++) { + // for all rows of U + for (size_t k = 0; k < N; k++) { + // have to go in reverse order + size_t i = N - 1 - k; + + // for all columns of U + for (size_t j = i + 1; j < N; j++) { + // for all existing x + // subtract the component they + // contribute to the solution + X(i, c) -= U(i, j) * X(j, c); + } + + // divide by the factor + // on current + // term to be solved + X(i, c) /= U(i, i); + } + } + + //printf("X:\n"); X.print(); + return X; + } + + // inverse alias + inline Matrix I() const + { + return inverse(); + } + +}; + +template <> +Matrix::operator float() +{ + return (*this)(0,0); +} + +typedef Matrix Matrix3f; + +}; // namespace matrix diff --git a/matrix/Quaternion.hpp b/matrix/Quaternion.hpp new file mode 100644 index 0000000000..91b344cd3d --- /dev/null +++ b/matrix/Quaternion.hpp @@ -0,0 +1,89 @@ +/** + * @file Matrix.hpp + * + * A quaternion class. + * + * @author James Goppert + */ + +#pragma once +#include +#include +#include + +namespace matrix +{ + +template +class Dcm; + +template +class Euler; + +template +class Quaternion : public Vector +{ +public: + virtual ~Quaternion() {}; + + Quaternion() : Vector() + { + // TODO + Quaternion &q = *this; + q(0) = 1; + q(1) = 0; + q(2) = 0; + q(3) = 0; + } + + Quaternion(const Dcm & dcm) { + // TODO + Quaternion &q = *this; + q(0) = 0; + q(1) = 0; + q(2) = 0; + q(3) = 0; + } + + Quaternion(const Euler & e) { + // TODO + Quaternion &q = *this; + q(0) = 0; + q(1) = 0; + q(2) = 0; + q(3) = 0; + } + + Quaternion(Type a, Type b, Type c, Type d) : Vector() + { + // TODO + Quaternion &q = *this; + q(0) = a; + q(1) = b; + q(2) = c; + q(3) = d; + } + + Quaternion operator*(const Quaternion &q) const + { + // TODO + const Quaternion &p = *this; + Quaternion r; + r(0) = 0; + r(1) = 0; + r(2) = 0; + r(3) = 0; + return r; + } + + Matrix derivative() const { + // TODO + Matrix d; + return d; + } + +}; + +typedef Quaternion Quatf; + +}; // namespace matrix diff --git a/matrix/Vector.hpp b/matrix/Vector.hpp new file mode 100644 index 0000000000..3f8731bfc1 --- /dev/null +++ b/matrix/Vector.hpp @@ -0,0 +1,52 @@ +/** + * @file Vector.hpp + * + * Vector class. + * + * @author James Goppert + */ + +#pragma once +#include + +namespace matrix +{ + +template +class Vector : public Matrix +{ +public: + virtual ~Vector() {}; + + Vector() : Matrix() + { + } + + inline Type operator()(size_t i) const + { + const Matrix &v = *this; + return v(i, 0); + } + + inline Type &operator()(size_t i) + { + Matrix &v = *this; + return v(i, 0); + } + + Type dot(const Vector & b) { + Vector &a(*this); + Type r = 0; + for (int i = 0; i<3; i++) { + r += a(i)*b(i); + } + return r; + } + + Type norm() { + Vector &a(*this); + return sqrt(a.dot(a)); + } +}; + +}; // namespace matrix diff --git a/matrix/Vector3.hpp b/matrix/Vector3.hpp new file mode 100644 index 0000000000..ff4d87208c --- /dev/null +++ b/matrix/Vector3.hpp @@ -0,0 +1,46 @@ +/** + * @file Vector3.hpp + * + * 3D vector class. + * + * @author James Goppert + */ + +#pragma once +#include + +namespace matrix +{ + +template +class Vector3 : public Vector +{ +public: + virtual ~Vector3() {}; + + Vector3() : Vector() + { + } + + Vector3(Type x, Type y, Type z) : Vector() + { + Vector3 &v(*this); + v(0) = x; + v(1) = y; + v(2) = z; + } + + Vector3 cross(const Vector3 & b) { + // TODO + Vector3 &a(*this); + Vector3 c; + c(0) = 0; + c(1) = 0; + c(2) = 0; + return c; + } +}; + +typedef Vector3 Vector3f; + +}; // namespace matrix diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000000..4c37fe51c9 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,20 @@ +set(tests + setIdentity + inverse + matrixMult + vectorAssignment + matrixAssignment + matrixScalarMult + transpose + quaternion + dcm + vector + vector3 + euler + ) + +foreach(test ${tests}) + add_executable(${test} + ${test}.cpp) + add_test(${test} ${test}) +endforeach() diff --git a/test/dcm.cpp b/test/dcm.cpp new file mode 100644 index 0000000000..aa150a3552 --- /dev/null +++ b/test/dcm.cpp @@ -0,0 +1,13 @@ +#include "Dcm.hpp" +#include +#include + +using namespace matrix; + +int main() +{ + Dcmf dcm; + Quatf q = Quatf(dcm); + Eulerf e = Eulerf(dcm); + return 0; +} diff --git a/test/euler.cpp b/test/euler.cpp new file mode 100644 index 0000000000..d5b3a4c30b --- /dev/null +++ b/test/euler.cpp @@ -0,0 +1,15 @@ +#include "Euler.hpp" +#include +#include + +using namespace matrix; + +int main() +{ + Eulerf e; + float dp = e.T()*e; + Dcmf dcm = Dcmf(e); + Quatf q = Quatf(e); + float n = e.norm(); + return 0; +} diff --git a/test/inverse.cpp b/test/inverse.cpp new file mode 100644 index 0000000000..73f7c0b432 --- /dev/null +++ b/test/inverse.cpp @@ -0,0 +1,30 @@ +#include "Matrix.hpp" +#include +#include + +using namespace matrix; + +int main() +{ + float data[9] = {1, 0, 0, 0, 1, 0, 1, 0, 1}; + Matrix3f A(data); + Matrix3f A_I = A.inverse(); + float data_check[9] = {1, 0, 0, 0, 1, 0, -1, 0, 1}; + Matrix3f A_I_check(data_check); + (void)A_I; + assert(A_I == A_I_check); + + // stess test + static const size_t n = 100; + Matrix A_large; + A_large.setIdentity(); + Matrix A_large_I; + A_large_I.setZero(); + + for (size_t i = 0; i < 100; i++) { + A_large_I = A_large.inverse(); + assert(A_large == A_large_I); + } + + return 0; +} diff --git a/test/matrixAssignment.cpp b/test/matrixAssignment.cpp new file mode 100644 index 0000000000..5a625d0cc1 --- /dev/null +++ b/test/matrixAssignment.cpp @@ -0,0 +1,29 @@ +#include "Matrix.hpp" +#include + +using namespace matrix; + +int main() +{ + Matrix3f m; + m.setZero(); + m(0, 0) = 1; + m(0, 1) = 2; + m(0, 2) = 3; + m(1, 0) = 4; + m(1, 1) = 5; + m(1, 2) = 6; + m(2, 0) = 7; + m(2, 1) = 8; + m(2, 2) = 9; + + m.print(); + + float data[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; + Matrix3f m2(data); + m2.print(); + + assert(m == m2); + + return 0; +} diff --git a/test/matrixMult.cpp b/test/matrixMult.cpp new file mode 100644 index 0000000000..7b42d947d4 --- /dev/null +++ b/test/matrixMult.cpp @@ -0,0 +1,26 @@ +#include "Matrix.hpp" +#include +#include + +using namespace matrix; + +int main() +{ + float data[9] = {1, 0, 0, 0, 1, 0, 1, 0, 1}; + Matrix3f A(data); + float data_check[9] = {1, 0, 0, 0, 1, 0, -1, 0, 1}; + Matrix3f A_I(data_check); + Matrix3f I; + I.setIdentity(); + A.print(); + A_I.print(); + Matrix3f R = A * A_I; + R.print(); + assert(R == I); + + Matrix3f R2 = A; + R2 *= A_I; + R2.print(); + assert(R2 == I); + return 0; +} diff --git a/test/matrixScalarMult.cpp b/test/matrixScalarMult.cpp new file mode 100644 index 0000000000..78bdb5b27f --- /dev/null +++ b/test/matrixScalarMult.cpp @@ -0,0 +1,18 @@ +#include "Matrix.hpp" +#include +#include + +using namespace matrix; + +int main() +{ + float data[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; + Matrix3f A(data); + A = A * 2; + float data_check[9] = {2, 4, 6, 8, 10, 12, 14, 16, 18}; + Matrix3f A_check(data_check); + A.print(); + A_check.print(); + assert(A == A_check); + return 0; +} diff --git a/test/quaternion.cpp b/test/quaternion.cpp new file mode 100644 index 0000000000..40c36adf58 --- /dev/null +++ b/test/quaternion.cpp @@ -0,0 +1,15 @@ +#include "Quaternion.hpp" +#include +#include + +using namespace matrix; + +int main() +{ + Quatf p(1, 0, 0, 0); + Quatf q(0, 1, 0, 0); + Quatf r = p*q; + Dcmf dcm = Dcmf(p); + Eulerf e = Eulerf(p); + return 0; +} diff --git a/test/setIdentity.cpp b/test/setIdentity.cpp new file mode 100644 index 0000000000..f80e437939 --- /dev/null +++ b/test/setIdentity.cpp @@ -0,0 +1,25 @@ +#include "Matrix.hpp" +#include + +using namespace matrix; + +int main() +{ + Matrix3f A; + A.setIdentity(); + assert(A.rows() == 3); + assert(A.cols() == 3); + + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + if (i == j) { + assert(A(i, j) == 1); + + } else { + assert(A(i, j) == 0); + } + } + } + + return 0; +} diff --git a/test/transpose.cpp b/test/transpose.cpp new file mode 100644 index 0000000000..3623fc1f9a --- /dev/null +++ b/test/transpose.cpp @@ -0,0 +1,18 @@ +#include "Matrix.hpp" +#include +#include + +using namespace matrix; + +int main() +{ + float data[9] = {1, 2, 3, 4, 5, 6}; + Matrix A(data); + Matrix A_T = A.transpose(); + float data_check[9] = {1, 4, 2, 5, 3, 6}; + Matrix A_T_check(data_check); + A_T.print(); + A_T_check.print(); + assert(A_T == A_T_check); + return 0; +} diff --git a/test/vector.cpp b/test/vector.cpp new file mode 100644 index 0000000000..3da9f8a01a --- /dev/null +++ b/test/vector.cpp @@ -0,0 +1,13 @@ +#include "Vector.hpp" +#include +#include + +using namespace matrix; + +int main() +{ + Vector v; + float n = v.norm(); + float r = v.dot(v); + return 0; +} diff --git a/test/vector3.cpp b/test/vector3.cpp new file mode 100644 index 0000000000..f79186504e --- /dev/null +++ b/test/vector3.cpp @@ -0,0 +1,13 @@ +#include "Vector3.hpp" +#include +#include + +using namespace matrix; + +int main() +{ + Vector3f a(1, 0, 0); + Vector3f b(0, 1, 0); + Vector3f c = a.cross(b); + return 0; +} diff --git a/test/vectorAssignment.cpp b/test/vectorAssignment.cpp new file mode 100644 index 0000000000..7d7c7a36a4 --- /dev/null +++ b/test/vectorAssignment.cpp @@ -0,0 +1,28 @@ +#include "Vector3.hpp" +#include + +using namespace matrix; + +int main() +{ + Vector3f v; + v(0) = 1; + v(1) = 2; + v(2) = 3; + + v.print(); + + assert(v(0) == 1); + assert(v(1) == 2); + assert(v(2) == 3); + + Vector3f v2(4, 5, 6); + + v2.print(); + + assert(v2(0) == 4); + assert(v2(1) == 5); + assert(v2(2) == 6); + + return 0; +}