diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..d9cf81d --- /dev/null +++ b/.clang-format @@ -0,0 +1,86 @@ +--- +Language: Cpp +AccessModifierOffset: -4 +AlignAfterOpenBracket: AlwaysBreak +AlignConsecutiveAssignments: true +AlignConsecutiveDeclarations: false +AlignEscapedNewlinesLeft: false +AlignOperands: true +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: true +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: true +BinPackArguments: false +BinPackParameters: false +BraceWrapping: + AfterClass: true + AfterControlStatement: true + AfterEnum: true + AfterFunction: true + AfterNamespace: false + AfterStruct: true + AfterUnion: true + BeforeCatch: true + BeforeElse: true + IndentBraces: false +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Custom +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: true +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 80 +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + - Regex: '^(<|"(gtest|isl|json)/)' + Priority: 3 + - Regex: '.*' + Priority: 1 +IncludeIsMainRegex: '$' +IndentCaseLabels: false +IndentWidth: 4 +IndentWrappedFunctionNames: false +KeepEmptyLinesAtTheStartOfBlocks: true +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 200 +PointerAlignment: Left +ReflowComments: true +SortIncludes: true +SpaceAfterCStyleCast: true +SpaceAfterTemplateKeyword: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: ControlStatements +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp11 +TabWidth: 4 +UseTab: Never +... + diff --git a/.clang_complete b/.clang_complete new file mode 100644 index 0000000..25ea966 --- /dev/null +++ b/.clang_complete @@ -0,0 +1,5 @@ +-I. +-Iinclude +-Ibuild-debug/src +-Ivendor/Box2D/Box2D/include +-Ivendor/googletest/include \ No newline at end of file diff --git a/include/cece/math/Matrix.hpp b/include/cece/math/Matrix.hpp new file mode 100644 index 0000000..b11861f --- /dev/null +++ b/include/cece/math/Matrix.hpp @@ -0,0 +1,316 @@ +/* ************************************************************************ */ +/* Georgiev Lab (c) 2015-2017 */ +/* ************************************************************************ */ +/* Department of Cybernetics */ +/* Faculty of Applied Sciences */ +/* University of West Bohemia in Pilsen */ +/* ************************************************************************ */ +/* */ +/* This file is part of CeCe. */ +/* */ +/* CeCe 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. */ +/* */ +/* CeCe 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 CeCe. If not, see . */ +/* */ +/* ************************************************************************ */ + +#pragma once + +/* ************************************************************************ */ + +// CeCe +#include "cece/math/Zero.hpp" +#include "cece/math/MatrixBase.hpp" +#include "cece/math/Vector.hpp" +#include "cece/unit/Units.hpp" + +/* ************************************************************************ */ + +namespace cece { +namespace math { + +/* ************************************************************************ */ + +/** + * @brief 2D matrix implementation. + * + * @tparam T Type of stored value. + * @tparam R Number of rows. + * @tparam C Number of columns. + */ +template +struct Matrix : public MatrixBase +{ + +// Public Types +public: + + + /// Row type. + using RowType = Vector; + + /// Column type. + using ColumnType = Vector; + + +// Public Data Members +public: + + + /// Matrix data. + Vector m; + + +// Public Ctors +public: + + + /** + * @brief Default constructor. + */ + Matrix(); + + + /** + * @brief Zero constructor. + * + * @param[in] zero Zero value. + */ + Matrix(Zero_t zero); + + + /** + * @brief Constructor. + * + * @param src Initial data + */ + Matrix(const T (&src)[R][C]); + + + /** + * @brief Constructor. + * + * @param src Initial data + */ + Matrix(const RowType (&src)[R]); + + + /** + * @brief Copy constructor. + * + * @param src Source matrix. + */ + Matrix(const Matrix& src); + + + /** + * @brief Move constructor. + * + * @param src Source matrix. + */ + Matrix(Matrix&& src); + + +// Public Operators +public: + + + /** + * @brief Copy assignment operator. + * + * @param src The source matrix. + * + * @return *this. + */ + Matrix& operator=(const Matrix& src); + + + /** + * @brief Move assignment operator. + * + * @param src The source matrix. + * + * @return *this. + */ + Matrix& operator=(Matrix&& src); + + + /** + * @brief Row access operator. + * + * @param[in] pos The row number. + * + * @return Row. + */ + RowType& operator[](int pos) noexcept; + + + /** + * @brief Row access operator. + * + * @param pos The row number. + * + * @return Row. + */ + const RowType& operator[](int pos) const noexcept; + + + /** + * @brief Element access operator. + * + * @param coord Coordinates. + * + * @return Element. + */ + T& operator[](Vector2 coord) noexcept; + + + /** + * @brief Element access operator. + * + * @param coord Coordinates. + * + * @return Element. + */ + const T& operator[](Vector2 coord) const noexcept; + +}; + +/* ************************************************************************ */ + +} +} + +/* ************************************************************************ */ +/* ************************************************************************ */ +/* ************************************************************************ */ + +namespace cece { +namespace math { + +/* ************************************************************************ */ + +template +inline Matrix::Matrix() +{ + // Nothing to do +} + +/* ************************************************************************ */ + +template +inline Matrix::Matrix(Zero_t zero) +{ + for (int row = 0; row < R; ++row) + for (int col = 0; col < C; ++col) + m[row][col] = Zero; +} + +/* ************************************************************************ */ + +template +inline Matrix::Matrix(const T (&src)[R][C]) +{ + for (int row = 0; row < R; ++row) + for (int col = 0; col < C; ++col) + m[row][col] = src[row][col]; +} + +/* ************************************************************************ */ + +template +inline Matrix::Matrix(const RowType (&src)[R]) +{ + for (int row = 0; row < R; ++row) + for (int col = 0; col < C; ++col) + m[row][col] = src[row][col]; +} + +/* ************************************************************************ */ + +template +inline Matrix::Matrix(const Matrix& src) +{ + for (int row = 0; row < R; ++row) + for (int col = 0; col < C; ++col) + m[row][col] = src[row][col]; +} + +/* ************************************************************************ */ + +template +inline Matrix::Matrix(Matrix&& src) +{ + for (int row = 0; row < R; ++row) + for (int col = 0; col < C; ++col) + m[row][col] = std::move(src[row][col]); +} + +/* ************************************************************************ */ + +template +inline Matrix& Matrix::operator=(const Matrix& src) +{ + for (int row = 0; row < R; ++row) + for (int col = 0; col < C; ++col) + m[row][col] = src[row][col]; +} + +/* ************************************************************************ */ + +template +inline Matrix& Matrix::operator=(Matrix&& src) +{ + for (int row = 0; row < R; ++row) + for (int col = 0; col < C; ++col) + m[row][col] = std::move(src[row][col]); +} + +/* ************************************************************************ */ + +template +inline Matrix::RowType& Matrix::operator[](int pos) noexcept +{ + return m[pos]; +} + +/* ************************************************************************ */ + +template +inline const Matrix::RowType& Matrix::operator[](int pos) const noexcept +{ + return m[pos]; +} + +/* ************************************************************************ */ + +template +inline T& Matrix::operator[](Vector2 coord) noexcept +{ + return m[coord.x][coord.y]; +} + +/* ************************************************************************ */ + +template +inline const T& Matrix::operator[](Vector2 coord) const noexcept +{ + return m[coord.x][coord.y]; +} + +/* ************************************************************************ */ + +} +} + +/* ************************************************************************ */ + diff --git a/include/cece/math/MatrixBase.hpp b/include/cece/math/MatrixBase.hpp new file mode 100644 index 0000000..13785c3 --- /dev/null +++ b/include/cece/math/MatrixBase.hpp @@ -0,0 +1,390 @@ +/* ************************************************************************ */ +/* Georgiev Lab (c) 2015-2017 */ +/* ************************************************************************ */ +/* Department of Cybernetics */ +/* Faculty of Applied Sciences */ +/* University of West Bohemia in Pilsen */ +/* ************************************************************************ */ +/* */ +/* This file is part of CeCe. */ +/* */ +/* CeCe 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. */ +/* */ +/* CeCe 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 CeCe. If not, see . */ +/* */ +/* ************************************************************************ */ + +#pragma once + +/* ************************************************************************ */ + +// CeCe +#include "cece/math/Vector.hpp" + +/* ************************************************************************ */ + +namespace cece { +namespace math { + +/* ************************************************************************ */ + +/** + * @brief 2D fixed size matrix base class. + * + * @tparam MatrixType Matrix type. + * @tparam T Type of stored value. + * @tparam R Number of rows. + * @tparam C Number of cols. + */ +template< + template typename MatrixType, + typename T, + int R, + int C +> +struct MatrixBase +{ + +// Public Types +public: + + + /// VectorBase value type. + using ValueType = T; + + +// Public Operators +public: + + + /** + * @brief Addition operator. + * + * @param rhs Right operand. + * + * @tparam T1 The second type. + * + * @return *this. + */ + template + MatrixType& operator+=(const MatrixType& rhs); + + + /** + * @brief Substraction operator. + * + * @param rhs Right operand. + * + * @tparam T1 The second type. + * + * @return *this. + */ + template + MatrixType& operator-=(const MatrixType& rhs); + + + /** + * @brief Multiplication operator. + * + * @param rhs Right operand. + * + * @tparam T1 The second type. + * + * @return *this. + */ + template + MatrixType& operator*=(const T1& rhs); + + + /** + * @brief Division operator. + * + * @param rhs Right operand. + * + * @tparam T1 The second type. + * + * @return *this. + */ + template + MatrixType& operator/=(const T1& rhs); + +}; + +/* ************************************************************************ */ + +/** + * @brief Addition operator. + * + * @param lhs Left operand. + * @param rhs Right operand. + * + * @tparam T1 Type of value in first matrix. + * @tparam T2 Type of value in second matrix. + * @tparam R Number of rows. + * @tparam C Number of columns. + * + * @return Result matrix. + */ +template +MatrixBase() + std::declval()), R, C> operator+( + const MatrixBase& lhs, + const MatrixBase& rhs +); + +/* ************************************************************************ */ + +/** + * @brief Substraction operator. + * + * @param lhs Left operand. + * @param rhs Right operand. + * + * @tparam T1 Type of value in first matrix. + * @tparam T2 Type of value in second matrix. + * @tparam R Number of rows. + * @tparam C Number of columns. + * + * @return Result matrix. + */ +template +MatrixBase() - std::declval()), R, C> operator-( + const MatrixBase& lhs, + const MatrixBase& rhs +); + +/* ************************************************************************ */ + +/** + * @brief Multiplication operator. + * + * @param lhs Left operand. + * @param rhs Right operand. + * + * @tparam T1 Type of value in first matrix. + * @tparam T2 Type of value in second matrix. + * @tparam R Number of rows. + * @tparam C Number of columns. + * + * @return Result matrix. + */ +template +MatrixBase() * std::declval()), R, C> operator*( + const MatrixBase& lhs, + const T2& rhs +); + +/* ************************************************************************ */ + +/** + * @brief Multiplication operator. + * + * @param lhs Left operand. + * @param rhs Right operand. + * + * @tparam T1 Type of value in first matrix. + * @tparam T2 Type of value in second matrix. + * @tparam R Number of rows. + * @tparam C Number of columns. + * + * @return Result matrix. + */ +template +MatrixBase() * std::declval()), R, C> operator*( + const T2& lhs + const MatrixBase& rhs, +); + +/* ************************************************************************ */ + +/** + * @brief Multiplication operator. + * + * @param lhs Left operand. + * @param rhs Right operand. + * + * @tparam T1 Type of value in first matrix. + * @tparam T2 Type of value in second matrix. + * @tparam R Number of rows. + * @tparam C Number of columns. + * + * @return Result matrix. + */ +template +MatrixBase() / std::declval()), R, C> operator/( + const MatrixBase& lhs, + const T2& rhs +); + +/* ************************************************************************ */ + +} +} + +/* ************************************************************************ */ +/* ************************************************************************ */ +/* ************************************************************************ */ + +namespace cece { +namespace math { + +/* ************************************************************************ */ + +template typename MatrixType, typename T, int R, int C> +template +inline MatrixType& MatrixBase::operator+=(const MatrixType& rhs) +{ + auto& self = *static_cast*>(this); + + for (int row = 0; row < R; ++row) + for (int col = 0; col < C; ++col) + self[row][col] += rhs[row][col]; + + return self; +} + +/* ************************************************************************ */ + +template typename MatrixType, typename T, int R, int C> +template +inline MatrixType& MatrixBase::operator-=(const MatrixType& rhs) +{ + auto& self = *static_cast*>(this); + + for (int row = 0; row < R; ++row) + for (int col = 0; col < C; ++col) + self[row][col] -= rhs[row][col]; + + return self; +} + +/* ************************************************************************ */ + +template typename MatrixType, typename T, int R, int C> +template +inline MatrixType& MatrixBase::operator*=(const T1& rhs) +{ + auto& self = *static_cast*>(this); + + for (int row = 0; row < R; ++row) + for (int col = 0; col < C; ++col) + self[row][col] *= rhs; + + return self; +} + +/* ************************************************************************ */ + +template typename MatrixType, typename T, int R, int C> +template +inline MatrixType& MatrixBase::operator/=(const T1& rhs) +{ + auto& self = *static_cast*>(this); + + for (int row = 0; row < R; ++row) + for (int col = 0; col < C; ++col) + self[row][col] /= rhs; + + return self; +} + +/* ************************************************************************ */ + +template +inline MatrixBase() + std::declval()), R, C> operator+( + const MatrixBase& lhs, + const MatrixBase& rhs +) +{ + MatrixBase() + std::declval()), R, C> res; + + for (int row = 0; row < R; ++row) + for (int col = 0; col < C; ++col) + res[row][col] = lhs[row][col] + rhs[row][col]; + + return res; +} + +/* ************************************************************************ */ + +template +inline MatrixBase() - std::declval()), R, C> operator-( + const MatrixBase& lhs, + const MatrixBase& rhs +) +{ + MatrixBase() + std::declval()), R, C> res; + + for (int row = 0; row < R; ++row) + for (int col = 0; col < C; ++col) + res[row][col] = lhs[row][col] - rhs[row][col]; + + return res; +} + +/* ************************************************************************ */ + +template +inline MatrixBase() * std::declval()), R, C> operator*( + const MatrixBase& lhs, + const T2& rhs +) +{ + MatrixBase() * std::declval()), R, C> res; + + for (int row = 0; row < R; ++row) + for (int col = 0; col < C; ++col) + res[row][col] = lhs[row][col] * rhs; + + return res; +} + +/* ************************************************************************ */ + +template +inline MatrixBase() * std::declval()), R, C> operator*( + const T2& lhs + const MatrixBase& rhs, +) +{ + MatrixBase() * std::declval()), R, C> res; + + for (int row = 0; row < R; ++row) + for (int col = 0; col < C; ++col) + res[row][col] = rhs * lhs[row][col]; + + return res; +} + +/* ************************************************************************ */ + +template +inline MatrixBase() / std::declval()), R, C> operator/( + const MatrixBase& lhs, + const T2& rhs +) +{ + MatrixBase() + std::declval()), R, C> res; + + for (int row = 0; row < R; ++row) + for (int col = 0; col < C; ++col) + res[row][col] = lhs[row][col] / rhs; + + return res; +} + +/* ************************************************************************ */ + +} +} + +/* ************************************************************************ */ + diff --git a/include/cece/math/Vector.hpp b/include/cece/math/Vector.hpp index 23c4480..3a8bba9 100644 --- a/include/cece/math/Vector.hpp +++ b/include/cece/math/Vector.hpp @@ -1,5 +1,5 @@ /* ************************************************************************ */ -/* Georgiev Lab (c) 2015-2016 */ +/* Georgiev Lab (c) 2015-2017 */ /* ************************************************************************ */ /* Department of Cybernetics */ /* Faculty of Applied Sciences */ @@ -29,6 +29,7 @@ // C++ #include +#include #include // CeCe @@ -36,10 +37,9 @@ #include "cece/Assert.hpp" #include "cece/StaticArray.hpp" #include "cece/math/Zero.hpp" -#include "cece/io/InStream.hpp" -#include "cece/io/OutStream.hpp" #include "cece/unit/math.hpp" #include "cece/unit/Units.hpp" +#include "cece/math/VectorBase.hpp" /* ************************************************************************ */ @@ -49,29 +49,31 @@ namespace math { /* ************************************************************************ */ /** - * @brief N dimensional vector. + * @brief N dimensional vector. * - * @tparam T Element type. - * @tparam N Number of elements. + * @tparam T Element type. + * @tparam N Number of elements. */ -template -class BasicVector +template +class Vector : public VectorBase { + static_assert(N > 0, "Cannot create empty vector"); + // Public Types public: - /// BasicVector value type. + /// Vector value type. using ValueType = T; -// Public Contants +// Public Data Members public: - /// Number of elements - static constexpr unsigned SIZE = N; + // Member data. + StaticArray m; // Public Ctors @@ -79,400 +81,225 @@ class BasicVector /** - * @brief Default constructor. + * @brief Default constructor. */ - BasicVector() noexcept - : m_data{} - { - // Nothing to do - } + constexpr Vector() noexcept; /** - * @brief Constructor. + * @brief Constructor. * - * @param data - */ - explicit BasicVector(StaticArray data) noexcept - : m_data(data) - { - // Nothing to do - } - - - /** - * @brief Zero value constructor. + * @param data The source data. */ - BasicVector(Zero_t) noexcept - { - for (unsigned i = 0; i < N; ++i) - m_data[i] = T{}; - } + Vector(std::initializer_list data); /** - * @brief Copy constructor. + * @brief Constructor. * - * @param v Source vector. + * @param data The source data. */ - template - explicit BasicVector(const BasicVector& v) noexcept - { - for (unsigned i = 0; i < N; ++i) - m_data[i] = static_cast(v[i]); - } - - -// Public Operators -public: + explicit Vector(T (&data)[N]); /** - * @brief Unary plus operator. + * @brief Constructor. * - * @return + * @param data The source data. */ - BasicVector operator+() const noexcept - { - return *this; - } + explicit Vector(const StaticArray& data); /** - * @brief Unary minus operator. + * @brief Zero value constructor. * - * @return + * @param[in] zero The zero value. */ - BasicVector operator-() const noexcept - { - BasicVector res; - - for (unsigned i = 0; i < N; ++i) - res[i] = -m_data[i]; - - return res; - } + Vector(Zero_t zero); /** - * @brief Addition operator. - * - * @tparam T1 Type of right operand. + * @brief Copy constructor. * - * @param rhs Right operand. - * - * @return *this. + * @param[in] src The source vector. */ - template::value>::type* = nullptr> - BasicVector& operator+=(const BasicVector& rhs) noexcept - { - for (unsigned i = 0; i < N; ++i) - m_data[i] += rhs[i]; - - return *this; - } + Vector(const Vector& src); /** - * @brief Subtraction operator. + * @brief Move constructor. * - * @tparam T1 Type of value in BasicVector operand. - * - * @param rhs Right operand. - * - * @return *this. + * @param[in] src The source vector. */ - template::value>::type* = nullptr> - BasicVector& operator-=(const BasicVector& rhs) noexcept - { - for (unsigned i = 0; i < N; ++i) - m_data[i] -= rhs[i]; - - return *this; - } + Vector(Vector&& src); /** - * @brief Multiplication operator. - * - * @tparam T1 Type of right operand. + * @brief Copy constructor. * - * @param rhs Right operand. + * @param v The source vector. * - * @return *this. + * @tparam T2 The source vector element type. */ - template::value>::type* = nullptr> - BasicVector& operator*=(T1 rhs) noexcept - { - for (unsigned i = 0; i < N; ++i) - m_data[i] *= rhs; - - return *this; - } - + template::value>::type* = nullptr> + explicit Vector(const Vector& src); - /** - * @brief Multiplication operator. - * - * @tparam T1 Type of value in BasicVector operand. - * - * @param rhs Right operand. - * - * @return *this. - */ - template::value>::type* = nullptr> - BasicVector& operator*=(const BasicVector& rhs) noexcept - { - for (unsigned i = 0; i < N; ++i) - m_data[i] *= rhs[i]; - return *this; - } +// Public Operators +public: /** - * @brief Division operator. - * - * @tparam T1 Type of right operand. + * @brief Copy constructor. * - * @param rhs Right operand. + * @param[in] zero The zero value. * - * @return *this. + * @return *this. */ - template::value>::type* = nullptr> - BasicVector& operator/=(T1 rhs) noexcept - { - for (unsigned i = 0; i < N; ++i) - m_data[i] /= rhs; - - return *this; - } + Vector& operator=(Zero_t zero); /** - * @brief Division operator. - * - * @tparam T1 Type of value in BasicVector operand. + * @brief Copy constructor. * - * @param rhs Right operand. + * @param[in] data The source data. * - * @return *this. + * @return *this. */ - template::value>::type* = nullptr> - BasicVector& operator/=(const BasicVector& rhs) noexcept - { - for (unsigned i = 0; i < N; ++i) - m_data[i] /= rhs[i]; - - return *this; - } + Vector& operator=(std::initializer_list data); /** - * @brief Access operator. + * @brief Copy constructor. * - * @param pos + * @param[in] data The source data. * - * @return + * @return *this. */ - T& operator[](unsigned pos) noexcept - { - return m_data[pos]; - } + Vector& operator=(T (&data)[N]); /** - * @brief Access operator. + * @brief Copy constructor. * - * @param pos + * @param[in] data The source data. * - * @return + * @return *this. */ - const T& operator[](unsigned pos) const noexcept - { - return m_data[pos]; - } - - -// Public Accessors -public: + Vector& operator=(const StaticArray& data); /** - * @brief Check if given value is in given range. + * @brief Copy constructor. * - * @param value Given value. - * @param low Minimum value (>=). - * @param high Maximum value (<). + * @param[in] src The source vector. * - * @return + * @return *this. */ - static bool inRange(T value, T low, T high) noexcept - { - return value >= low && value < high; - } + Vector& operator=(const Vector& src); /** - * @brief Check if current vector is in given range. - * - * @param low Minimum coordinates (>=). - * @param high Maximum coordinates (<). + * @brief Move constructor. * - * @return - */ - bool inRange(const BasicVector& low, const BasicVector& high) const noexcept - { - bool res = true; - - for (unsigned i = 0; i < N; ++i) - res = res && inRange(m_data[i], low[i], high[i]); - - return res; - } - - -// Public Operations -public: - - - /** - * @brief Calculate vector length. + * @param[in] src The source vector. * - * @return + * @return *this. */ - T getLength() const noexcept - { - using std::sqrt; - return static_cast(sqrt(getLengthSquared())); - } + Vector& operator=(Vector&& src); /** - * @brief Calculate vector length - squared. + * @brief Copy constructor. * - * @return - */ - decltype(T{} * T{}) getLengthSquared() const noexcept - { - return dot(*this); - } - - - /** - * @brief Calculate dot of two vectors. + * @param v The source vector. * - * @param rhs Second vector. + * @tparam T2 The source vector element type. * - * @return Dot product. + * @return *this. */ - decltype(T{} * T{}) dot(const BasicVector& rhs) const noexcept - { - decltype(T{} * T{}) res{}; - - for (unsigned i = 0; i < N; ++i) - res += m_data[i] * rhs[i]; - - return res; - } + template::value>::type* = nullptr> + Vector& operator=(const Vector& src); /** - * @brief Calculate vectors squared distance. + * @brief Access operator. * - * @param rhs Second vector. + * @param pos The position. * - * @return Distance. + * @return Reference to the element. */ - decltype(std::declval() * std::declval()) distanceSquared(const BasicVector& rhs) const noexcept - { - return (*this - rhs).getLengthSquared(); - } + T& operator[](int pos) noexcept; /** - * @brief Calculate vectors distance. - * - * @param rhs Second vector. + * @brief Access operator. * - * @return Distance. - */ - T distance(const BasicVector& rhs) const noexcept - { - return (*this - rhs).getLength(); - } - - - /** - * @brief Inverse current vector (1 / *this). + * @param pos The position. * - * @return + * @return Reference to the element. */ - template - BasicVector inversed() const noexcept - { - BasicVector res; - - for (unsigned i = 0; i < N; ++i) - res[i] = T2(1) / m_data[i]; - - return res; - } + constexpr const T& operator[](int pos) const noexcept; -// Public Operations +// Public Accessors public: /** - * @brief Create from single value. - * - * @param val + * @brief Returns vector size. * - * @return + * @return The size. */ - static BasicVector createSingle(T val) noexcept - { - BasicVector res; - - for (unsigned i = 0; i < N; ++i) - res[i] = val; - - return res; - } + constexpr int getSize() const noexcept; - -// Private Data Members -private: - - - /// BasicVector data. - StaticArray m_data; }; /* ************************************************************************ */ /** - * @brief Two dimensional vector. + * @brief 2D vector specialization. + * + * @tparam T Element type. */ template -class BasicVector +struct Vector : public VectorBase { // Public Types public: - /// BasicVector value type. + /// Element type. using ValueType = T; -// Public Contants +// Public Data Members public: - /// Number of elements - static constexpr unsigned SIZE = 2; + union + { + struct + { + /// X coordinate. + T x; + + /// Y coordinate. + T y; + }; + + struct + { + /// Width + T width; + + /// Height. + T height; + }; + + T m[2]; + }; // Public Ctors @@ -480,215 +307,128 @@ class BasicVector /** - * @brief Default constructor. + * @brief Default constructor. */ - BasicVector() noexcept - : m_x{} - , m_y{} - { - // Nothing to do - } + constexpr Vector(); /** - * @brief Constructor. + * @brief Constructor. * - * @param x - * @param y + * @param x The X and Y coordinate. */ - BasicVector(T x, T y) noexcept - : m_x(x) - , m_y(y) - { - // Nothing to do - } + explicit constexpr Vector(T value); /** - * @brief Zero value constructor. + * @brief Constructor. + * + * @param x The X coordinate. + * @param y The Y coordinate. */ - BasicVector(Zero_t) noexcept - : m_x{} - , m_y{} - { - // Nothing to do - } + constexpr Vector(T x, T y); /** - * @brief Copy constructor. + * @brief Zero value constructor. * - * @param rhs Source vector. + * @param[in] zero The zero value. */ - template - explicit BasicVector(const BasicVector& rhs) noexcept - : m_x(static_cast(rhs.getX())) - , m_y(static_cast(rhs.getY())) - { - // Nothing to do - } - - -// Public Operators -public: + constexpr Vector(Zero_t zero); /** - * @brief Access operator. - * - * @param pos + * @brief Copy constructor. * - * @return + * @param[in] src The source vector. */ - T& operator[](unsigned pos) noexcept - { - CECE_ASSERT(pos < SIZE); - return (&m_x)[pos]; - } + constexpr Vector(const Vector& src); /** - * @brief Access operator. + * @brief Move constructor. * - * @param pos - * - * @return + * @param[in] src The source vector. */ - const T& operator[](unsigned pos) const noexcept - { - CECE_ASSERT(pos < SIZE); - return (&m_x)[pos]; - } + constexpr Vector(Vector&& src); /** - * @brief Unary plus operator. + * @brief Copy constructor. + * + * @param rhs Source vector. * - * @return + * @tparam T2 The source vector element type. */ - BasicVector operator+() const noexcept - { - return *this; - } + template::value>::type* = nullptr> + constexpr Vector(const Vector& rhs); - /** - * @brief Unary minus operator. - * - * @return - */ - BasicVector operator-() const noexcept - { - return BasicVector{-getX(), -getY()}; - } +// Public Operators +public: /** - * @brief Addition operator. - * - * @tparam T1 Type of right operand. + * @brief Copy constructor. * - * @param rhs Right operand. + * @param[in] zero The zero value. * - * @return *this. + * @return *this. */ - template - BasicVector& operator+=(const BasicVector& rhs) noexcept - { - m_x += rhs.getX(); - m_y += rhs.getY(); - return *this; - } + Vector& operator=(Zero_t zero); /** - * @brief Subtraction operator. + * @brief Copy constructor. * - * @tparam T1 Type of value in BasicVector operand. + * @param[in] src The source vector. * - * @param rhs Right operand. - * - * @return *this. + * @return *this. */ - template - BasicVector& operator-=(const BasicVector& rhs) noexcept - { - m_x -= rhs.getX(); - m_y -= rhs.getY(); - return *this; - } + Vector& operator=(const Vector& src); /** - * @brief Multiplication operator. - * - * @tparam T1 Type of right operand. + * @brief Move constructor. * - * @param rhs Right operand. + * @param[in] src The source vector. * - * @return *this. + * @return *this. */ - template - BasicVector& operator*=(T1 rhs) noexcept - { - m_x *= rhs; - m_y *= rhs; - return *this; - } + Vector& operator=(Vector&& src); /** - * @brief Multiplication operator. + * @brief Copy constructor. * - * @tparam T1 Type of value in BasicVector operand. + * @param v The source vector. * - * @param rhs Right operand. + * @tparam T2 The source vector element type. * - * @return *this. + * @return *this. */ - template - BasicVector& operator*=(const BasicVector& rhs) noexcept - { - m_x *= rhs.getX(); - m_y *= rhs.getY(); - return *this; - } + template::value>::type* = nullptr> + Vector& operator=(const Vector& src); /** - * @brief Division operator. + * @brief Access operator. * - * @tparam T1 Type of right operand. + * @param pos The position. * - * @param rhs Right operand. - * - * @return *this. + * @return Reference to the element. */ - template - BasicVector& operator/=(T1 rhs) noexcept - { - m_x /= rhs; - m_y /= rhs; - return *this; - } + T& operator[](int pos) noexcept; /** - * @brief Division operator. - * - * @tparam T1 Type of value in BasicVector operand. + * @brief Access operator. * - * @param rhs Right operand. + * @param pos The position. * - * @return *this. + * @return Reference to the element. */ - template - BasicVector& operator/=(const BasicVector& rhs) noexcept - { - m_x /= rhs.getX(); - m_y /= rhs.getY(); - return *this; - } + constexpr const T& operator[](int pos) const noexcept; // Public Accessors @@ -696,530 +436,299 @@ class BasicVector /** - * @brief Returns vector size. + * @brief Returns vector size. * - * @return + * @return The size. */ - unsigned getSize() const noexcept - { - return SIZE; - } + constexpr int getSize() const noexcept; /** - * @brief Returns X coordinate. + * @brief Returns X coordinate. * - * @return + * @return The X coordinate. */ - T& x() noexcept - { - return m_x; - } + constexpr const T& getX() const noexcept; /** - * @brief Returns X coordinate. + * @brief Set X coordinate. * - * @return + * @param[in] x The X coordinate. */ - const T& getX() const noexcept - { - return m_x; - } + void setX(T x); /** - * @brief Returns Y coordinate. + * @brief Returns Y coordinate. * - * @return + * @return The Y coordinate. */ - T& y() noexcept - { - return m_y; - } + constexpr const T& getY() const noexcept; /** - * @brief Returns Y coordinate. + * @brief Set Y coordinate. * - * @return + * @param[in] y The Y coordinate. */ - const T& getY() const noexcept - { - return m_y; - } + void setY(T y); /** - * @brief Returns width. + * @brief Gets the width. * - * @return + * @return The width. */ - T& width() noexcept - { - return m_x; - } + constexpr const T& getWidth() const noexcept; /** - * @brief Returns width. + * @brief Set the width. * - * @return + * @param[in] width The width. */ - const T& getWidth() const noexcept - { - return m_x; - } + void setWidth(T width); /** - * @brief Returns height. + * @brief Gets the height. * - * @return + * @return The height. */ - T& height() noexcept - { - return m_y; - } + constexpr const T& getHeight() const noexcept; /** - * @brief Returns height. + * @brief Sets the height. * - * @return + * @param[in] height The height */ - const T& getHeight() const noexcept - { - return m_y; - } + void setHeight(T height); -// Public Mutators +// Public Deprecated public: - /** - * @brief Set X coordinate. - * - * @param x - */ - void setX(T x) noexcept + // @deprecated + bool inRange(const Vector& low, const Vector& high) const noexcept { - m_x = x; + return math::inRange(*this, low, high); } - /** - * @brief Set Y coordinate. - * - * @param y - */ - void setY(T y) noexcept + // @deprecated + bool inRange(const Vector& high) const noexcept { - m_y = y; + return math::inRange(*this, high); } - /** - * @brief Check if given value is in given range. - * - * @param value Given value. - * @param low Minimum value (>=). - * @param high Maximum value (<). - * - * @return - */ - static bool inRange(T value, T low, T high) noexcept + // @deprecated + static Vector createSingle(T val) noexcept { - return value >= low && value < high; + return Vector(val, val); } - /** - * @brief Check if current vector is in given range. - * - * @param low Minimum coordinates (>=). - * @param high Maximum coordinates (<). - * - * @return - */ - bool inRange(const BasicVector& low, const BasicVector& high) const noexcept + // @deprecated + template + Vector inversed() const noexcept + { + return T2(1) / *this; + } + + + // @deprecated + Vector rotated(unit::Angle angle) const noexcept { - return ( - inRange(getX(), low.getX(), high.getX()) && - inRange(getY(), low.getY(), high.getY()) - ); + return rotate(*this, angle); } +}; + +/* ************************************************************************ */ + +/** + * @brief 3D vector specialization. + * + * @tparam T Element type. + */ +template +struct Vector : public VectorBase +{ -// Public Operations +// Public Types public: - /** - * @brief Calculate vector length. - * - * @return - */ - T getLength() const noexcept + /// Vector element type. + using ValueType = T; + + +// Public Data Members +public: + + + union { - using std::sqrt; - return static_cast(sqrt(getLengthSquared())); - } + struct + { + /// X coordinate. + T x; + + /// Y coordinate. + T y; + + /// Z coordinate. + T z; + }; + + struct + { + /// Width. + T width; + + /// Height. + T height; + + /// Depth. + T depth; + }; + + T m[3]; + }; + + +// Public Ctors +public: /** - * @brief Calculate vector length - squared. - * - * @return + * @brief Default constructor. */ - decltype(T{} * T{}) getLengthSquared() const noexcept - { - return dot(*this); - } + constexpr Vector() noexcept; /** - * @brief Calculate dot of two vectors. + * @brief Constructor. * - * @param rhs Second vector. - * - * @return Dot product. + * @param val The X, Y and Z coordinate. */ - decltype(T{} * T{}) dot(const BasicVector& rhs) const noexcept - { - return {getX() * rhs.getX() + getY() * rhs.getY()}; - } + explicit constexpr Vector(T val); /** - * @brief Calculate vectors squared distance. - * - * @param rhs Second vector. + * @brief Constructor. * - * @return Distance. + * @param x The X coordinate. + * @param y The Y coordinate. + * @param y The Z coordinate. */ - decltype(std::declval() * std::declval()) distanceSquared(const BasicVector& rhs) const noexcept - { - return (*this - rhs).getLengthSquared(); - } + constexpr Vector(T x, T y, T z); /** - * @brief Calculate vectors distance. + * @brief Zero value constructor. * - * @param rhs Second vector. - * - * @return Distance. + * @param[in] zero The zero value. */ - T distance(const BasicVector& rhs) const noexcept - { - return (*this - rhs).getLength(); - } + constexpr Vector(Zero_t zero); /** - * @brief Inverse current vector (1 / *this). + * @brief Copy constructor. * - * @return + * @param[in] src The source vector. */ - template - BasicVector inversed() const noexcept - { - return BasicVector{T2(1) / getX(), T2(1) / getY()}; - } + constexpr Vector(const Vector& src); /** - * @brief Rotate current vector and return rotated version. - * - * @param angle Rotation angle. + * @brief Move constructor. * - * @return + * @param[in] src The source vector. */ - BasicVector rotated(unit::Angle angle) const noexcept - { - return BasicVector( - static_cast(getX() * cos(static_cast(angle)) - getY() * sin(static_cast(angle))), - static_cast(getX() * sin(static_cast(angle)) + getY() * cos(static_cast(angle))) - ); - } + constexpr Vector(Vector&& src); /** - * @brief Create from single value. + * @brief Copy constructor. * - * @param val + * @param rhs Source vector. * - * @return + * @tparam T2 The source vector element type. */ - static BasicVector createSingle(T val) noexcept - { - return BasicVector{val, val}; - } + template::value>::type* = nullptr> + constexpr Vector(const Vector& rhs); -// Private Data Members -private: - - /// X coordinate. - T m_x{}; - - /// Y coordinate. - T m_y{}; - -}; - -/* ************************************************************************ */ - -/** - * @brief Three dimensional vector. - */ -template -class BasicVector -{ - -// Public Types -public: - - - /// BasicVector value type. - using ValueType = T; - - -// Public Contants -public: - - - /// Number of elements - static constexpr unsigned SIZE = 3; - - -// Public Ctors -public: - - - /** - * @brief Default constructor. - */ - BasicVector() noexcept - : m_x{} - , m_y{} - , m_z{} - { - // Nothing to do - } - - - /** - * @brief Constructor. - * - * @param x - * @param y - * @param z - */ - BasicVector(T x, T y, T z) noexcept - : m_x(x) - , m_y(y) - , m_z(z) - { - // Nothing to do - } - - - /** - * @brief Zero value constructor. - */ - BasicVector(Zero_t) noexcept - : m_x{} - , m_y{} - , m_z{} - { - // Nothing to do - } - - - /** - * @brief Copy constructor. - * - * @param rhs Source vector. - */ - template - explicit BasicVector(const BasicVector& rhs) noexcept - : m_x(static_cast(rhs.getX())) - , m_y(static_cast(rhs.getY())) - , m_z(static_cast(rhs.getZ())) - { - // Nothing to do - } - - -// Public Operators -public: - - - /** - * @brief Access operator. - * - * @param pos - * - * @return - */ - T& operator[](unsigned pos) noexcept - { - CECE_ASSERT(pos < SIZE); - return (&m_x)[pos]; - } - - - /** - * @brief Access operator. - * - * @param pos - * - * @return - */ - const T& operator[](unsigned pos) const noexcept - { - CECE_ASSERT(pos < SIZE); - return (&m_x)[pos]; - } - - - /** - * @brief Unary plus operator. - * - * @return - */ - BasicVector operator+() const noexcept - { - return *this; - } +// Public Operators +public: /** - * @brief Unary minus operator. + * @brief Copy constructor. * - * @return - */ - BasicVector operator-() const noexcept - { - return BasicVector{-getX(), -getY(), -getZ()}; - } - - - /** - * @brief Addition operator. + * @param[in] zero The zero value. * - * @tparam T1 Type of right operand. - * - * @param rhs Right operand. - * - * @return *this. + * @return *this. */ - template::value>::type* = nullptr> - BasicVector& operator+=(const BasicVector& rhs) noexcept - { - m_x += rhs.getX(); - m_y += rhs.getY(); - m_z += rhs.getZ(); - return *this; - } + Vector& operator=(Zero_t zero); /** - * @brief Subtraction operator. - * - * @tparam T1 Type of value in BasicVector operand. + * @brief Copy constructor. * - * @param rhs Right operand. + * @param[in] src The source vector. * - * @return *this. + * @return *this. */ - template::value>::type* = nullptr> - BasicVector& operator-=(const BasicVector& rhs) noexcept - { - m_x -= rhs.getX(); - m_y -= rhs.getY(); - m_z -= rhs.getZ(); - return *this; - } + Vector& operator=(const Vector& src); /** - * @brief Multiplication operator. - * - * @tparam T1 Type of right operand. + * @brief Move constructor. * - * @param rhs Right operand. + * @param[in] src The source vector. * - * @return *this. + * @return *this. */ - template::value>::type* = nullptr> - BasicVector& operator*=(T1 rhs) noexcept - { - m_x *= rhs; - m_y *= rhs; - m_z *= rhs; - return *this; - } + Vector& operator=(Vector&& src); /** - * @brief Multiplication operator. + * @brief Copy constructor. * - * @tparam T1 Type of value in BasicVector operand. + * @param v The source vector. * - * @param rhs Right operand. + * @tparam T2 The source vector element type. * - * @return *this. + * @return *this. */ - template::value>::type* = nullptr> - BasicVector& operator*=(const BasicVector& rhs) noexcept - { - m_x *= rhs.getX(); - m_y *= rhs.getY(); - m_z *= rhs.getZ(); - return *this; - } + template::value>::type* = nullptr> + Vector& operator=(const Vector& src); /** - * @brief Division operator. + * @brief Access operator. * - * @tparam T1 Type of right operand. + * @param pos The position. * - * @param rhs Right operand. - * - * @return *this. + * @return Reference to the element. */ - template::value>::type* = nullptr> - BasicVector& operator/=(T1 rhs) noexcept - { - m_x /= rhs; - m_y /= rhs; - m_z /= rhs; - return *this; - } + T& operator[](int pos) noexcept; /** - * @brief Division operator. + * @brief Access operator. * - * @tparam T1 Type of value in BasicVector operand. + * @param pos The position. * - * @param rhs Right operand. - * - * @return *this. + * @return Reference to the element. */ - template::value>::type* = nullptr> - BasicVector& operator/=(const BasicVector& rhs) noexcept - { - m_x /= rhs.getX(); - m_y /= rhs.getY(); - m_z /= rhs.getZ(); - return *this; - } + constexpr const T& operator[](int pos) const noexcept; // Public Accessors @@ -1227,1387 +736,1010 @@ class BasicVector /** - * @brief Returns vector size. + * @brief Returns vector size. * - * @return + * @return The size. */ - unsigned getSize() const noexcept - { - return SIZE; - } + constexpr int getSize() const noexcept; /** - * @brief Returns X coordinate. + * @brief Returns X coordinate. * - * @return + * @return The X coordinate. */ - T& x() noexcept - { - return m_x; - } + constexpr const T& getX() const noexcept; /** - * @brief Returns X coordinate. + * @brief Set X coordinate. * - * @return + * @param x The X coordinate. */ - const T& getX() const noexcept - { - return m_x; - } + void setX(T x); /** - * @brief Returns Y coordinate. + * @brief Returns Y coordinate. * - * @return + * @return The Y coordinate. */ - T& y() noexcept - { - return m_y; - } + constexpr const T& getY() const noexcept; /** - * @brief Returns Y coordinate. + * @brief Set Y coordinate. * - * @return + * @param y The Y coordinate. */ - const T& getY() const noexcept - { - return m_y; - } + void setY(T y); /** - * @brief Returns Z coordinate. + * @brief Returns Z coordinate. * - * @return + * @return The Z coordinate. */ - T& z() noexcept - { - return m_z; - } + constexpr const T& getZ() const noexcept; /** - * @brief Returns Z coordinate. + * @brief Set Z coordinate. * - * @return + * @param z The Z coordinate. */ - const T& getZ() const noexcept - { - return m_z; - } + void setZ(T z); /** - * @brief Returns width. + * @brief Gets the width. * - * @return + * @return The width. */ - T& width() noexcept - { - return m_x; - } + constexpr const T& getWidth() const noexcept; /** - * @brief Returns width. + * @brief Set the width. * - * @return + * @param[in] width The width. */ - const T& getWidth() const noexcept - { - return m_x; - } + void setWidth(T width); /** - * @brief Returns height. + * @brief Gets the height. * - * @return + * @return The height. */ - T& height() noexcept - { - return m_y; - } + constexpr const T& getHeight() const noexcept; /** - * @brief Returns height. + * @brief Sets the height. * - * @return + * @param[in] height The height */ - const T& getHeight() const noexcept - { - return m_y; - } + void setHeight(T height); /** - * @brief Returns depth. + * @brief Gets the depth. * - * @return + * @return The depth. */ - T& depth() noexcept - { - return m_z; - } + constexpr const T& getDepth() const noexcept; /** - * @brief Returns depth. + * @brief Sets the depth. * - * @return + * @param[in] depth The depth */ - const T& getDepth() const noexcept - { - return m_z; - } + void setDepth(T depth); - /** - * @brief Check if given value is in given range. - * - * @param value Given value. - * @param low Minimum value (>=). - * @param high Maximum value (<). - * - * @return - */ - static bool inRange(T value, T low, T high) noexcept - { - return value >= low && value < high; - } +// Public Deprecated +public: - /** - * @brief Check if current vector is in given range. - * - * @param low Minimum coordinates (>=). - * @param high Maximum coordinates (<). - * - * @return - */ - bool inRange(const BasicVector& low, const BasicVector& high) const noexcept + // @deprecated + bool inRange(const Vector& low, const Vector& high) const noexcept { - return ( - inRange(getX(), low.getX(), high.getX()) && - inRange(getY(), low.getY(), high.getY()) && - inRange(getZ(), low.getZ(), high.getZ()) - ); + return math::inRange(*this, low, high); } - -// Public Mutators -public: - - - /** - * @brief Set X coordinate. - * - * @param x - */ - void setX(T x) noexcept + // @deprecated + bool inRange(const Vector& high) const noexcept { - m_x = x; + return math::inRange(*this, high); } - /** - * @brief Set Y coordinate. - * - * @param y - */ - void setY(T y) noexcept + // @deprecated + static Vector createSingle(T val) noexcept { - m_y = y; + return Vector(val, val, val); } - /** - * @brief Set Z coordinate. - * - * @param z - */ - void setZ(T z) noexcept + // @deprecated + template + Vector inversed() const noexcept { - m_z = z; + return T2(1) / *this; } +}; +/* ************************************************************************ */ -// Public Operations -public: - - - /** - * @brief Calculate vector length. - * - * @return - */ - template::value>::type* = nullptr> - T getLength() const noexcept - { - using std::sqrt; - return static_cast(sqrt(getLengthSquared())); - } +/** + * @brief 2D vector alias. + */ +template +using Vector2 = Vector; +/* ************************************************************************ */ - /** - * @brief Calculate vector length - squared. - * - * @return - */ - decltype(T{} * T{}) getLengthSquared() const noexcept - { - return dot(*this); - } +/** + * @brief 3D vector alias. + */ +template +using Vector3 = Vector; +/* ************************************************************************ */ - /** - * @brief Calculate dot of two vectors. - * - * @param rhs Second vector. - * - * @return Dot product. - */ - decltype(T{} * T{}) dot(const BasicVector& rhs) const noexcept - { - return { - getX() * rhs.getX() + - getY() * rhs.getY() + - getZ() * rhs.getZ() - }; - } +/** + * @brief Vector for integer size. + * @deprecated + */ +using Size = Vector; +/* ************************************************************************ */ - /** - * @brief Calculate vectors squared distance. - * - * @param rhs Second vector. - * - * @return Distance. - */ - decltype(std::declval() * std::declval()) distanceSquared(const BasicVector& rhs) const noexcept - { - return (*this - rhs).getLengthSquared(); - } +/** + * @brief Vector for coordinates. + * @deprecated + */ +using Coordinate = Vector; +/* ************************************************************************ */ - /** - * @brief Calculate vectors distance. - * - * @param rhs Second vector. - * - * @return Distance. - */ - T distance(const BasicVector& rhs) const noexcept - { - return (*this - rhs).getLength(); - } +/** + * @brief Vector of int. + * @deprecated + */ +using VectorInt = Vector; +/* ************************************************************************ */ - /** - * @brief Inverse current vector (1 / *this). - * - * @return - */ - template - BasicVector inversed() const noexcept - { - return BasicVector{ - T2(1) / getX(), - T2(1) / getY(), - T2(1) / getZ() - }; - } +/** + * @brief Vector of float. + * @deprecated + */ +using VectorFloat = Vector; +/* ************************************************************************ */ - /** - * @brief Create from single value. - * - * @param val - * - * @return - */ - static BasicVector createSingle(T val) noexcept - { - return {val, val, val}; - } +/** + * @brief Vector of double. + * @deprecated + */ +using VectorDouble = Vector; +/* ************************************************************************ */ -// Private Data Members -private: +/** + * @brief Vector of long double. + * @deprecated + */ +using VectorLongDouble = Vector; - /// X coordinate. - T m_x{}; +/* ************************************************************************ */ - /// Y coordinate. - T m_y{}; +/** + * @brief Vector of float. + * @deprecated + */ +using VectorReal = Vector; - /// Z coordinate. - T m_z{}; +/* ************************************************************************ */ -}; +/** + * @brief Vector of integers. + */ +using IntVector = Vector; /* ************************************************************************ */ /** - * @brief Basic vector. + * @brief Vector of float. */ -template -using Vector = BasicVector; +using FloatVector = Vector; /* ************************************************************************ */ /** - * @brief Vector for integer size. + * @brief Vector of double. */ -using Size = Vector; +using DoubleVector = Vector; /* ************************************************************************ */ /** - * @brief Vector for coordinates. + * @brief Vector of long double. */ -using Coordinate = Vector; +using LongDoubleVector = Vector; /* ************************************************************************ */ /** - * @brief Vector of int. + * @brief Vector of float. */ -using VectorInt = Vector; +using RealVector = Vector; /* ************************************************************************ */ /** - * @brief Vector of unsigned int. + * @brief Vector for indices. */ -using VectorUint = Vector; +using IndexVector = Vector; /* ************************************************************************ */ /** - * @brief Vector of float. + * @brief Vector for sizes. */ -using VectorFloat = Vector; +using SizeVector = Vector; /* ************************************************************************ */ /** - * @brief Addition operator. + * @brief Rotate the vector counter-clockwise and return rotated version. * - * @tparam T1 Type of value in first BasicVector. - * @tparam T2 Type of value in second BasicVector. - * @tparam N BasicVector size. + * @param[in] vec The vector. + * @param[in] angle Rotation angle. * - * @param lhs Left operand. - * @param rhs Right operand. + * @tparam T The vector element type. * - * @return Result vector. + * @return Rotated vector. */ -template -inline BasicVector operator+(const BasicVector& lhs, const BasicVector& rhs) noexcept -{ - BasicVector res; - - for (unsigned i = 0; i < N; ++i) - res[i] = lhs[i] + rhs[i]; - - return res; -} +template +constexpr Vector rotate(const Vector& vec, unit::Angle angle) noexcept; /* ************************************************************************ */ /** - * @brief Addition operator. + * @brief Calculate cross product of two vectors. * - * @tparam T1 Type of value in first BasicVector. - * @tparam T2 Type of value in second BasicVector. + * @param lhs Left operand. + * @param rhs Right operand. * - * @param lhs Left operand. - * @param rhs Right operand. + * @tparam T1 The first type. + * @tparam T2 The second type. * - * @return Result vector. + * @return Cross product. */ template -inline BasicVector operator+(const BasicVector& lhs, const BasicVector& rhs) noexcept +constexpr Vector() * std::declval()), 3> +cross(const Vector& lhs, const Vector& rhs); + +/* ************************************************************************ */ + +extern template class Vector; +extern template class Vector; +extern template class Vector; +extern template class Vector; +extern template class Vector; +extern template class Vector; +extern template class Vector; +extern template class Vector; +extern template class Vector; +extern template class Vector; + +/* ************************************************************************ */ + +/// @deprecated +template +using BasicVector = Vector; + +/* ************************************************************************ */ + +} +} + +/* ************************************************************************ */ +/* ************************************************************************ */ +/* ************************************************************************ */ + +namespace cece { +namespace math { + +/* ************************************************************************ */ + +template +inline constexpr Vector::Vector() noexcept + : m{} { - return BasicVector{ - lhs.getX() + rhs.getX(), - lhs.getY() + rhs.getY() - }; + // Nothing to do } /* ************************************************************************ */ -/** - * @brief Addition operator. - * - * @tparam T1 Type of value in first BasicVector. - * @tparam T2 Type of second operand. - * @tparam N BasicVector size. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return Result vector. - */ -template -inline BasicVector operator+(const BasicVector& lhs, T2 rhs) noexcept +template +inline Vector::Vector(std::initializer_list data) { - BasicVector res; + CECE_ASSERT(data.size() == N); - for (unsigned i = 0; i < N; ++i) - res[i] = lhs[i] + rhs; + using std::begin; + auto it = begin(data); - return res; + for (int i = 0; i < N; ++i, ++it) + m[i] = *it; } /* ************************************************************************ */ -/** - * @brief Addition operator. - * - * @tparam T1 Type of value in first BasicVector. - * @tparam T2 Type of second operand. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return Result vector. - */ -template -inline BasicVector operator+(const BasicVector& lhs, T2 rhs) noexcept +template +inline Vector::Vector(T (&data)[N]) { - return BasicVector{ - lhs.getX() + rhs, - lhs.getY() + rhs - }; + using std::begin; + auto it = begin(data); + + for (int i = 0; i < N; ++i, ++it) + m[i] = *it; } /* ************************************************************************ */ -/** - * @brief Addition operator. - * - * @tparam T1 Type of first operand. - * @tparam T2 Type of value in second BasicVector. - * @tparam N BasicVector size. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return Result vector. - */ -template -inline BasicVector operator+(T1 lhs, const BasicVector& rhs) noexcept +template +inline Vector::Vector(const StaticArray& data) + : m(data) { - BasicVector res; + // Nothing to do +} - for (unsigned i = 0; i < N; ++i) - res[i] = lhs + rhs[i]; +/* ************************************************************************ */ - return res; +template +inline Vector::Vector(Zero_t zero) +{ + for (int i = 0; i < N; ++i) + m[i] = T{}; } /* ************************************************************************ */ -/** - * @brief Addition operator. - * - * @tparam T1 Type of first operand. - * @tparam T2 Type of value in second BasicVector. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return Result vector. - */ -template -inline BasicVector operator+(T1 lhs, const BasicVector& rhs) noexcept +template +inline Vector::Vector(const Vector& src) { - return BasicVector{ - lhs + rhs.getX(), - lhs + rhs.getY() - }; + for (int i = 0; i < N; ++i) + m[i] = src.m[i]; } /* ************************************************************************ */ -/** - * @brief Substract operator. - * - * @tparam T1 Type of value in first BasicVector. - * @tparam T2 Type of value in second BasicVector. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return Result vector. - */ -template -inline BasicVector operator-(const BasicVector& lhs, const BasicVector& rhs) noexcept +template +inline Vector::Vector(Vector&& src) { - BasicVector res; + for (int i = 0; i < N; ++i) + m[i] = std::move(src.m[i]); +} - for (unsigned i = 0; i < N; ++i) - res[i] = lhs[i] - rhs[i]; +/* ************************************************************************ */ - return res; +template +template::value>::type*> +inline Vector::Vector(const Vector& src) +{ + for (int i = 0; i < N; ++i) + m[i] = T(src[i]); } /* ************************************************************************ */ -/** - * @brief Substract operator. - * - * @tparam T1 Type of value in first BasicVector. - * @tparam T2 Type of value in second BasicVector. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return Result vector. - */ -template -inline BasicVector operator-(const BasicVector& lhs, const BasicVector& rhs) noexcept +template +inline Vector& Vector::operator=(Zero_t zero) { - return BasicVector{ - lhs.getX() - rhs.getX(), - lhs.getY() - rhs.getY() - }; + for (int i = 0; i < N; ++i) + m[i] = T{}; + + return *this; } /* ************************************************************************ */ -/** - * @brief Substract operator. - * - * @tparam T1 Type of value in first BasicVector. - * @tparam T2 Type of second operand. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return Result vector. - */ -template -inline BasicVector operator-(const BasicVector& lhs, T2 rhs) noexcept +template +inline Vector& Vector::operator=(std::initializer_list data) { - BasicVector res; + CECE_ASSERT(data.size() == N); + + using std::begin; + auto it = begin(data); - for (unsigned i = 0; i < N; ++i) - res[i] = lhs[i] - rhs; + for (int i = 0; i < N; ++i, ++it) + m[i] = *it; - return res; + return *this; } /* ************************************************************************ */ -/** - * @brief Substract operator. - * - * @tparam T1 Type of value in first BasicVector. - * @tparam T2 Type of second operand. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return Result vector. - */ -template -inline BasicVector operator-(const BasicVector& lhs, T2 rhs) noexcept +template +inline Vector& Vector::operator=(T (&data)[N]) { - return BasicVector{ - lhs.getX() - rhs, - lhs.getY() - rhs - }; + using std::begin; + auto it = begin(data); + + for (int i = 0; i < N; ++i, ++it) + m[i] = *it; + + return *this; } /* ************************************************************************ */ -/** - * @brief Substract operator. - * - * @tparam T1 Type of first operand. - * @tparam T2 Type of value in second BasicVector. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return Result vector. - */ -template -inline BasicVector operator-(T1 lhs, const BasicVector& rhs) noexcept +template +inline Vector& Vector::operator=(const StaticArray& data) { - BasicVector res; + m = data; - for (unsigned i = 0; i < N; ++i) - res[i] = lhs - rhs[i]; + return *this; +} + +/* ************************************************************************ */ - return res; +template +inline Vector& Vector::operator=(const Vector& src) +{ + for (int i = 0; i < N; ++i) + m[i] = src.m[i]; + + return *this; } /* ************************************************************************ */ -/** - * @brief Substract operator. - * - * @tparam T1 Type of first operand. - * @tparam T2 Type of value in second BasicVector. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return Result vector. - */ -template -inline BasicVector operator-(T1 lhs, const BasicVector& rhs) noexcept +template +inline Vector& Vector::operator=(Vector&& src) { - return BasicVector{ - lhs - rhs.getX(), - lhs - rhs.getY() - }; + for (int i = 0; i < N; ++i) + m[i] = std::move(src.m[i]); + + return *this; } /* ************************************************************************ */ -/** - * @brief Multiplication operator. - * - * @tparam T1 Type of value in first BasicVector. - * @tparam T2 Type of value in second BasicVector. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return Result vector. - */ -template -inline BasicVector operator*(const BasicVector& lhs, const BasicVector& rhs) noexcept +template +template::value>::type*> +inline Vector& Vector::operator=(const Vector& src) +{ + for (int i = 0; i < N; ++i) + m[i] = T(src[i]); + + return *this; +} + +/* ************************************************************************ */ + +template +inline T& Vector::operator[](int pos) noexcept +{ + CECE_ASSERT(pos >= 0); + CECE_ASSERT(pos < N); + return m[pos]; +} + +/* ************************************************************************ */ + +template +inline constexpr const T& Vector::operator[](int pos) const noexcept +{ +#if __cplusplus >= 201402L + CECE_ASSERT(pos >= 0); + CECE_ASSERT(pos < N); +#endif + return m[pos]; +} + +/* ************************************************************************ */ + +template +inline constexpr int Vector::getSize() const noexcept +{ + return N; +} + +/* ************************************************************************ */ + +template +inline constexpr Vector::Vector() + : x{} + , y{} +{ + // Nothing to do +} + +/* ************************************************************************ */ + +template +inline constexpr Vector::Vector(T val) + : x{val} + , y{val} +{ + // Nothing to do +} + +/* ************************************************************************ */ + +template +inline constexpr Vector::Vector(T x, T y) + : x{std::move(x)} + , y{std::move(y)} +{ + // Nothing to do +} + +/* ************************************************************************ */ + +template +inline constexpr Vector::Vector(Zero_t zero) + : x{} + , y{} +{ + // Nothing to do +} + +/* ************************************************************************ */ + +template +inline constexpr Vector::Vector(const Vector& src) + : x{src.getX()} + , y{src.getY()} +{ + // Nothing to do +} + +/* ************************************************************************ */ + +template +inline constexpr Vector::Vector(Vector&& src) + : x{std::move(src.x)} + , y{std::move(src.y)} { - BasicVector res; + // Nothing to do +} - for (unsigned i = 0; i < N; ++i) - res[i] = lhs[i] * rhs[i]; +/* ************************************************************************ */ - return res; +template +template::value>::type*> +inline constexpr Vector::Vector(const Vector& rhs) + : x(rhs.getX()) + , y(rhs.getY()) +{ + // Nothing to do } /* ************************************************************************ */ -/** - * @brief Multiplication operator. - * - * @tparam T1 Type of value in first BasicVector. - * @tparam T2 Type of value in second BasicVector. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return Result vector. - */ -template -inline BasicVector operator*(const BasicVector& lhs, const BasicVector& rhs) noexcept +template +inline Vector& Vector::operator=(Zero_t zero) { - return BasicVector{ - lhs.getX() * rhs.getX(), - lhs.getY() * rhs.getY() - }; + x = T{}; + y = T{}; + + return *this; } /* ************************************************************************ */ -/** - * @brief Multiplication operator. - * - * @tparam T1 Type of value in first BasicVector. - * @tparam T2 Type of second operand. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return Result vector. - */ -template -inline BasicVector operator*(const BasicVector& lhs, T2 rhs) noexcept +template +inline Vector& Vector::operator=(const Vector& src) { - BasicVector res; - - for (unsigned i = 0; i < N; ++i) - res[i] = lhs[i] * rhs; + x = src.x; + y = src.y; - return res; + return *this; } /* ************************************************************************ */ -/** - * @brief Multiplication operator. - * - * @tparam T1 Type of value in first BasicVector. - * @tparam T2 Type of second operand. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return Result vector. - */ -template -inline BasicVector operator*(const BasicVector& lhs, T2 rhs) noexcept +template +inline Vector& Vector::operator=(Vector&& src) { - return BasicVector{ - lhs.getX() * rhs, - lhs.getY() * rhs - }; + x = std::move(src.x); + y = std::move(src.y); + + return *this; } /* ************************************************************************ */ -/** - * @brief Multiplication operator. - * - * @tparam T1 Type of first operand. - * @tparam T2 Type of value in second BasicVector. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return Result vector. - */ -template -inline BasicVector operator*(T1 lhs, const BasicVector& rhs) noexcept +template +template::value>::type*> +inline Vector& Vector::operator=(const Vector& src) { - BasicVector res; - - for (unsigned i = 0; i < N; ++i) - res[i] = lhs * rhs[i]; + x = T(src.getX()); + y = T(src.getY()); - return res; + return *this; } /* ************************************************************************ */ -/** - * @brief Multiplication operator. - * - * @tparam T1 Type of first operand. - * @tparam T2 Type of value in second BasicVector. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return Result vector. - */ -template -inline BasicVector operator*(T1 lhs, const BasicVector& rhs) noexcept +template +inline T& Vector::operator[](int pos) noexcept { - return BasicVector{ - lhs * rhs.getX(), - lhs * rhs.getY() - }; + CECE_ASSERT(pos >= 0); + CECE_ASSERT(pos < 2); + return (&x)[pos]; } /* ************************************************************************ */ -/** - * @brief Division operator. - * - * @tparam T1 Type of value in first BasicVector. - * @tparam T2 Type of value in second BasicVector. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return Result vector. - */ -template -inline BasicVector operator/(const BasicVector& lhs, const BasicVector& rhs) noexcept +template +inline constexpr const T& Vector::operator[](int pos) const noexcept { - BasicVector res; +#if __cplusplus >= 201402L + CECE_ASSERT(pos >= 0); + CECE_ASSERT(pos < 2); +#endif + return (&x)[pos]; +} - for (unsigned i = 0; i < N; ++i) - res[i] = lhs[i] / rhs[i]; +/* ************************************************************************ */ - return res; +template +inline constexpr int Vector::getSize() const noexcept +{ + return 2; } /* ************************************************************************ */ -/** - * @brief Division operator. - * - * @tparam T1 Type of value in first BasicVector. - * @tparam T2 Type of value in second BasicVector. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return Result vector. - */ -template -inline BasicVector operator/(const BasicVector& lhs, const BasicVector& rhs) noexcept +template +inline constexpr const T& Vector::getX() const noexcept { - return BasicVector{ - lhs.getX() / rhs.getX(), - lhs.getY() / rhs.getY() - }; + return x; } /* ************************************************************************ */ -/** - * @brief Division operator. - * - * @tparam T1 Type of value in first BasicVector. - * @tparam T2 Type of second operand. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return Result vector. - */ -template -inline BasicVector operator/(const BasicVector& lhs, T2 rhs) noexcept +template +inline void Vector::setX(T x) { - BasicVector res; + this->x = std::move(x); +} - for (unsigned i = 0; i < N; ++i) - res[i] = lhs[i] / rhs; +/* ************************************************************************ */ - return res; +template +inline constexpr const T& Vector::getY() const noexcept +{ + return y; } /* ************************************************************************ */ -/** - * @brief Division operator. - * - * @tparam T1 Type of value in first BasicVector. - * @tparam T2 Type of second operand. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return Result vector. - */ -template -inline BasicVector operator/(const BasicVector& lhs, T2 rhs) noexcept +template +inline void Vector::setY(T y) { - return BasicVector{ - lhs.getX() / rhs, - lhs.getY() / rhs - }; + this->y = std::move(y); } /* ************************************************************************ */ -/** - * @brief Division operator. - * - * @tparam T1 Type of first operand. - * @tparam T2 Type of value in second BasicVector. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return Result vector. - */ -template -inline BasicVector operator/(T1 lhs, const BasicVector& rhs) noexcept +template +inline constexpr const T& Vector::getWidth() const noexcept { - BasicVector res; + return width; +} - for (unsigned i = 0; i < N; ++i) - res[i] = lhs / rhs[i]; +/* ************************************************************************ */ - return res; +template +inline void Vector::setWidth(T width) +{ + this->width = std::move(width); } /* ************************************************************************ */ -/** - * @brief Division operator. - * - * @tparam T1 Type of first operand. - * @tparam T2 Type of value in second BasicVector. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return Result vector. - */ -template -inline BasicVector operator/(T1 lhs, const BasicVector& rhs) noexcept +template +inline constexpr const T& Vector::getHeight() const noexcept { - return BasicVector{ - lhs / rhs.getX(), - lhs / rhs.getY() - }; + return height; } /* ************************************************************************ */ -/** - * @brief Compare vectors. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return - */ -template -inline bool operator==(const BasicVector& lhs, const BasicVector& rhs) noexcept +template +inline void Vector::setHeight(T height) { - bool res = true; + this->height = std::move(height); +} - for (unsigned i = 0; i < N; ++i) - res = res && lhs[i] == rhs[i]; +/* ************************************************************************ */ - return res; +template +inline constexpr Vector::Vector() noexcept + : x{} + , y{} + , z{} +{ + // Nothing to do } /* ************************************************************************ */ -/** - * @brief Compare vectors. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return - */ -template -inline bool operator==(const BasicVector& lhs, const BasicVector& rhs) noexcept +template +inline constexpr Vector::Vector(T val) + : x{val} + , y{val} + , z{val} { - return - lhs.getX() == rhs.getX() && - lhs.getY() == rhs.getY() - ; + // Nothing to do } /* ************************************************************************ */ -/** - * @brief Compare vectors. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return - */ -template -inline bool operator==(const BasicVector& lhs, Zero_t rhs) noexcept +template +inline constexpr Vector::Vector(T x, T y, T z) + : x{std::move(x)} + , y{std::move(y)} + , z{std::move(z)} { - return lhs == BasicVector(Zero); + // Nothing to do } /* ************************************************************************ */ -/** - * @brief Compare vectors. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return - */ -template -inline bool operator==(Zero_t lhs, const BasicVector& rhs) noexcept +template +inline constexpr Vector::Vector(Zero_t zero) + : x{} + , y{} + , z{} { - return BasicVector(Zero) == rhs; + // Nothing to do } /* ************************************************************************ */ -/** - * @brief Compare vectors. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return - */ -template -inline bool operator!=(const BasicVector& lhs, const BasicVector& rhs) noexcept +template +inline constexpr Vector::Vector(const Vector& src) + : x{src.getX()} + , y{src.getY()} + , z{src.getZ()} { - return !operator==(lhs, rhs); + // Nothing to do } /* ************************************************************************ */ -/** - * @brief Compare vectors. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return - */ -template -inline bool operator!=(const BasicVector& lhs, Zero_t rhs) noexcept +template +inline constexpr Vector::Vector(Vector&& src) + : x{std::move(src.x)} + , y{std::move(src.y)} + , z{std::move(src.z)} { - return !operator==(lhs, rhs); + // Nothing to do } /* ************************************************************************ */ -/** - * @brief Compare vectors. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return - */ -template -inline bool operator!=(Zero_t lhs, const BasicVector& rhs) noexcept +template +template::value>::type*> +inline constexpr Vector::Vector(const Vector& rhs) + : x(rhs.getX()) + , y(rhs.getY()) + , z(rhs.getZ()) { - return !operator==(lhs, rhs); + // Nothing to do } /* ************************************************************************ */ -/** - * @brief Compare vectors. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return - */ -template -inline bool operator<(const BasicVector& lhs, const BasicVector& rhs) noexcept +template +inline Vector& Vector::operator=(Zero_t zero) { - bool res = true; - - for (unsigned i = 0; i < N; ++i) - res = res && ((lhs[i] < rhs[i]) || !(rhs[i] < lhs[i])); + x = T{}; + y = T{}; + z = T{}; - return res; + return *this; } /* ************************************************************************ */ -/** - * @brief Compare vectors. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return - */ -template -inline bool operator<(const BasicVector& lhs, Zero_t rhs) noexcept +template +inline Vector& Vector::operator=(const Vector& src) { - return lhs < BasicVector{Zero}; + x = src.x; + y = src.y; + z = src.z; + + return *this; } /* ************************************************************************ */ -/** - * @brief Compare vectors. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return - */ -template -inline bool operator<(Zero_t lhs, const BasicVector& rhs) noexcept +template +inline Vector& Vector::operator=(Vector&& src) { - return BasicVector{Zero} < rhs; + x = std::move(src.x); + y = std::move(src.y); + z = std::move(src.z); + + return *this; } /* ************************************************************************ */ -/** - * @brief Compare vectors. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return - */ -template -inline bool operator<=(const BasicVector& lhs, const BasicVector& rhs) noexcept +template +template::value>::type*> +inline Vector& Vector::operator=(const Vector& src) { - return !operator>(lhs, rhs); + x = T(src.getX()); + y = T(src.getY()); + z = T(src.getZ()); + + return *this; } /* ************************************************************************ */ -/** - * @brief Compare vectors. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return - */ -template -inline bool operator<=(const BasicVector& lhs, Zero_t rhs) noexcept +template +inline T& Vector::operator[](int pos) noexcept { - return !operator>(lhs, rhs); + CECE_ASSERT(pos >= 0); + CECE_ASSERT(pos < 3); + return (&x)[pos]; } /* ************************************************************************ */ -/** - * @brief Compare vectors. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return - */ -template -inline bool operator<=(Zero_t lhs, const BasicVector& rhs) noexcept +template +inline constexpr const T& Vector::operator[](int pos) const noexcept { - return !operator>(lhs, rhs); +#if __cplusplus >= 201402L + CECE_ASSERT(pos >= 0); + CECE_ASSERT(pos < 3); +#endif + return (&x)[pos]; } /* ************************************************************************ */ -/** - * @brief Compare vectors. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return - */ -template -inline bool operator>(const BasicVector& lhs, const BasicVector& rhs) noexcept +template +inline constexpr const T& Vector::getX() const noexcept { - // Reversed operands - return operator<(rhs, lhs); + return x; } /* ************************************************************************ */ -/** - * @brief Compare vectors. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return - */ -template -inline bool operator>(const BasicVector& lhs, Zero_t rhs) noexcept +template +inline constexpr int Vector::getSize() const noexcept { - // Reversed operands - return operator<(rhs, lhs); + return 3; } /* ************************************************************************ */ -/** - * @brief Compare vectors. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return - */ -template -inline bool operator>(Zero_t lhs, const BasicVector& rhs) noexcept +template +inline void Vector::setX(T x) { - // Reversed operands - return operator<(rhs, lhs); + this->x = std::move(x); } /* ************************************************************************ */ -/** - * @brief Compare vectors. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return - */ -template -inline bool operator>=(const BasicVector& lhs, const BasicVector& rhs) noexcept +template +inline constexpr const T& Vector::getY() const noexcept { - return !operator<(lhs, rhs); + return y; } /* ************************************************************************ */ -/** - * @brief Compare vectors. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return - */ -template -inline bool operator>=(const BasicVector& lhs, Zero_t rhs) noexcept +template +inline void Vector::setY(T y) { - return !operator<(lhs, rhs); + this->y = std::move(y); } /* ************************************************************************ */ -/** - * @brief Compare vectors. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return - */ -template -inline bool operator>=(Zero_t lhs, const BasicVector& rhs) noexcept +template +inline constexpr const T& Vector::getZ() const noexcept { - return !operator<(lhs, rhs); + return z; } /* ************************************************************************ */ -/** - * @brief Calculate dot product of two vectors. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return Dot product. - */ -template -inline decltype(T1{} * T2{}) dot(const BasicVector& lhs, const BasicVector& rhs) noexcept +template +inline void Vector::setZ(T z) { - decltype(T1{} * T2{}) res{}; - - for (unsigned i = 0; i < N; ++i) - res += lhs[i] * rhs[i]; - - return res; + this->z = std::move(z); } /* ************************************************************************ */ -/** - * @brief Calculate cross product of two vectors. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return Cross product. - */ -template -inline -decltype(std::declval() * std::declval()) -cross(const BasicVector& lhs, const BasicVector& rhs) noexcept +template +inline constexpr const T& Vector::getWidth() const noexcept { - return {lhs.getX() * rhs.getY() - lhs.getY() * rhs.getX()}; + return width; } /* ************************************************************************ */ -/** - * @brief Calculate cross product of two vectors. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return Cross product. - */ -template -inline -BasicVector() * std::declval()), 2> -cross(const BasicVector& lhs, const T2& rhs) noexcept +template +inline void Vector::setWidth(T width) { - return {rhs * lhs.getY(), -rhs * lhs.getX()}; + this->width = std::move(width); } /* ************************************************************************ */ -/** - * @brief Calculate cross product of two vectors. - * - * @param lhs Left operand. - * @param rhs Right operand. - * - * @return Cross product. - */ -template -inline -BasicVector() * std::declval()), 2> -cross(const T1& lhs, const BasicVector& rhs) noexcept +template +inline constexpr const T& Vector::getHeight() const noexcept { - return {-lhs * rhs.getY(), lhs * rhs.getX()}; + return height; } /* ************************************************************************ */ -/** - * @brief Input stream operator. - * - * @param is Input stream. - * @param vector Result value. - * - * @return is. - */ -template -io::InStream& operator>>(io::InStream& is, BasicVector& vector) +template +inline void Vector::setHeight(T height) { - unsigned i = 0; - - for (; i < N; ++i) - { - if (!(is >> std::skipws >> vector[i])) - break; - } - - if (i == 0) - return is; + this->height = std::move(height); +} - // Copy missing values - // TODO: have this feature? - for (unsigned j = i; j < N; ++j) - vector[j] = vector[i - 1]; +/* ************************************************************************ */ - return is; +template +inline constexpr const T& Vector::getDepth() const noexcept +{ + return depth; } /* ************************************************************************ */ -/** - * @brief Output stream operator. - * - * @param os Output stream. - * @param vector Input value. - * - * @return os. - */ -template -io::OutStream& operator<<(io::OutStream& os, const BasicVector& vector) noexcept +template +inline void Vector::setDepth(T depth) { - for (unsigned i = 0; i < N; ++i) - { - if (i != 0) - os << " "; + this->depth = std::move(depth); +} - os << vector[i]; - } +/* ************************************************************************ */ - return os; +template +inline constexpr Vector rotate(const Vector& vec, unit::Angle angle) noexcept +{ + return { + static_cast(vec.getX() * cos(static_cast(angle)) - vec.getY() * sin(static_cast(angle))), + static_cast(vec.getX() * sin(static_cast(angle)) + vec.getY() * cos(static_cast(angle))) + }; } /* ************************************************************************ */ -extern template class BasicVector; -extern template class BasicVector; -extern template class BasicVector; +template +inline constexpr Vector() * std::declval()), 3> cross( + const Vector& lhs, + const Vector& rhs +) +{ + return { + lhs.getY() * rhs.getZ() - lhs.getZ() * rhs.getY(), + lhs.getZ() * rhs.getX() - lhs.getX() * rhs.getZ(), + lhs.getX() * rhs.getY() - lhs.getY() * rhs.getX() + }; +} /* ************************************************************************ */ diff --git a/include/cece/math/VectorBase.hpp b/include/cece/math/VectorBase.hpp new file mode 100644 index 0000000..e55c2d4 --- /dev/null +++ b/include/cece/math/VectorBase.hpp @@ -0,0 +1,1012 @@ +/* ************************************************************************ */ +/* Georgiev Lab (c) 2015-2017 */ +/* ************************************************************************ */ +/* Department of Cybernetics */ +/* Faculty of Applied Sciences */ +/* University of West Bohemia in Pilsen */ +/* ************************************************************************ */ +/* */ +/* This file is part of CeCe. */ +/* */ +/* CeCe 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. */ +/* */ +/* CeCe 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 CeCe. If not, see . */ +/* */ +/* ************************************************************************ */ + +#pragma once + +/* ************************************************************************ */ + +// C++ +#include +#include + +// CeCe +#include "cece/common.hpp" +#include "cece/Assert.hpp" +#include "cece/math/Zero.hpp" + +/* ************************************************************************ */ + +namespace cece { +namespace math { + +/* ************************************************************************ */ + +/** + * @brief Vector adaptor. + * + * @tparam VectorType The vector type. + * @tparam T Value type. + * @tparam N Vector size. + */ +template< + template typename VectorType, + typename T, + int N +> +class VectorBase +{ + +// Public Types +public: + + + /// VectorBase value type. + using ValueType = T; + + +// Public Operators +public: + + + /** + * @brief Unary plus operator. + * + * @return Vector. + */ + VectorType operator+() const noexcept; + + + /** + * @brief Unary minus operator. + * + * @return Vector. + */ + VectorType operator-() const noexcept; + + + /** + * @brief Addition operator. + * + * @param rhs The right operand. + * + * @tparam T1 The second type. + * + * @return *this. + */ + template + VectorType& operator+=(const VectorType& rhs); + + + /** + * @brief Subtraction operator. + * + * @param rhs The right operand. + * + * @tparam T1 The second type. + * + * @return *this. + */ + template + VectorType& operator-=(const VectorType& rhs); + + + /** + * @brief Multiplication operator. + * + * @param rhs The right operand. + * + * @tparam T1 Type of right operand. + * + * @return *this. + */ + template + VectorType& operator*=(T1 rhs); + + + /** + * @brief Multiplication operator. + * + * @param rhs The right operand. + * + * @tparam T1 The second type. + * + * @return *this. + */ + template + VectorType& operator*=(const VectorType& rhs); + + + /** + * @brief Division operator. + * + * @param rhs The right operand. + * + * @tparam T1 Type of right operand. + * + * @return *this. + */ + template + VectorType& operator/=(T1 rhs); + + + /** + * @brief Division operator. + * + * @param rhs Right operand. + * + * @tparam T1 The second type. + * + * @return *this. + */ + template + VectorType& operator/=(const VectorType& rhs); + + +// Public Operations +public: + + + /** + * @brief Calculate vector length. + * + * @return The length. + */ + T getLength() const; + + + /** + * @brief Calculate vector length - squared. + * + * @return The length squared. + */ + decltype(std::declval() * std::declval()) getLengthSquared() const; + +}; + +/* ************************************************************************ */ + +/** + * @brief Addition operator. + * + * @param lhs The left operand. + * @param rhs The right operand. + * + * @tparam VectorType Vector type. + * @tparam T1 Type of value in first VectorBase. + * @tparam T2 Type of value in second VectorBase. + * @tparam Tags Vector type tags. + * + * @return Result vector. + */ +template typename VectorType, typename T1, typename T2, int N> +VectorType() + std::declval()), N> operator+( + const VectorType& lhs, + const VectorType& rhs +); + +/* ************************************************************************ */ + +/** + * @brief Substract operator. + * + * @param lhs The left operand. + * @param rhs The right operand. + * + * @tparam VectorType Vector type. + * @tparam T1 Type of value in first VectorBase. + * @tparam T2 Type of value in second VectorBase. + * @tparam Tags Vector type tags. + * + * @return Result vector. + */ +template typename VectorType, typename T1, typename T2, int N> +VectorType() - std::declval()), N> operator-( + const VectorType& lhs, + const VectorType& rhs +); + +/* ************************************************************************ */ + +/** + * @brief Multiplication operator. + * + * @param lhs The left operand. + * @param rhs The right operand. + * + * @tparam VectorType Vector type. + * @tparam T1 Type of value in first VectorBase. + * @tparam T2 Type of value in second VectorBase. + * @tparam Tags Vector type tags. + * + * @return Result vector. + */ +template typename VectorType, typename T1, typename T2, int N> +VectorType() * std::declval()), N> operator*( + const VectorType& lhs, + const VectorType& rhs +); + +/* ************************************************************************ */ + +/** + * @brief Multiplication operator. + * + * @param lhs The left operand. + * @param rhs The right operand. + * + * @tparam VectorType Vector type. + * @tparam T1 Type of value in first VectorBase. + * @tparam T2 Type of value in second VectorBase. + * @tparam Tags Vector type tags. + * + * @return Result vector. + */ +template typename VectorType, typename T1, typename T2, int N> +VectorType() * std::declval()), N> operator*( + const VectorType& lhs, + const T2& rhs +); + +/* ************************************************************************ */ + +/** + * @brief Multiplication operator. + * + * @param lhs The left operand. + * @param rhs The right operand. + * + * @tparam VectorType Vector type. + * @tparam T1 Type of value in first VectorBase. + * @tparam T2 Type of value in second VectorBase. + * @tparam Tags Vector type tags. + * + * @return Result vector. + */ +template typename VectorType, typename T1, typename T2, int N> +VectorType() * std::declval()), N> operator*( + const T1& lhs, + const VectorType& rhs +); + +/* ************************************************************************ */ + +/** + * @brief Division operator. + * + * @param lhs The left operand. + * @param rhs The right operand. + * + * @tparam VectorType Vector type. + * @tparam T1 Type of value in first VectorBase. + * @tparam T2 Type of value in second VectorBase. + * @tparam Tags Vector type tags. + * + * @return Result vector. + */ +template typename VectorType, typename T1, typename T2, int N> +VectorType() / std::declval()), N> operator/( + const VectorType& lhs, + const VectorType& rhs +); + +/* ************************************************************************ */ + +/** + * @brief Division operator. + * + * @param lhs The left operand. + * @param rhs The right operand. + * + * @tparam VectorType Vector type. + * @tparam T1 Type of value in first VectorBase. + * @tparam T2 Type of value in second VectorBase. + * @tparam Tags Vector type tags. + * + * @return Result vector. + */ +template typename VectorType, typename T1, typename T2, int N> +VectorType() / std::declval()), N> operator/( + const VectorType& lhs, + const T2& rhs +); + +/* ************************************************************************ */ + +/** + * @brief Division operator. + * + * @param lhs The left operand. + * @param rhs The right operand. + * + * @tparam VectorType Vector type. + * @tparam T1 Type of value in first VectorBase. + * @tparam T2 Type of value in second VectorBase. + * @tparam Tags Vector type tags. + * + * @return Result vector. + */ +template typename VectorType, typename T1, typename T2, int N> +VectorType() / std::declval()), N> operator/( + const T1& lhs, + const VectorType& rhs +); + +/* ************************************************************************ */ + +/** + * @brief Compare vectors. + * + * @param lhs The left operand. + * @param rhs The right operand. + * + * @tparam VectorType Vector type. + * @tparam T1 Type of value in first VectorBase. + * @tparam T2 Type of value in second VectorBase. + * @tparam Tags Vector type tags. + * + * @return Operation result. + */ +template typename VectorType, typename T1, typename T2, int N> +bool operator==( + const VectorType& lhs, + const VectorType& rhs +); + +/* ************************************************************************ */ + +/** + * @brief Compare vectors. + * + * @param lhs The left operand. + * @param rhs The right operand. + * + * @tparam VectorType Vector type. + * @tparam T1 Type of value in first VectorBase. + * @tparam Tags Vector type tags. + * + * @return Operation result. + */ +template typename VectorType, typename T1, int N> +bool operator==( + const VectorType& lhs, + const Zero_t& rhs +); + +/* ************************************************************************ */ + +/** + * @brief Compare vectors. + * + * @param lhs The left operand. + * @param rhs The right operand. + * + * @tparam VectorType Vector type. + * @tparam T2 Type of value in second VectorBase. + * @tparam Tags Vector type tags. + * + * @return Operation result. + */ +template typename VectorType, typename T2, int N> +bool operator==( + const Zero_t& lhs, + const VectorType& rhs +); + +/* ************************************************************************ */ + +/** + * @brief Compare vectors. + * + * @param lhs The left operand. + * @param rhs The right operand. + * + * @tparam VectorType Vector type. + * @tparam T1 Type of value in first VectorBase. + * @tparam T2 Type of value in second VectorBase. + * @tparam Tags Vector type tags. + * + * @return Operation result. + */ +template typename VectorType, typename T1, typename T2, int N> +bool operator!=( + const VectorType& lhs, + const VectorType& rhs +); + +/* ************************************************************************ */ + +/** + * @brief Compare vectors. + * + * @param lhs The left operand. + * @param rhs The right operand. + * + * @tparam VectorType Vector type. + * @tparam T1 Type of value in first VectorBase. + * @tparam Tags Vector type tags. + * + * @return Operation result. + */ +template typename VectorType, typename T1, int N> +bool operator!=( + const VectorType& lhs, + const Zero_t& rhs +); + +/* ************************************************************************ */ + +/** + * @brief Compare vectors. + * + * @param lhs The left operand. + * @param rhs The right operand. + * + * @tparam VectorType Vector type. + * @tparam T2 Type of value in second VectorBase. + * @tparam Tags Vector type tags. + * + * @return Operation result. + */ +template typename VectorType, typename T2, int N> +bool operator!=( + const Zero_t& lhs, + const VectorType& rhs +); + +/* ************************************************************************ */ + +/** + * @brief Calculate dot product of two vectors. + * + * @param lhs Left operand. + * @param rhs Right operand. + * + * @tparam VectorType Vector type. + * @tparam T1 Type of value in first VectorBase. + * @tparam T2 Type of value in second VectorBase. + * @tparam Tags Vector type tags. + * + * @return Dot product. + */ +template typename VectorType, typename T1, typename T2, int N> +decltype(std::declval() * std::declval()) dot( + const VectorType& lhs, + const VectorType& rhs +); + +/* ************************************************************************ */ + +/** + * @brief Calculate distance of two vectors. + * + * @param lhs Left operand. + * @param rhs Right operand. + * + * @tparam VectorType Vector type. + * @tparam T1 Type of value in first VectorBase. + * @tparam T2 Type of value in second VectorBase. + * @tparam Tags Vector type tags. + * + * @return Distance. + */ +template typename VectorType, typename T1, typename T2, int N> +decltype(std::declval() - std::declval())>() * std::declval() - std::declval())>()) distanceSquared( + const VectorType& lhs, + const VectorType& rhs +); + +/* ************************************************************************ */ + +/** + * @brief Calculate distance of two vectors. + * + * @param lhs Left operand. + * @param rhs Right operand. + * + * @tparam VectorType Vector type. + * @tparam T1 Type of value in first VectorBase. + * @tparam T2 Type of value in second VectorBase. + * @tparam Tags Vector type tags. + * + * @return Distance. + */ +template typename VectorType, typename T1, typename T2, int N> +decltype(std::declval() - std::declval()) distance( + const VectorType& lhs, + const VectorType& rhs +); + +/* ************************************************************************ */ + +/** + * @brief Check if value is in given range. + * + * @code + * value >= low && value < high; + * @endcode + * + * @param[in] value The tested value. + * @param[in] low The low value. + * @param[in] high The high value. + * + * @tparam VectorType Vector type. + * @tparam T Type of value. + * @tparam Tags Vector type tags. + * + * @return If value is in range. + */ +template typename VectorType, typename T, int N> +bool inRange( + const VectorType& value, + const VectorType& low, + const VectorType& high +); + +/* ************************************************************************ */ + +/** + * @brief Check if value is in given range. + * + * @code + * value >= Zero && value < high; + * @endcode + * + * @param[in] value The tested value. + * @param[in] high The high value. + * + * @tparam VectorType Vector type. + * @tparam T Type of value. + * @tparam Tags Vector type tags. + * + * @return If value is in range. + */ +template typename VectorType, typename T, int N> +bool inRange( + const VectorType& value, + const VectorType& high +); + +/* ************************************************************************ */ + +} +} + +/* ************************************************************************ */ +/* ************************************************************************ */ +/* ************************************************************************ */ + +namespace cece { +namespace math { + +/* ************************************************************************ */ + +template typename VectorType, typename T, int N> +inline VectorType VectorBase::operator+() const noexcept +{ + return *static_cast*>(this); +} + +/* ************************************************************************ */ + +template typename VectorType, typename T, int N> +inline VectorType VectorBase::operator-() const noexcept +{ + VectorType res; + + // Typed alias + auto& self = *static_cast*>(this); + + for (int i = 0; i < N; ++i) + res[i] = -self[i]; + + return res; +} + +/* ************************************************************************ */ + +template typename VectorType, typename T, int N> +template +inline VectorType& VectorBase::operator+=(const VectorType& rhs) +{ + // Typed alias + auto& self = *static_cast*>(this); + + for (int i = 0; i < N; ++i) + self[i] += rhs[i]; + + return self; +} + +/* ************************************************************************ */ + +template typename VectorType, typename T, int N> +template +inline VectorType& VectorBase::operator-=(const VectorType& rhs) +{ + // Typed alias + auto& self = *static_cast*>(this); + + for (int i = 0; i < N; ++i) + self[i] -= rhs[i]; + + return self; +} + +/* ************************************************************************ */ + +template typename VectorType, typename T, int N> +template +inline VectorType& VectorBase::operator*=(T1 rhs) +{ + // Typed alias + auto& self = *static_cast*>(this); + + for (int i = 0; i < N; ++i) + self[i] *= rhs; + + return self; +} + +/* ************************************************************************ */ + +template typename VectorType, typename T, int N> +template +inline VectorType& VectorBase::operator*=(const VectorType& rhs) +{ + // Typed alias + auto& self = *static_cast*>(this); + + for (int i = 0; i < N; ++i) + self[i] *= rhs[i]; + + return self; +} + +/* ************************************************************************ */ + +template typename VectorType, typename T, int N> +template +inline VectorType& VectorBase::operator/=(T1 rhs) +{ + // Typed alias + auto& self = *static_cast*>(this); + + for (int i = 0; i < N; ++i) + self[i] /= rhs; + + return self; +} + +/* ************************************************************************ */ + +template typename VectorType, typename T, int N> +template +inline VectorType& VectorBase::operator/=(const VectorType& rhs) +{ + // Typed alias + auto& self = *static_cast*>(this); + + for (int i = 0; i < N; ++i) + self[i] /= rhs[i]; + + return self; +} + +/* ************************************************************************ */ + +template typename VectorType, typename T, int N> +inline T VectorBase::getLength() const +{ + using std::sqrt; + return static_cast(sqrt(getLengthSquared())); +} + +/* ************************************************************************ */ + +template typename VectorType, typename T, int N> +inline decltype(std::declval() * std::declval()) VectorBase::getLengthSquared() const +{ + decltype(std::declval() * std::declval()) res{}; + + // Typed alias + auto& self = *static_cast*>(this); + + for (int i = 0; i < N; ++i) + res += self[i] * self[i]; + + return res; +} + +/* ************************************************************************ */ + +template typename VectorType, typename T1, typename T2, int N> +inline VectorType() + std::declval()), N> operator+( + const VectorType& lhs, + const VectorType& rhs +) +{ + VectorType() + std::declval()), N> res; + + for (int i = 0; i < N; ++i) + res[i] = lhs[i] + rhs[i]; + + return res; +} + +/* ************************************************************************ */ + +template typename VectorType, typename T1, typename T2, int N> +inline VectorType() - std::declval()), N> operator-( + const VectorType& lhs, + const VectorType& rhs +) +{ + VectorType() - std::declval()), N> res; + + for (int i = 0; i < N; ++i) + res[i] = lhs[i] - rhs[i]; + + return res; +} + +/* ************************************************************************ */ + +template typename VectorType, typename T1, typename T2, int N> +inline VectorType() * std::declval()), N> operator*( + const VectorType& lhs, + const VectorType& rhs +) +{ + VectorType() * std::declval()), N> res; + + for (int i = 0; i < N; ++i) + res[i] = lhs[i] * rhs[i]; + + return res; +} + +/* ************************************************************************ */ + +template typename VectorType, typename T1, typename T2, int N> +inline VectorType() * std::declval()), N> operator*( + const VectorType& lhs, + const T2& rhs +) +{ + VectorType() * std::declval()), N> res; + + for (int i = 0; i < N; ++i) + res[i] = lhs[i] * rhs; + + return res; +} + +/* ************************************************************************ */ + +template typename VectorType, typename T1, typename T2, int N> +inline VectorType() * std::declval()), N> operator*( + const T1& lhs, + const VectorType& rhs +) +{ + VectorType() * std::declval()), N> res; + + for (int i = 0; i < N; ++i) + res[i] = lhs * rhs[i]; + + return res; +} + +/* ************************************************************************ */ + +template typename VectorType, typename T1, typename T2, int N> +inline VectorType() / std::declval()), N> operator/( + const VectorType& lhs, + const VectorType& rhs +) +{ + VectorType() / std::declval()), N> res; + + for (int i = 0; i < N; ++i) + res[i] = lhs[i] / rhs[i]; + + return res; +} + +/* ************************************************************************ */ + +template typename VectorType, typename T1, typename T2, int N> +inline VectorType() / std::declval()), N> operator/( + const VectorType& lhs, + const T2& rhs +) +{ + VectorType() / std::declval()), N> res; + + for (int i = 0; i < N; ++i) + res[i] = lhs[i] / rhs; + + return res; +} + +/* ************************************************************************ */ + +template typename VectorType, typename T1, typename T2, int N> +inline VectorType() / std::declval()), N> operator/( + const T1& lhs, + const VectorType& rhs +) +{ + VectorType() / std::declval()), N> res; + + for (int i = 0; i < N; ++i) + res[i] = lhs / rhs[i]; + + return res; +} + +/* ************************************************************************ */ + +template typename VectorType, typename T1, typename T2, int N> +inline bool operator==( + const VectorType& lhs, + const VectorType& rhs +) +{ + bool res = true; + + for (int i = 0; i < N; ++i) + res = res && lhs[i] == rhs[i]; + + return res; +} + +/* ************************************************************************ */ + +template typename VectorType, typename T1, int N> +inline bool operator==( + const VectorType& lhs, + const Zero_t& rhs +) +{ + return operator==(lhs, VectorType(Zero)); +} + +/* ************************************************************************ */ + +template typename VectorType, typename T2, int N> +inline bool operator==( + const Zero_t& lhs, + const VectorType& rhs +) +{ + return operator==(VectorType(lhs), rhs); +} + +/* ************************************************************************ */ + +template typename VectorType, typename T1, typename T2, int N> +inline bool operator!=( + const VectorType& lhs, + const VectorType& rhs +) +{ + return !operator==(lhs, rhs); +} + +/* ************************************************************************ */ + +template typename VectorType, typename T1, int N> +inline bool operator!=( + const VectorType& lhs, + const Zero_t& rhs +) +{ + return !operator==(lhs, rhs); +} + +/* ************************************************************************ */ + +template typename VectorType, typename T2, int N> +inline bool operator!=( + const Zero_t& lhs, + const VectorType& rhs +) +{ + return !operator==(lhs, rhs); +} + +/* ************************************************************************ */ + +template typename VectorType, typename T1, typename T2, int N> +inline decltype(std::declval() * std::declval()) dot( + const VectorType& lhs, + const VectorType& rhs +) +{ + decltype(std::declval() * std::declval()) res{}; + + for (int i = 0; i < N; ++i) + res += lhs[i] * rhs[i]; + + return res; +} + +/* ************************************************************************ */ + +template typename VectorType, typename T1, typename T2, int N> +inline decltype(std::declval() - std::declval())>() * std::declval() - std::declval())>()) distanceSquared( + const VectorType& lhs, + const VectorType& rhs +) +{ + return (lhs - rhs).getLengthSquared(); +} + +/* ************************************************************************ */ + +template typename VectorType, typename T1, typename T2, int N> +inline decltype(std::declval() - std::declval()) distance( + const VectorType& lhs, + const VectorType& rhs +) +{ + return (lhs - rhs).getLength(); +} + +/* ************************************************************************ */ + +template typename VectorType, typename T, int N> +inline bool inRange( + const VectorType& value, + const VectorType& low, + const VectorType& high +) +{ + bool res = true; + + for (int i = 0; i < N; ++i) + res = res && (value[i] >= low[i] && value[i] < high[i]); + + return res; +} + +/* ************************************************************************ */ + +template typename VectorType, typename T, int N> +inline bool inRange( + const VectorType& value, + const VectorType& high +) +{ + return inRange(value, VectorType(Zero), high); +} + +/* ************************************************************************ */ + +} +} + +/* ************************************************************************ */ diff --git a/include/cece/math/VectorIo.hpp b/include/cece/math/VectorIo.hpp new file mode 100644 index 0000000..a4ae960 --- /dev/null +++ b/include/cece/math/VectorIo.hpp @@ -0,0 +1,125 @@ +/* ************************************************************************ */ +/* Georgiev Lab (c) 2015-2017 */ +/* ************************************************************************ */ +/* Department of Cybernetics */ +/* Faculty of Applied Sciences */ +/* University of West Bohemia in Pilsen */ +/* ************************************************************************ */ +/* */ +/* This file is part of CeCe. */ +/* */ +/* CeCe 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. */ +/* */ +/* CeCe 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 CeCe. If not, see . */ +/* */ +/* ************************************************************************ */ + +#pragma once + +/* ************************************************************************ */ + +// CeCe +#include "cece/common.hpp" +#include "cece/Assert.hpp" +#include "cece/io/InStream.hpp" +#include "cece/io/OutStream.hpp" +#include "cece/math/VectorBase.hpp" + +/* ************************************************************************ */ + +namespace cece { +namespace math { + +/* ************************************************************************ */ + +/** + * @brief Input stream operator. + * + * @param is Input stream. + * @param vector Result value. + * + * @tparam VectorType Vector type. + * @tparam T Type of value. + * @tparam Tags Vector type tags. + * + * @return Input stream. + */ +template typename VectorType, typename T, int... Tags> +io::InStream& operator>>(io::InStream& is, VectorType& vector); + +/* ************************************************************************ */ + +/** + * @brief Output stream operator. + * + * @param os Output stream. + * @param vector Input value. + * + * @tparam VectorType Vector type. + * @tparam T Type of value. + * @tparam Tags Vector type tags. + * + * @return Output stream. + */ +template typename VectorType, typename T, int... Tags> +io::OutStream& operator<<(io::OutStream& os, const VectorType& vector); + +/* ************************************************************************ */ + +} +} + +/* ************************************************************************ */ +/* ************************************************************************ */ +/* ************************************************************************ */ + +namespace cece { +namespace math { + +/* ************************************************************************ */ + +template typename VectorType, typename T, int... Tags> +inline io::InStream& operator>>(io::InStream& is, VectorType& vector) +{ + // Read all elements + for (int i = 0; i < vector.getSize(); ++i) + { + // Unable to read element + if (!(is >> std::skipws >> vector[i])) + break; + } + + return is; +} + +/* ************************************************************************ */ + +template typename VectorType, typename T, int... Tags> +inline io::OutStream& operator<<(io::OutStream& os, const VectorType& vector) +{ + for (int i = 0; i < vector.getSize(); ++i) + { + if (i != 0) + os << " "; + + os << vector[i]; + } + + return os; +} + +/* ************************************************************************ */ + +} +} + +/* ************************************************************************ */ diff --git a/include/cece/math/VectorRange.hpp b/include/cece/math/VectorRange.hpp index 1784654..4ef1912 100644 --- a/include/cece/math/VectorRange.hpp +++ b/include/cece/math/VectorRange.hpp @@ -1,5 +1,5 @@ /* ************************************************************************ */ -/* Georgiev Lab (c) 2015-2016 */ +/* Georgiev Lab (c) 2015-2017 */ /* ************************************************************************ */ /* Department of Cybernetics */ /* Faculty of Applied Sciences */ @@ -39,9 +39,9 @@ namespace math { /* ************************************************************************ */ /** - * @brief Wrapper for vector iterator. + * @brief Wrapper for vector iterator. * - * @tparam T Element type of Vector. + * @tparam T Element type of Vector. */ template struct IteratorVector @@ -64,11 +64,11 @@ struct IteratorVector /** - * @brief Constructor. + * @brief Constructor. * - * @param value Current value. - * @param max Maximum value. - * @param min Minimum value. + * @param value Current value. + * @param max Maximum value. + * @param min Minimum value. */ IteratorVector(Vector value, Vector max, Vector min = Zero) noexcept : m_value(std::move(value)) @@ -84,7 +84,7 @@ struct IteratorVector /** - * @brief Cast to value. + * @brief Cast to value. */ operator Vector() const noexcept { @@ -93,11 +93,11 @@ struct IteratorVector /** - * @brief Compares values. + * @brief Compares values. * - * @param rhs Second value. + * @param rhs Second value. * - * @return Are values equal? + * @return Are values equal? */ bool operator==(const IteratorVector& rhs) const noexcept { @@ -106,11 +106,11 @@ struct IteratorVector /** - * @brief Compares values. + * @brief Compares values. * - * @param rhs Second value. + * @param rhs Second value. * - * @return Aren't values equal? + * @return Aren't values equal? */ bool operator!=(const IteratorVector& rhs) const noexcept { @@ -119,9 +119,9 @@ struct IteratorVector /** - * @brief Dereference operator. + * @brief Dereference operator. * - * @return A reference to the current token. + * @return A reference to the current token. */ reference operator*() const noexcept { @@ -130,9 +130,9 @@ struct IteratorVector /** - * @brief Dereference operator. + * @brief Dereference operator. * - * @return A pointer to the current token. + * @return A pointer to the current token. */ pointer operator->() const noexcept { @@ -141,20 +141,20 @@ struct IteratorVector /** - * @brief Increment operator. + * @brief Increment operator. * - * @return *this. + * @return *this. */ IteratorVector& operator++() noexcept { - if (m_value.x() == m_max.x()) + if (m_value.x == m_max.x) { - m_value.x() = m_min.x(); - ++m_value.y(); + m_value.x = m_min.x; + ++m_value.y; } else { - ++m_value.x(); + ++m_value.x; } return *this; @@ -162,11 +162,15 @@ struct IteratorVector /** - * @brief Post-increment operator. + * @brief Post-increment operator. * - * @note Is deleted (because I'm to lazy to write it). + * @note Is deleted (because I'm to lazy to write it). + * + * @param[in] dummy The dummy. + * + * @return Iterator. */ - IteratorVector operator++(int) = delete; + IteratorVector operator++(int dummy) = delete; // Private Data Members @@ -199,7 +203,7 @@ template constexpr IteratorRange> range(Vector begin, Vector end) noexcept { return makeRange( - IteratorVector{begin, end - T{1}, begin}, + IteratorVector{begin, end - Vector{1}, begin}, IteratorVector{Vector{begin.getX(), end.getY()}, Zero, Zero} ); } diff --git a/include/cece/math/Zero.hpp b/include/cece/math/Zero.hpp index b02b3ca..7b13f36 100644 --- a/include/cece/math/Zero.hpp +++ b/include/cece/math/Zero.hpp @@ -1,5 +1,5 @@ /* ************************************************************************ */ -/* Georgiev Lab (c) 2015-2016 */ +/* Georgiev Lab (c) 2015-2017 */ /* ************************************************************************ */ /* Department of Cybernetics */ /* Faculty of Applied Sciences */ @@ -33,8 +33,8 @@ namespace math { /* ************************************************************************ */ /** - * @brief Special value used by other types to check if value is zero. The idea is - * similar with nullptr (nullptr_t). + * @brief Special value used by other types to check if value is zero. The + * idea is similar with nullptr (nullptr_t). */ constexpr struct Zero_t {} Zero{}; diff --git a/include/cece/math/constants.hpp b/include/cece/math/constants.hpp index 18a6a27..1e97488 100644 --- a/include/cece/math/constants.hpp +++ b/include/cece/math/constants.hpp @@ -1,5 +1,5 @@ /* ************************************************************************ */ -/* Georgiev Lab (c) 2015-2016 */ +/* Georgiev Lab (c) 2015-2017 */ /* ************************************************************************ */ /* Department of Cybernetics */ /* Faculty of Applied Sciences */ @@ -38,14 +38,14 @@ namespace math { /* ************************************************************************ */ /** - * @brief PI constant. + * @brief PI constant. */ constexpr RealType PI = 3.14159265359; /* ************************************************************************ */ /** - * @brief Euler number constant. + * @brief Euler number constant. */ constexpr RealType E = 2.718281828459; diff --git a/include/cece/unit/VectorUnits.hpp b/include/cece/unit/VectorUnits.hpp index 2cecbdd..bd06b2a 100644 --- a/include/cece/unit/VectorUnits.hpp +++ b/include/cece/unit/VectorUnits.hpp @@ -106,12 +106,11 @@ namespace math { /* ************************************************************************ */ -extern template class BasicVector; -extern template class BasicVector; -extern template class BasicVector; -extern template class BasicVector; -extern template class BasicVector; -extern template class BasicVector; +extern template class Vector; +extern template class Vector; +extern template class Vector; +extern template class Vector; +extern template class Vector; /* ************************************************************************ */ diff --git a/src/math/CMakeLists.txt b/src/math/CMakeLists.txt index 526f590..5aac37e 100644 --- a/src/math/CMakeLists.txt +++ b/src/math/CMakeLists.txt @@ -1,5 +1,5 @@ # ######################################################################### # -# Georgiev Lab (c) 2015-2016 # +# Georgiev Lab (c) 2015-2017 # # ######################################################################### # # Department of Cybernetics # # Faculty of Applied Sciences # diff --git a/src/math/Vector.cpp b/src/math/Vector.cpp index 4e89d5d..2cfb36e 100644 --- a/src/math/Vector.cpp +++ b/src/math/Vector.cpp @@ -33,9 +33,16 @@ namespace math { /* ************************************************************************ */ -template class BasicVector; -template class BasicVector; -template class BasicVector; +template class Vector; +template class Vector; +template class Vector; +template class Vector; +template class Vector; +template class Vector; +template class Vector; +template class Vector; +template class Vector; +template class Vector; /* ************************************************************************ */ diff --git a/src/simulation/DefaultSimulation.cpp b/src/simulation/DefaultSimulation.cpp index fb1556b..4caa039 100644 --- a/src/simulation/DefaultSimulation.cpp +++ b/src/simulation/DefaultSimulation.cpp @@ -41,6 +41,7 @@ #include "cece/Exception.hpp" #include "cece/log/Log.hpp" #include "cece/unit/UnitIo.hpp" +#include "cece/math/VectorIo.hpp" #include "cece/io/FileStream.hpp" #include "cece/io/OutStream.hpp" #include "cece/plugin/Api.hpp" diff --git a/src/simulation/Object.cpp b/src/simulation/Object.cpp index cee26c1..44931d0 100644 --- a/src/simulation/Object.cpp +++ b/src/simulation/Object.cpp @@ -37,6 +37,7 @@ #include "cece/Assert.hpp" #include "cece/log/Log.hpp" #include "cece/unit/UnitIo.hpp" +#include "cece/math/VectorIo.hpp" #include "cece/io/FileStream.hpp" #include "cece/config/Configuration.hpp" #include "cece/plugin/Context.hpp" diff --git a/src/simulation/Simulation.cpp b/src/simulation/Simulation.cpp index 9f2e197..4b04f75 100644 --- a/src/simulation/Simulation.cpp +++ b/src/simulation/Simulation.cpp @@ -31,6 +31,7 @@ // CeCe #include "cece/unit/UnitIo.hpp" +#include "cece/math/VectorIo.hpp" #include "cece/plugin/Api.hpp" #include "cece/simulation/Initializer.hpp" #include "cece/simulation/Module.hpp" diff --git a/src/unit/VectorUnits.cpp b/src/unit/VectorUnits.cpp index 7972d18..af6e05e 100644 --- a/src/unit/VectorUnits.cpp +++ b/src/unit/VectorUnits.cpp @@ -33,12 +33,11 @@ namespace math { /* ************************************************************************ */ -template class BasicVector; -template class BasicVector; -template class BasicVector; -template class BasicVector; -template class BasicVector; -template class BasicVector; +template class Vector; +template class Vector; +template class Vector; +template class Vector; +template class Vector; /* ************************************************************************ */ diff --git a/unittests/math/CMakeLists.txt b/unittests/math/CMakeLists.txt index 03f6f4e..1e1fc3f 100644 --- a/unittests/math/CMakeLists.txt +++ b/unittests/math/CMakeLists.txt @@ -1,5 +1,5 @@ # ######################################################################### # -# Georgiev Lab (c) 2015-2016 # +# Georgiev Lab (c) 2015-2017 # # ######################################################################### # # Department of Cybernetics # # Faculty of Applied Sciences # @@ -23,9 +23,14 @@ # # # ######################################################################### # -cece_add_test(core +cece_add_test(math SOURCES + VectorBase_test.cpp + Vector_test.cpp + Vector2_test.cpp + Vector3_test.cpp VectorRangeTest.cpp + VectorIo_test.cpp ) # ######################################################################### # diff --git a/unittests/math/Vector2_test.cpp b/unittests/math/Vector2_test.cpp new file mode 100644 index 0000000..ec9cb93 --- /dev/null +++ b/unittests/math/Vector2_test.cpp @@ -0,0 +1,715 @@ +/* ************************************************************************ */ +/* Georgiev Lab (c) 2015-2017 */ +/* ************************************************************************ */ +/* Department of Cybernetics */ +/* Faculty of Applied Sciences */ +/* University of West Bohemia in Pilsen */ +/* ************************************************************************ */ +/* */ +/* This file is part of CeCe. */ +/* */ +/* CeCe 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. */ +/* */ +/* CeCe 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 CeCe. If not, see . */ +/* */ +/* ************************************************************************ */ + +// GTest +#include "gtest/gtest.h" + +// CeCe +#include "cece/math/Vector.hpp" +#include "cece/unit/math.hpp" + +/* ************************************************************************ */ + +using namespace cece; +using namespace cece::math; + +/* ************************************************************************ */ + +TEST(Vector2, ctor) +{ + { + Vector2 vec; + + EXPECT_EQ(0, vec.getX()); + EXPECT_EQ(0, vec.getY()); + EXPECT_EQ(0, vec.getWidth()); + EXPECT_EQ(0, vec.getHeight()); + EXPECT_EQ(0, vec[0]); + EXPECT_EQ(0, vec[1]); + } + + { + constexpr Vector2 vec; + + EXPECT_EQ(0, vec.getX()); + EXPECT_EQ(0, vec.getY()); + EXPECT_EQ(0, vec.getWidth()); + EXPECT_EQ(0, vec.getHeight()); + EXPECT_EQ(0, vec[0]); + EXPECT_EQ(0, vec[1]); + } + + { + Vector2 vec(Zero); + + EXPECT_EQ(0, vec.getX()); + EXPECT_EQ(0, vec.getY()); + EXPECT_EQ(0, vec.getWidth()); + EXPECT_EQ(0, vec.getHeight()); + EXPECT_EQ(0, vec[0]); + EXPECT_EQ(0, vec[1]); + } + + { + constexpr Vector2 vec(Zero); + + EXPECT_EQ(0, vec.getX()); + EXPECT_EQ(0, vec.getY()); + EXPECT_EQ(0, vec.getWidth()); + EXPECT_EQ(0, vec.getHeight()); + EXPECT_EQ(0, vec[0]); + EXPECT_EQ(0, vec[1]); + } + + { + Vector2 vec(12.3f); + + EXPECT_FLOAT_EQ(12.3f, vec.getX()); + EXPECT_FLOAT_EQ(12.3f, vec.getY()); + EXPECT_FLOAT_EQ(12.3f, vec.getWidth()); + EXPECT_FLOAT_EQ(12.3f, vec.getHeight()); + EXPECT_FLOAT_EQ(12.3f, vec[0]); + EXPECT_FLOAT_EQ(12.3f, vec[1]); + } + + { + constexpr Vector2 vec(12.3f); + + EXPECT_FLOAT_EQ(12.3f, vec.getX()); + EXPECT_FLOAT_EQ(12.3f, vec.getY()); + EXPECT_FLOAT_EQ(12.3f, vec.getWidth()); + EXPECT_FLOAT_EQ(12.3f, vec.getHeight()); + EXPECT_FLOAT_EQ(12.3f, vec[0]); + EXPECT_FLOAT_EQ(12.3f, vec[1]); + } + + { + Vector2 vec = {1.2f, 3.0f}; + + EXPECT_FLOAT_EQ(1.2f, vec.getX()); + EXPECT_FLOAT_EQ(3.0f, vec.getY()); + EXPECT_FLOAT_EQ(1.2f, vec.getWidth()); + EXPECT_FLOAT_EQ(3.0f, vec.getHeight()); + EXPECT_FLOAT_EQ(1.2f, vec[0]); + EXPECT_FLOAT_EQ(3.0f, vec[1]); + } + + { + constexpr Vector2 vec = {1.2f, 3.0f}; + + EXPECT_FLOAT_EQ(1.2f, vec.getX()); + EXPECT_FLOAT_EQ(3.0f, vec.getY()); + EXPECT_FLOAT_EQ(1.2f, vec.getWidth()); + EXPECT_FLOAT_EQ(3.0f, vec.getHeight()); + EXPECT_FLOAT_EQ(1.2f, vec[0]); + EXPECT_FLOAT_EQ(3.0f, vec[1]); + } + + { + const Vector2 vec1 = {1.2f, 3.0f}; + + EXPECT_FLOAT_EQ(1.2f, vec1.getX()); + EXPECT_FLOAT_EQ(3.0f, vec1.getY()); + EXPECT_FLOAT_EQ(1.2f, vec1.getWidth()); + EXPECT_FLOAT_EQ(3.0f, vec1.getHeight()); + EXPECT_FLOAT_EQ(1.2f, vec1[0]); + EXPECT_FLOAT_EQ(3.0f, vec1[1]); + + Vector2 vec2(vec1); + + EXPECT_FLOAT_EQ(1.2f, vec2.getX()); + EXPECT_FLOAT_EQ(3.0f, vec2.getY()); + EXPECT_FLOAT_EQ(1.2f, vec2.getWidth()); + EXPECT_FLOAT_EQ(3.0f, vec2.getHeight()); + EXPECT_FLOAT_EQ(1.2f, vec2[0]); + EXPECT_FLOAT_EQ(3.0f, vec2[1]); + } + + { + constexpr const Vector2 vec1 = {1.2f, 3.0f}; + + EXPECT_FLOAT_EQ(1.2f, vec1.getX()); + EXPECT_FLOAT_EQ(3.0f, vec1.getY()); + EXPECT_FLOAT_EQ(1.2f, vec1.getWidth()); + EXPECT_FLOAT_EQ(3.0f, vec1.getHeight()); + EXPECT_FLOAT_EQ(1.2f, vec1[0]); + EXPECT_FLOAT_EQ(3.0f, vec1[1]); + + constexpr Vector2 vec2(vec1); + + EXPECT_FLOAT_EQ(1.2f, vec2.getX()); + EXPECT_FLOAT_EQ(3.0f, vec2.getY()); + EXPECT_FLOAT_EQ(1.2f, vec2.getWidth()); + EXPECT_FLOAT_EQ(3.0f, vec2.getHeight()); + EXPECT_FLOAT_EQ(1.2f, vec2[0]); + EXPECT_FLOAT_EQ(3.0f, vec2[1]); + } + + { + Vector2 vec1 = {1.2f, 3.0f}; + + EXPECT_FLOAT_EQ(1.2f, vec1.getX()); + EXPECT_FLOAT_EQ(3.0f, vec1.getY()); + EXPECT_FLOAT_EQ(1.2f, vec1.getWidth()); + EXPECT_FLOAT_EQ(3.0f, vec1.getHeight()); + EXPECT_FLOAT_EQ(1.2f, vec1[0]); + EXPECT_FLOAT_EQ(3.0f, vec1[1]); + + Vector2 vec2(std::move(vec1)); + + EXPECT_FLOAT_EQ(1.2f, vec2.getX()); + EXPECT_FLOAT_EQ(3.0f, vec2.getY()); + EXPECT_FLOAT_EQ(1.2f, vec2.getWidth()); + EXPECT_FLOAT_EQ(3.0f, vec2.getHeight()); + EXPECT_FLOAT_EQ(1.2f, vec2[0]); + EXPECT_FLOAT_EQ(3.0f, vec2[1]); + } + + { + constexpr Vector2 vec1 = {1.2f, 3.0f}; + + EXPECT_FLOAT_EQ(1.2f, vec1.getX()); + EXPECT_FLOAT_EQ(3.0f, vec1.getY()); + EXPECT_FLOAT_EQ(1.2f, vec1.getWidth()); + EXPECT_FLOAT_EQ(3.0f, vec1.getHeight()); + EXPECT_FLOAT_EQ(1.2f, vec1[0]); + EXPECT_FLOAT_EQ(3.0f, vec1[1]); + + constexpr Vector2 vec2(std::move(vec1)); + + EXPECT_FLOAT_EQ(1.2f, vec2.getX()); + EXPECT_FLOAT_EQ(3.0f, vec2.getY()); + EXPECT_FLOAT_EQ(1.2f, vec2.getWidth()); + EXPECT_FLOAT_EQ(3.0f, vec2.getHeight()); + EXPECT_FLOAT_EQ(1.2f, vec2[0]); + EXPECT_FLOAT_EQ(3.0f, vec2[1]); + } + + { + const Vector2 vec1 = {1, 3}; + + EXPECT_EQ(1, vec1.getX()); + EXPECT_EQ(3, vec1.getY()); + EXPECT_EQ(1, vec1.getWidth()); + EXPECT_EQ(3, vec1.getHeight()); + EXPECT_EQ(1, vec1[0]); + EXPECT_EQ(3, vec1[1]); + + Vector2 vec2(vec1); + + EXPECT_FLOAT_EQ(1.0f, vec2.getX()); + EXPECT_FLOAT_EQ(3.0f, vec2.getY()); + EXPECT_FLOAT_EQ(1.0f, vec2.getWidth()); + EXPECT_FLOAT_EQ(3.0f, vec2.getHeight()); + EXPECT_FLOAT_EQ(1.0f, vec2[0]); + EXPECT_FLOAT_EQ(3.0f, vec2[1]); + } + + { + constexpr const Vector2 vec1 = {1, 3}; + + EXPECT_EQ(1, vec1.getX()); + EXPECT_EQ(3, vec1.getY()); + EXPECT_EQ(1, vec1.getWidth()); + EXPECT_EQ(3, vec1.getHeight()); + EXPECT_EQ(1, vec1[0]); + EXPECT_EQ(3, vec1[1]); + + constexpr Vector2 vec2(vec1); + + EXPECT_FLOAT_EQ(1.0f, vec2.getX()); + EXPECT_FLOAT_EQ(3.0f, vec2.getY()); + EXPECT_FLOAT_EQ(1.0f, vec2.getWidth()); + EXPECT_FLOAT_EQ(3.0f, vec2.getHeight()); + EXPECT_FLOAT_EQ(1.0f, vec2[0]); + EXPECT_FLOAT_EQ(3.0f, vec2[1]); + } +} + +/* ************************************************************************ */ + +TEST(Vector2, assignment) +{ + { + Vector2 vec{1, 1}; + + EXPECT_EQ(1, vec[0]); + EXPECT_EQ(1, vec[1]); + + vec = Zero; + + EXPECT_EQ(0, vec[0]); + EXPECT_EQ(0, vec[1]); + } + + { + Vector2 vec; + + EXPECT_EQ(0, vec[0]); + EXPECT_EQ(0, vec[1]); + + vec = {1.2f, 3.0f}; + + EXPECT_FLOAT_EQ(1.2f, vec[0]); + EXPECT_FLOAT_EQ(3.0f, vec[1]); + } + + { + const Vector2 vec1 = {1.2f, 3.0f}; + + EXPECT_FLOAT_EQ(1.2f, vec1[0]); + EXPECT_FLOAT_EQ(3.0f, vec1[1]); + + Vector2 vec2; + + vec2 = vec1; + + EXPECT_FLOAT_EQ(1.2f, vec2[0]); + EXPECT_FLOAT_EQ(3.0f, vec2[1]); + } + + { + Vector2 vec1 = {1.2f, 3.0f}; + + EXPECT_FLOAT_EQ(1.2f, vec1[0]); + EXPECT_FLOAT_EQ(3.0f, vec1[1]); + + Vector2 vec2; + + vec2 = std::move(vec1); + + EXPECT_FLOAT_EQ(1.2f, vec2[0]); + EXPECT_FLOAT_EQ(3.0f, vec2[1]); + } + + { + const Vector2 vec1 = {1, 3}; + + EXPECT_EQ(1, vec1[0]); + EXPECT_EQ(3, vec1[1]); + + Vector2 vec2; + + vec2 = vec1; + + EXPECT_FLOAT_EQ(1.0, vec2[0]); + EXPECT_FLOAT_EQ(3.0f, vec2[1]); + } +} + +/* ************************************************************************ */ + +TEST(Vector2, operators) +{ + { + Vector2 vec1{1.0f, 2.0f}; + + EXPECT_FLOAT_EQ(1.0f, vec1[0]); + EXPECT_FLOAT_EQ(2.0f, vec1[1]); + + Vector2 vec2 = +vec1; + + EXPECT_FLOAT_EQ(1.0f, vec2[0]); + EXPECT_FLOAT_EQ(2.0f, vec2[1]); + } + + { + Vector2 vec1{1.0f, 2.0f}; + + EXPECT_FLOAT_EQ(1.0f, vec1[0]); + EXPECT_FLOAT_EQ(2.0f, vec1[1]); + + Vector2 vec2 = -vec1; + + EXPECT_FLOAT_EQ(-1.0f, vec2[0]); + EXPECT_FLOAT_EQ(-2.0f, vec2[1]); + } + + { + Vector2 vec1{1.0f, 2.0f}; + + EXPECT_FLOAT_EQ(1.0f, vec1[0]); + EXPECT_FLOAT_EQ(2.0f, vec1[1]); + + Vector2 vec2{1.0f, 2.0f}; + vec1 += vec2; + + EXPECT_FLOAT_EQ(2.0f, vec1[0]); + EXPECT_FLOAT_EQ(4.0f, vec1[1]); + } + + { + Vector2 vec1{1.0f, 2.0f}; + + EXPECT_FLOAT_EQ(1.0f, vec1[0]); + EXPECT_FLOAT_EQ(2.0f, vec1[1]); + + Vector2 vec2{1.0f, 2.0f}; + vec1 -= vec2; + + EXPECT_FLOAT_EQ(0.0f, vec1[0]); + EXPECT_FLOAT_EQ(0.0f, vec1[1]); + } + + { + Vector2 vec1{1.0f, 2.0f}; + + EXPECT_FLOAT_EQ(1.0f, vec1[0]); + EXPECT_FLOAT_EQ(2.0f, vec1[1]); + + vec1 *= 2.0; + + EXPECT_FLOAT_EQ(2.0f, vec1[0]); + EXPECT_FLOAT_EQ(4.0f, vec1[1]); + } + + { + Vector2 vec1{1.0f, 2.0f}; + + EXPECT_FLOAT_EQ(1.0f, vec1[0]); + EXPECT_FLOAT_EQ(2.0f, vec1[1]); + + vec1 /= 2.0; + + EXPECT_FLOAT_EQ(0.5f, vec1[0]); + EXPECT_FLOAT_EQ(1.0f, vec1[1]); + } +} + +/* ************************************************************************ */ + +TEST(Vector2, memberFunctions) +{ + { + const Vector2 vec; + + EXPECT_FLOAT_EQ(0, vec.getLength()); + } + + { + const Vector2 vec{1.0f, 2.0f}; + + EXPECT_FLOAT_EQ(2.2360680f, vec.getLength()); + } + + { + const Vector2 vec; + + EXPECT_FLOAT_EQ(0, vec.getLengthSquared()); + } + + { + const Vector2 vec{1.0f, 2.0f}; + + EXPECT_FLOAT_EQ(5, vec.getLengthSquared()); + } +} + +/* ************************************************************************ */ + +TEST(Vector2, mutators) +{ + { + Vector2 vec; + + EXPECT_EQ(0, vec.getX()); + EXPECT_EQ(0, vec.getY()); + + vec.setX(100); + + EXPECT_EQ(100, vec.getX()); + EXPECT_EQ(0, vec.getY()); + + vec.setY(50); + + EXPECT_EQ(100, vec.getX()); + EXPECT_EQ(50, vec.getY()); + } + + { + Vector2 vec; + + EXPECT_EQ(0, vec.x); + EXPECT_EQ(0, vec.y); + + vec.x = 100; + + EXPECT_EQ(100, vec.x); + EXPECT_EQ(0, vec.y); + + vec.y = 50; + + EXPECT_EQ(100, vec.x); + EXPECT_EQ(50, vec.y); + } + + { + Vector2 vec; + + EXPECT_EQ(0, vec.x); + EXPECT_EQ(0, vec.y); + EXPECT_EQ(0, vec.width); + EXPECT_EQ(0, vec.height); + + vec.setWidth(100); + + EXPECT_EQ(100, vec.x); + EXPECT_EQ(0, vec.y); + EXPECT_EQ(100, vec.width); + EXPECT_EQ(0, vec.height); + + vec.setHeight(50); + + EXPECT_EQ(100, vec.x); + EXPECT_EQ(50, vec.y); + EXPECT_EQ(100, vec.width); + EXPECT_EQ(50, vec.height); + } +} + +/* ************************************************************************ */ + +TEST(Vector2, functions) +{ + { + Vector2 vec(1, 0); + + EXPECT_EQ(1, vec.getX()); + EXPECT_EQ(0, vec.getY()); + + auto rot = rotate(vec, unit::deg2rad(90)); + + EXPECT_EQ(0, rot.getX()); + EXPECT_EQ(1, rot.getY()); + } + + { + Vector2 vec(1, 0); + + EXPECT_EQ(1, vec.getX()); + EXPECT_EQ(0, vec.getY()); + + auto rot = rotate(vec, unit::deg2rad(-90)); + + EXPECT_EQ(0, rot.getX()); + EXPECT_EQ(-1, rot.getY()); + } + + { + Vector2 vec(1, 0); + + EXPECT_EQ(1, vec.getX()); + EXPECT_EQ(0, vec.getY()); + + auto rot = rotate(vec, unit::deg2rad(180)); + + EXPECT_EQ(-1, rot.getX()); + EXPECT_EQ(0, rot.getY()); + } + + { + constexpr Vector2 vec(1, 0); + + EXPECT_EQ(1, vec.getX()); + EXPECT_EQ(0, vec.getY()); + + /*constexpr*/ auto rot = rotate(vec, unit::deg2rad(180)); + + EXPECT_EQ(-1, rot.getX()); + EXPECT_EQ(0, rot.getY()); + } + + { + Vector2 vec1(0.94333f, 0.73733f); + Vector2 vec2(0.16110f, 0.61872f); + + EXPECT_FLOAT_EQ(0.94333f, vec1.getX()); + EXPECT_FLOAT_EQ(0.73733f, vec1.getY()); + + EXPECT_FLOAT_EQ(0.16110f, vec2.getX()); + EXPECT_FLOAT_EQ(0.61872f, vec2.getY()); + + auto res = dot(vec1, vec2); + + EXPECT_FLOAT_EQ( + 0.94333f * 0.16110f + + 0.73733f * 0.61872f, + res + ); + } + + { + constexpr Vector2 vec1(0.94333f, 0.73733f); + constexpr Vector2 vec2(0.16110f, 0.61872f); + + EXPECT_FLOAT_EQ(0.94333f, vec1.getX()); + EXPECT_FLOAT_EQ(0.73733f, vec1.getY()); + + EXPECT_FLOAT_EQ(0.16110f, vec2.getX()); + EXPECT_FLOAT_EQ(0.61872f, vec2.getY()); + + /*constexpr*/ auto res = dot(vec1, vec2); + + EXPECT_FLOAT_EQ( + 0.94333f * 0.16110f + + 0.73733f * 0.61872f, + res + ); + } + + + { + const Vector2 vec; + + EXPECT_FLOAT_EQ(0.0f, distanceSquared(vec, vec)); + } + + { + const Vector2 vec{1.0f, 2.0f}; + + EXPECT_FLOAT_EQ(0.0f, distanceSquared(vec, vec)); + } + + { + const Vector2 vec1{1.0f, 2.0f}; + const Vector2 vec2{5.0f, 4.0f}; + + EXPECT_FLOAT_EQ(20.0f, distanceSquared(vec1, vec2)); + } + + { + const Vector2 vec1{1.0f, 2.0f}; + const Vector2 vec2{5.0f, 4.0f}; + + EXPECT_FLOAT_EQ(4.4721360f, distance(vec1, vec2)); + } +} + +/* ************************************************************************ */ + +TEST(Vector2, freeOperators) +{ + { + const Vector2 vec1(5.3f, 8.9f); + const Vector2 vec2(3.3f, 1.2f); + + EXPECT_FLOAT_EQ(5.3f, vec1.getX()); + EXPECT_FLOAT_EQ(8.9f, vec1.getY()); + + EXPECT_FLOAT_EQ(3.3f, vec2.getX()); + EXPECT_FLOAT_EQ(1.2f, vec2.getY()); + + const auto vec3 = vec1 + vec2; + const auto vec4 = vec2 + vec1; + + EXPECT_FLOAT_EQ(5.3f + 3.3f, vec3.getX()); + EXPECT_FLOAT_EQ(8.9f + 1.2f, vec3.getY()); + + EXPECT_FLOAT_EQ(3.3f + 5.3f, vec4.getX()); + EXPECT_FLOAT_EQ(1.2f + 8.9f, vec4.getY()); + } + + { + const Vector2 vec1(5.3f, 8.9f); + const Vector2 vec2(3.3f, 1.2f); + + EXPECT_FLOAT_EQ(5.3f, vec1.getX()); + EXPECT_FLOAT_EQ(8.9f, vec1.getY()); + + EXPECT_FLOAT_EQ(3.3f, vec2.getX()); + EXPECT_FLOAT_EQ(1.2f, vec2.getY()); + + const auto vec3 = vec1 - vec2; + const auto vec4 = vec2 - vec1; + + EXPECT_FLOAT_EQ(5.3f - 3.3f, vec3.getX()); + EXPECT_FLOAT_EQ(8.9f - 1.2f, vec3.getY()); + + EXPECT_FLOAT_EQ(3.3f - 5.3f, vec4.getX()); + EXPECT_FLOAT_EQ(1.2f - 8.9f, vec4.getY()); + } + + { + const Vector2 vec1(5.3f, 8.9f); + + EXPECT_FLOAT_EQ(5.3f, vec1.getX()); + EXPECT_FLOAT_EQ(8.9f, vec1.getY()); + + const auto vec3 = vec1 * 3.2f; + const auto vec4 = 3.2f * vec1; + + EXPECT_FLOAT_EQ(5.3f * 3.2f, vec3.getX()); + EXPECT_FLOAT_EQ(8.9f * 3.2f, vec3.getY()); + + EXPECT_FLOAT_EQ(3.2f * 5.3f, vec4.getX()); + EXPECT_FLOAT_EQ(3.2f * 8.9f, vec4.getY()); + } + + { + const Vector2 vec1(5.3f, 8.9f); + + EXPECT_FLOAT_EQ(5.3f, vec1.getX()); + EXPECT_FLOAT_EQ(8.9f, vec1.getY()); + + const auto vec3 = vec1 / 3.2f; + const auto vec4 = 3.2f / vec1; + + EXPECT_FLOAT_EQ(5.3f / 3.2f, vec3.getX()); + EXPECT_FLOAT_EQ(8.9f / 3.2f, vec3.getY()); + + EXPECT_FLOAT_EQ(3.2f / 5.3f, vec4.getX()); + EXPECT_FLOAT_EQ(3.2f / 8.9f, vec4.getY()); + } + + { + const Vector2 vec1(5.3f, 8.9f); + const Vector2 vec2(5.3f, 8.9f); + const Vector2 vec3(1.3f, 8.9f); + const Vector2 vec4(5.3f, 0.9f); + + EXPECT_EQ(vec1, vec1); + EXPECT_EQ(vec1, vec2); + EXPECT_NE(vec1, vec3); + EXPECT_NE(vec1, vec4); + + EXPECT_EQ(vec2, vec1); + EXPECT_EQ(vec2, vec2); + EXPECT_NE(vec2, vec3); + EXPECT_NE(vec2, vec4); + + EXPECT_NE(vec3, vec1); + EXPECT_NE(vec3, vec2); + EXPECT_EQ(vec3, vec3); + EXPECT_NE(vec3, vec4); + + EXPECT_NE(vec4, vec1); + EXPECT_NE(vec4, vec2); + EXPECT_NE(vec4, vec3); + EXPECT_EQ(vec4, vec4); + } + +} + +/* ************************************************************************ */ diff --git a/unittests/math/Vector3_test.cpp b/unittests/math/Vector3_test.cpp new file mode 100644 index 0000000..b997726 --- /dev/null +++ b/unittests/math/Vector3_test.cpp @@ -0,0 +1,1544 @@ +/* ************************************************************************ */ +/* Georgiev Lab (c) 2015-2017 */ +/* ************************************************************************ */ +/* Department of Cybernetics */ +/* Faculty of Applied Sciences */ +/* University of West Bohemia in Pilsen */ +/* ************************************************************************ */ +/* */ +/* This file is part of CeCe. */ +/* */ +/* CeCe 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. */ +/* */ +/* CeCe 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 CeCe. If not, see . */ +/* */ +/* ************************************************************************ */ + +// GTest +#include "gtest/gtest.h" + +// CeCe +#include "cece/math/Vector.hpp" + +/* ************************************************************************ */ + +using namespace cece; +using namespace cece::math; + +/* ************************************************************************ */ + +TEST(Vector3, ctorDefault) +{ + { + Vector3 vec; + + EXPECT_EQ(0, vec.getX()); + EXPECT_EQ(0, vec.getY()); + EXPECT_EQ(0, vec.getZ()); + EXPECT_EQ(0, vec[0]); + EXPECT_EQ(0, vec[1]); + EXPECT_EQ(0, vec[2]); + } + + { + constexpr Vector3 vec; + + EXPECT_EQ(0, vec.getX()); + EXPECT_EQ(0, vec.getY()); + EXPECT_EQ(0, vec.getZ()); + EXPECT_EQ(0, vec[0]); + EXPECT_EQ(0, vec[1]); + EXPECT_EQ(0, vec[2]); + } + + { + Vector3 vec; + + EXPECT_EQ(0, vec.getX()); + EXPECT_EQ(0, vec.getY()); + EXPECT_EQ(0, vec.getZ()); + EXPECT_EQ(0, vec[0]); + EXPECT_EQ(0, vec[1]); + EXPECT_EQ(0, vec[2]); + } + + { + constexpr Vector3 vec; + + EXPECT_EQ(0, vec.getX()); + EXPECT_EQ(0, vec.getY()); + EXPECT_EQ(0, vec.getZ()); + EXPECT_EQ(0, vec[0]); + EXPECT_EQ(0, vec[1]); + EXPECT_EQ(0, vec[2]); + } + + { + Vector3 vec; + + EXPECT_FLOAT_EQ(0.0f, vec.getX()); + EXPECT_FLOAT_EQ(0.0f, vec.getY()); + EXPECT_FLOAT_EQ(0.0f, vec.getZ()); + EXPECT_FLOAT_EQ(0.0f, vec[0]); + EXPECT_FLOAT_EQ(0.0f, vec[1]); + EXPECT_FLOAT_EQ(0.0f, vec[2]); + } + + { + Vector3 vec; + + EXPECT_DOUBLE_EQ(0.0, vec.getX()); + EXPECT_DOUBLE_EQ(0.0, vec.getY()); + EXPECT_DOUBLE_EQ(0.0, vec.getZ()); + EXPECT_DOUBLE_EQ(0.0, vec[0]); + EXPECT_DOUBLE_EQ(0.0, vec[1]); + EXPECT_DOUBLE_EQ(0.0, vec[2]); + } +} + +/* ************************************************************************ */ + +TEST(Vector3, ctorZero) +{ + { + Vector3 vec(Zero); + + EXPECT_EQ(0, vec.getX()); + EXPECT_EQ(0, vec.getY()); + EXPECT_EQ(0, vec.getZ()); + EXPECT_EQ(0, vec[0]); + EXPECT_EQ(0, vec[1]); + EXPECT_EQ(0, vec[2]); + } + + { + constexpr Vector3 vec(Zero); + + EXPECT_EQ(0, vec.getX()); + EXPECT_EQ(0, vec.getY()); + EXPECT_EQ(0, vec.getZ()); + EXPECT_EQ(0, vec[0]); + EXPECT_EQ(0, vec[1]); + EXPECT_EQ(0, vec[2]); + } + + { + Vector3 vec(Zero); + + EXPECT_EQ(0, vec.getX()); + EXPECT_EQ(0, vec.getY()); + EXPECT_EQ(0, vec.getZ()); + EXPECT_EQ(0, vec[0]); + EXPECT_EQ(0, vec[1]); + EXPECT_EQ(0, vec[2]); + } + + { + Vector3 vec(Zero); + + EXPECT_FLOAT_EQ(0.0f, vec.getX()); + EXPECT_FLOAT_EQ(0.0f, vec.getY()); + EXPECT_FLOAT_EQ(0.0f, vec.getZ()); + EXPECT_FLOAT_EQ(0.0f, vec[0]); + EXPECT_FLOAT_EQ(0.0f, vec[1]); + EXPECT_FLOAT_EQ(0.0f, vec[2]); + } + + { + Vector3 vec(Zero); + + EXPECT_DOUBLE_EQ(0.0, vec.getX()); + EXPECT_DOUBLE_EQ(0.0, vec.getY()); + EXPECT_DOUBLE_EQ(0.0, vec.getZ()); + EXPECT_DOUBLE_EQ(0.0, vec[0]); + EXPECT_DOUBLE_EQ(0.0, vec[1]); + EXPECT_DOUBLE_EQ(0.0, vec[2]); + } +} + +/* ************************************************************************ */ + +TEST(Vector3, ctorSingle) +{ + { + Vector3 vec{1}; + + EXPECT_EQ(1, vec.getX()); + EXPECT_EQ(1, vec.getY()); + EXPECT_EQ(1, vec.getZ()); + EXPECT_EQ(1, vec[0]); + EXPECT_EQ(1, vec[1]); + EXPECT_EQ(1, vec[2]); + } + + { + constexpr Vector3 vec{1}; + + EXPECT_EQ(1, vec.getX()); + EXPECT_EQ(1, vec.getY()); + EXPECT_EQ(1, vec.getZ()); + EXPECT_EQ(1, vec[0]); + EXPECT_EQ(1, vec[1]); + EXPECT_EQ(1, vec[2]); + } + + { + Vector3 vec{3}; + + EXPECT_EQ(3, vec.getX()); + EXPECT_EQ(3, vec.getY()); + EXPECT_EQ(3, vec.getZ()); + EXPECT_EQ(3, vec[0]); + EXPECT_EQ(3, vec[1]); + EXPECT_EQ(3, vec[2]); + } + + { + Vector3 vec{1.2f}; + + EXPECT_FLOAT_EQ(1.2f, vec.getX()); + EXPECT_FLOAT_EQ(1.2f, vec.getY()); + EXPECT_FLOAT_EQ(1.2f, vec.getZ()); + EXPECT_FLOAT_EQ(1.2f, vec[0]); + EXPECT_FLOAT_EQ(1.2f, vec[1]); + EXPECT_FLOAT_EQ(1.2f, vec[2]); + } + + { + Vector3 vec{1.2}; + + EXPECT_DOUBLE_EQ(1.2, vec.getX()); + EXPECT_DOUBLE_EQ(1.2, vec.getY()); + EXPECT_DOUBLE_EQ(1.2, vec.getZ()); + EXPECT_DOUBLE_EQ(1.2, vec[0]); + EXPECT_DOUBLE_EQ(1.2, vec[1]); + EXPECT_DOUBLE_EQ(1.2, vec[2]); + } +} + +/* ************************************************************************ */ + +TEST(Vector3, ctorElements) +{ + { + Vector3 vec = {1, 3, -8}; + + EXPECT_EQ(1, vec.getX()); + EXPECT_EQ(3, vec.getY()); + EXPECT_EQ(-8, vec.getZ()); + EXPECT_EQ(1, vec[0]); + EXPECT_EQ(3, vec[1]); + EXPECT_EQ(-8, vec[2]); + } + + { + Vector3 vec = {1, 3, 8}; + + EXPECT_EQ(1, vec.getX()); + EXPECT_EQ(3, vec.getY()); + EXPECT_EQ(8, vec.getZ()); + EXPECT_EQ(1, vec[0]); + EXPECT_EQ(3, vec[1]); + EXPECT_EQ(8, vec[2]); + } + + { + Vector3 vec = {1.2f, 3.0f, -8.1f}; + + EXPECT_FLOAT_EQ(1.2f, vec.getX()); + EXPECT_FLOAT_EQ(3.0f, vec.getY()); + EXPECT_FLOAT_EQ(-8.1f, vec.getZ()); + EXPECT_FLOAT_EQ(1.2f, vec[0]); + EXPECT_FLOAT_EQ(3.0f, vec[1]); + EXPECT_FLOAT_EQ(-8.1f, vec[2]); + } + + { + Vector3 vec = {1.2, 3.0, -8.1}; + + EXPECT_DOUBLE_EQ(1.2, vec.getX()); + EXPECT_DOUBLE_EQ(3.0, vec.getY()); + EXPECT_DOUBLE_EQ(-8.1, vec.getZ()); + EXPECT_DOUBLE_EQ(1.2, vec[0]); + EXPECT_DOUBLE_EQ(3.0, vec[1]); + EXPECT_DOUBLE_EQ(-8.1, vec[2]); + } +} + +/* ************************************************************************ */ + +TEST(Vector3, ctorCopy) +{ + { + const Vector3 vec1 = {1, 3, -8}; + + EXPECT_EQ(1, vec1.getX()); + EXPECT_EQ(3, vec1.getY()); + EXPECT_EQ(-8, vec1.getZ()); + EXPECT_EQ(1, vec1[0]); + EXPECT_EQ(3, vec1[1]); + EXPECT_EQ(-8, vec1[2]); + + Vector3 vec2(vec1); + + EXPECT_FLOAT_EQ(1.0f, vec2.getX()); + EXPECT_FLOAT_EQ(3.0f, vec2.getY()); + EXPECT_FLOAT_EQ(-8.0f, vec2.getZ()); + EXPECT_FLOAT_EQ(1.0f, vec2[0]); + EXPECT_FLOAT_EQ(3.0f, vec2[1]); + EXPECT_FLOAT_EQ(-8.0f, vec2[2]); + } + + { + const Vector3 vec1 = {1, 3, 8}; + + EXPECT_EQ(1, vec1.getX()); + EXPECT_EQ(3, vec1.getY()); + EXPECT_EQ(8, vec1.getZ()); + EXPECT_EQ(1, vec1[0]); + EXPECT_EQ(3, vec1[1]); + EXPECT_EQ(8, vec1[2]); + + Vector3 vec2(vec1); + + EXPECT_EQ(1, vec2.getX()); + EXPECT_EQ(3, vec2.getY()); + EXPECT_EQ(8, vec2.getZ()); + EXPECT_EQ(1, vec2[0]); + EXPECT_EQ(3, vec2[1]); + EXPECT_EQ(8, vec2[2]); + } + + { + const Vector3 vec1 = {1.2f, 3.0f, -8.1f}; + + EXPECT_FLOAT_EQ(1.2f, vec1.getX()); + EXPECT_FLOAT_EQ(3.0f, vec1.getY()); + EXPECT_FLOAT_EQ(-8.1f, vec1.getZ()); + EXPECT_FLOAT_EQ(1.2f, vec1[0]); + EXPECT_FLOAT_EQ(3.0f, vec1[1]); + EXPECT_FLOAT_EQ(-8.1f, vec1[2]); + + Vector3 vec2(vec1); + + EXPECT_FLOAT_EQ(1.2f, vec2.getX()); + EXPECT_FLOAT_EQ(3.0f, vec2.getY()); + EXPECT_FLOAT_EQ(-8.1f, vec2.getZ()); + EXPECT_FLOAT_EQ(1.2f, vec2[0]); + EXPECT_FLOAT_EQ(3.0f, vec2[1]); + EXPECT_FLOAT_EQ(-8.1f, vec2[2]); + } + + { + const Vector3 vec1 = {1.2, 3.0, -8.1}; + + EXPECT_DOUBLE_EQ(1.2, vec1.getX()); + EXPECT_DOUBLE_EQ(3.0, vec1.getY()); + EXPECT_DOUBLE_EQ(-8.1, vec1.getZ()); + EXPECT_DOUBLE_EQ(1.2, vec1[0]); + EXPECT_DOUBLE_EQ(3.0, vec1[1]); + EXPECT_DOUBLE_EQ(-8.1, vec1[2]); + + Vector3 vec2(vec1); + + EXPECT_DOUBLE_EQ(1.2, vec2.getX()); + EXPECT_DOUBLE_EQ(3.0, vec2.getY()); + EXPECT_DOUBLE_EQ(-8.1, vec2.getZ()); + EXPECT_DOUBLE_EQ(1.2, vec2[0]); + EXPECT_DOUBLE_EQ(3.0, vec2[1]); + EXPECT_DOUBLE_EQ(-8.1, vec2[2]); + } + +} + +/* ************************************************************************ */ + +TEST(Vector3, ctorMove) +{ + { + Vector3 vec1 = {1, 3, -8}; + + EXPECT_EQ(1, vec1.getX()); + EXPECT_EQ(3, vec1.getY()); + EXPECT_EQ(-8, vec1.getZ()); + EXPECT_EQ(1, vec1[0]); + EXPECT_EQ(3, vec1[1]); + EXPECT_EQ(-8, vec1[2]); + + Vector3 vec2(std::move(vec1)); + + EXPECT_EQ(1, vec2.getX()); + EXPECT_EQ(3, vec2.getY()); + EXPECT_EQ(-8, vec2.getZ()); + EXPECT_EQ(1, vec2[0]); + EXPECT_EQ(3, vec2[1]); + EXPECT_EQ(-8, vec2[2]); + } + + { + Vector3 vec1 = {1, 3, 8}; + + EXPECT_EQ(1, vec1.getX()); + EXPECT_EQ(3, vec1.getY()); + EXPECT_EQ(8, vec1.getZ()); + EXPECT_EQ(1, vec1[0]); + EXPECT_EQ(3, vec1[1]); + EXPECT_EQ(8, vec1[2]); + + Vector3 vec2(std::move(vec1)); + + EXPECT_EQ(1, vec2.getX()); + EXPECT_EQ(3, vec2.getY()); + EXPECT_EQ(8, vec2.getZ()); + EXPECT_EQ(1, vec2[0]); + EXPECT_EQ(3, vec2[1]); + EXPECT_EQ(8, vec2[2]); + } + + { + Vector3 vec1 = {1.2f, 3.0f, -8.1f}; + + EXPECT_FLOAT_EQ(1.2f, vec1.getX()); + EXPECT_FLOAT_EQ(3.0f, vec1.getY()); + EXPECT_FLOAT_EQ(-8.1f, vec1.getZ()); + EXPECT_FLOAT_EQ(1.2f, vec1[0]); + EXPECT_FLOAT_EQ(3.0f, vec1[1]); + EXPECT_FLOAT_EQ(-8.1f, vec1[2]); + + Vector3 vec2(std::move(vec1)); + + EXPECT_FLOAT_EQ(1.2f, vec2.getX()); + EXPECT_FLOAT_EQ(3.0f, vec2.getY()); + EXPECT_FLOAT_EQ(-8.1f, vec2.getZ()); + EXPECT_FLOAT_EQ(1.2f, vec2[0]); + EXPECT_FLOAT_EQ(3.0f, vec2[1]); + EXPECT_FLOAT_EQ(-8.1f, vec2[2]); + } + + { + Vector3 vec1 = {1.2, 3.0, -8.1}; + + EXPECT_DOUBLE_EQ(1.2, vec1.getX()); + EXPECT_DOUBLE_EQ(3.0, vec1.getY()); + EXPECT_DOUBLE_EQ(-8.1, vec1.getZ()); + EXPECT_DOUBLE_EQ(1.2, vec1[0]); + EXPECT_DOUBLE_EQ(3.0, vec1[1]); + EXPECT_DOUBLE_EQ(-8.1, vec1[2]); + + Vector3 vec2(std::move(vec1)); + + EXPECT_DOUBLE_EQ(1.2, vec2.getX()); + EXPECT_DOUBLE_EQ(3.0, vec2.getY()); + EXPECT_DOUBLE_EQ(-8.1, vec2.getZ()); + EXPECT_DOUBLE_EQ(1.2, vec2[0]); + EXPECT_DOUBLE_EQ(3.0, vec2[1]); + EXPECT_DOUBLE_EQ(-8.1, vec2[2]); + } +} + +/* ************************************************************************ */ + +TEST(Vector3, assignmentZero) +{ + { + Vector3 vec{1, 1, 1}; + + EXPECT_EQ(1, vec[0]); + EXPECT_EQ(1, vec[1]); + EXPECT_EQ(1, vec[2]); + + vec = Zero; + + EXPECT_EQ(0, vec[0]); + EXPECT_EQ(0, vec[1]); + EXPECT_EQ(0, vec[2]); + } + + { + Vector3 vec{1, 1, 1}; + + EXPECT_EQ(1, vec[0]); + EXPECT_EQ(1, vec[1]); + EXPECT_EQ(1, vec[2]); + + vec = Zero; + + EXPECT_EQ(0, vec[0]); + EXPECT_EQ(0, vec[1]); + EXPECT_EQ(0, vec[2]); + } + + { + Vector3 vec{1.0f, 1.0f, 1.0f}; + + EXPECT_FLOAT_EQ(1.0f, vec[0]); + EXPECT_FLOAT_EQ(1.0f, vec[1]); + EXPECT_FLOAT_EQ(1.0f, vec[2]); + + vec = Zero; + + EXPECT_FLOAT_EQ(0.0f, vec[0]); + EXPECT_FLOAT_EQ(0.0f, vec[1]); + EXPECT_FLOAT_EQ(0.0f, vec[2]); + } + + { + Vector3 vec{1.0, 1.0, 1.0}; + + EXPECT_DOUBLE_EQ(1.0, vec[0]); + EXPECT_DOUBLE_EQ(1.0, vec[1]); + EXPECT_DOUBLE_EQ(1.0, vec[2]); + + vec = Zero; + + EXPECT_DOUBLE_EQ(0.0, vec[0]); + EXPECT_DOUBLE_EQ(0.0, vec[1]); + EXPECT_DOUBLE_EQ(0.0, vec[2]); + } +} + +/* ************************************************************************ */ + +TEST(Vector3, assignmentElements) +{ + { + Vector3 vec; + + EXPECT_EQ(0, vec[0]); + EXPECT_EQ(0, vec[1]); + EXPECT_EQ(0, vec[2]); + + vec = {1, 3, -8}; + + EXPECT_EQ(1, vec[0]); + EXPECT_EQ(3, vec[1]); + EXPECT_EQ(-8, vec[2]); + } + + { + Vector3 vec; + + EXPECT_EQ(0, vec[0]); + EXPECT_EQ(0, vec[1]); + EXPECT_EQ(0, vec[2]); + + vec = {1, 3, 8}; + + EXPECT_EQ(1, vec[0]); + EXPECT_EQ(3, vec[1]); + EXPECT_EQ(8, vec[2]); + } + + { + Vector3 vec; + + EXPECT_FLOAT_EQ(0.0f, vec[0]); + EXPECT_FLOAT_EQ(0.0f, vec[1]); + EXPECT_FLOAT_EQ(0.0f, vec[2]); + + vec = {1.2f, 3.0f, -8.1f}; + + EXPECT_FLOAT_EQ(1.2f, vec[0]); + EXPECT_FLOAT_EQ(3.0f, vec[1]); + EXPECT_FLOAT_EQ(-8.1f, vec[2]); + } + + { + Vector3 vec; + + EXPECT_DOUBLE_EQ(0.0, vec[0]); + EXPECT_DOUBLE_EQ(0.0, vec[1]); + EXPECT_DOUBLE_EQ(0.0, vec[2]); + + vec = {1.2, 3.0, -8.1}; + + EXPECT_DOUBLE_EQ(1.2, vec[0]); + EXPECT_DOUBLE_EQ(3.0, vec[1]); + EXPECT_DOUBLE_EQ(-8.1, vec[2]); + } +} + +/* ************************************************************************ */ + +TEST(Vector3, assignmentCopy) +{ + { + const Vector3 vec1 = {1, 3, -8}; + + EXPECT_EQ(1, vec1[0]); + EXPECT_EQ(3, vec1[1]); + EXPECT_EQ(-8, vec1[2]); + + Vector3 vec2; + + vec2 = vec1; + + EXPECT_FLOAT_EQ(1.0, vec2[0]); + EXPECT_FLOAT_EQ(3.0f, vec2[1]); + EXPECT_FLOAT_EQ(-8.0f, vec2[2]); + } + + { + const Vector3 vec1 = {1, 3, 8}; + + EXPECT_EQ(1, vec1[0]); + EXPECT_EQ(3, vec1[1]); + EXPECT_EQ(8, vec1[2]); + + Vector3 vec2; + + vec2 = vec1; + + EXPECT_EQ(1, vec2[0]); + EXPECT_EQ(3, vec2[1]); + EXPECT_EQ(8, vec2[2]); + } + + { + const Vector3 vec1 = {1.2f, 3.0f, -8.1f}; + + EXPECT_FLOAT_EQ(1.2f, vec1[0]); + EXPECT_FLOAT_EQ(3.0f, vec1[1]); + EXPECT_FLOAT_EQ(-8.1f, vec1[2]); + + Vector3 vec2; + + vec2 = vec1; + + EXPECT_FLOAT_EQ(1.2f, vec2[0]); + EXPECT_FLOAT_EQ(3.0f, vec2[1]); + EXPECT_FLOAT_EQ(-8.1f, vec2[2]); + } + + { + const Vector3 vec1 = {1.2, 3.0, -8.1}; + + EXPECT_DOUBLE_EQ(1.2, vec1[0]); + EXPECT_DOUBLE_EQ(3.0, vec1[1]); + EXPECT_DOUBLE_EQ(-8.1, vec1[2]); + + Vector3 vec2; + + vec2 = vec1; + + EXPECT_DOUBLE_EQ(1.2, vec2[0]); + EXPECT_DOUBLE_EQ(3.0, vec2[1]); + EXPECT_DOUBLE_EQ(-8.1, vec2[2]); + } +} + +/* ************************************************************************ */ + +TEST(Vector3, assignmentMove) +{ + { + Vector3 vec1 = {1, 3, -8}; + + EXPECT_EQ(1, vec1[0]); + EXPECT_EQ(3, vec1[1]); + EXPECT_EQ(-8, vec1[2]); + + Vector3 vec2; + + vec2 = std::move(vec1); + + EXPECT_EQ(1, vec2[0]); + EXPECT_EQ(3, vec2[1]); + EXPECT_EQ(-8, vec2[2]); + } + + { + Vector3 vec1 = {1, 3, 8}; + + EXPECT_EQ(1, vec1[0]); + EXPECT_EQ(3, vec1[1]); + EXPECT_EQ(8, vec1[2]); + + Vector3 vec2; + + vec2 = std::move(vec1); + + EXPECT_EQ(1, vec2[0]); + EXPECT_EQ(3, vec2[1]); + EXPECT_EQ(8, vec2[2]); + } + + { + Vector3 vec1 = {1.2f, 3.0f, -8.1f}; + + EXPECT_FLOAT_EQ(1.2f, vec1[0]); + EXPECT_FLOAT_EQ(3.0f, vec1[1]); + EXPECT_FLOAT_EQ(-8.1f, vec1[2]); + + Vector3 vec2; + + vec2 = std::move(vec1); + + EXPECT_FLOAT_EQ(1.2f, vec2[0]); + EXPECT_FLOAT_EQ(3.0f, vec2[1]); + EXPECT_FLOAT_EQ(-8.1f, vec2[2]); + } + + { + Vector3 vec1 = {1.2, 3.0, -8.1}; + + EXPECT_DOUBLE_EQ(1.2, vec1[0]); + EXPECT_DOUBLE_EQ(3.0, vec1[1]); + EXPECT_DOUBLE_EQ(-8.1, vec1[2]); + + Vector3 vec2; + + vec2 = std::move(vec1); + + EXPECT_DOUBLE_EQ(1.2, vec2[0]); + EXPECT_DOUBLE_EQ(3.0, vec2[1]); + EXPECT_DOUBLE_EQ(-8.1, vec2[2]); + } +} + +/* ************************************************************************ */ + +TEST(Vector3, operatorUnaryPlus) +{ + { + Vector3 vec1{1, 2, -8}; + + EXPECT_EQ(1, vec1[0]); + EXPECT_EQ(2, vec1[1]); + EXPECT_EQ(-8, vec1[2]); + + Vector3 vec2 = +vec1; + + EXPECT_EQ(1, vec2[0]); + EXPECT_EQ(2, vec2[1]); + EXPECT_EQ(-8, vec2[2]); + } + + { + Vector3 vec1{1, 2, 8}; + + EXPECT_EQ(1, vec1[0]); + EXPECT_EQ(2, vec1[1]); + EXPECT_EQ(8, vec1[2]); + + Vector3 vec2 = +vec1; + + EXPECT_EQ(1, vec2[0]); + EXPECT_EQ(2, vec2[1]); + EXPECT_EQ(8, vec2[2]); + } + + { + Vector3 vec1{1.0f, 2.0f, -8.1f}; + + EXPECT_FLOAT_EQ(1.0f, vec1[0]); + EXPECT_FLOAT_EQ(2.0f, vec1[1]); + EXPECT_FLOAT_EQ(-8.1f, vec1[2]); + + Vector3 vec2 = +vec1; + + EXPECT_FLOAT_EQ(1.0f, vec2[0]); + EXPECT_FLOAT_EQ(2.0f, vec2[1]); + EXPECT_FLOAT_EQ(-8.1f, vec2[2]); + } + + { + Vector3 vec1{1.0, 2.0, -8.1}; + + EXPECT_DOUBLE_EQ(1.0, vec1[0]); + EXPECT_DOUBLE_EQ(2.0, vec1[1]); + EXPECT_DOUBLE_EQ(-8.1, vec1[2]); + + Vector3 vec2 = +vec1; + + EXPECT_DOUBLE_EQ(1.0, vec2[0]); + EXPECT_DOUBLE_EQ(2.0, vec2[1]); + EXPECT_DOUBLE_EQ(-8.1, vec2[2]); + } +} + +/* ************************************************************************ */ + +TEST(Vector3, operatorUnaryMinus) +{ + { + Vector3 vec1{1, 2, -8}; + + EXPECT_EQ(1, vec1[0]); + EXPECT_EQ(2, vec1[1]); + EXPECT_EQ(-8, vec1[2]); + + Vector3 vec2 = -vec1; + + EXPECT_EQ(-1, vec2[0]); + EXPECT_EQ(-2, vec2[1]); + EXPECT_EQ(8, vec2[2]); + } + + { + Vector3 vec1{1, 2, 8}; + + EXPECT_EQ(1, vec1[0]); + EXPECT_EQ(2, vec1[1]); + EXPECT_EQ(8, vec1[2]); + + Vector3 vec2 = -vec1; + + EXPECT_EQ(-1, vec2[0]); + EXPECT_EQ(-2, vec2[1]); + EXPECT_EQ(-8, vec2[2]); + } + + { + Vector3 vec1{1.0f, 2.0f, -8.1f}; + + EXPECT_FLOAT_EQ(1.0f, vec1[0]); + EXPECT_FLOAT_EQ(2.0f, vec1[1]); + EXPECT_FLOAT_EQ(-8.1f, vec1[2]); + + Vector3 vec2 = -vec1; + + EXPECT_FLOAT_EQ(-1.0f, vec2[0]); + EXPECT_FLOAT_EQ(-2.0f, vec2[1]); + EXPECT_FLOAT_EQ(8.1f, vec2[2]); + } + + { + Vector3 vec1{1.0, 2.0, -8.1}; + + EXPECT_DOUBLE_EQ(1.0, vec1[0]); + EXPECT_DOUBLE_EQ(2.0, vec1[1]); + EXPECT_DOUBLE_EQ(-8.1, vec1[2]); + + Vector3 vec2 = -vec1; + + EXPECT_DOUBLE_EQ(-1.0, vec2[0]); + EXPECT_DOUBLE_EQ(-2.0, vec2[1]); + EXPECT_DOUBLE_EQ(8.1, vec2[2]); + } +} + +/* ************************************************************************ */ + +TEST(Vector3, operatorPlus) +{ + { + Vector3 vec1{1, 2, -8}; + + EXPECT_EQ(1, vec1[0]); + EXPECT_EQ(2, vec1[1]); + EXPECT_EQ(-8, vec1[2]); + + Vector3 vec2{1, 2, -8}; + vec1 += vec2; + + EXPECT_EQ(2, vec1[0]); + EXPECT_EQ(4, vec1[1]); + EXPECT_EQ(-16, vec1[2]); + } + + { + Vector3 vec1{1, 2, 8}; + + EXPECT_EQ(1, vec1[0]); + EXPECT_EQ(2, vec1[1]); + EXPECT_EQ(8, vec1[2]); + + Vector3 vec2{1, 2, 8}; + vec1 += vec2; + + EXPECT_EQ(2, vec1[0]); + EXPECT_EQ(4, vec1[1]); + EXPECT_EQ(16, vec1[2]); + } + + { + Vector3 vec1{1.0f, 2.0f, -8.1f}; + + EXPECT_FLOAT_EQ(1.0f, vec1[0]); + EXPECT_FLOAT_EQ(2.0f, vec1[1]); + EXPECT_FLOAT_EQ(-8.1f, vec1[2]); + + Vector3 vec2{1.0f, 2.0f, -8.1f}; + vec1 += vec2; + + EXPECT_FLOAT_EQ(2.0f, vec1[0]); + EXPECT_FLOAT_EQ(4.0f, vec1[1]); + EXPECT_FLOAT_EQ(-16.2f, vec1[2]); + } + + { + Vector3 vec1{1.0, 2.0, -8.1}; + + EXPECT_DOUBLE_EQ(1.0, vec1[0]); + EXPECT_DOUBLE_EQ(2.0, vec1[1]); + EXPECT_DOUBLE_EQ(-8.1, vec1[2]); + + Vector3 vec2{1.0, 2.0, -8.1}; + vec1 += vec2; + + EXPECT_DOUBLE_EQ(2.0, vec1[0]); + EXPECT_DOUBLE_EQ(4.0, vec1[1]); + EXPECT_DOUBLE_EQ(-16.2, vec1[2]); + } +} + +/* ************************************************************************ */ + +TEST(Vector3, operatorMinus) +{ + { + Vector3 vec1{1, 2, -8}; + + EXPECT_EQ(1, vec1[0]); + EXPECT_EQ(2, vec1[1]); + EXPECT_EQ(-8, vec1[2]); + + Vector3 vec2{1, 2, -8}; + vec1 -= vec2; + + EXPECT_EQ(0, vec1[0]); + EXPECT_EQ(0, vec1[1]); + EXPECT_EQ(0, vec1[2]); + } + + { + Vector3 vec1{1, 2, 8}; + + EXPECT_EQ(1, vec1[0]); + EXPECT_EQ(2, vec1[1]); + EXPECT_EQ(8, vec1[2]); + + Vector3 vec2{1, 2, 8}; + vec1 -= vec2; + + EXPECT_EQ(0, vec1[0]); + EXPECT_EQ(0, vec1[1]); + EXPECT_EQ(0, vec1[2]); + } + + { + Vector3 vec1{1.0f, 2.0f, -8.1f}; + + EXPECT_FLOAT_EQ(1.0f, vec1[0]); + EXPECT_FLOAT_EQ(2.0f, vec1[1]); + EXPECT_FLOAT_EQ(-8.1f, vec1[2]); + + Vector3 vec2{1.0f, 2.0f, -8.1f}; + vec1 -= vec2; + + EXPECT_FLOAT_EQ(0.0f, vec1[0]); + EXPECT_FLOAT_EQ(0.0f, vec1[1]); + EXPECT_FLOAT_EQ(0.0f, vec1[2]); + } + + { + Vector3 vec1{1.0, 2.0, -8.1}; + + EXPECT_DOUBLE_EQ(1.0, vec1[0]); + EXPECT_DOUBLE_EQ(2.0, vec1[1]); + EXPECT_DOUBLE_EQ(-8.1, vec1[2]); + + Vector3 vec2{1.0, 2.0, -8.1}; + vec1 -= vec2; + + EXPECT_DOUBLE_EQ(0.0, vec1[0]); + EXPECT_DOUBLE_EQ(0.0, vec1[1]); + EXPECT_DOUBLE_EQ(0.0, vec1[2]); + } +} + +/* ************************************************************************ */ + +TEST(Vector3, operatorMult) +{ + { + Vector3 vec1{1, 2, -8}; + + EXPECT_EQ(1, vec1[0]); + EXPECT_EQ(2, vec1[1]); + EXPECT_EQ(-8, vec1[2]); + + vec1 *= 2.0; + + EXPECT_EQ(2, vec1[0]); + EXPECT_EQ(4, vec1[1]); + EXPECT_EQ(-16, vec1[2]); + } + + { + Vector3 vec1{1, 2, 8}; + + EXPECT_EQ(1, vec1[0]); + EXPECT_EQ(2, vec1[1]); + EXPECT_EQ(8, vec1[2]); + + vec1 *= 2.0; + + EXPECT_EQ(2, vec1[0]); + EXPECT_EQ(4, vec1[1]); + EXPECT_EQ(16, vec1[2]); + } + + { + Vector3 vec1{1.0f, 2.0f, -8.1f}; + + EXPECT_FLOAT_EQ(1.0f, vec1[0]); + EXPECT_FLOAT_EQ(2.0f, vec1[1]); + EXPECT_FLOAT_EQ(-8.1f, vec1[2]); + + vec1 *= 2.0; + + EXPECT_FLOAT_EQ(2.0f, vec1[0]); + EXPECT_FLOAT_EQ(4.0f, vec1[1]); + EXPECT_FLOAT_EQ(-16.2f, vec1[2]); + } + + { + Vector3 vec1{1.0, 2.0, -8.1}; + + EXPECT_DOUBLE_EQ(1.0, vec1[0]); + EXPECT_DOUBLE_EQ(2.0, vec1[1]); + EXPECT_DOUBLE_EQ(-8.1, vec1[2]); + + vec1 *= 2.0; + + EXPECT_DOUBLE_EQ(2.0, vec1[0]); + EXPECT_DOUBLE_EQ(4.0, vec1[1]); + EXPECT_DOUBLE_EQ(-16.2, vec1[2]); + } +} + +/* ************************************************************************ */ + +TEST(Vector3, operatorDiv) +{ + { + Vector3 vec1{1, 2, -8}; + + EXPECT_EQ(1, vec1[0]); + EXPECT_EQ(2, vec1[1]); + EXPECT_EQ(-8, vec1[2]); + + vec1 /= 2.0; + + EXPECT_EQ(0, vec1[0]); + EXPECT_EQ(1, vec1[1]); + EXPECT_EQ(-4, vec1[2]); + } + + { + Vector3 vec1{1, 2, 8}; + + EXPECT_EQ(1, vec1[0]); + EXPECT_EQ(2, vec1[1]); + EXPECT_EQ(8, vec1[2]); + + vec1 /= 2.0; + + EXPECT_EQ(0, vec1[0]); + EXPECT_EQ(1, vec1[1]); + EXPECT_EQ(4, vec1[2]); + } + + { + Vector3 vec1{1.0f, 2.0f, -8.1f}; + + EXPECT_FLOAT_EQ(1.0f, vec1[0]); + EXPECT_FLOAT_EQ(2.0f, vec1[1]); + EXPECT_FLOAT_EQ(-8.1f, vec1[2]); + + vec1 /= 2.0; + + EXPECT_FLOAT_EQ(0.5f, vec1[0]); + EXPECT_FLOAT_EQ(1.0f, vec1[1]); + EXPECT_FLOAT_EQ(-4.05f, vec1[2]); + } + + { + Vector3 vec1{1.0, 2.0, -8.1}; + + EXPECT_DOUBLE_EQ(1.0, vec1[0]); + EXPECT_DOUBLE_EQ(2.0, vec1[1]); + EXPECT_DOUBLE_EQ(-8.1, vec1[2]); + + vec1 /= 2.0; + + EXPECT_DOUBLE_EQ(0.5, vec1[0]); + EXPECT_DOUBLE_EQ(1.0, vec1[1]); + EXPECT_DOUBLE_EQ(-4.05, vec1[2]); + } +} + +/* ************************************************************************ */ + +TEST(Vector3, memberFunctions) +{ + { + const Vector3 vec; + + EXPECT_FLOAT_EQ(0, vec.getLength()); + } + + { + const Vector3 vec{1.0f, 2.0f, 3.0f}; + + EXPECT_FLOAT_EQ(3.7416574f, vec.getLength()); + } + + { + const Vector3 vec; + + EXPECT_FLOAT_EQ(0, vec.getLengthSquared()); + } + + { + const Vector3 vec{1.0f, 2.0f, 3.0f}; + + EXPECT_FLOAT_EQ(14, vec.getLengthSquared()); + } +} + +/* ************************************************************************ */ + +TEST(Vector3, mutators) +{ + { + Vector3 vec; + + EXPECT_EQ(0, vec.getX()); + EXPECT_EQ(0, vec.getY()); + EXPECT_EQ(0, vec.getZ()); + + vec.setX(100); + + EXPECT_EQ(100, vec.getX()); + EXPECT_EQ(0, vec.getY()); + EXPECT_EQ(0, vec.getZ()); + + vec.setY(50); + + EXPECT_EQ(100, vec.getX()); + EXPECT_EQ(50, vec.getY()); + EXPECT_EQ(0, vec.getZ()); + + vec.setZ(10); + + EXPECT_EQ(100, vec.getX()); + EXPECT_EQ(50, vec.getY()); + EXPECT_EQ(10, vec.getZ()); + } + + { + Vector3 vec; + + EXPECT_EQ(0, vec.x); + EXPECT_EQ(0, vec.y); + EXPECT_EQ(0, vec.z); + + vec.x = 100; + + EXPECT_EQ(100, vec.x); + EXPECT_EQ(0, vec.y); + EXPECT_EQ(0, vec.z); + + vec.y = 50; + + EXPECT_EQ(100, vec.x); + EXPECT_EQ(50, vec.y); + EXPECT_EQ(0, vec.z); + + vec.z = 10; + + EXPECT_EQ(100, vec.x); + EXPECT_EQ(50, vec.y); + EXPECT_EQ(10, vec.z); + } + + { + Vector3 vec; + + EXPECT_EQ(0, vec.getX()); + EXPECT_EQ(0, vec.getY()); + EXPECT_EQ(0, vec.getZ()); + + vec.setX(100); + + EXPECT_EQ(100, vec.getX()); + EXPECT_EQ(0, vec.getY()); + EXPECT_EQ(0, vec.getZ()); + + vec.setY(50); + + EXPECT_EQ(100, vec.getX()); + EXPECT_EQ(50, vec.getY()); + EXPECT_EQ(0, vec.getZ()); + + vec.setZ(10); + + EXPECT_EQ(100, vec.getX()); + EXPECT_EQ(50, vec.getY()); + EXPECT_EQ(10, vec.getZ()); + } + + { + Vector3 vec; + + EXPECT_EQ(0, vec.x); + EXPECT_EQ(0, vec.y); + EXPECT_EQ(0, vec.z); + + vec.x = 100; + + EXPECT_EQ(100, vec.x); + EXPECT_EQ(0, vec.y); + EXPECT_EQ(0, vec.z); + + vec.y = 50; + + EXPECT_EQ(100, vec.x); + EXPECT_EQ(50, vec.y); + EXPECT_EQ(0, vec.z); + + vec.z = 10; + + EXPECT_EQ(100, vec.x); + EXPECT_EQ(50, vec.y); + EXPECT_EQ(10, vec.z); + } + + { + Vector3 vec; + + EXPECT_FLOAT_EQ(0, vec.getX()); + EXPECT_FLOAT_EQ(0, vec.getY()); + EXPECT_FLOAT_EQ(0, vec.getZ()); + + vec.setX(100.3f); + + EXPECT_FLOAT_EQ(100.3f, vec.getX()); + EXPECT_FLOAT_EQ(0, vec.getY()); + EXPECT_FLOAT_EQ(0, vec.getZ()); + + vec.setY(50); + + EXPECT_FLOAT_EQ(100.3f, vec.getX()); + EXPECT_FLOAT_EQ(50, vec.getY()); + EXPECT_FLOAT_EQ(0, vec.getZ()); + + vec.setZ(10); + + EXPECT_FLOAT_EQ(100.3f, vec.getX()); + EXPECT_FLOAT_EQ(50, vec.getY()); + EXPECT_FLOAT_EQ(10, vec.getZ()); + } + + { + Vector3 vec; + + EXPECT_FLOAT_EQ(0, vec.x); + EXPECT_FLOAT_EQ(0, vec.y); + EXPECT_FLOAT_EQ(0, vec.z); + + vec.x = 100.3f; + + EXPECT_FLOAT_EQ(100.3f, vec.x); + EXPECT_FLOAT_EQ(0, vec.y); + EXPECT_FLOAT_EQ(0, vec.z); + + vec.y = 50; + + EXPECT_FLOAT_EQ(100.3f, vec.x); + EXPECT_FLOAT_EQ(50, vec.y); + EXPECT_FLOAT_EQ(0, vec.z); + + vec.z = 10; + + EXPECT_FLOAT_EQ(100.3f, vec.x); + EXPECT_FLOAT_EQ(50, vec.y); + EXPECT_FLOAT_EQ(10, vec.z); + } + + { + Vector3 vec; + + EXPECT_DOUBLE_EQ(0, vec.getX()); + EXPECT_DOUBLE_EQ(0, vec.getY()); + EXPECT_DOUBLE_EQ(0, vec.getZ()); + + vec.setX(100.3); + + EXPECT_DOUBLE_EQ(100.3, vec.getX()); + EXPECT_DOUBLE_EQ(0, vec.getY()); + EXPECT_DOUBLE_EQ(0, vec.getZ()); + + vec.setY(50); + + EXPECT_DOUBLE_EQ(100.3, vec.getX()); + EXPECT_DOUBLE_EQ(50, vec.getY()); + EXPECT_DOUBLE_EQ(0, vec.getZ()); + + vec.setZ(10); + + EXPECT_DOUBLE_EQ(100.3, vec.getX()); + EXPECT_DOUBLE_EQ(50, vec.getY()); + EXPECT_DOUBLE_EQ(10, vec.getZ()); + } + + { + Vector3 vec; + + EXPECT_DOUBLE_EQ(0, vec.getX()); + EXPECT_DOUBLE_EQ(0, vec.getY()); + EXPECT_DOUBLE_EQ(0, vec.getZ()); + + vec.setWidth(100.3); + + EXPECT_DOUBLE_EQ(100.3, vec.getX()); + EXPECT_DOUBLE_EQ(0, vec.getY()); + EXPECT_DOUBLE_EQ(0, vec.getZ()); + + vec.setHeight(50); + + EXPECT_DOUBLE_EQ(100.3, vec.getX()); + EXPECT_DOUBLE_EQ(50, vec.getY()); + EXPECT_DOUBLE_EQ(0, vec.getZ()); + + vec.setDepth(10); + + EXPECT_DOUBLE_EQ(100.3, vec.getX()); + EXPECT_DOUBLE_EQ(50, vec.getY()); + EXPECT_DOUBLE_EQ(10, vec.getZ()); + EXPECT_DOUBLE_EQ(100.3, vec.getWidth()); + EXPECT_DOUBLE_EQ(50, vec.getHeight()); + EXPECT_DOUBLE_EQ(10, vec.getDepth()); + } + + { + Vector3 vec; + + EXPECT_DOUBLE_EQ(0, vec.x); + EXPECT_DOUBLE_EQ(0, vec.y); + EXPECT_DOUBLE_EQ(0, vec.z); + + vec.x = 100.3; + + EXPECT_DOUBLE_EQ(100.3, vec.x); + EXPECT_DOUBLE_EQ(0, vec.y); + EXPECT_DOUBLE_EQ(0, vec.z); + + vec.y = 50; + + EXPECT_DOUBLE_EQ(100.3, vec.x); + EXPECT_DOUBLE_EQ(50, vec.y); + EXPECT_DOUBLE_EQ(0, vec.z); + + vec.z = 10; + + EXPECT_DOUBLE_EQ(100.3, vec.x); + EXPECT_DOUBLE_EQ(50, vec.y); + EXPECT_DOUBLE_EQ(10, vec.z); + } +} + +/* ************************************************************************ */ + +TEST(Vector3, functions) +{ + { + Vector3 vec1(0.94333f, 0.73733f, 0.92636f); + Vector3 vec2(0.16110f, 0.61872f, 0.21556f); + + EXPECT_FLOAT_EQ(0.94333f, vec1.getX()); + EXPECT_FLOAT_EQ(0.73733f, vec1.getY()); + EXPECT_FLOAT_EQ(0.92636f, vec1.getZ()); + + EXPECT_FLOAT_EQ(0.16110f, vec2.getX()); + EXPECT_FLOAT_EQ(0.61872f, vec2.getY()); + EXPECT_FLOAT_EQ(0.21556f, vec2.getZ()); + + auto vec3 = cross(vec1, vec2); + + EXPECT_FLOAT_EQ(0.73733f * 0.21556f - 0.92636f * 0.61872f, vec3.getX()); + EXPECT_FLOAT_EQ(0.92636f * 0.16110f - 0.94333f * 0.21556f, vec3.getY()); + EXPECT_FLOAT_EQ(0.94333f * 0.61872f - 0.73733f * 0.16110f, vec3.getZ()); + } + + { + Vector3 vec1(0.94333f, 0.73733f, 0.92636f); + Vector3 vec2(0.16110f, 0.61872f, 0.21556f); + + EXPECT_FLOAT_EQ(0.94333f, vec1.getX()); + EXPECT_FLOAT_EQ(0.73733f, vec1.getY()); + EXPECT_FLOAT_EQ(0.92636f, vec1.getZ()); + + EXPECT_FLOAT_EQ(0.16110f, vec2.getX()); + EXPECT_FLOAT_EQ(0.61872f, vec2.getY()); + EXPECT_FLOAT_EQ(0.21556f, vec2.getZ()); + + auto res = dot(vec1, vec2); + + EXPECT_FLOAT_EQ( + 0.94333f * 0.16110f + + 0.73733f * 0.61872f + + 0.92636f * 0.21556f, + res + ); + } + + { + const Vector3 vec; + + EXPECT_FLOAT_EQ(0.0f, distanceSquared(vec, vec)); + } + + { + const Vector3 vec{1.0f, 2.0f, 3.0f}; + + EXPECT_FLOAT_EQ(0.0f, distanceSquared(vec, vec)); + } + + { + const Vector3 vec1{1.0f, 2.0f, 3.0f}; + const Vector3 vec2{5.0f, 4.0f, 3.0f}; + + EXPECT_FLOAT_EQ(20.0f, distanceSquared(vec1, vec2)); + } + + { + const Vector3 vec1{1.0f, 2.0f, 3.0f}; + const Vector3 vec2{5.0f, 4.0f, 3.0f}; + + EXPECT_FLOAT_EQ(4.4721360f, distance(vec1, vec2)); + } +} + +/* ************************************************************************ */ + +TEST(Vector3, freeOperators) +{ + { + const Vector3 vec1(5.3f, 8.9f, -8.1f); + const Vector3 vec2(3.3f, 1.2f, 2.5f); + + EXPECT_FLOAT_EQ(5.3f, vec1.getX()); + EXPECT_FLOAT_EQ(8.9f, vec1.getY()); + EXPECT_FLOAT_EQ(-8.1f, vec1.getZ()); + + EXPECT_FLOAT_EQ(3.3f, vec2.getX()); + EXPECT_FLOAT_EQ(1.2f, vec2.getY()); + EXPECT_FLOAT_EQ(2.5f, vec2.getZ()); + + const auto vec3 = vec1 + vec2; + const auto vec4 = vec2 + vec1; + + EXPECT_FLOAT_EQ(5.3f + 3.3f, vec3.getX()); + EXPECT_FLOAT_EQ(8.9f + 1.2f, vec3.getY()); + EXPECT_FLOAT_EQ(-8.1f + 2.5f, vec3.getZ()); + + EXPECT_FLOAT_EQ(3.3f + 5.3f, vec4.getX()); + EXPECT_FLOAT_EQ(1.2f + 8.9f, vec4.getY()); + EXPECT_FLOAT_EQ(2.5f + -8.1f, vec4.getZ()); + } + + { + const Vector3 vec1(5.3f, 8.9f, -8.1f); + const Vector3 vec2(3.3f, 1.2f, 2.5f); + + EXPECT_FLOAT_EQ(5.3f, vec1.getX()); + EXPECT_FLOAT_EQ(8.9f, vec1.getY()); + EXPECT_FLOAT_EQ(-8.1f, vec1.getZ()); + + EXPECT_FLOAT_EQ(3.3f, vec2.getX()); + EXPECT_FLOAT_EQ(1.2f, vec2.getY()); + EXPECT_FLOAT_EQ(2.5f, vec2.getZ()); + + const auto vec3 = vec1 - vec2; + const auto vec4 = vec2 - vec1; + + EXPECT_FLOAT_EQ(5.3f - 3.3f, vec3.getX()); + EXPECT_FLOAT_EQ(8.9f - 1.2f, vec3.getY()); + EXPECT_FLOAT_EQ(-8.1f - 2.5f, vec3.getZ()); + + EXPECT_FLOAT_EQ(3.3f - 5.3f, vec4.getX()); + EXPECT_FLOAT_EQ(1.2f - 8.9f, vec4.getY()); + EXPECT_FLOAT_EQ(2.5f - -8.1f, vec4.getZ()); + } + + { + const Vector3 vec1(5.3f, 8.9f, -8.1f); + + EXPECT_FLOAT_EQ(5.3f, vec1.getX()); + EXPECT_FLOAT_EQ(8.9f, vec1.getY()); + EXPECT_FLOAT_EQ(-8.1f, vec1.getZ()); + + const auto vec3 = vec1 * 3.2f; + const auto vec4 = 3.2f * vec1; + + EXPECT_FLOAT_EQ(5.3f * 3.2f, vec3.getX()); + EXPECT_FLOAT_EQ(8.9f * 3.2f, vec3.getY()); + EXPECT_FLOAT_EQ(-8.1f * 3.2f, vec3.getZ()); + + EXPECT_FLOAT_EQ(3.2f * 5.3f, vec4.getX()); + EXPECT_FLOAT_EQ(3.2f * 8.9f, vec4.getY()); + EXPECT_FLOAT_EQ(3.2f * -8.1f, vec4.getZ()); + } + + { + const Vector3 vec1(5.3f, 8.9f, -8.1f); + + EXPECT_FLOAT_EQ(5.3f, vec1.getX()); + EXPECT_FLOAT_EQ(8.9f, vec1.getY()); + EXPECT_FLOAT_EQ(-8.1f, vec1.getZ()); + + const auto vec3 = vec1 / 3.2f; + const auto vec4 = 3.2f / vec1; + + EXPECT_FLOAT_EQ(5.3f / 3.2f, vec3.getX()); + EXPECT_FLOAT_EQ(8.9f / 3.2f, vec3.getY()); + EXPECT_FLOAT_EQ(-8.1f / 3.2f, vec3.getZ()); + + EXPECT_FLOAT_EQ(3.2f / 5.3f, vec4.getX()); + EXPECT_FLOAT_EQ(3.2f / 8.9f, vec4.getY()); + EXPECT_FLOAT_EQ(3.2f / -8.1f, vec4.getZ()); + } + + { + const Vector3 vec1(5.3f, 8.9f, -8.1f); + const Vector3 vec2(5.3f, 8.9f, -8.1f); + const Vector3 vec3(1.3f, 8.9f, -3.1f); + const Vector3 vec4(5.3f, 0.9f, -1.1f); + + EXPECT_EQ(vec1, vec1); + EXPECT_EQ(vec1, vec2); + EXPECT_NE(vec1, vec3); + EXPECT_NE(vec1, vec4); + + EXPECT_EQ(vec2, vec1); + EXPECT_EQ(vec2, vec2); + EXPECT_NE(vec2, vec3); + EXPECT_NE(vec2, vec4); + + EXPECT_NE(vec3, vec1); + EXPECT_NE(vec3, vec2); + EXPECT_EQ(vec3, vec3); + EXPECT_NE(vec3, vec4); + + EXPECT_NE(vec4, vec1); + EXPECT_NE(vec4, vec2); + EXPECT_NE(vec4, vec3); + EXPECT_EQ(vec4, vec4); + } + +} + +/* ************************************************************************ */ diff --git a/unittests/math/VectorBase_test.cpp b/unittests/math/VectorBase_test.cpp new file mode 100644 index 0000000..d963584 --- /dev/null +++ b/unittests/math/VectorBase_test.cpp @@ -0,0 +1,461 @@ +/* ************************************************************************ */ +/* Georgiev Lab (c) 2015-2017 */ +/* ************************************************************************ */ +/* Department of Cybernetics */ +/* Faculty of Applied Sciences */ +/* University of West Bohemia in Pilsen */ +/* ************************************************************************ */ +/* */ +/* This file is part of CeCe. */ +/* */ +/* CeCe 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. */ +/* */ +/* CeCe 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 CeCe. If not, see . */ +/* */ +/* ************************************************************************ */ + +// GTest +#include "gtest/gtest.h" + +// CeCe +#include "cece/math/Zero.hpp" +#include "cece/math/VectorBase.hpp" + +/* ************************************************************************ */ + +using namespace cece; +using namespace cece::math; + +/* ************************************************************************ */ + +template +struct Vec2 : public VectorBase +{ + Vec2() : x{}, y{} {} + Vec2(Zero_t) : x{}, y{} {} + Vec2(T x, T y) : x{x}, y{y} {} + + T& operator[](int pos) { return (&x)[pos]; } + const T& operator[](int pos) const { return (&x)[pos]; } + + int getSize() const noexcept { return 2; } + T getX() const noexcept { return x; } + void setX(T x) { this->x = x; } + T getY() const noexcept { return y; } + void setY(T y) { this->y = y; } + + T x; + T y; +}; + +/* ************************************************************************ */ + +template +std::ostream& operator<<(std::ostream& os, const Vec2& vec) +{ + return os << "(x = " << vec.x << ", y = " << vec.y << ")"; +} + +/* ************************************************************************ */ + +TEST(VectorBase, operators) +{ + { + Vec2 vec1{1.0f, 2.0f}; + + EXPECT_FLOAT_EQ(1.0f, vec1[0]); + EXPECT_FLOAT_EQ(2.0f, vec1[1]); + + Vec2 vec2 = +vec1; + + EXPECT_FLOAT_EQ(1.0f, vec2[0]); + EXPECT_FLOAT_EQ(2.0f, vec2[1]); + } + + { + Vec2 vec1{1.0f, 2.0f}; + + EXPECT_FLOAT_EQ(1.0f, vec1[0]); + EXPECT_FLOAT_EQ(2.0f, vec1[1]); + + Vec2 vec2 = -vec1; + + EXPECT_FLOAT_EQ(-1.0f, vec2[0]); + EXPECT_FLOAT_EQ(-2.0f, vec2[1]); + } + + { + Vec2 vec1{1.0f, 2.0f}; + + EXPECT_FLOAT_EQ(1.0f, vec1[0]); + EXPECT_FLOAT_EQ(2.0f, vec1[1]); + + Vec2 vec2{1.0f, 2.0f}; + vec1 += vec2; + + EXPECT_FLOAT_EQ(2.0f, vec1[0]); + EXPECT_FLOAT_EQ(4.0f, vec1[1]); + } + + { + Vec2 vec1{1, 2}; + + EXPECT_EQ(1, vec1[0]); + EXPECT_EQ(2, vec1[1]); + + Vec2 vec2{1.0f, 2.0f}; + vec1 += vec2; + + EXPECT_EQ(2, vec1[0]); + EXPECT_EQ(4, vec1[1]); + } + + { + Vec2 vec1{1.0f, 2.0f}; + + EXPECT_FLOAT_EQ(1.0f, vec1[0]); + EXPECT_FLOAT_EQ(2.0f, vec1[1]); + + Vec2 vec2{1.0f, 2.0f}; + vec1 -= vec2; + + EXPECT_FLOAT_EQ(0.0f, vec1[0]); + EXPECT_FLOAT_EQ(0.0f, vec1[1]); + } + + { + Vec2 vec1{1.0f, 2.0f}; + + EXPECT_FLOAT_EQ(1.0f, vec1[0]); + EXPECT_FLOAT_EQ(2.0f, vec1[1]); + + vec1 *= 2.0; + + EXPECT_FLOAT_EQ(2.0f, vec1[0]); + EXPECT_FLOAT_EQ(4.0f, vec1[1]); + } + + { + Vec2 vec1{1.0f, 2.0f}; + Vec2 vec2{5.0f, 3.0f}; + + EXPECT_FLOAT_EQ(1.0f, vec1[0]); + EXPECT_FLOAT_EQ(2.0f, vec1[1]); + + EXPECT_FLOAT_EQ(5.0f, vec2[0]); + EXPECT_FLOAT_EQ(3.0f, vec2[1]); + + vec1 *= vec2; + + EXPECT_FLOAT_EQ(1.0f * 5.0f, vec1[0]); + EXPECT_FLOAT_EQ(2.0f * 3.0f, vec1[1]); + } + + { + Vec2 vec1{1.0f, 2.0f}; + + EXPECT_FLOAT_EQ(1.0f, vec1[0]); + EXPECT_FLOAT_EQ(2.0f, vec1[1]); + + vec1 /= 2.0; + + EXPECT_FLOAT_EQ(0.5f, vec1[0]); + EXPECT_FLOAT_EQ(1.0f, vec1[1]); + } + + { + Vec2 vec1{1.0f, 2.0f}; + Vec2 vec2{2.0f, 6.0f}; + + EXPECT_FLOAT_EQ(1.0f, vec1[0]); + EXPECT_FLOAT_EQ(2.0f, vec1[1]); + + EXPECT_FLOAT_EQ(2.0f, vec2[0]); + EXPECT_FLOAT_EQ(6.0f, vec2[1]); + + vec1 /= vec2; + + EXPECT_FLOAT_EQ(1.0f / 2.0f, vec1[0]); + EXPECT_FLOAT_EQ(2.0f / 6.0f, vec1[1]); + } +} + +/* ************************************************************************ */ + +TEST(VectorBase, memberFunctions) +{ + { + const Vec2 vec; + + EXPECT_FLOAT_EQ(0, vec.getLength()); + } + + { + const Vec2 vec{1.0f, 2.0f}; + + EXPECT_FLOAT_EQ(2.2360680f, vec.getLength()); + } + + { + const Vec2 vec; + + EXPECT_FLOAT_EQ(0, vec.getLengthSquared()); + } + + { + const Vec2 vec{1.0f, 2.0f}; + + EXPECT_FLOAT_EQ(5, vec.getLengthSquared()); + } +} + +/* ************************************************************************ */ + +TEST(VectorBase, mutators) +{ + { + Vec2 vec; + + EXPECT_EQ(0, vec.getX()); + EXPECT_EQ(0, vec.getY()); + + vec.setX(100); + + EXPECT_EQ(100, vec.getX()); + EXPECT_EQ(0, vec.getY()); + + vec.setY(50); + + EXPECT_EQ(100, vec.getX()); + EXPECT_EQ(50, vec.getY()); + } + + { + Vec2 vec; + + EXPECT_EQ(0, vec.x); + EXPECT_EQ(0, vec.y); + + vec.x = 100; + + EXPECT_EQ(100, vec.x); + EXPECT_EQ(0, vec.y); + + vec.y = 50; + + EXPECT_EQ(100, vec.x); + EXPECT_EQ(50, vec.y); + } +} + +/* ************************************************************************ */ + +TEST(VectorBase, functions) +{ + { + Vec2 vec1(0.94333f, 0.73733f); + Vec2 vec2(0.16110f, 0.61872f); + + EXPECT_FLOAT_EQ(0.94333f, vec1.getX()); + EXPECT_FLOAT_EQ(0.73733f, vec1.getY()); + + EXPECT_FLOAT_EQ(0.16110f, vec2.getX()); + EXPECT_FLOAT_EQ(0.61872f, vec2.getY()); + + auto res = dot(vec1, vec2); + + EXPECT_FLOAT_EQ( + 0.94333f * 0.16110f + + 0.73733f * 0.61872f, + res + ); + } + + { + const Vec2 vecMin{-10.0f, -5.0f}; + const Vec2 vecMax{10.0f, 20.0f}; + + Vec2 vec1; + Vec2 vec2{-15.0f, 0.0f}; + Vec2 vec3{5.0f, 0.0f}; + Vec2 vec4{5.0f, 25.0f}; + + EXPECT_TRUE(inRange(vec1, vecMin, vecMax)); + EXPECT_FALSE(inRange(vec2, vecMin, vecMax)); + EXPECT_TRUE(inRange(vec3, vecMin, vecMax)); + EXPECT_FALSE(inRange(vec4, vecMin, vecMax)); + } + + { + const Vec2 vecMax{10.0f, 20.0f}; + + Vec2 vec1; + Vec2 vec2{-15.0f, 0.0f}; + Vec2 vec3{5.0f, 0.0f}; + + EXPECT_TRUE(inRange(vec1, vecMax)); + EXPECT_FALSE(inRange(vec2, vecMax)); + EXPECT_TRUE(inRange(vec3, vecMax)); + } +} + +/* ************************************************************************ */ + +TEST(VectorBase, freeOperators) +{ + { + const Vec2 vec1(5.3f, 8.9f); + const Vec2 vec2(3.3f, 1.2f); + + EXPECT_FLOAT_EQ(5.3f, vec1.getX()); + EXPECT_FLOAT_EQ(8.9f, vec1.getY()); + + EXPECT_FLOAT_EQ(3.3f, vec2.getX()); + EXPECT_FLOAT_EQ(1.2f, vec2.getY()); + + const auto vec3 = vec1 + vec2; + const auto vec4 = vec2 + vec1; + + EXPECT_FLOAT_EQ(5.3f + 3.3f, vec3.getX()); + EXPECT_FLOAT_EQ(8.9f + 1.2f, vec3.getY()); + + EXPECT_FLOAT_EQ(3.3f + 5.3f, vec4.getX()); + EXPECT_FLOAT_EQ(1.2f + 8.9f, vec4.getY()); + } + + { + const Vec2 vec1(5.3f, 8.9f); + const Vec2 vec2(3.3f, 1.2f); + + EXPECT_FLOAT_EQ(5.3f, vec1.getX()); + EXPECT_FLOAT_EQ(8.9f, vec1.getY()); + + EXPECT_FLOAT_EQ(3.3f, vec2.getX()); + EXPECT_FLOAT_EQ(1.2f, vec2.getY()); + + const auto vec3 = vec1 - vec2; + const auto vec4 = vec2 - vec1; + + EXPECT_FLOAT_EQ(5.3f - 3.3f, vec3.getX()); + EXPECT_FLOAT_EQ(8.9f - 1.2f, vec3.getY()); + + EXPECT_FLOAT_EQ(3.3f - 5.3f, vec4.getX()); + EXPECT_FLOAT_EQ(1.2f - 8.9f, vec4.getY()); + } + + { + const Vec2 vec1(5.3f, 8.9f); + + EXPECT_FLOAT_EQ(5.3f, vec1.getX()); + EXPECT_FLOAT_EQ(8.9f, vec1.getY()); + + const auto vec3 = vec1 * 3.2f; + const auto vec4 = 3.2f * vec1; + + EXPECT_FLOAT_EQ(5.3f * 3.2f, vec3.getX()); + EXPECT_FLOAT_EQ(8.9f * 3.2f, vec3.getY()); + + EXPECT_FLOAT_EQ(3.2f * 5.3f, vec4.getX()); + EXPECT_FLOAT_EQ(3.2f * 8.9f, vec4.getY()); + } + + { + const Vec2 vec1(5.3f, 8.9f); + const Vec2 vec2(1.8f, 3.5f); + + EXPECT_FLOAT_EQ(5.3f, vec1.getX()); + EXPECT_FLOAT_EQ(8.9f, vec1.getY()); + + EXPECT_FLOAT_EQ(1.8f, vec2.getX()); + EXPECT_FLOAT_EQ(3.5f, vec2.getY()); + + const auto vec3 = vec1 * vec2; + const auto vec4 = vec2 * vec1; + + EXPECT_FLOAT_EQ(5.3f * 1.8f, vec3.getX()); + EXPECT_FLOAT_EQ(8.9f * 3.5f, vec3.getY()); + + EXPECT_FLOAT_EQ(1.8f * 5.3f, vec4.getX()); + EXPECT_FLOAT_EQ(3.5f * 8.9f, vec4.getY()); + } + + { + const Vec2 vec1(5.3f, 8.9f); + + EXPECT_FLOAT_EQ(5.3f, vec1.getX()); + EXPECT_FLOAT_EQ(8.9f, vec1.getY()); + + const auto vec3 = vec1 / 3.2f; + const auto vec4 = 3.2f / vec1; + + EXPECT_FLOAT_EQ(5.3f / 3.2f, vec3.getX()); + EXPECT_FLOAT_EQ(8.9f / 3.2f, vec3.getY()); + + EXPECT_FLOAT_EQ(3.2f / 5.3f, vec4.getX()); + EXPECT_FLOAT_EQ(3.2f / 8.9f, vec4.getY()); + } + + { + const Vec2 vec1(5.3f, 8.9f); + const Vec2 vec2(1.8f, 3.5f); + + EXPECT_FLOAT_EQ(5.3f, vec1.getX()); + EXPECT_FLOAT_EQ(8.9f, vec1.getY()); + + EXPECT_FLOAT_EQ(1.8f, vec2.getX()); + EXPECT_FLOAT_EQ(3.5f, vec2.getY()); + + const auto vec3 = vec1 / vec2; + const auto vec4 = vec2 / vec1; + + EXPECT_FLOAT_EQ(5.3f / 1.8f, vec3.getX()); + EXPECT_FLOAT_EQ(8.9f / 3.5f, vec3.getY()); + + EXPECT_FLOAT_EQ(1.8f / 5.3f, vec4.getX()); + EXPECT_FLOAT_EQ(3.5f / 8.9f, vec4.getY()); + } + + { + const Vec2 vec0(Zero); + const Vec2 vec1(5.3f, 8.9f); + const Vec2 vec2(5.3f, 8.9f); + const Vec2 vec3(1.3f, 8.9f); + const Vec2 vec4(5.3f, 0.9f); + const Vec2 vec5(1.3f, 0.9f); + + EXPECT_EQ(vec0, Zero); + EXPECT_EQ(Zero, vec0); + + EXPECT_EQ(vec1, vec1); + EXPECT_EQ(vec1, vec2); + EXPECT_NE(vec1, vec3); + EXPECT_NE(vec1, vec4); + + EXPECT_EQ(vec2, vec1); + EXPECT_EQ(vec2, vec2); + EXPECT_NE(vec2, vec3); + EXPECT_NE(vec2, vec4); + + EXPECT_NE(vec3, vec1); + EXPECT_NE(vec3, vec2); + EXPECT_EQ(vec3, vec3); + EXPECT_NE(vec3, vec4); + + EXPECT_NE(vec4, vec1); + EXPECT_NE(vec4, vec2); + EXPECT_NE(vec4, vec3); + EXPECT_EQ(vec4, vec4); + } + +} + +/* ************************************************************************ */ diff --git a/unittests/math/VectorIo_test.cpp b/unittests/math/VectorIo_test.cpp new file mode 100644 index 0000000..bcff064 --- /dev/null +++ b/unittests/math/VectorIo_test.cpp @@ -0,0 +1,136 @@ +/* ************************************************************************ */ +/* Georgiev Lab (c) 2015-2016 */ +/* ************************************************************************ */ +/* Department of Cybernetics */ +/* Faculty of Applied Sciences */ +/* University of West Bohemia in Pilsen */ +/* ************************************************************************ */ +/* */ +/* This file is part of CeCe. */ +/* */ +/* CeCe 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. */ +/* */ +/* CeCe 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 CeCe. If not, see . */ +/* */ +/* ************************************************************************ */ + +// GTest +#include "gtest/gtest.h" + +// CeCe +#include "cece/io/StringStream.hpp" +#include "cece/math/VectorIo.hpp" +#include "cece/math/Vector.hpp" + +/* ************************************************************************ */ + +using namespace cece; +using namespace cece::math; + +/* ************************************************************************ */ + +TEST(VectorIo, read) +{ + { + io::InStringStream iss("200 100"); + + Vector2 vec; + iss >> vec; + + EXPECT_EQ(200, vec.x); + EXPECT_EQ(100, vec.y); + } + + { + io::InStringStream iss("200 100"); + + Vector2 vec; + iss >> vec; + + EXPECT_FLOAT_EQ(200.f, vec.x); + EXPECT_FLOAT_EQ(100.f, vec.y); + } + + { + io::InStringStream iss("2.3 100.15"); + + Vector2 vec; + iss >> vec; + + EXPECT_FLOAT_EQ(2.3f, vec.x); + EXPECT_FLOAT_EQ(100.15f, vec.y); + } +} + +/* ************************************************************************ */ + +TEST(VectorIo, readFail) +{ + { + io::InStringStream iss("200"); + + Vector2 vec; + iss >> vec; + EXPECT_FALSE(iss); + } + + { + io::InStringStream iss("23.3"); + + Vector2 vec; + iss >> vec; + EXPECT_FALSE(iss); + } +} + +/* ************************************************************************ */ + +TEST(VectorIo, write) +{ + { + io::OutStringStream oss; + + Vector2 vec{200, 100}; + EXPECT_EQ(200, vec.x); + EXPECT_EQ(100, vec.y); + + oss << vec; + + EXPECT_EQ("200 100", oss.str()); + } + + { + io::OutStringStream oss; + + Vector2 vec{200.f, 100.f}; + EXPECT_FLOAT_EQ(200.f, vec.x); + EXPECT_FLOAT_EQ(100.f, vec.y); + + oss << vec; + + EXPECT_EQ("200 100", oss.str()); + } + + { + io::OutStringStream oss; + + Vector2 vec{2.3f, 100.15f}; + EXPECT_FLOAT_EQ(2.3f, vec.x); + EXPECT_FLOAT_EQ(100.15f, vec.y); + + oss << vec; + + EXPECT_EQ("2.3 100.15", oss.str()); + } +} + +/* ************************************************************************ */ diff --git a/unittests/math/Vector_test.cpp b/unittests/math/Vector_test.cpp new file mode 100644 index 0000000..4f18e8c --- /dev/null +++ b/unittests/math/Vector_test.cpp @@ -0,0 +1,581 @@ +/* ************************************************************************ */ +/* Georgiev Lab (c) 2015-2017 */ +/* ************************************************************************ */ +/* Department of Cybernetics */ +/* Faculty of Applied Sciences */ +/* University of West Bohemia in Pilsen */ +/* ************************************************************************ */ +/* */ +/* This file is part of CeCe. */ +/* */ +/* CeCe 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. */ +/* */ +/* CeCe 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 CeCe. If not, see . */ +/* */ +/* ************************************************************************ */ + +// GTest +#include "gtest/gtest.h" + +// CeCe +#include "cece/math/Vector.hpp" + +/* ************************************************************************ */ + +using namespace cece; +using namespace cece::math; + +/* ************************************************************************ */ + +TEST(Vector, ctor) +{ + { + Vector vec; + + EXPECT_EQ(5, vec.getSize()); + EXPECT_EQ(0, vec[0]); + EXPECT_EQ(0, vec[1]); + EXPECT_EQ(0, vec[2]); + EXPECT_EQ(0, vec[3]); + EXPECT_EQ(0, vec[4]); + } + + { + Vector vec(Zero); + + EXPECT_EQ(10, vec.getSize()); + EXPECT_EQ(0, vec[0]); + EXPECT_EQ(0, vec[1]); + EXPECT_EQ(0, vec[2]); + EXPECT_EQ(0, vec[3]); + EXPECT_EQ(0, vec[4]); + EXPECT_EQ(0, vec[5]); + EXPECT_EQ(0, vec[6]); + EXPECT_EQ(0, vec[7]); + EXPECT_EQ(0, vec[8]); + EXPECT_EQ(0, vec[9]); + } + + { + Vector vec = {1.2f, 3.0f, 0.0f, 45.1f, -34.f}; + + EXPECT_EQ(5, vec.getSize()); + EXPECT_FLOAT_EQ(1.2f, vec[0]); + EXPECT_FLOAT_EQ(3.0f, vec[1]); + EXPECT_FLOAT_EQ(0.0f, vec[2]); + EXPECT_FLOAT_EQ(45.1f, vec[3]); + EXPECT_FLOAT_EQ(-34.0f, vec[4]); + } + + { + float data[5] = {1.2f, 3.0f, 0.0f, 45.1f, -34.f}; + + Vector vec(data); + + EXPECT_EQ(5, vec.getSize()); + EXPECT_FLOAT_EQ(1.2f, vec[0]); + EXPECT_FLOAT_EQ(3.0f, vec[1]); + EXPECT_FLOAT_EQ(0.0f, vec[2]); + EXPECT_FLOAT_EQ(45.1f, vec[3]); + EXPECT_FLOAT_EQ(-34.0f, vec[4]); + } + + { + StaticArray data = {1.2f, 3.0f, 0.0f, 45.1f, -34.f}; + + Vector vec(data); + + EXPECT_EQ(5, vec.getSize()); + EXPECT_FLOAT_EQ(1.2f, vec[0]); + EXPECT_FLOAT_EQ(3.0f, vec[1]); + EXPECT_FLOAT_EQ(0.0f, vec[2]); + EXPECT_FLOAT_EQ(45.1f, vec[3]); + EXPECT_FLOAT_EQ(-34.0f, vec[4]); + } + + { + const Vector vec1 = {1.2f, 3.0f, 0.0f, 45.1f, -34.f}; + + EXPECT_EQ(5, vec1.getSize()); + EXPECT_FLOAT_EQ(1.2f, vec1[0]); + EXPECT_FLOAT_EQ(3.0f, vec1[1]); + EXPECT_FLOAT_EQ(0.0f, vec1[2]); + EXPECT_FLOAT_EQ(45.1f, vec1[3]); + EXPECT_FLOAT_EQ(-34.0f, vec1[4]); + + Vector vec2(vec1); + + EXPECT_EQ(5, vec2.getSize()); + EXPECT_FLOAT_EQ(1.2f, vec2[0]); + EXPECT_FLOAT_EQ(3.0f, vec2[1]); + EXPECT_FLOAT_EQ(0.0f, vec2[2]); + EXPECT_FLOAT_EQ(45.1f, vec2[3]); + EXPECT_FLOAT_EQ(-34.0f, vec2[4]); + } + + { + Vector vec1 = {1.2f, 3.0f, 0.0f, 45.1f, -34.f}; + + EXPECT_EQ(5, vec1.getSize()); + EXPECT_FLOAT_EQ(1.2f, vec1[0]); + EXPECT_FLOAT_EQ(3.0f, vec1[1]); + EXPECT_FLOAT_EQ(0.0f, vec1[2]); + EXPECT_FLOAT_EQ(45.1f, vec1[3]); + EXPECT_FLOAT_EQ(-34.0f, vec1[4]); + + Vector vec2(std::move(vec1)); + + EXPECT_EQ(5, vec2.getSize()); + EXPECT_FLOAT_EQ(1.2f, vec2[0]); + EXPECT_FLOAT_EQ(3.0f, vec2[1]); + EXPECT_FLOAT_EQ(0.0f, vec2[2]); + EXPECT_FLOAT_EQ(45.1f, vec2[3]); + EXPECT_FLOAT_EQ(-34.0f, vec2[4]); + } + + { + const Vector vec1 = {1, 3, 0, 45, -34}; + + EXPECT_EQ(5, vec1.getSize()); + EXPECT_EQ(1, vec1[0]); + EXPECT_EQ(3, vec1[1]); + EXPECT_EQ(0, vec1[2]); + EXPECT_EQ(45, vec1[3]); + EXPECT_EQ(-34, vec1[4]); + + Vector vec2(vec1); + + EXPECT_EQ(5, vec2.getSize()); + EXPECT_FLOAT_EQ(1.0, vec2[0]); + EXPECT_FLOAT_EQ(3.0f, vec2[1]); + EXPECT_FLOAT_EQ(0.0f, vec2[2]); + EXPECT_FLOAT_EQ(45.0f, vec2[3]); + EXPECT_FLOAT_EQ(-34.0f, vec2[4]); + } +} + +/* ************************************************************************ */ + +TEST(Vector, assignment) +{ + { + Vector vec{1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + + EXPECT_EQ(10, vec.getSize()); + EXPECT_EQ(1, vec[0]); + EXPECT_EQ(1, vec[1]); + EXPECT_EQ(1, vec[2]); + EXPECT_EQ(1, vec[3]); + EXPECT_EQ(1, vec[4]); + EXPECT_EQ(1, vec[5]); + EXPECT_EQ(1, vec[6]); + EXPECT_EQ(1, vec[7]); + EXPECT_EQ(1, vec[8]); + EXPECT_EQ(1, vec[9]); + + vec = Zero; + + EXPECT_EQ(10, vec.getSize()); + EXPECT_EQ(0, vec[0]); + EXPECT_EQ(0, vec[1]); + EXPECT_EQ(0, vec[2]); + EXPECT_EQ(0, vec[3]); + EXPECT_EQ(0, vec[4]); + EXPECT_EQ(0, vec[5]); + EXPECT_EQ(0, vec[6]); + EXPECT_EQ(0, vec[7]); + EXPECT_EQ(0, vec[8]); + EXPECT_EQ(0, vec[9]); + } + + { + Vector vec; + + EXPECT_EQ(5, vec.getSize()); + EXPECT_EQ(0, vec[0]); + EXPECT_EQ(0, vec[1]); + EXPECT_EQ(0, vec[2]); + EXPECT_EQ(0, vec[3]); + EXPECT_EQ(0, vec[4]); + + vec = {1.2f, 3.0f, 0.0f, 45.1f, -34.f}; + + EXPECT_EQ(5, vec.getSize()); + EXPECT_FLOAT_EQ(1.2f, vec[0]); + EXPECT_FLOAT_EQ(3.0f, vec[1]); + EXPECT_FLOAT_EQ(0.0f, vec[2]); + EXPECT_FLOAT_EQ(45.1f, vec[3]); + EXPECT_FLOAT_EQ(-34.0f, vec[4]); + } + + { + Vector vec; + + EXPECT_EQ(5, vec.getSize()); + EXPECT_EQ(0, vec[0]); + EXPECT_EQ(0, vec[1]); + EXPECT_EQ(0, vec[2]); + EXPECT_EQ(0, vec[3]); + EXPECT_EQ(0, vec[4]); + + float data[5] = {1.2f, 3.0f, 0.0f, 45.1f, -34.f}; + + vec = data; + + EXPECT_EQ(5, vec.getSize()); + EXPECT_FLOAT_EQ(1.2f, vec[0]); + EXPECT_FLOAT_EQ(3.0f, vec[1]); + EXPECT_FLOAT_EQ(0.0f, vec[2]); + EXPECT_FLOAT_EQ(45.1f, vec[3]); + EXPECT_FLOAT_EQ(-34.0f, vec[4]); + } + + { + Vector vec; + + EXPECT_EQ(5, vec.getSize()); + EXPECT_EQ(0, vec[0]); + EXPECT_EQ(0, vec[1]); + EXPECT_EQ(0, vec[2]); + EXPECT_EQ(0, vec[3]); + EXPECT_EQ(0, vec[4]); + + StaticArray data = {1.2f, 3.0f, 0.0f, 45.1f, -34.f}; + + vec = data; + + EXPECT_EQ(5, vec.getSize()); + EXPECT_FLOAT_EQ(1.2f, vec[0]); + EXPECT_FLOAT_EQ(3.0f, vec[1]); + EXPECT_FLOAT_EQ(0.0f, vec[2]); + EXPECT_FLOAT_EQ(45.1f, vec[3]); + EXPECT_FLOAT_EQ(-34.0f, vec[4]); + } + + { + const Vector vec1 = {1.2f, 3.0f, 0.0f, 45.1f, -34.f}; + + EXPECT_EQ(5, vec1.getSize()); + EXPECT_FLOAT_EQ(1.2f, vec1[0]); + EXPECT_FLOAT_EQ(3.0f, vec1[1]); + EXPECT_FLOAT_EQ(0.0f, vec1[2]); + EXPECT_FLOAT_EQ(45.1f, vec1[3]); + EXPECT_FLOAT_EQ(-34.0f, vec1[4]); + + Vector vec2; + + vec2 = vec1; + + EXPECT_EQ(5, vec2.getSize()); + EXPECT_FLOAT_EQ(1.2f, vec2[0]); + EXPECT_FLOAT_EQ(3.0f, vec2[1]); + EXPECT_FLOAT_EQ(0.0f, vec2[2]); + EXPECT_FLOAT_EQ(45.1f, vec2[3]); + EXPECT_FLOAT_EQ(-34.0f, vec2[4]); + } + + { + Vector vec1 = {1.2f, 3.0f, 0.0f, 45.1f, -34.f}; + + EXPECT_EQ(5, vec1.getSize()); + EXPECT_FLOAT_EQ(1.2f, vec1[0]); + EXPECT_FLOAT_EQ(3.0f, vec1[1]); + EXPECT_FLOAT_EQ(0.0f, vec1[2]); + EXPECT_FLOAT_EQ(45.1f, vec1[3]); + EXPECT_FLOAT_EQ(-34.0f, vec1[4]); + + Vector vec2; + + vec2 = std::move(vec1); + + EXPECT_EQ(5, vec2.getSize()); + EXPECT_FLOAT_EQ(1.2f, vec2[0]); + EXPECT_FLOAT_EQ(3.0f, vec2[1]); + EXPECT_FLOAT_EQ(0.0f, vec2[2]); + EXPECT_FLOAT_EQ(45.1f, vec2[3]); + EXPECT_FLOAT_EQ(-34.0f, vec2[4]); + } + + { + const Vector vec1 = {1, 3, 0, 45, -34}; + + EXPECT_EQ(5, vec1.getSize()); + EXPECT_EQ(1, vec1[0]); + EXPECT_EQ(3, vec1[1]); + EXPECT_EQ(0, vec1[2]); + EXPECT_EQ(45, vec1[3]); + EXPECT_EQ(-34, vec1[4]); + + Vector vec2; + + vec2 = vec1; + + EXPECT_EQ(5, vec2.getSize()); + EXPECT_FLOAT_EQ(1.0, vec2[0]); + EXPECT_FLOAT_EQ(3.0f, vec2[1]); + EXPECT_FLOAT_EQ(0.0f, vec2[2]); + EXPECT_FLOAT_EQ(45.0f, vec2[3]); + EXPECT_FLOAT_EQ(-34.0f, vec2[4]); + } +} + +/* ************************************************************************ */ + +TEST(Vector, operators) +{ + { + Vector vec1{1.0f, 2.0f, -5.0f, 0.0f, -300.8f}; + + EXPECT_EQ(5, vec1.getSize()); + EXPECT_FLOAT_EQ(1.0f, vec1[0]); + EXPECT_FLOAT_EQ(2.0f, vec1[1]); + EXPECT_FLOAT_EQ(-5.0f, vec1[2]); + EXPECT_FLOAT_EQ(0.0f, vec1[3]); + EXPECT_FLOAT_EQ(-300.8f, vec1[4]); + + Vector vec2 = +vec1; + + EXPECT_EQ(5, vec2.getSize()); + EXPECT_FLOAT_EQ(1.0f, vec2[0]); + EXPECT_FLOAT_EQ(2.0f, vec2[1]); + EXPECT_FLOAT_EQ(-5.0f, vec2[2]); + EXPECT_FLOAT_EQ(0.0f, vec2[3]); + EXPECT_FLOAT_EQ(-300.8f, vec2[4]); + } + + { + Vector vec1{1.0f, 2.0f, -5.0f, 0.0f, -300.8f}; + + EXPECT_EQ(5, vec1.getSize()); + EXPECT_FLOAT_EQ(1.0f, vec1[0]); + EXPECT_FLOAT_EQ(2.0f, vec1[1]); + EXPECT_FLOAT_EQ(-5.0f, vec1[2]); + EXPECT_FLOAT_EQ(0.0f, vec1[3]); + EXPECT_FLOAT_EQ(-300.8f, vec1[4]); + + Vector vec2 = -vec1; + + EXPECT_EQ(5, vec2.getSize()); + EXPECT_FLOAT_EQ(-1.0f, vec2[0]); + EXPECT_FLOAT_EQ(-2.0f, vec2[1]); + EXPECT_FLOAT_EQ(5.0f, vec2[2]); + EXPECT_FLOAT_EQ(0.0f, vec2[3]); + EXPECT_FLOAT_EQ(300.8f, vec2[4]); + } + + { + Vector vec1{1.0f, 2.0f, -5.0f, 0.0f, -3.8f}; + + EXPECT_EQ(5, vec1.getSize()); + EXPECT_FLOAT_EQ(1.0f, vec1[0]); + EXPECT_FLOAT_EQ(2.0f, vec1[1]); + EXPECT_FLOAT_EQ(-5.0f, vec1[2]); + EXPECT_FLOAT_EQ(0.0f, vec1[3]); + EXPECT_FLOAT_EQ(-3.8f, vec1[4]); + + Vector vec2{1.0f, 2.0f, 3.0f, 4.0f, 5.0f}; + vec1 += vec2; + + EXPECT_EQ(5, vec1.getSize()); + EXPECT_FLOAT_EQ(2.0f, vec1[0]); + EXPECT_FLOAT_EQ(4.0f, vec1[1]); + EXPECT_FLOAT_EQ(-2.0f, vec1[2]); + EXPECT_FLOAT_EQ(4.0f, vec1[3]); + EXPECT_FLOAT_EQ(1.2f, vec1[4]); + } + + { + Vector vec1{1.0f, 2.0f, -5.0f, 0.0f, -3.8f}; + + EXPECT_EQ(5, vec1.getSize()); + EXPECT_FLOAT_EQ(1.0f, vec1[0]); + EXPECT_FLOAT_EQ(2.0f, vec1[1]); + EXPECT_FLOAT_EQ(-5.0f, vec1[2]); + EXPECT_FLOAT_EQ(0.0f, vec1[3]); + EXPECT_FLOAT_EQ(-3.8f, vec1[4]); + + Vector vec2{1.0f, 2.0f, 3.0f, 4.0f, 5.0f}; + vec1 -= vec2; + + EXPECT_EQ(5, vec1.getSize()); + EXPECT_FLOAT_EQ(0.0f, vec1[0]); + EXPECT_FLOAT_EQ(0.0f, vec1[1]); + EXPECT_FLOAT_EQ(-8.0f, vec1[2]); + EXPECT_FLOAT_EQ(-4.0f, vec1[3]); + EXPECT_FLOAT_EQ(-8.8f, vec1[4]); + } + + { + Vector vec1{1.0f, 2.0f, -5.0f, 0.0f, -3.8f}; + + EXPECT_EQ(5, vec1.getSize()); + EXPECT_FLOAT_EQ(1.0f, vec1[0]); + EXPECT_FLOAT_EQ(2.0f, vec1[1]); + EXPECT_FLOAT_EQ(-5.0f, vec1[2]); + EXPECT_FLOAT_EQ(0.0f, vec1[3]); + EXPECT_FLOAT_EQ(-3.8f, vec1[4]); + + vec1 *= 2.0; + + EXPECT_EQ(5, vec1.getSize()); + EXPECT_FLOAT_EQ(2.0f, vec1[0]); + EXPECT_FLOAT_EQ(4.0f, vec1[1]); + EXPECT_FLOAT_EQ(-10.0f, vec1[2]); + EXPECT_FLOAT_EQ(0.0f, vec1[3]); + EXPECT_FLOAT_EQ(-7.6f, vec1[4]); + } + + { + Vector vec1{1.0f, 2.0f, -5.0f, 0.0f, -3.8f}; + + EXPECT_EQ(5, vec1.getSize()); + EXPECT_FLOAT_EQ(1.0f, vec1[0]); + EXPECT_FLOAT_EQ(2.0f, vec1[1]); + EXPECT_FLOAT_EQ(-5.0f, vec1[2]); + EXPECT_FLOAT_EQ(0.0f, vec1[3]); + EXPECT_FLOAT_EQ(-3.8f, vec1[4]); + + Vector vec2{1.0f, 2.0f, 3.0f, 4.0f, 5.0f}; + vec1 *= vec2; + + EXPECT_EQ(5, vec1.getSize()); + EXPECT_FLOAT_EQ(1.0f, vec1[0]); + EXPECT_FLOAT_EQ(4.0f, vec1[1]); + EXPECT_FLOAT_EQ(-15.0f, vec1[2]); + EXPECT_FLOAT_EQ(0.0f, vec1[3]); + EXPECT_FLOAT_EQ(-19.0f, vec1[4]); + } + + { + Vector vec1{1.0f, 2.0f, -5.0f, 0.0f, -3.8f}; + + EXPECT_EQ(5, vec1.getSize()); + EXPECT_FLOAT_EQ(1.0f, vec1[0]); + EXPECT_FLOAT_EQ(2.0f, vec1[1]); + EXPECT_FLOAT_EQ(-5.0f, vec1[2]); + EXPECT_FLOAT_EQ(0.0f, vec1[3]); + EXPECT_FLOAT_EQ(-3.8f, vec1[4]); + + vec1 /= 2.0; + + EXPECT_EQ(5, vec1.getSize()); + EXPECT_FLOAT_EQ(0.5f, vec1[0]); + EXPECT_FLOAT_EQ(1.0f, vec1[1]); + EXPECT_FLOAT_EQ(-2.5f, vec1[2]); + EXPECT_FLOAT_EQ(0.0f, vec1[3]); + EXPECT_FLOAT_EQ(-1.9f, vec1[4]); + } + + { + Vector vec1{1.0f, 2.0f, -5.0f, 0.0f, -3.8f}; + + EXPECT_EQ(5, vec1.getSize()); + EXPECT_FLOAT_EQ(1.0f, vec1[0]); + EXPECT_FLOAT_EQ(2.0f, vec1[1]); + EXPECT_FLOAT_EQ(-5.0f, vec1[2]); + EXPECT_FLOAT_EQ(0.0f, vec1[3]); + EXPECT_FLOAT_EQ(-3.8f, vec1[4]); + + Vector vec2{1.0f, 2.0f, 3.0f, 4.0f, 5.0f}; + vec1 /= vec2; + + EXPECT_EQ(5, vec1.getSize()); + EXPECT_FLOAT_EQ(1.0f, vec1[0]); + EXPECT_FLOAT_EQ(1.0f, vec1[1]); + EXPECT_FLOAT_EQ(-5.0f / 3.0f, vec1[2]); + EXPECT_FLOAT_EQ(0.0f, vec1[3]); + EXPECT_FLOAT_EQ(-3.8f / 5.0f, vec1[4]); + } +} + +/* ************************************************************************ */ + +TEST(Vector, memberFunctions) +{ + { + const Vector vec; + + EXPECT_FLOAT_EQ(0, vec.getLength()); + } + + { + const Vector vec{1.0f, 2.0f, 3.0f, 4.0f, 5.0f}; + + EXPECT_FLOAT_EQ(7.4162f, vec.getLength()); + } + + { + const Vector vec; + + EXPECT_FLOAT_EQ(0, vec.getLengthSquared()); + } + + { + const Vector vec{1.0f, 2.0f, 3.0f, 4.0f, 5.0f}; + + EXPECT_FLOAT_EQ(55, vec.getLengthSquared()); + } + + { + const Vector vec; + + EXPECT_FLOAT_EQ(vec.getLengthSquared(), dot(vec, vec)); + } + + { + const Vector vec{1.0f, 2.0f, 3.0f, 4.0f, 5.0f}; + + EXPECT_FLOAT_EQ(vec.getLengthSquared(), dot(vec, vec)); + } + + { + const Vector vec1; + const Vector vec2; + + EXPECT_FLOAT_EQ(0, dot(vec1, vec2)); + } + + { + const Vector vec1{1.0f, 2.0f, 3.0f, 4.0f, 5.0f}; + const Vector vec2{5.0f, 4.0f, 3.0f, 2.0f, 1.0f}; + + EXPECT_FLOAT_EQ(35, dot(vec1, vec2)); + } + + { + const Vector vec; + + EXPECT_FLOAT_EQ(0.0f, distanceSquared(vec, vec)); + } + + { + const Vector vec{1.0f, 2.0f, 3.0f, 4.0f, 5.0f}; + + EXPECT_FLOAT_EQ(0.0f, distanceSquared(vec, vec)); + } + + { + const Vector vec1{1.0f, 2.0f, 3.0f, 4.0f, 5.0f}; + const Vector vec2{5.0f, 4.0f, 3.0f, 2.0f, 1.0f}; + + EXPECT_FLOAT_EQ(40.0f, distanceSquared(vec1, vec2)); + } + + { + const Vector vec1{1.0f, 2.0f, 3.0f, 4.0f, 5.0f}; + const Vector vec2{5.0f, 4.0f, 3.0f, 2.0f, 1.0f}; + + EXPECT_FLOAT_EQ(6.3245554f, distance(vec1, vec2)); + } +} + +/* ************************************************************************ */