|
|
|
|
#ifndef Magnum_Math_Vector_h
|
|
|
|
|
#define Magnum_Math_Vector_h
|
|
|
|
|
/*
|
|
|
|
|
This file is part of Magnum.
|
|
|
|
|
|
|
|
|
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
|
|
|
|
|
2020, 2021, 2022, 2023 Vladimír Vondruš <mosra@centrum.cz>
|
|
|
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
|
copy of this software and associated documentation files (the "Software"),
|
|
|
|
|
to deal in the Software without restriction, including without limitation
|
|
|
|
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
|
and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
|
Software is furnished to do so, subject to the following conditions:
|
|
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included
|
|
|
|
|
in all copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
|
|
|
DEALINGS IN THE SOFTWARE.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/** @file
|
|
|
|
|
* @brief Class @ref Magnum::Math::Vector, function @ref Magnum::Math::dot(), @ref Magnum::Math::angle()
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/* std::declval() is said to be in <utility> but libstdc++, libc++ and MSVC STL
|
|
|
|
|
all have it directly in <type_traits> because it just makes sense */
|
|
|
|
|
#include <type_traits>
|
|
|
|
|
#include <Corrade/Containers/Pair.h>
|
|
|
|
|
#ifndef CORRADE_SINGLES_NO_DEBUG
|
Math: made dot(), angle(), *lerp() and cross() free functions.
It is often annoying to write e.g. this, especially in generic code:
T dot = Math::Vector<size, T>::dot(a, b);
When this is more than enough and the compiler can infer the rest from
the context:
T dot = Math::dot(a, b);
There are more downsides and confusing cases (you can call
Math::Vector<3, T>::dot(), Math::Vector3<T>::dot() and Color3::dot() and
it is still the same function), so I made these as free functions in
Math namespace. You can now also abuse ADL for the calls, but I would
advise against that for better readability:
T d = dot(a, b); // dot?! what on earth is dot? and what is a?
The only downside found when porting is that you need to specify the
type somehow when having both parameters as initializer lists:
T d = dot({2.0f, -1.5f}, {1.0f, 2.5f}); // error
T d = dot(Complex{2.0f, -1.5f}, {1.0f, 2.5f}); // okay
But that's probably reasonable (and it's also highly corner case,
the functions were used this way only in tests).
The original static member functions are of course still present, but
marked as deprecated and will be removed at some point in future.
11 years ago
|
|
|
#include <Corrade/Utility/Debug.h>
|
|
|
|
|
#endif
|
|
|
|
|
#include <Corrade/Utility/DebugAssert.h>
|
|
|
|
|
#include <Corrade/Utility/StlMath.h>
|
|
|
|
|
|
|
|
|
|
#include "Magnum/Magnum.h"
|
|
|
|
|
#include "Magnum/visibility.h"
|
|
|
|
|
#include "Magnum/Math/Angle.h"
|
|
|
|
|
#include "Magnum/Math/BitVector.h"
|
|
|
|
|
#include "Magnum/Math/TypeTraits.h"
|
|
|
|
|
|
|
|
|
|
#ifdef MAGNUM_BUILD_DEPRECATED
|
|
|
|
|
/* Some APIs returned std::pair before */
|
|
|
|
|
#include <Corrade/Containers/PairStl.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
namespace Magnum { namespace Math {
|
|
|
|
|
|
|
|
|
|
#ifndef DOXYGEN_GENERATING_OUTPUT
|
|
|
|
|
/* Documented in Functions.h, defined here because Vector needs them */
|
|
|
|
|
template<class T> inline typename std::enable_if<IsScalar<T>::value, bool>::type isNan(T value) {
|
|
|
|
|
return std::isnan(UnderlyingTypeOf<T>(value));
|
|
|
|
|
}
|
|
|
|
|
/* Keeping the same parameter names as in Functions.h so the note about
|
|
|
|
|
NaN propagation works here too */
|
|
|
|
|
template<class T> constexpr typename std::enable_if<IsScalar<T>::value, T>::type min(T value, T min) {
|
|
|
|
|
return min < value ? min : value;
|
|
|
|
|
}
|
|
|
|
|
template<class T> constexpr typename std::enable_if<IsScalar<T>::value, T>::type max(T value, T max) {
|
|
|
|
|
return value < max ? max : value;
|
|
|
|
|
}
|
|
|
|
|
template<class T> constexpr typename std::enable_if<IsScalar<T>::value, T>::type clamp(T value, T min, T max) {
|
|
|
|
|
return Math::min(Math::max(value, min), max);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
namespace Implementation {
|
|
|
|
|
template<std::size_t, class, class> struct VectorConverter;
|
|
|
|
|
/* Needed by DualQuaternion and Functions.h (to avoid dependency between them) */
|
|
|
|
|
template<class T, class U> T lerp(const T& a, const T& b, U t) {
|
|
|
|
|
return T((U(1) - t)*a + t*b);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<bool integral> struct IsZero;
|
|
|
|
|
template<> struct IsZero<false> {
|
|
|
|
|
template<std::size_t size, class T> bool operator()(const Vector<size, T>& vec) const {
|
|
|
|
|
/* Proper comparison should be with epsilon^2, but the value is not
|
|
|
|
|
representable in given precision. Comparing to epsilon instead. */
|
|
|
|
|
return std::abs(vec.dot()) < TypeTraits<T>::epsilon();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
template<> struct IsZero<true> {
|
|
|
|
|
template<std::size_t size, class T> bool operator()(const Vector<size, T>& vec) const {
|
|
|
|
|
return vec == Vector<size, T>{};
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* Used to make friends to speed up debug builds */
|
|
|
|
|
template<std::size_t, class> struct MatrixDeterminant;
|
|
|
|
|
/* To make gather() / scatter() faster */
|
|
|
|
|
template<std::size_t, std::size_t> struct GatherComponentAt;
|
|
|
|
|
template<std::size_t, std::size_t, bool> struct ScatterComponentOr;
|
|
|
|
|
template<class T, std::size_t valueSize, char, char...> constexpr T scatterRecursive(const T&, const Vector<valueSize, typename T::Type>&, std::size_t);
|
|
|
|
|
}
|
|
|
|
|
|
Math: made dot(), angle(), *lerp() and cross() free functions.
It is often annoying to write e.g. this, especially in generic code:
T dot = Math::Vector<size, T>::dot(a, b);
When this is more than enough and the compiler can infer the rest from
the context:
T dot = Math::dot(a, b);
There are more downsides and confusing cases (you can call
Math::Vector<3, T>::dot(), Math::Vector3<T>::dot() and Color3::dot() and
it is still the same function), so I made these as free functions in
Math namespace. You can now also abuse ADL for the calls, but I would
advise against that for better readability:
T d = dot(a, b); // dot?! what on earth is dot? and what is a?
The only downside found when porting is that you need to specify the
type somehow when having both parameters as initializer lists:
T d = dot({2.0f, -1.5f}, {1.0f, 2.5f}); // error
T d = dot(Complex{2.0f, -1.5f}, {1.0f, 2.5f}); // okay
But that's probably reasonable (and it's also highly corner case,
the functions were used this way only in tests).
The original static member functions are of course still present, but
marked as deprecated and will be removed at some point in future.
11 years ago
|
|
|
/** @relatesalso Vector
|
|
|
|
|
@brief Dot product of two vectors
|
|
|
|
|
|
|
|
|
|
Returns `0` when two vectors are perpendicular, `> 0` when two vectors are in
|
|
|
|
|
the same general direction, `1` when two *normalized* vectors are parallel,
|
|
|
|
|
`< 0` when two vectors are in opposite general direction and `-1` when two
|
|
|
|
|
* *normalized* vectors are antiparallel. @f[
|
Math: made dot(), angle(), *lerp() and cross() free functions.
It is often annoying to write e.g. this, especially in generic code:
T dot = Math::Vector<size, T>::dot(a, b);
When this is more than enough and the compiler can infer the rest from
the context:
T dot = Math::dot(a, b);
There are more downsides and confusing cases (you can call
Math::Vector<3, T>::dot(), Math::Vector3<T>::dot() and Color3::dot() and
it is still the same function), so I made these as free functions in
Math namespace. You can now also abuse ADL for the calls, but I would
advise against that for better readability:
T d = dot(a, b); // dot?! what on earth is dot? and what is a?
The only downside found when porting is that you need to specify the
type somehow when having both parameters as initializer lists:
T d = dot({2.0f, -1.5f}, {1.0f, 2.5f}); // error
T d = dot(Complex{2.0f, -1.5f}, {1.0f, 2.5f}); // okay
But that's probably reasonable (and it's also highly corner case,
the functions were used this way only in tests).
The original static member functions are of course still present, but
marked as deprecated and will be removed at some point in future.
11 years ago
|
|
|
\boldsymbol a \cdot \boldsymbol b = \sum_{i=0}^{n-1} \boldsymbol a_i \boldsymbol b_i
|
|
|
|
|
@f]
|
|
|
|
|
@see @ref Vector::dot() const, @ref Vector::operator-(), @ref Vector2::perpendicular()
|
|
|
|
|
*/
|
|
|
|
|
template<std::size_t size, class T> inline T dot(const Vector<size, T>& a, const Vector<size, T>& b) {
|
|
|
|
|
T out{};
|
|
|
|
|
for(std::size_t i = 0; i != size; ++i)
|
|
|
|
|
out += a._data[i]*b._data[i];
|
|
|
|
|
return out;
|
Math: made dot(), angle(), *lerp() and cross() free functions.
It is often annoying to write e.g. this, especially in generic code:
T dot = Math::Vector<size, T>::dot(a, b);
When this is more than enough and the compiler can infer the rest from
the context:
T dot = Math::dot(a, b);
There are more downsides and confusing cases (you can call
Math::Vector<3, T>::dot(), Math::Vector3<T>::dot() and Color3::dot() and
it is still the same function), so I made these as free functions in
Math namespace. You can now also abuse ADL for the calls, but I would
advise against that for better readability:
T d = dot(a, b); // dot?! what on earth is dot? and what is a?
The only downside found when porting is that you need to specify the
type somehow when having both parameters as initializer lists:
T d = dot({2.0f, -1.5f}, {1.0f, 2.5f}); // error
T d = dot(Complex{2.0f, -1.5f}, {1.0f, 2.5f}); // okay
But that's probably reasonable (and it's also highly corner case,
the functions were used this way only in tests).
The original static member functions are of course still present, but
marked as deprecated and will be removed at some point in future.
11 years ago
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** @relatesalso Vector
|
|
|
|
|
@brief Angle between normalized vectors
|
|
|
|
|
|
|
|
|
|
Expects that both vectors are normalized. Enabled only for floating-point
|
|
|
|
|
types. @f[
|
|
|
|
|
\theta = \arccos \left( \frac{\boldsymbol a \cdot \boldsymbol b}{|\boldsymbol a| |\boldsymbol b|} \right) = \arccos (\boldsymbol a \cdot \boldsymbol b)
|
Math: made dot(), angle(), *lerp() and cross() free functions.
It is often annoying to write e.g. this, especially in generic code:
T dot = Math::Vector<size, T>::dot(a, b);
When this is more than enough and the compiler can infer the rest from
the context:
T dot = Math::dot(a, b);
There are more downsides and confusing cases (you can call
Math::Vector<3, T>::dot(), Math::Vector3<T>::dot() and Color3::dot() and
it is still the same function), so I made these as free functions in
Math namespace. You can now also abuse ADL for the calls, but I would
advise against that for better readability:
T d = dot(a, b); // dot?! what on earth is dot? and what is a?
The only downside found when porting is that you need to specify the
type somehow when having both parameters as initializer lists:
T d = dot({2.0f, -1.5f}, {1.0f, 2.5f}); // error
T d = dot(Complex{2.0f, -1.5f}, {1.0f, 2.5f}); // okay
But that's probably reasonable (and it's also highly corner case,
the functions were used this way only in tests).
The original static member functions are of course still present, but
marked as deprecated and will be removed at some point in future.
11 years ago
|
|
|
@f]
|
|
|
|
|
|
|
|
|
|
To avoid numerical issues when two vectors are very close to each other, the
|
|
|
|
|
dot product is clamped to the @f$ [-1, +1] @f$ range before being passed to
|
|
|
|
|
@f$ \arccos @f$.
|
Math: made dot(), angle(), *lerp() and cross() free functions.
It is often annoying to write e.g. this, especially in generic code:
T dot = Math::Vector<size, T>::dot(a, b);
When this is more than enough and the compiler can infer the rest from
the context:
T dot = Math::dot(a, b);
There are more downsides and confusing cases (you can call
Math::Vector<3, T>::dot(), Math::Vector3<T>::dot() and Color3::dot() and
it is still the same function), so I made these as free functions in
Math namespace. You can now also abuse ADL for the calls, but I would
advise against that for better readability:
T d = dot(a, b); // dot?! what on earth is dot? and what is a?
The only downside found when porting is that you need to specify the
type somehow when having both parameters as initializer lists:
T d = dot({2.0f, -1.5f}, {1.0f, 2.5f}); // error
T d = dot(Complex{2.0f, -1.5f}, {1.0f, 2.5f}); // okay
But that's probably reasonable (and it's also highly corner case,
the functions were used this way only in tests).
The original static member functions are of course still present, but
marked as deprecated and will be removed at some point in future.
11 years ago
|
|
|
@see @ref Vector::isNormalized(),
|
|
|
|
|
@ref angle(const Complex<T>&, const Complex<T>&),
|
|
|
|
|
@ref angle(const Quaternion<T>&, const Quaternion<T>&)
|
|
|
|
|
*/
|
|
|
|
|
template<std::size_t size, class FloatingPoint> inline
|
|
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT
|
|
|
|
|
Rad<FloatingPoint>
|
|
|
|
|
#else
|
|
|
|
|
typename std::enable_if<std::is_floating_point<FloatingPoint>::value, Rad<FloatingPoint>>::type
|
|
|
|
|
#endif
|
|
|
|
|
angle(const Vector<size, FloatingPoint>& normalizedA, const Vector<size, FloatingPoint>& normalizedB) {
|
|
|
|
|
CORRADE_DEBUG_ASSERT(normalizedA.isNormalized() && normalizedB.isNormalized(),
|
|
|
|
|
"Math::angle(): vectors" << normalizedA << "and" << normalizedB << "are not normalized", {});
|
|
|
|
|
return Rad<FloatingPoint>(std::acos(clamp(dot(normalizedA, normalizedB), FloatingPoint(-1), FloatingPoint(1))));
|
Math: made dot(), angle(), *lerp() and cross() free functions.
It is often annoying to write e.g. this, especially in generic code:
T dot = Math::Vector<size, T>::dot(a, b);
When this is more than enough and the compiler can infer the rest from
the context:
T dot = Math::dot(a, b);
There are more downsides and confusing cases (you can call
Math::Vector<3, T>::dot(), Math::Vector3<T>::dot() and Color3::dot() and
it is still the same function), so I made these as free functions in
Math namespace. You can now also abuse ADL for the calls, but I would
advise against that for better readability:
T d = dot(a, b); // dot?! what on earth is dot? and what is a?
The only downside found when porting is that you need to specify the
type somehow when having both parameters as initializer lists:
T d = dot({2.0f, -1.5f}, {1.0f, 2.5f}); // error
T d = dot(Complex{2.0f, -1.5f}, {1.0f, 2.5f}); // okay
But that's probably reasonable (and it's also highly corner case,
the functions were used this way only in tests).
The original static member functions are of course still present, but
marked as deprecated and will be removed at some point in future.
11 years ago
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@brief Vector
|
|
|
|
|
@tparam size Vector size
|
|
|
|
|
@tparam T Underlying data type
|
|
|
|
|
|
|
|
|
|
See @ref matrix-vector for brief introduction.
|
|
|
|
|
@configurationvalueref{Magnum::Math::Vector}
|
|
|
|
|
*/
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
template<std::size_t size, class T> class Vector {
|
|
|
|
|
static_assert(size != 0, "Vector cannot have zero elements");
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
typedef T Type; /**< @brief Underlying data type */
|
|
|
|
|
|
|
|
|
|
enum: std::size_t {
|
|
|
|
|
Size = size /**< Vector size */
|
|
|
|
|
};
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Vector from an array
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
* @return Reference to the data as if it was Vector, thus doesn't
|
|
|
|
|
* perform any copying.
|
|
|
|
|
*
|
|
|
|
|
* @attention Use with caution, the function doesn't check whether the
|
|
|
|
|
* array is long enough.
|
|
|
|
|
*/
|
|
|
|
|
static Vector<size, T>& from(T* data) {
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
return *reinterpret_cast<Vector<size, T>*>(data);
|
|
|
|
|
}
|
|
|
|
|
/** @overload */
|
|
|
|
|
static const Vector<size, T>& from(const T* data) {
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
return *reinterpret_cast<const Vector<size, T>*>(data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Pad a vector
|
|
|
|
|
*
|
|
|
|
|
* If size of @p a is smaller than @ref Size, it is padded from right
|
|
|
|
|
* with @p value, otherwise it's cut.
|
|
|
|
|
* @see @ref Vector4::pad(const Vector<otherSize, T>&, T, T)
|
|
|
|
|
*/
|
|
|
|
|
template<std::size_t otherSize> constexpr static Vector<size, T> pad(const Vector<otherSize, T>& a, T value = T()) {
|
|
|
|
|
return padInternal<otherSize>(typename Containers::Implementation::GenerateSequence<size>::Type{}, a, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Default constructor
|
|
|
|
|
*
|
|
|
|
|
* Equivalent to @ref Vector(ZeroInitT).
|
|
|
|
|
*/
|
|
|
|
|
constexpr /*implicit*/ Vector() noexcept: _data{} {}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Construct a zero vector
|
|
|
|
|
*
|
|
|
|
|
* @f[
|
|
|
|
|
* \boldsymbol v = \boldsymbol 0
|
|
|
|
|
* @f]
|
|
|
|
|
*/
|
|
|
|
|
constexpr explicit Vector(ZeroInitT) noexcept: _data{} {}
|
|
|
|
|
|
|
|
|
|
/** @brief Construct a vector without initializing the contents */
|
|
|
|
|
explicit Vector(Magnum::NoInitT) noexcept {}
|
|
|
|
|
|
|
|
|
|
/** @brief Construct a vector from components */
|
|
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT
|
|
|
|
|
template<class ...U> constexpr /*implicit*/ Vector(T first, U... next) noexcept;
|
|
|
|
|
#else
|
|
|
|
|
template<class ...U, class V = typename std::enable_if<sizeof...(U)+1 == size, T>::type> constexpr /*implicit*/ Vector(T first, U... next) noexcept: _data{first, next...} {}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/** @brief Construct a vector with one value for all components */
|
|
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT
|
|
|
|
|
constexpr explicit Vector(T value) noexcept;
|
|
|
|
|
#else
|
|
|
|
|
template<class U, class V = typename std::enable_if<std::is_same<T, U>::value && size != 1, T>::type> constexpr explicit Vector(U value) noexcept: Vector(typename Containers::Implementation::GenerateSequence<size>::Type{}, value) {}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Construct a vector from another of different type
|
|
|
|
|
*
|
|
|
|
|
* Performs only default casting on the values, no rounding or
|
|
|
|
|
* anything else. Example usage:
|
|
|
|
|
*
|
|
|
|
|
* @snippet MagnumMath.cpp Vector-conversion
|
|
|
|
|
*/
|
|
|
|
|
template<class U> constexpr explicit Vector(const Vector<size, U>& other) noexcept: Vector(typename Containers::Implementation::GenerateSequence<size>::Type{}, other) {}
|
|
|
|
|
|
|
|
|
|
/** @brief Construct a vector from external representation */
|
|
|
|
|
template<class U, class V = decltype(Implementation::VectorConverter<size, T, U>::from(std::declval<U>()))> constexpr explicit Vector(const U& other) noexcept: Vector(Implementation::VectorConverter<size, T, U>::from(other)) {}
|
|
|
|
|
|
|
|
|
|
/** @brief Convert a vector to external representation */
|
|
|
|
|
template<class U, class V = decltype(Implementation::VectorConverter<size, T, U>::to(std::declval<Vector<size, T>>()))> constexpr explicit operator U() const {
|
|
|
|
|
return Implementation::VectorConverter<size, T, U>::to(*this);
|
|
|
|
|
}
|
|
|
|
|
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
/**
|
|
|
|
|
* @brief Raw data
|
|
|
|
|
*
|
|
|
|
|
* Contrary to what Doxygen shows, returns reference to an
|
|
|
|
|
* one-dimensional fixed-size array of `size` elements, i.e.
|
|
|
|
|
* @cpp T(&)[size] @ce.
|
|
|
|
|
* @see @ref operator[]()
|
|
|
|
|
* @todoc Fix once there's a possibility to patch the signature in a
|
|
|
|
|
* post-processing step (https://github.com/mosra/m.css/issues/56)
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
*/
|
|
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT
|
|
|
|
|
T* data();
|
|
|
|
|
constexpr const T* data() const; /**< @overload */
|
|
|
|
|
#else
|
|
|
|
|
auto data() -> T(&)[size] { return _data; }
|
|
|
|
|
constexpr auto data() const -> const T(&)[size] { return _data; }
|
|
|
|
|
#endif
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Value at given position
|
|
|
|
|
*
|
|
|
|
|
* @see @ref data()
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
*/
|
|
|
|
|
T& operator[](std::size_t pos) { return _data[pos]; }
|
|
|
|
|
constexpr T operator[](std::size_t pos) const { return _data[pos]; } /**< @overload */
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Equality comparison
|
|
|
|
|
*
|
|
|
|
|
* @see @ref Math::equal()
|
|
|
|
|
*/
|
|
|
|
|
bool operator==(const Vector<size, T>& other) const {
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
for(std::size_t i = 0; i != size; ++i)
|
|
|
|
|
if(!TypeTraits<T>::equals(_data[i], other._data[i])) return false;
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Non-equality comparison
|
|
|
|
|
*
|
|
|
|
|
* @see @ref Math::notEqual()
|
|
|
|
|
*/
|
|
|
|
|
bool operator!=(const Vector<size, T>& other) const {
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
return !operator==(other);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Component-wise less than comparison
|
|
|
|
|
*
|
|
|
|
|
* @m_keyword{lessThan(),GLSL lessThan(),}
|
|
|
|
|
*/
|
|
|
|
|
BitVector<size> operator<(const Vector<size, T>& other) const;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Component-wise less than or equal comparison
|
|
|
|
|
*
|
|
|
|
|
* @m_keyword{lessThanEqual(),GLSL lessThanEqual(),}
|
|
|
|
|
*/
|
|
|
|
|
BitVector<size> operator<=(const Vector<size, T>& other) const;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Component-wise greater than or equal comparison
|
|
|
|
|
*
|
|
|
|
|
* @m_keyword{greaterThanEqual(),GLSL greaterThanEqual(),}
|
|
|
|
|
*/
|
|
|
|
|
BitVector<size> operator>=(const Vector<size, T>& other) const;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Component-wise greater than comparison
|
|
|
|
|
*
|
|
|
|
|
* @m_keyword{greaterThan(),GLSL greaterThan(),}
|
|
|
|
|
*/
|
|
|
|
|
BitVector<size> operator>(const Vector<size, T>& other) const;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Whether the vector is zero
|
|
|
|
|
*
|
|
|
|
|
* @f[
|
|
|
|
|
* |\boldsymbol a \cdot \boldsymbol a - 0| < \epsilon^2 \cong \epsilon
|
|
|
|
|
* @f]
|
|
|
|
|
* @see @ref dot(), @ref normalized()
|
|
|
|
|
*/
|
|
|
|
|
bool isZero() const {
|
|
|
|
|
return Implementation::IsZero<std::is_integral<T>::value>{}(*this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Whether the vector is normalized
|
|
|
|
|
*
|
|
|
|
|
* The vector is normalized if it has unit length: @f[
|
|
|
|
|
* |\boldsymbol a \cdot \boldsymbol a - 1| < 2 \epsilon + \epsilon^2 \cong 2 \epsilon
|
|
|
|
|
* @f]
|
|
|
|
|
* @see @ref dot(), @ref normalized()
|
|
|
|
|
*/
|
|
|
|
|
bool isNormalized() const {
|
|
|
|
|
return Implementation::isNormalizedSquared(dot());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Promotion
|
|
|
|
|
* @m_since_latest
|
|
|
|
|
*
|
|
|
|
|
* Returns the value as-is.
|
|
|
|
|
*/
|
|
|
|
|
constexpr Vector<size, T> operator+() const { return *this; }
|
|
|
|
|
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
/**
|
|
|
|
|
* @brief Negated vector
|
|
|
|
|
*
|
|
|
|
|
* Enabled only for signed types. @f[
|
|
|
|
|
* \boldsymbol b_i = -\boldsymbol a_i
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
* @f]
|
|
|
|
|
* @see @ref flipped(), @ref Vector2::perpendicular()
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
*/
|
|
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
constexpr Vector<size, T>
|
|
|
|
|
#else
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class U = T> constexpr typename std::enable_if<std::is_signed<U>::value, Vector<size, T>>::type
|
|
|
|
|
#endif
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
operator-() const {
|
|
|
|
|
return negateInternal(typename Containers::Implementation::GenerateSequence<size>::Type{});
|
|
|
|
|
}
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Add and assign a vector
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
*
|
|
|
|
|
* The computation is done in-place. @f[
|
|
|
|
|
* \boldsymbol a_i = \boldsymbol a_i + \boldsymbol b_i
|
|
|
|
|
* @f]
|
|
|
|
|
*/
|
|
|
|
|
Vector<size, T>& operator+=(const Vector<size, T>& other) {
|
|
|
|
|
for(std::size_t i = 0; i != size; ++i)
|
|
|
|
|
_data[i] += other._data[i];
|
|
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Add a vector
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
*
|
|
|
|
|
* @see @ref operator+=(), @ref sum()
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
*/
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
constexpr Vector<size, T> operator+(const Vector<size, T>& other) const {
|
|
|
|
|
return addInternal(other, typename Containers::Implementation::GenerateSequence<size>::Type{});
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Subtract and assign a vector
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
*
|
|
|
|
|
* The computation is done in-place. @f[
|
|
|
|
|
* \boldsymbol a_i = \boldsymbol a_i - \boldsymbol b_i
|
|
|
|
|
* @f]
|
|
|
|
|
*/
|
|
|
|
|
Vector<size, T>& operator-=(const Vector<size, T>& other) {
|
|
|
|
|
for(std::size_t i = 0; i != size; ++i)
|
|
|
|
|
_data[i] -= other._data[i];
|
|
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Subtract a vector
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
*
|
|
|
|
|
* @see @ref operator-=()
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
*/
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
constexpr Vector<size, T> operator-(const Vector<size, T>& other) const {
|
|
|
|
|
return subtractInternal(other, typename Containers::Implementation::GenerateSequence<size>::Type{});
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Multiply with a scalar and assign
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
*
|
|
|
|
|
* The computation is done in-place. @f[
|
|
|
|
|
* \boldsymbol a_i = b \boldsymbol a_i
|
|
|
|
|
* @f]
|
|
|
|
|
* @see @ref operator*=(const Vector<size, T>&),
|
|
|
|
|
* @ref operator*=(FloatingPoint)
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
*/
|
|
|
|
|
Vector<size, T>& operator*=(T scalar) {
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
for(std::size_t i = 0; i != size; ++i)
|
|
|
|
|
_data[i] *= scalar;
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Multiply with a scalar
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
*
|
|
|
|
|
* @see @ref operator*(const Vector<size, T>&) const,
|
|
|
|
|
* @ref operator*=(T), @ref operator*(T, const Vector<size, T>&),
|
|
|
|
|
* @ref operator*(FloatingPoint) const
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
*/
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
constexpr Vector<size, T> operator*(T scalar) const {
|
|
|
|
|
return multiplyInternal(scalar, typename Containers::Implementation::GenerateSequence<size>::Type{});
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Multiply a scalar with a vector
|
|
|
|
|
*
|
|
|
|
|
* Same as @ref operator*(T) const.
|
|
|
|
|
*/
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
constexpr friend Vector<size, T> operator*(
|
|
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT
|
|
|
|
|
T
|
|
|
|
|
#else
|
|
|
|
|
typename std::common_type<T>::type
|
|
|
|
|
#endif
|
|
|
|
|
scalar, const Vector<size, T>& vector)
|
|
|
|
|
{
|
|
|
|
|
return vector*scalar;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Multiply an integral vector with a floating-point scalar and assign
|
|
|
|
|
*
|
|
|
|
|
* Similar to @ref operator*=(T), except that the multiplication is
|
|
|
|
|
* done in floating-point. The computation is done in-place.
|
|
|
|
|
*/
|
|
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT
|
|
|
|
|
template<class FloatingPoint> Vector<size, T>&
|
|
|
|
|
#else
|
|
|
|
|
template<class FloatingPoint, class Integral = T> typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Vector<size, T>&>::type
|
|
|
|
|
#endif
|
|
|
|
|
operator*=(FloatingPoint scalar) {
|
|
|
|
|
for(std::size_t i = 0; i != size; ++i)
|
|
|
|
|
_data[i] = T(_data[i]*scalar);
|
|
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Multiply an integral vector with a floating-point scalar
|
|
|
|
|
*
|
|
|
|
|
* Similar to @ref operator*(T) const, except that the multiplication
|
|
|
|
|
* is done in floating-point.
|
|
|
|
|
*/
|
|
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class FloatingPoint> constexpr Vector<size, T>
|
|
|
|
|
#else
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class FloatingPoint, class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Vector<size, T>>::type
|
|
|
|
|
#endif
|
|
|
|
|
operator*(FloatingPoint scalar) const {
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
return multiplyIntegerInternal(scalar, typename Containers::Implementation::GenerateSequence<size>::Type{});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Multiply a floating-point scalar with an integral vector
|
|
|
|
|
*
|
|
|
|
|
* Same as @ref operator*(FloatingPoint) const.
|
|
|
|
|
*/
|
|
|
|
|
/* Note that this one isn't correctly picked up on MSVC 2015, there's
|
|
|
|
|
an out-of-class overload wrapped in CORRADE_MSVC2015_COMPATIBILITY
|
|
|
|
|
which is (and the two don't conflict, apparently, so both are
|
|
|
|
|
present) */
|
|
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class FloatingPoint> friend constexpr Vector<size, T>
|
|
|
|
|
#else
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class FloatingPoint, class Integral = T> friend constexpr typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Vector<size, T>>::type
|
|
|
|
|
#endif
|
|
|
|
|
operator*(FloatingPoint scalar, const Vector<size, T>& vector) {
|
|
|
|
|
return vector*scalar;
|
|
|
|
|
}
|
|
|
|
|
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
/**
|
|
|
|
|
* @brief Divide with a scalar and assign
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
*
|
|
|
|
|
* The computation is done in-place. @f[
|
|
|
|
|
* \boldsymbol a_i = \frac{\boldsymbol a_i} b
|
|
|
|
|
* @f]
|
|
|
|
|
* @see @ref operator/=(const Vector<size, T>&),
|
|
|
|
|
* @ref operator/=(FloatingPoint)
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
*/
|
|
|
|
|
Vector<size, T>& operator/=(T scalar) {
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
for(std::size_t i = 0; i != size; ++i)
|
|
|
|
|
_data[i] /= scalar;
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Divide with a scalar
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
*
|
|
|
|
|
* @see @ref operator/(const Vector<size, T>&) const,
|
|
|
|
|
* @ref operator/=(T), @ref operator/(T, const Vector<size, T>&),
|
|
|
|
|
* @ref operator/(FloatingPoint) const
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
*/
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
constexpr Vector<size, T> operator/(T scalar) const {
|
|
|
|
|
return divideInternal(scalar, typename Containers::Implementation::GenerateSequence<size>::Type{});
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Divide a vector with a scalar and invert
|
|
|
|
|
*
|
|
|
|
|
* @f[
|
|
|
|
|
* \boldsymbol c_i = \frac b {\boldsymbol a_i}
|
|
|
|
|
* @f]
|
|
|
|
|
* @see @ref operator/(T) const
|
|
|
|
|
*/
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
friend constexpr Vector<size, T> operator/(
|
|
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT
|
|
|
|
|
T
|
|
|
|
|
#else
|
|
|
|
|
typename std::common_type<T>::type
|
|
|
|
|
#endif
|
|
|
|
|
scalar, const Vector<size, T>& vector)
|
|
|
|
|
{
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
return divideInternal(scalar, vector, typename Containers::Implementation::GenerateSequence<size>::Type{});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Divide an integral vector with a floating-point scalar and assign
|
|
|
|
|
*
|
|
|
|
|
* Similar to @ref operator/=(T), except that the division is done in
|
|
|
|
|
* floating-point. The computation is done in-place.
|
|
|
|
|
*/
|
|
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT
|
|
|
|
|
template<class FloatingPoint> Vector<size, Integral>&
|
|
|
|
|
#else
|
|
|
|
|
template<class FloatingPoint, class Integral = T> typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Vector<size, T>&>::type
|
|
|
|
|
#endif
|
|
|
|
|
operator/=(FloatingPoint scalar) {
|
|
|
|
|
for(std::size_t i = 0; i != size; ++i)
|
|
|
|
|
_data[i] = T(_data[i]/scalar);
|
|
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Divide an integral vector with a floating-point scalar
|
|
|
|
|
*
|
|
|
|
|
* Similar to @ref operator/(T) const, except that the division is done
|
|
|
|
|
* in floating-point.
|
|
|
|
|
*/
|
|
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class FloatingPoint> Vector<size, T> constexpr
|
|
|
|
|
#else
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class FloatingPoint, class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Vector<size, T>>::type
|
|
|
|
|
#endif
|
|
|
|
|
operator/(FloatingPoint scalar) const {
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
return divideIntegerInternal(scalar, typename Containers::Implementation::GenerateSequence<size>::Type{});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Multiply a vector component-wise and assign
|
|
|
|
|
*
|
|
|
|
|
* The computation is done in-place. @f[
|
|
|
|
|
* \boldsymbol a_i = \boldsymbol a_i \boldsymbol b_i
|
|
|
|
|
* @f]
|
|
|
|
|
* @see @ref operator*=(T),
|
|
|
|
|
* @ref operator*=(const Vector<size, FloatingPoint>&)
|
|
|
|
|
*/
|
|
|
|
|
Vector<size, T>& operator*=(const Vector<size, T>& other) {
|
|
|
|
|
for(std::size_t i = 0; i != size; ++i)
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
_data[i] *= other._data[i];
|
|
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Multiply a vector component-wise
|
|
|
|
|
*
|
|
|
|
|
* @see @ref operator*(T) const, @ref operator*=(const Vector<size, T>&),
|
|
|
|
|
* @ref operator*(const Vector<size, FloatingPoint>&) const,
|
|
|
|
|
* @ref product()
|
|
|
|
|
*/
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
constexpr Vector<size, T> operator*(const Vector<size, T>& other) const {
|
|
|
|
|
return multiplyInternal(other, typename Containers::Implementation::GenerateSequence<size>::Type{});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Multiply an integral vector with a floating-point vector component-wise and assign
|
|
|
|
|
*
|
|
|
|
|
* Similar to @ref operator*=(const Vector<size, T>&), except that the
|
|
|
|
|
* multiplication is done in floating-point. The computation is done
|
|
|
|
|
* in-place.
|
|
|
|
|
*/
|
|
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT
|
|
|
|
|
template<class FloatingPoint> Vector<size, T>&
|
|
|
|
|
#else
|
|
|
|
|
template<class FloatingPoint, class Integral = T> typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Vector<size, T>&>::type
|
|
|
|
|
#endif
|
|
|
|
|
operator*=(const Vector<size, FloatingPoint>& other) {
|
|
|
|
|
for(std::size_t i = 0; i != size; ++i)
|
|
|
|
|
_data[i] = T(_data[i]*other._data[i]);
|
|
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Multiply an integral vector with a floating-point vector component-wise
|
|
|
|
|
*
|
|
|
|
|
* Similar to @ref operator*(const Vector<size, T>&) const, except that
|
|
|
|
|
* the multiplication is done in floating-point. The result is always
|
|
|
|
|
* an integral vector, convert both arguments to the same
|
|
|
|
|
* floating-point type to have a floating-point result.
|
|
|
|
|
*/
|
|
|
|
|
template<class FloatingPoint
|
|
|
|
|
#ifndef DOXYGEN_GENERATING_OUTPUT
|
|
|
|
|
, class Integral = T, typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value>::type* = nullptr
|
|
|
|
|
#endif
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
> constexpr Vector<size, T> operator*(const Vector<size, FloatingPoint>& other) const {
|
|
|
|
|
return multiplyIntegerInternal(other, typename Containers::Implementation::GenerateSequence<size>::Type{});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Multiply a floating-point vector with an integral vector component-wise
|
|
|
|
|
*
|
|
|
|
|
* Same as @ref operator*(const Vector<size, FloatingPoint>&) const.
|
|
|
|
|
*/
|
|
|
|
|
/* This was originally friend operator*(const Vector<size, FloatingPoint>&, const Vector<size, T>&),
|
|
|
|
|
but that made it not found on MSVC 2015 and 2017 (and possibly
|
|
|
|
|
newer?) for some reason. Making it a member operator makes it work,
|
|
|
|
|
but it additionally has to prevent a conflict with the
|
|
|
|
|
Integral*FloatingPoint variant above */
|
|
|
|
|
template<class Integral
|
|
|
|
|
#ifndef DOXYGEN_GENERATING_OUTPUT
|
|
|
|
|
, class FloatingPoint = T, typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value>::type* = nullptr
|
|
|
|
|
#endif
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
> constexpr Vector<size, Integral> operator*(const Vector<size, Integral>& other) const {
|
|
|
|
|
return other**this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Divide a vector component-wise and assign
|
|
|
|
|
*
|
|
|
|
|
* The computation is done in-place. @f[
|
|
|
|
|
* \boldsymbol a_i = \frac{\boldsymbol a_i}{\boldsymbol b_i}
|
|
|
|
|
* @f]
|
|
|
|
|
* @see @ref operator/=(T),
|
|
|
|
|
* @ref operator/=(const Vector<size, FloatingPoint>&)
|
|
|
|
|
*/
|
|
|
|
|
Vector<size, T>& operator/=(const Vector<size, T>& other) {
|
|
|
|
|
for(std::size_t i = 0; i != size; ++i)
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
_data[i] /= other._data[i];
|
|
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Divide a vector component-wise
|
|
|
|
|
*
|
|
|
|
|
* @see @ref operator/(T) const, @ref operator/=(const Vector<size, T>&),
|
|
|
|
|
* @ref operator/(const Vector<size, FloatingPoint>&) const
|
|
|
|
|
*/
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
constexpr Vector<size, T> operator/(const Vector<size, T>& other) const {
|
|
|
|
|
return divideInternal(other, typename Containers::Implementation::GenerateSequence<size>::Type{});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Divide an integral vector with a floating-point vector component-wise and assign
|
|
|
|
|
*
|
|
|
|
|
* Similar to @ref operator/=(const Vector<size, T>&), except that the
|
|
|
|
|
* division is done in floating-point. The computation is done
|
|
|
|
|
* in-place.
|
|
|
|
|
*/
|
|
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT
|
|
|
|
|
template<class FloatingPoint> Vector<size, T>&
|
|
|
|
|
#else
|
|
|
|
|
template<class FloatingPoint, class Integral = T> typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Vector<size, T>&>::type
|
|
|
|
|
#endif
|
|
|
|
|
operator/=(const Vector<size, FloatingPoint>& other) {
|
|
|
|
|
for(std::size_t i = 0; i != size; ++i)
|
|
|
|
|
_data[i] = T(_data[i]/other._data[i]);
|
|
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Divide an integral vector with a floating-point vector component-wise
|
|
|
|
|
*
|
|
|
|
|
* Similar to @ref Vector::operator/(const Vector<size, T>&) const,
|
|
|
|
|
* except that the division is done in floating-point. The result is
|
|
|
|
|
* always an integral vector, convert both arguments to the same
|
|
|
|
|
* floating-point type to have a floating-point result.
|
|
|
|
|
*/
|
|
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class FloatingPoint> constexpr Vector<size, T>
|
|
|
|
|
#else
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class FloatingPoint, class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Vector<size, T>>::type
|
|
|
|
|
#endif
|
|
|
|
|
operator/(const Vector<size, FloatingPoint>& other) const {
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
return divideIntegerInternal(other, typename Containers::Implementation::GenerateSequence<size>::Type{});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Do modulo of a vector and assign
|
|
|
|
|
*
|
|
|
|
|
* Enabled only for integral types. The computation is done in-place.
|
|
|
|
|
*/
|
|
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT
|
|
|
|
|
Vector<size, T>&
|
|
|
|
|
#else
|
|
|
|
|
template<class Integral = T> typename std::enable_if<std::is_integral<Integral>::value, Vector<size, T>&>::type
|
|
|
|
|
#endif
|
|
|
|
|
operator%=(T other) {
|
|
|
|
|
for(std::size_t i = 0; i != size; ++i)
|
|
|
|
|
_data[i] %= other;
|
|
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Modulo of a vector
|
|
|
|
|
*
|
|
|
|
|
* Enabled only for integral types.
|
|
|
|
|
*/
|
|
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
constexpr Vector<size, T>
|
|
|
|
|
#else
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value, Vector<size, T>>::type
|
|
|
|
|
#endif
|
|
|
|
|
operator%(T scalar) const {
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
return moduloInternal(scalar, typename Containers::Implementation::GenerateSequence<size>::Type{});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Do modulo of two vectors and assign
|
|
|
|
|
*
|
|
|
|
|
* Enabled only for integral types. The computation is done in-place.
|
|
|
|
|
*/
|
|
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT
|
|
|
|
|
Vector<size, T>&
|
|
|
|
|
#else
|
|
|
|
|
template<class Integral = T> typename std::enable_if<std::is_integral<Integral>::value, Vector<size, T>&>::type
|
|
|
|
|
#endif
|
|
|
|
|
operator%=(const Vector<size, T>& other) {
|
|
|
|
|
for(std::size_t i = 0; i != size; ++i)
|
|
|
|
|
_data[i] %= other._data[i];
|
|
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Modulo of two vectors
|
|
|
|
|
*
|
|
|
|
|
* Enabled only for integral types.
|
|
|
|
|
*/
|
|
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
constexpr Vector<size, T>
|
|
|
|
|
#else
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value, Vector<size, T>>::type
|
|
|
|
|
#endif
|
|
|
|
|
operator%(const Vector<size, T>& other) const {
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
return moduloInternal(other, typename Containers::Implementation::GenerateSequence<size>::Type{});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Bitwise NOT of a vector
|
|
|
|
|
*
|
|
|
|
|
* Enabled only for integral types.
|
|
|
|
|
*/
|
|
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
constexpr Vector<size, T>
|
|
|
|
|
#else
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value, Vector<size, T>>::type
|
|
|
|
|
#endif
|
|
|
|
|
operator~() const {
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
return invertInternal(typename Containers::Implementation::GenerateSequence<size>::Type{});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Do bitwise AND of two vectors and assign
|
|
|
|
|
*
|
|
|
|
|
* Enabled only for integral types. The computation is done in-place.
|
|
|
|
|
*/
|
|
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT
|
|
|
|
|
Vector<size, T>&
|
|
|
|
|
#else
|
|
|
|
|
template<class Integral = T> typename std::enable_if<std::is_integral<Integral>::value, Vector<size, T>&>::type
|
|
|
|
|
#endif
|
|
|
|
|
operator&=(const Vector<size, T>& other) {
|
|
|
|
|
for(std::size_t i = 0; i != size; ++i)
|
|
|
|
|
_data[i] &= other._data[i];
|
|
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Bitwise AND of two vectors
|
|
|
|
|
*
|
|
|
|
|
* Enabled only for integral types.
|
|
|
|
|
*/
|
|
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
constexpr Vector<size, T>
|
|
|
|
|
#else
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value, Vector<size, T>>::type
|
|
|
|
|
#endif
|
|
|
|
|
operator&(const Vector<size, T>& other) const {
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
return andInternal(other, typename Containers::Implementation::GenerateSequence<size>::Type{});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Do bitwise OR of two vectors and assign
|
|
|
|
|
*
|
|
|
|
|
* Enabled only for integral types. The computation is done in-place.
|
|
|
|
|
*/
|
|
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT
|
|
|
|
|
Vector<size, T>&
|
|
|
|
|
#else
|
|
|
|
|
template<class Integral = T> typename std::enable_if<std::is_integral<Integral>::value, Vector<size, T>&>::type
|
|
|
|
|
#endif
|
|
|
|
|
operator|=(const Vector<size, T>& other) {
|
|
|
|
|
for(std::size_t i = 0; i != size; ++i)
|
|
|
|
|
_data[i] |= other._data[i];
|
|
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Bitwise OR of two vectors
|
|
|
|
|
*
|
|
|
|
|
* Enabled only for integral types.
|
|
|
|
|
*/
|
|
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
constexpr Vector<size, T>
|
|
|
|
|
#else
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value, Vector<size, T>>::type
|
|
|
|
|
#endif
|
|
|
|
|
operator|(const Vector<size, T>& other) const {
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
return orInternal(other, typename Containers::Implementation::GenerateSequence<size>::Type{});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Do bitwise XOR of two vectors and assign
|
|
|
|
|
*
|
|
|
|
|
* Enabled only for integral types. The computation is done in-place.
|
|
|
|
|
*/
|
|
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT
|
|
|
|
|
Vector<size, T>&
|
|
|
|
|
#else
|
|
|
|
|
template<class Integral = T> typename std::enable_if<std::is_integral<Integral>::value, Vector<size, T>&>::type
|
|
|
|
|
#endif
|
|
|
|
|
operator^=(const Vector<size, T>& other) {
|
|
|
|
|
for(std::size_t i = 0; i != size; ++i)
|
|
|
|
|
_data[i] ^= other._data[i];
|
|
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Bitwise XOR of two vectors
|
|
|
|
|
*
|
|
|
|
|
* Enabled only for integral types.
|
|
|
|
|
*/
|
|
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
constexpr Vector<size, T>
|
|
|
|
|
#else
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value, Vector<size, T>>::type
|
|
|
|
|
#endif
|
|
|
|
|
operator^(const Vector<size, T>& other) const {
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
return xorInternal(other, typename Containers::Implementation::GenerateSequence<size>::Type{});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Do bitwise left shift of a vector and assign
|
|
|
|
|
*
|
|
|
|
|
* Enabled only for integral types. The computation is done in-place.
|
|
|
|
|
*/
|
|
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT
|
|
|
|
|
Vector<size, T>& operator<<=(T shift)
|
|
|
|
|
#else
|
|
|
|
|
template<class Integral = T> typename std::enable_if<std::is_integral<Integral>::value, Vector<size, T>&>::type operator<<=(typename std::common_type<T>::type shift)
|
|
|
|
|
#endif
|
|
|
|
|
{
|
|
|
|
|
for(std::size_t i = 0; i != size; ++i)
|
|
|
|
|
_data[i] <<= shift;
|
|
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Bitwise left shift of a vector
|
|
|
|
|
*
|
|
|
|
|
* Enabled only for integral types.
|
|
|
|
|
*/
|
|
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
constexpr Vector<size, T> operator<<(T shift) const
|
|
|
|
|
#else
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value, Vector<size, T>>::type
|
|
|
|
|
operator<<(typename std::common_type<T>::type shift) const
|
|
|
|
|
#endif
|
|
|
|
|
{
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
return shiftLeftInternal(shift, typename Containers::Implementation::GenerateSequence<size>::Type{});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Do bitwise right shift of a vector and assign
|
|
|
|
|
*
|
|
|
|
|
* Enabled only for integral types. The computation is done in-place.
|
|
|
|
|
*/
|
|
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT
|
|
|
|
|
Vector<size, T>& operator>>=(T shift)
|
|
|
|
|
#else
|
|
|
|
|
template<class Integral = T> typename std::enable_if<std::is_integral<Integral>::value, Vector<size, T>&>::type operator>>=(typename std::common_type<T>::type shift)
|
|
|
|
|
#endif
|
|
|
|
|
{
|
|
|
|
|
for(std::size_t i = 0; i != size; ++i)
|
|
|
|
|
_data[i] >>= shift;
|
|
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Bitwise left shift of a vector
|
|
|
|
|
*
|
|
|
|
|
* Enabled only for integral types.
|
|
|
|
|
*/
|
|
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
constexpr Vector<size, T> operator>>(T shift) const
|
|
|
|
|
#else
|
|
|
|
|
template<class Integral = T>
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
constexpr typename std::enable_if<std::is_integral<Integral>::value, Vector<size, T>>::type operator>>(typename std::common_type<T>::type shift) const
|
|
|
|
|
#endif
|
|
|
|
|
{
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
return shiftRightInternal(shift, typename Containers::Implementation::GenerateSequence<size>::Type{});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Dot product of the vector
|
|
|
|
|
*
|
|
|
|
|
* Should be used instead of @ref length() for comparing vector length
|
|
|
|
|
* with other values, because it doesn't compute the square root. @f[
|
|
|
|
|
* \boldsymbol a \cdot \boldsymbol a = \sum_{i=0}^{n-1} \boldsymbol a_i^2
|
|
|
|
|
* @f]
|
|
|
|
|
* @see @ref dot(const Vector<size, T>&, const Vector<size, T>&),
|
|
|
|
|
* @ref isNormalized(), @ref Distance::pointPointSquared(),
|
|
|
|
|
* @ref Intersection::pointSphere()
|
|
|
|
|
*/
|
Math: made dot(), angle(), *lerp() and cross() free functions.
It is often annoying to write e.g. this, especially in generic code:
T dot = Math::Vector<size, T>::dot(a, b);
When this is more than enough and the compiler can infer the rest from
the context:
T dot = Math::dot(a, b);
There are more downsides and confusing cases (you can call
Math::Vector<3, T>::dot(), Math::Vector3<T>::dot() and Color3::dot() and
it is still the same function), so I made these as free functions in
Math namespace. You can now also abuse ADL for the calls, but I would
advise against that for better readability:
T d = dot(a, b); // dot?! what on earth is dot? and what is a?
The only downside found when porting is that you need to specify the
type somehow when having both parameters as initializer lists:
T d = dot({2.0f, -1.5f}, {1.0f, 2.5f}); // error
T d = dot(Complex{2.0f, -1.5f}, {1.0f, 2.5f}); // okay
But that's probably reasonable (and it's also highly corner case,
the functions were used this way only in tests).
The original static member functions are of course still present, but
marked as deprecated and will be removed at some point in future.
11 years ago
|
|
|
T dot() const { return Math::dot(*this, *this); }
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Vector length
|
|
|
|
|
*
|
|
|
|
|
* See also @ref dot() const which is faster for comparing length with
|
|
|
|
|
* other values. @f[
|
|
|
|
|
* |\boldsymbol a| = \sqrt{\boldsymbol a \cdot \boldsymbol a}
|
|
|
|
|
* @f]
|
|
|
|
|
*
|
|
|
|
|
* For integral types the result may be imprecise, to get a
|
|
|
|
|
* floating-point value of desired precision, cast to a floating-point
|
|
|
|
|
* vector first:
|
|
|
|
|
*
|
|
|
|
|
* @snippet MagnumMath.cpp Vector-length-integer
|
|
|
|
|
*
|
|
|
|
|
* A [Manhattan length](https://en.wikipedia.org/wiki/Taxicab_geometry)
|
|
|
|
|
* might be more suitable than @ref length() in certain cases where the
|
|
|
|
|
* square root is undesirable --- it's a sum of absolute values:
|
|
|
|
|
*
|
|
|
|
|
* @snippet MagnumMath.cpp Vector-length-manhattan
|
|
|
|
|
*
|
|
|
|
|
* @see @ref lengthInverted(), @ref Math::sqrt(), @ref normalized(),
|
|
|
|
|
* @ref resized(), @ref Distance::pointPoint(),
|
|
|
|
|
* @ref Intersection::pointSphere()
|
|
|
|
|
* @todo something like std::hypot() for possibly better precision?
|
|
|
|
|
*/
|
|
|
|
|
T length() const { return T(std::sqrt(dot())); }
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Inverse vector length
|
|
|
|
|
*
|
|
|
|
|
* Enabled only for floating-point types. @f[
|
|
|
|
|
* \frac{1}{|\boldsymbol a|} = \frac{1}{\sqrt{\boldsymbol a \cdot \boldsymbol a}}
|
|
|
|
|
* @f]
|
|
|
|
|
* @see @ref length(), @ref Math::sqrtInverted(), @ref normalized(),
|
|
|
|
|
* @ref resized()
|
|
|
|
|
*/
|
|
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT
|
|
|
|
|
T
|
|
|
|
|
#else
|
|
|
|
|
template<class U = T> typename std::enable_if<std::is_floating_point<U>::value, T>::type
|
|
|
|
|
#endif
|
|
|
|
|
lengthInverted() const { return T(1)/length(); }
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Normalized vector (of unit length)
|
|
|
|
|
*
|
|
|
|
|
* Enabled only for floating-point types.
|
|
|
|
|
* @see @ref isNormalized(), @ref lengthInverted(), @ref resized()
|
|
|
|
|
* @m_keyword{normalize(),GLSL normalize(),}
|
|
|
|
|
*/
|
|
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT
|
|
|
|
|
Vector<size, T>
|
|
|
|
|
#else
|
|
|
|
|
template<class U = T> typename std::enable_if<std::is_floating_point<U>::value, Vector<size, T>>::type
|
|
|
|
|
#endif
|
|
|
|
|
normalized() const { return *this*lengthInverted(); }
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Resized vector
|
|
|
|
|
*
|
|
|
|
|
* Convenience equivalent to the following code. Due to operation order
|
|
|
|
|
* this function is faster than the obvious way of sizing
|
|
|
|
|
* a @ref normalized() vector. Enabled only for floating-point types.
|
|
|
|
|
*
|
|
|
|
|
* @snippet MagnumMath.cpp Vector-resized
|
|
|
|
|
*
|
|
|
|
|
* @see @ref normalized()
|
|
|
|
|
*/
|
|
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT
|
|
|
|
|
Vector<size, T>
|
|
|
|
|
#else
|
|
|
|
|
template<class U = T> typename std::enable_if<std::is_floating_point<U>::value, Vector<size, T>>::type
|
|
|
|
|
#endif
|
|
|
|
|
resized(T length) const {
|
|
|
|
|
return *this*(lengthInverted()*length);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Vector projected onto a line
|
|
|
|
|
*
|
|
|
|
|
* Returns a vector [projected](https://en.wikipedia.org/wiki/Vector_projection)
|
|
|
|
|
* onto @p line. Enabled only for floating-point types. @f[
|
|
|
|
|
* \operatorname{proj}_{\boldsymbol{b}}\,(\boldsymbol{a}) = \frac{\boldsymbol a \cdot \boldsymbol b}{\boldsymbol b \cdot \boldsymbol b} \boldsymbol b
|
|
|
|
|
* @f]
|
|
|
|
|
* @see @ref Math::dot(), @ref projectedOntoNormalized()
|
|
|
|
|
*/
|
|
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT
|
|
|
|
|
Vector<size, T>
|
|
|
|
|
#else
|
|
|
|
|
template<class U = T> typename std::enable_if<std::is_floating_point<U>::value, Vector<size, T>>::type
|
|
|
|
|
#endif
|
|
|
|
|
projected(const Vector<size, T>& line) const {
|
Math: made dot(), angle(), *lerp() and cross() free functions.
It is often annoying to write e.g. this, especially in generic code:
T dot = Math::Vector<size, T>::dot(a, b);
When this is more than enough and the compiler can infer the rest from
the context:
T dot = Math::dot(a, b);
There are more downsides and confusing cases (you can call
Math::Vector<3, T>::dot(), Math::Vector3<T>::dot() and Color3::dot() and
it is still the same function), so I made these as free functions in
Math namespace. You can now also abuse ADL for the calls, but I would
advise against that for better readability:
T d = dot(a, b); // dot?! what on earth is dot? and what is a?
The only downside found when porting is that you need to specify the
type somehow when having both parameters as initializer lists:
T d = dot({2.0f, -1.5f}, {1.0f, 2.5f}); // error
T d = dot(Complex{2.0f, -1.5f}, {1.0f, 2.5f}); // okay
But that's probably reasonable (and it's also highly corner case,
the functions were used this way only in tests).
The original static member functions are of course still present, but
marked as deprecated and will be removed at some point in future.
11 years ago
|
|
|
return line*Math::dot(*this, line)/line.dot();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Vector projected onto a normalized line
|
|
|
|
|
*
|
|
|
|
|
* Slightly faster alternative to @ref projected(), expects @p line to
|
|
|
|
|
* be normalized. Enabled only for floating-point types. @f[
|
|
|
|
|
* \operatorname{proj}_{\boldsymbol{b}}\,(\boldsymbol{a}) = \frac{\boldsymbol a \cdot \boldsymbol b}{\boldsymbol b \cdot \boldsymbol b} \boldsymbol b =
|
|
|
|
|
* (\boldsymbol a \cdot \boldsymbol b) \boldsymbol b
|
|
|
|
|
* @f]
|
|
|
|
|
* @see @ref Math::dot()
|
|
|
|
|
*/
|
|
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT
|
|
|
|
|
Vector<size, T>
|
|
|
|
|
#else
|
|
|
|
|
template<class U = T> typename std::enable_if<std::is_floating_point<U>::value, Vector<size, T>>::type
|
|
|
|
|
#endif
|
|
|
|
|
projectedOntoNormalized(const Vector<size, T>& line) const;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Flipped vector
|
|
|
|
|
*
|
|
|
|
|
* Returns the vector with components in reverse order. If you want to
|
|
|
|
|
* flip the vector *direction* instead, negate it.
|
|
|
|
|
* @see @ref operator-() const,
|
|
|
|
|
* @ref RectangularMatrix::flippedCols(),
|
|
|
|
|
* @ref RectangularMatrix::flippedRows()
|
|
|
|
|
*/
|
|
|
|
|
constexpr Vector<size, T> flipped() const {
|
|
|
|
|
return flippedInternal(typename Containers::Implementation::GenerateSequence<size>::Type{});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Sum of values in the vector
|
|
|
|
|
*
|
|
|
|
|
* @see @ref operator+(), @ref length()
|
|
|
|
|
*/
|
|
|
|
|
T sum() const;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Product of values in the vector
|
|
|
|
|
*
|
|
|
|
|
* @see @ref operator*(const Vector<size, T>&) const
|
|
|
|
|
*/
|
|
|
|
|
T product() const;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Minimal value in the vector
|
|
|
|
|
*
|
|
|
|
|
* <em>NaN</em>s are ignored, unless the vector is all <em>NaN</em>s.
|
|
|
|
|
* @see @ref Math::min(), @ref minmax(), @ref Math::isNan()
|
|
|
|
|
*/
|
|
|
|
|
T min() const;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Maximal value in the vector
|
|
|
|
|
*
|
|
|
|
|
* <em>NaN</em>s are ignored, unless the vector is all <em>NaN</em>s.
|
|
|
|
|
* @see @ref Math::max(), @ref minmax(), @ref Math::isNan()
|
|
|
|
|
*/
|
|
|
|
|
T max() const;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Minimal and maximal value in the vector
|
|
|
|
|
*
|
|
|
|
|
* <em>NaN</em>s are ignored, unless the vector is all <em>NaN</em>s.
|
|
|
|
|
* @see @ref min(), @ref max(), @ref Math::minmax(), @ref Math::isNan()
|
|
|
|
|
*/
|
|
|
|
|
Containers::Pair<T, T> minmax() const;
|
|
|
|
|
|
|
|
|
|
#ifndef DOXYGEN_GENERATING_OUTPUT
|
|
|
|
|
protected:
|
|
|
|
|
#else
|
|
|
|
|
private:
|
|
|
|
|
#endif
|
|
|
|
|
/* So derived classes can avoid the overhead of operator[] in debug
|
|
|
|
|
builds */
|
|
|
|
|
T _data[size];
|
|
|
|
|
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
/* Implementation for constexpr operators. Not SFINAE-restricted for
|
|
|
|
|
integers or integers + floats, not marked as inline friends, no
|
|
|
|
|
std::common_type<T> workarounds for scalars as the callers do all
|
|
|
|
|
that already. Protected as they're used directly by subclasses
|
|
|
|
|
through the MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION() macro to speed
|
|
|
|
|
up debug builds. */
|
|
|
|
|
template<std::size_t ...sequence> constexpr Vector<size, T> negateInternal(Containers::Implementation::Sequence<sequence...>) const {
|
|
|
|
|
/* All these explicitly cast to T because with e.g. Vector2s it
|
|
|
|
|
would otherwise cause narrowing warnings because stupid C
|
|
|
|
|
promotion rules make e.g. `short + short` result in an int */
|
|
|
|
|
return {T(-_data[sequence])...};
|
|
|
|
|
}
|
|
|
|
|
template<std::size_t ...sequence> constexpr Vector<size, T> addInternal(const Vector<size, T>& other, Containers::Implementation::Sequence<sequence...>) const {
|
|
|
|
|
return {T(_data[sequence] + other._data[sequence])...};
|
|
|
|
|
}
|
|
|
|
|
template<std::size_t ...sequence> constexpr Vector<size, T> subtractInternal(const Vector<size, T>& other, Containers::Implementation::Sequence<sequence...>) const {
|
|
|
|
|
return {T(_data[sequence] - other._data[sequence])...};
|
|
|
|
|
}
|
|
|
|
|
template<std::size_t ...sequence> constexpr Vector<size, T> multiplyInternal(T scalar, Containers::Implementation::Sequence<sequence...>) const {
|
|
|
|
|
return {T(_data[sequence]*scalar)...};
|
|
|
|
|
}
|
|
|
|
|
template<std::size_t ...sequence, class FloatingPoint> constexpr Vector<size, T> multiplyIntegerInternal(FloatingPoint scalar, Containers::Implementation::Sequence<sequence...>) const {
|
|
|
|
|
/* This has to cast even without C promotion rules in effect, to
|
|
|
|
|
convert a floating-point result back to an integer */
|
|
|
|
|
return {T(_data[sequence]*scalar)...};
|
|
|
|
|
}
|
|
|
|
|
template<std::size_t ...sequence> constexpr Vector<size, T> divideInternal(T scalar, Containers::Implementation::Sequence<sequence...>) const {
|
|
|
|
|
return {T(_data[sequence]/scalar)...};
|
|
|
|
|
}
|
|
|
|
|
template<std::size_t ...sequence, class FloatingPoint> constexpr Vector<size, T> divideIntegerInternal(FloatingPoint scalar, Containers::Implementation::Sequence<sequence...>) const {
|
|
|
|
|
/* This has to cast even without C promotion rules in effect, to
|
|
|
|
|
convert a floating-point result back to an integer */
|
|
|
|
|
return {T(_data[sequence]/scalar)...};
|
|
|
|
|
}
|
|
|
|
|
template<std::size_t ...sequence> constexpr static Vector<size, T> divideInternal(T scalar, const Vector<size, T>& vector, Containers::Implementation::Sequence<sequence...>) {
|
|
|
|
|
return {T(scalar/vector._data[sequence])...};
|
|
|
|
|
}
|
|
|
|
|
template<std::size_t ...sequence> constexpr Vector<size, T> multiplyInternal(const Vector<size, T>& other, Containers::Implementation::Sequence<sequence...>) const {
|
|
|
|
|
return {T(_data[sequence]*other._data[sequence])...};
|
|
|
|
|
}
|
|
|
|
|
template<std::size_t ...sequence, class FloatingPoint> constexpr Vector<size, T> multiplyIntegerInternal(const Vector<size, FloatingPoint>& other, Containers::Implementation::Sequence<sequence...>) const {
|
|
|
|
|
/* This has to cast even without C promotion rules in effect, to
|
|
|
|
|
convert a floating-point result back to an integer */
|
|
|
|
|
return {T(_data[sequence]*other._data[sequence])...};
|
|
|
|
|
}
|
|
|
|
|
template<std::size_t ...sequence> constexpr Vector<size, T> divideInternal(const Vector<size, T>& other, Containers::Implementation::Sequence<sequence...>) const {
|
|
|
|
|
return {T(_data[sequence]/other._data[sequence])...};
|
|
|
|
|
}
|
|
|
|
|
template<std::size_t ...sequence, class FloatingPoint> constexpr Vector<size, T> divideIntegerInternal(const Vector<size, FloatingPoint>& other, Containers::Implementation::Sequence<sequence...>) const {
|
|
|
|
|
/* This has to cast even without C promotion rules in effect, to
|
|
|
|
|
convert a floating-point result back to an integer */
|
|
|
|
|
return {T(_data[sequence]/other._data[sequence])...};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<std::size_t ...sequence> constexpr Vector<size, T> moduloInternal(T scalar, Containers::Implementation::Sequence<sequence...>) const {
|
|
|
|
|
return {T(_data[sequence] % scalar)...};
|
|
|
|
|
}
|
|
|
|
|
template<std::size_t ...sequence> constexpr Vector<size, T> moduloInternal(const Math::Vector<size, T>& other, Containers::Implementation::Sequence<sequence...>) const {
|
|
|
|
|
return {T(_data[sequence] % other._data[sequence])...};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<std::size_t ...sequence> constexpr Vector<size, T> invertInternal(Containers::Implementation::Sequence<sequence...>) const {
|
|
|
|
|
return {T(~_data[sequence])...};
|
|
|
|
|
}
|
|
|
|
|
template<std::size_t ...sequence> constexpr Vector<size, T> andInternal(const Math::Vector<size, T>& other, Containers::Implementation::Sequence<sequence...>) const {
|
|
|
|
|
return {T(_data[sequence] & other._data[sequence])...};
|
|
|
|
|
}
|
|
|
|
|
template<std::size_t ...sequence> constexpr Vector<size, T> orInternal(const Math::Vector<size, T>& other, Containers::Implementation::Sequence<sequence...>) const {
|
|
|
|
|
return {T(_data[sequence] | other._data[sequence])...};
|
|
|
|
|
}
|
|
|
|
|
template<std::size_t ...sequence> constexpr Vector<size, T> xorInternal(const Math::Vector<size, T>& other, Containers::Implementation::Sequence<sequence...>) const {
|
|
|
|
|
return {T(_data[sequence] ^ other._data[sequence])...};
|
|
|
|
|
}
|
|
|
|
|
template<std::size_t ...sequence> constexpr Vector<size, T> shiftLeftInternal(typename std::common_type<T>::type shift, Containers::Implementation::Sequence<sequence...>) const {
|
|
|
|
|
return {T(_data[sequence] << shift)...};
|
|
|
|
|
}
|
|
|
|
|
template<std::size_t ...sequence> constexpr Vector<size, T> shiftRightInternal(typename std::common_type<T>::type shift, Containers::Implementation::Sequence<sequence...>) const {
|
|
|
|
|
return {T(_data[sequence] >> shift)...};
|
|
|
|
|
}
|
|
|
|
|
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
private:
|
|
|
|
|
#ifndef DOXYGEN_GENERATING_OUTPUT
|
|
|
|
|
/* Since I added deprecated aliases to Shaders::VectorGL, this FUCKING
|
|
|
|
|
DUMPSTER FIRE DOXYGEN CRAP thinks this refers to Shaders::Vector or
|
|
|
|
|
whatever fucking insane thing. WHAT THE FUCK. */
|
|
|
|
|
template<std::size_t, class> friend class Vector;
|
|
|
|
|
#endif
|
|
|
|
|
/* These three needed to access _data to speed up debug builds */
|
|
|
|
|
template<std::size_t, std::size_t, class> friend class RectangularMatrix;
|
|
|
|
|
template<std::size_t, class> friend class Matrix;
|
|
|
|
|
template<std::size_t, class> friend struct Implementation::MatrixDeterminant;
|
|
|
|
|
/* To make gather() / scatter() faster */
|
|
|
|
|
template<std::size_t, std::size_t> friend struct Implementation::GatherComponentAt;
|
|
|
|
|
template<std::size_t, std::size_t, bool> friend struct Implementation::ScatterComponentOr;
|
|
|
|
|
template<class T_, std::size_t valueSize, char, char...> friend constexpr T_ Implementation::scatterRecursive(const T_&, const Vector<valueSize, typename T_::Type>&, std::size_t);
|
|
|
|
|
|
|
|
|
|
/* So the out-of-class comparators can access data directly to avoid
|
|
|
|
|
function call overhead */
|
|
|
|
|
template<std::size_t size_, class T_> friend BitVector<size_> equal(const Vector<size_, T_>&, const Vector<size_, T_>&);
|
|
|
|
|
template<std::size_t size_, class T_> friend BitVector<size_> notEqual(const Vector<size_, T_>&, const Vector<size_, T_>&);
|
|
|
|
|
|
|
|
|
|
template<std::size_t size_, class U> friend U dot(const Vector<size_, U>&, const Vector<size_, U>&);
|
|
|
|
|
|
|
|
|
|
/* Implementation for Vector<size, T>::Vector(const Vector<size, U>&) */
|
|
|
|
|
template<class U, std::size_t ...sequence> constexpr explicit Vector(Containers::Implementation::Sequence<sequence...>, const Vector<size, U>& vector) noexcept: _data{T(vector._data[sequence])...} {}
|
|
|
|
|
|
|
|
|
|
/* Implementation for Vector<size, T>::Vector(U) */
|
|
|
|
|
template<std::size_t ...sequence> constexpr explicit Vector(Containers::Implementation::Sequence<sequence...>, T value) noexcept: _data{Implementation::repeat(value, sequence)...} {}
|
|
|
|
|
|
|
|
|
|
template<std::size_t otherSize, std::size_t ...sequence> constexpr static Vector<size, T> padInternal(Containers::Implementation::Sequence<sequence...>, const Vector<otherSize, T>& a, T value) {
|
|
|
|
|
return {sequence < otherSize ? a[sequence] : value...};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<std::size_t ...sequence> constexpr Vector<size, T> flippedInternal(Containers::Implementation::Sequence<sequence...>) const {
|
|
|
|
|
return {_data[size - 1 - sequence]...};
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/** @relatesalso Vector
|
|
|
|
|
@brief Component-wise equality comparison
|
|
|
|
|
@m_since{2019,10}
|
|
|
|
|
|
|
|
|
|
Unlike @ref Vector::operator==() returns a @ref BitVector instead of a single
|
|
|
|
|
value. Vector complement to @ref equal(T, T).
|
|
|
|
|
*/
|
|
|
|
|
template<std::size_t size, class T> inline BitVector<size> equal(const Vector<size, T>& a, const Vector<size, T>& b) {
|
|
|
|
|
BitVector<size> out;
|
|
|
|
|
|
|
|
|
|
for(std::size_t i = 0; i != size; ++i)
|
|
|
|
|
out.set(i, TypeTraits<T>::equals(a._data[i], b._data[i]));
|
|
|
|
|
|
|
|
|
|
return out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** @relatesalso Vector
|
|
|
|
|
@brief Component-wise non-equality comparison
|
|
|
|
|
@m_since{2019,10}
|
|
|
|
|
|
|
|
|
|
Unlike @ref Vector::operator!=() returns a @ref BitVector instead of a single
|
|
|
|
|
value. Vector complement to @ref notEqual(T, T).
|
|
|
|
|
*/
|
|
|
|
|
template<std::size_t size, class T> inline BitVector<size> notEqual(const Vector<size, T>& a, const Vector<size, T>& b) {
|
|
|
|
|
BitVector<size> out;
|
|
|
|
|
|
|
|
|
|
for(std::size_t i = 0; i != size; ++i)
|
|
|
|
|
out.set(i, !TypeTraits<T>::equals(a._data[i], b._data[i]));
|
|
|
|
|
|
|
|
|
|
return out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifndef CORRADE_SINGLES_NO_DEBUG
|
|
|
|
|
/** @debugoperator{Vector} */
|
|
|
|
|
template<std::size_t size, class T> Debug& operator<<(Debug& debug, const Vector<size, T>& value) {
|
|
|
|
|
/** @todo might make sense to propagate the flags also, for hex value
|
|
|
|
|
printing etc */
|
|
|
|
|
const bool packed = debug.immediateFlags() >= Debug::Flag::Packed;
|
|
|
|
|
debug << (packed ? "{" : "Vector(") << Debug::nospace;
|
|
|
|
|
for(std::size_t i = 0; i != size; ++i) {
|
|
|
|
|
if(i != 0) debug << Debug::nospace << ",";
|
|
|
|
|
debug << value[i];
|
|
|
|
|
}
|
|
|
|
|
return debug << Debug::nospace << (packed ? "}" : ")");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Explicit instantiation for commonly used types */
|
|
|
|
|
#ifndef DOXYGEN_GENERATING_OUTPUT
|
|
|
|
|
extern template MAGNUM_EXPORT Debug& operator<<(Debug&, const Vector<2, Float>&);
|
|
|
|
|
extern template MAGNUM_EXPORT Debug& operator<<(Debug&, const Vector<3, Float>&);
|
|
|
|
|
extern template MAGNUM_EXPORT Debug& operator<<(Debug&, const Vector<4, Float>&);
|
|
|
|
|
extern template MAGNUM_EXPORT Debug& operator<<(Debug&, const Vector<2, Int>&);
|
|
|
|
|
extern template MAGNUM_EXPORT Debug& operator<<(Debug&, const Vector<3, Int>&);
|
|
|
|
|
extern template MAGNUM_EXPORT Debug& operator<<(Debug&, const Vector<4, Int>&);
|
|
|
|
|
extern template MAGNUM_EXPORT Debug& operator<<(Debug&, const Vector<2, UnsignedInt>&);
|
|
|
|
|
extern template MAGNUM_EXPORT Debug& operator<<(Debug&, const Vector<3, UnsignedInt>&);
|
|
|
|
|
extern template MAGNUM_EXPORT Debug& operator<<(Debug&, const Vector<4, UnsignedInt>&);
|
|
|
|
|
extern template MAGNUM_EXPORT Debug& operator<<(Debug&, const Vector<2, Double>&);
|
|
|
|
|
extern template MAGNUM_EXPORT Debug& operator<<(Debug&, const Vector<3, Double>&);
|
|
|
|
|
extern template MAGNUM_EXPORT Debug& operator<<(Debug&, const Vector<4, Double>&);
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifndef DOXYGEN_GENERATING_OUTPUT
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
#define MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(size, Type_) \
|
|
|
|
|
static Type_<T>& from(T* data) { \
|
|
|
|
|
return *reinterpret_cast<Type_<T>*>(data); \
|
|
|
|
|
} \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
static const Type_<T>& from(const T* data) { \
|
|
|
|
|
return *reinterpret_cast<const Type_<T>*>(data); \
|
|
|
|
|
} \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<std::size_t otherSize> constexpr static Type_<T> pad(const Math::Vector<otherSize, T>& a, T value = T()) { \
|
|
|
|
|
return Math::Vector<size, T>::pad(a, value); \
|
|
|
|
|
} \
|
|
|
|
|
\
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
constexpr Type_<T> operator+() const { \
|
|
|
|
|
return Math::Vector<size, T>::operator+(); \
|
|
|
|
|
} \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class U = T> constexpr typename std::enable_if<std::is_signed<U>::value, Type_<T>>::type \
|
|
|
|
|
operator-() const { \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
return Math::Vector<size, T>::negateInternal(typename Containers::Implementation::GenerateSequence<size>::Type{}); \
|
|
|
|
|
} \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
Type_<T>& operator+=(const Math::Vector<size, T>& other) { \
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
Math::Vector<size, T>::operator+=(other); \
|
|
|
|
|
return *this; \
|
|
|
|
|
} \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
constexpr Type_<T> operator+(const Math::Vector<size, T>& other) const { \
|
|
|
|
|
return Math::Vector<size, T>::addInternal(other, typename Containers::Implementation::GenerateSequence<size>::Type{}); \
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
} \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
Type_<T>& operator-=(const Math::Vector<size, T>& other) { \
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
Math::Vector<size, T>::operator-=(other); \
|
|
|
|
|
return *this; \
|
|
|
|
|
} \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
constexpr Type_<T> operator-(const Math::Vector<size, T>& other) const { \
|
|
|
|
|
return Math::Vector<size, T>::subtractInternal(other, typename Containers::Implementation::GenerateSequence<size>::Type{}); \
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
} \
|
|
|
|
|
\
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
Type_<T>& operator*=(T scalar) { \
|
|
|
|
|
Math::Vector<size, T>::operator*=(scalar); \
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
return *this; \
|
|
|
|
|
} \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
constexpr Type_<T> operator*(T scalar) const { \
|
|
|
|
|
return Math::Vector<size, T>::multiplyInternal(scalar, typename Containers::Implementation::GenerateSequence<size>::Type{}); \
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
} \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
friend constexpr Type_<T> operator*(typename std::common_type<T>::type scalar, const Type_<T>& vector) { \
|
|
|
|
|
return scalar*static_cast<const Math::Vector<size, T>&>(vector); \
|
|
|
|
|
} \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class FloatingPoint, class Integral = T> typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Type_<T>&>::type operator*=(FloatingPoint scalar) { \
|
|
|
|
|
Math::Vector<size, T>::operator*=(scalar); \
|
|
|
|
|
return *this; \
|
|
|
|
|
} \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class FloatingPoint, class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Type_<T>>::type operator*(FloatingPoint scalar) const { \
|
|
|
|
|
return Math::Vector<size, T>::multiplyIntegerInternal(scalar, typename Containers::Implementation::GenerateSequence<size>::Type{}); \
|
|
|
|
|
} \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class FloatingPoint, class Integral = T> friend constexpr typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Type_<T>>::type operator*(FloatingPoint scalar, const Type_<T>& vector) { \
|
|
|
|
|
return scalar*static_cast<const Math::Vector<size, T>&>(vector); \
|
|
|
|
|
} \
|
|
|
|
|
\
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
Type_<T>& operator/=(T scalar) { \
|
|
|
|
|
Math::Vector<size, T>::operator/=(scalar); \
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
return *this; \
|
|
|
|
|
} \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
constexpr Type_<T> operator/(T scalar) const { \
|
|
|
|
|
return Math::Vector<size, T>::divideInternal(scalar, typename Containers::Implementation::GenerateSequence<size>::Type{}); \
|
|
|
|
|
} \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
friend constexpr Type_<T> operator/(typename std::common_type<T>::type scalar, const Type_<T>& vector) { \
|
|
|
|
|
return scalar/static_cast<const Math::Vector<size, T>&>(vector); \
|
|
|
|
|
} \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class FloatingPoint, class Integral = T> typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Type_<T>&>::type operator/=(FloatingPoint scalar) { \
|
|
|
|
|
Math::Vector<size, T>::operator/=(scalar); \
|
|
|
|
|
return *this; \
|
|
|
|
|
} \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class FloatingPoint, class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Type_<T>>::type operator/(FloatingPoint scalar) const { \
|
|
|
|
|
return Math::Vector<size, T>::divideIntegerInternal(scalar, typename Containers::Implementation::GenerateSequence<size>::Type{}); \
|
|
|
|
|
} \
|
|
|
|
|
\
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
Type_<T>& operator*=(const Math::Vector<size, T>& other) { \
|
|
|
|
|
Math::Vector<size, T>::operator*=(other); \
|
|
|
|
|
return *this; \
|
|
|
|
|
} \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
constexpr Type_<T> operator*(const Math::Vector<size, T>& other) const { \
|
|
|
|
|
return Math::Vector<size, T>::multiplyInternal(other, typename Containers::Implementation::GenerateSequence<size>::Type{}); \
|
|
|
|
|
} \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class FloatingPoint, class Integral = T> typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Type_<T>&>::type operator*=(const Math::Vector<size, FloatingPoint>& other) { \
|
|
|
|
|
Math::Vector<size, T>::operator*=(other); \
|
|
|
|
|
return *this; \
|
|
|
|
|
} \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class FloatingPoint, class Integral = T, typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value>::type* = nullptr> constexpr Type_<T> operator*(const Math::Vector<size, FloatingPoint>& other) const { \
|
|
|
|
|
return Math::Vector<size, T>::multiplyIntegerInternal(other, typename Containers::Implementation::GenerateSequence<size>::Type{}); \
|
|
|
|
|
} \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class Integral, class FloatingPoint = T, typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value>::type* = nullptr> constexpr Type_<Integral> operator*(const Math::Vector<size, Integral>& other) const { \
|
|
|
|
|
return other**this; \
|
|
|
|
|
} \
|
|
|
|
|
\
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
Type_<T>& operator/=(const Math::Vector<size, T>& other) { \
|
|
|
|
|
Math::Vector<size, T>::operator/=(other); \
|
|
|
|
|
return *this; \
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
} \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
constexpr Type_<T> operator/(const Math::Vector<size, T>& other) const { \
|
|
|
|
|
return Math::Vector<size, T>::divideInternal(other, typename Containers::Implementation::GenerateSequence<size>::Type{}); \
|
|
|
|
|
} \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class FloatingPoint, class Integral = T> typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Type_<T>&>::type operator/=(const Math::Vector<size, FloatingPoint>& other) { \
|
|
|
|
|
Math::Vector<size, T>::operator/=(other); \
|
|
|
|
|
return *this; \
|
|
|
|
|
} \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class FloatingPoint, class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Type_<T>>::type operator/(const Math::Vector<size, FloatingPoint>& other) const { \
|
|
|
|
|
return Math::Vector<size, T>::divideIntegerInternal(other, typename Containers::Implementation::GenerateSequence<size>::Type{}); \
|
|
|
|
|
} \
|
|
|
|
|
\
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class Integral = T> typename std::enable_if<std::is_integral<Integral>::value, Type_<T>&>::type operator%=(T scalar) { \
|
|
|
|
|
Math::Vector<size, T>::operator%=(scalar); \
|
|
|
|
|
return *this; \
|
|
|
|
|
} \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value, Type_<T>>::type operator%(T scalar) const { \
|
|
|
|
|
return Math::Vector<size, T>::moduloInternal(scalar, typename Containers::Implementation::GenerateSequence<size>::Type{}); \
|
|
|
|
|
} \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class Integral = T> typename std::enable_if<std::is_integral<Integral>::value, Type_<T>&>::type operator%=(const Math::Vector<size, T>& other) { \
|
|
|
|
|
Math::Vector<size, T>::operator%=(other); \
|
|
|
|
|
return *this; \
|
|
|
|
|
} \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value, Type_<T>>::type operator%(const Math::Vector<size, T>& other) const { \
|
|
|
|
|
return Math::Vector<size, T>::moduloInternal(other, typename Containers::Implementation::GenerateSequence<size>::Type{}); \
|
|
|
|
|
} \
|
|
|
|
|
\
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value, Type_<T>>::type operator~() const { \
|
|
|
|
|
return Math::Vector<size, T>::invertInternal(typename Containers::Implementation::GenerateSequence<size>::Type{}); \
|
|
|
|
|
} \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class Integral = T> typename std::enable_if<std::is_integral<Integral>::value, Type_<T>&>::type operator&=(const Math::Vector<size, T>& other) { \
|
|
|
|
|
Math::Vector<size, T>::operator&=(other); \
|
|
|
|
|
return *this; \
|
|
|
|
|
} \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value, Type_<T>>::type operator&(const Math::Vector<size, T>& other) const { \
|
|
|
|
|
return Math::Vector<size, T>::andInternal(other, typename Containers::Implementation::GenerateSequence<size>::Type{}); \
|
|
|
|
|
} \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class Integral = T> typename std::enable_if<std::is_integral<Integral>::value, Type_<T>&>::type operator|=(const Math::Vector<size, T>& other) { \
|
|
|
|
|
Math::Vector<size, T>::operator|=(other); \
|
|
|
|
|
return *this; \
|
|
|
|
|
} \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value, Type_<T>>::type operator|(const Math::Vector<size, T>& other) const { \
|
|
|
|
|
return Math::Vector<size, T>::orInternal(other, typename Containers::Implementation::GenerateSequence<size>::Type{}); \
|
|
|
|
|
} \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class Integral = T> typename std::enable_if<std::is_integral<Integral>::value, Type_<T>&>::type operator^=(const Math::Vector<size, T>& other) { \
|
|
|
|
|
Math::Vector<size, T>::operator^=(other); \
|
|
|
|
|
return *this; \
|
|
|
|
|
} \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value, Type_<T>>::type operator^(const Math::Vector<size, T>& other) const { \
|
|
|
|
|
return Math::Vector<size, T>::xorInternal(other, typename Containers::Implementation::GenerateSequence<size>::Type{}); \
|
|
|
|
|
} \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class Integral = T> typename std::enable_if<std::is_integral<Integral>::value, Type_<T>&>::type operator<<=(typename std::common_type<T>::type shift) { \
|
|
|
|
|
Math::Vector<size, T>::operator<<=(shift); \
|
|
|
|
|
return *this; \
|
|
|
|
|
} \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value, Type_<T>>::type operator<<(typename std::common_type<T>::type shift) const { \
|
|
|
|
|
return Math::Vector<size, T>::shiftLeftInternal(shift, typename Containers::Implementation::GenerateSequence<size>::Type{}); \
|
|
|
|
|
} \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class Integral = T> typename std::enable_if<std::is_integral<Integral>::value, Type_<T>&>::type operator>>=(typename std::common_type<T>::type shift) { \
|
|
|
|
|
Math::Vector<size, T>::operator>>=(shift); \
|
|
|
|
|
return *this; \
|
|
|
|
|
} \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value, Type_<T>>::type operator>>(typename std::common_type<T>::type shift) const { \
|
|
|
|
|
return Math::Vector<size, T>::shiftRightInternal(shift, typename Containers::Implementation::GenerateSequence<size>::Type{}); \
|
|
|
|
|
} \
|
|
|
|
|
\
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class U = T> typename std::enable_if<std::is_floating_point<U>::value, Type_<T>>::type normalized() const { \
|
|
|
|
|
return Math::Vector<size, T>::normalized(); \
|
|
|
|
|
} \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class U = T> typename std::enable_if<std::is_floating_point<U>::value, Type_<T>>::type resized(T length) const { \
|
|
|
|
|
return Math::Vector<size, T>::resized(length); \
|
|
|
|
|
} \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class U = T> typename std::enable_if<std::is_floating_point<U>::value, Type_<T>>::type projected(const Math::Vector<size, T>& other) const { \
|
|
|
|
|
return Math::Vector<size, T>::projected(other); \
|
|
|
|
|
} \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class U = T> typename std::enable_if<std::is_floating_point<U>::value, Type_<T>>::type projectedOntoNormalized(const Math::Vector<size, T>& other) const { \
|
|
|
|
|
return Math::Vector<size, T>::projectedOntoNormalized(other); \
|
|
|
|
|
} \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
constexpr Type_<T> flipped() const { \
|
|
|
|
|
return Math::Vector<size, T>::flipped(); \
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef CORRADE_MSVC2015_COMPATIBILITY
|
|
|
|
|
/* MSVC 2015 doesn't correctly pick up the in-class inline friend that does
|
|
|
|
|
this, resulting in float*VectorNi expressions being wrongly executed as
|
|
|
|
|
int*VectorNi due to an implicit conversion fallback. This overload is picked
|
|
|
|
|
up correctly (and doesn't conflict with the in-class one), subclasses then
|
|
|
|
|
need to use the MAGNUM_VECTORn_OPERATOR_IMPLEMENTATION() overloads as well
|
|
|
|
|
to return a correct subtype. See VectorTest::multiplyDivideIntegral(),
|
|
|
|
|
VectorTest::subclass() and corresponding cases in Vector2Test, Vector3Test,
|
|
|
|
|
Vector4Test and ColorTest for regression tests. */
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<std::size_t size, class FloatingPoint, class Integral> constexpr typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Vector<size, Integral>>::type operator*(FloatingPoint scalar, const Vector<size, Integral>& vector) {
|
|
|
|
|
return vector*scalar;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define MAGNUM_VECTORn_OPERATOR_IMPLEMENTATION(size, Type) \
|
Math: make const Vector operators constexpr.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
2 years ago
|
|
|
template<class FloatingPoint, class Integral> constexpr typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Type<Integral>>::type operator*(FloatingPoint scalar, const Type<Integral>& vector) { \
|
|
|
|
|
return vector*scalar; \
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
template<std::size_t size, class T> inline BitVector<size> Vector<size, T>::operator<(const Vector<size, T>& other) const {
|
|
|
|
|
BitVector<size> out;
|
|
|
|
|
|
|
|
|
|
for(std::size_t i = 0; i != size; ++i)
|
|
|
|
|
out.set(i, _data[i] < other._data[i]);
|
|
|
|
|
|
|
|
|
|
return out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<std::size_t size, class T> inline BitVector<size> Vector<size, T>::operator<=(const Vector<size, T>& other) const {
|
|
|
|
|
BitVector<size> out;
|
|
|
|
|
|
|
|
|
|
for(std::size_t i = 0; i != size; ++i)
|
|
|
|
|
out.set(i, _data[i] <= other._data[i]);
|
|
|
|
|
|
|
|
|
|
return out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<std::size_t size, class T> inline BitVector<size> Vector<size, T>::operator>=(const Vector<size, T>& other) const {
|
|
|
|
|
BitVector<size> out;
|
|
|
|
|
|
|
|
|
|
for(std::size_t i = 0; i != size; ++i)
|
|
|
|
|
out.set(i, _data[i] >= other._data[i]);
|
|
|
|
|
|
|
|
|
|
return out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<std::size_t size, class T> inline BitVector<size> Vector<size, T>::operator>(const Vector<size, T>& other) const {
|
|
|
|
|
BitVector<size> out;
|
|
|
|
|
|
|
|
|
|
for(std::size_t i = 0; i != size; ++i)
|
|
|
|
|
out.set(i, _data[i] > other._data[i]);
|
|
|
|
|
|
|
|
|
|
return out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<std::size_t size, class T>
|
|
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT
|
|
|
|
|
inline Vector<size, T>
|
|
|
|
|
#else
|
|
|
|
|
template<class U> inline typename std::enable_if<std::is_floating_point<U>::value, Vector<size, T>>::type
|
|
|
|
|
#endif
|
|
|
|
|
Vector<size, T>::projectedOntoNormalized(const Vector<size, T>& line) const {
|
|
|
|
|
CORRADE_DEBUG_ASSERT(line.isNormalized(),
|
|
|
|
|
"Math::Vector::projectedOntoNormalized(): line" << line << "is not normalized", {});
|
Math: made dot(), angle(), *lerp() and cross() free functions.
It is often annoying to write e.g. this, especially in generic code:
T dot = Math::Vector<size, T>::dot(a, b);
When this is more than enough and the compiler can infer the rest from
the context:
T dot = Math::dot(a, b);
There are more downsides and confusing cases (you can call
Math::Vector<3, T>::dot(), Math::Vector3<T>::dot() and Color3::dot() and
it is still the same function), so I made these as free functions in
Math namespace. You can now also abuse ADL for the calls, but I would
advise against that for better readability:
T d = dot(a, b); // dot?! what on earth is dot? and what is a?
The only downside found when porting is that you need to specify the
type somehow when having both parameters as initializer lists:
T d = dot({2.0f, -1.5f}, {1.0f, 2.5f}); // error
T d = dot(Complex{2.0f, -1.5f}, {1.0f, 2.5f}); // okay
But that's probably reasonable (and it's also highly corner case,
the functions were used this way only in tests).
The original static member functions are of course still present, but
marked as deprecated and will be removed at some point in future.
11 years ago
|
|
|
return line*Math::dot(*this, line);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<std::size_t size, class T> inline T Vector<size, T>::sum() const {
|
|
|
|
|
T out(_data[0]);
|
|
|
|
|
|
|
|
|
|
for(std::size_t i = 1; i != size; ++i)
|
|
|
|
|
out += _data[i];
|
|
|
|
|
|
|
|
|
|
return out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<std::size_t size, class T> inline T Vector<size, T>::product() const {
|
|
|
|
|
T out(_data[0]);
|
|
|
|
|
|
|
|
|
|
for(std::size_t i = 1; i != size; ++i)
|
|
|
|
|
out *= _data[i];
|
|
|
|
|
|
|
|
|
|
return out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
namespace Implementation {
|
|
|
|
|
/* Non-floating-point types, the first is a non-NaN for sure */
|
|
|
|
|
template<std::size_t size, class T> constexpr std::size_t firstNonNan(const T(&)[size], std::false_type) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
/* Floating-point types, return the first that's not NaN */
|
|
|
|
|
template<std::size_t size, class T> inline std::size_t firstNonNan(const T(&data)[size], std::true_type) {
|
|
|
|
|
/* Find the first non-NaN value to compare against. If all are NaN,
|
|
|
|
|
return the last value so the following loop in min/max/minmax()
|
|
|
|
|
doesn't even execute. */
|
|
|
|
|
for(std::size_t i = 0; i != size; ++i)
|
|
|
|
|
if(!isNan(data[i])) return i;
|
|
|
|
|
return size - 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<std::size_t size, class T> inline T Vector<size, T>::min() const {
|
|
|
|
|
std::size_t i = Implementation::firstNonNan(_data, IsFloatingPoint<T>{});
|
|
|
|
|
T out(_data[i]);
|
|
|
|
|
|
|
|
|
|
for(++i; i != size; ++i)
|
|
|
|
|
out = Math::min(out, _data[i]);
|
|
|
|
|
|
|
|
|
|
return out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<std::size_t size, class T> inline T Vector<size, T>::max() const {
|
|
|
|
|
std::size_t i = Implementation::firstNonNan(_data, IsFloatingPoint<T>{});
|
|
|
|
|
T out(_data[i]);
|
|
|
|
|
|
|
|
|
|
for(++i; i != size; ++i)
|
|
|
|
|
out = Math::max(out, _data[i]);
|
|
|
|
|
|
|
|
|
|
return out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<std::size_t size, class T> inline Containers::Pair<T, T> Vector<size, T>::minmax() const {
|
|
|
|
|
std::size_t i = Implementation::firstNonNan(_data, IsFloatingPoint<T>{});
|
|
|
|
|
T min{_data[i]}, max{_data[i]};
|
|
|
|
|
|
|
|
|
|
for(++i; i != size; ++i) {
|
|
|
|
|
if(_data[i] < min)
|
|
|
|
|
min = _data[i];
|
|
|
|
|
else if(_data[i] > max)
|
|
|
|
|
max = _data[i];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {min, max};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifndef MAGNUM_NO_MATH_STRICT_WEAK_ORDERING
|
|
|
|
|
namespace Implementation {
|
|
|
|
|
|
|
|
|
|
template<std::size_t size, class T> struct StrictWeakOrdering<Vector<size, T>> {
|
|
|
|
|
bool operator()(const Vector<size, T>& a, const Vector<size, T>& b) const {
|
|
|
|
|
for(std::size_t i = 0; i < size; ++i) {
|
|
|
|
|
if(a[i] < b[i])
|
|
|
|
|
return true;
|
|
|
|
|
if(a[i] > b[i])
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false; /* a and b are equivalent */
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
}}
|
|
|
|
|
|
|
|
|
|
#endif
|