Browse Source

Math: rename BoolVector to BitVector.

Because it somewhat confusingly may have implied that it's really
composed of 8-bit bools, and not bits. The same reasoning was used to
pick the name for Corrade's Containers::BitArray.

Backwards compatibility aliases are in place as usual, however the
internal BoolVectorConverter is now BitVectorConverter and there
unfortunately cannot be any backwards compatibility. This breaks only
GLM and Eigen integration in the magnum-integration repo, which I'm
fixing immediately. I don't expect any user code to use this internal
helper. For regular vectors maybe, for this one definitely not.
pull/578/head
Vladimír Vondruš 4 years ago
parent
commit
5312a016f4
  1. 6
      doc/changelog-old.dox
  2. 18
      doc/changelog.dox
  3. 2
      doc/matrix-vector.dox
  4. 18
      doc/snippets/MagnumMath-cpp14.cpp
  5. 6
      doc/snippets/MagnumMath.cpp
  6. 2
      doc/transformations.dox
  7. 2
      doc/types.dox
  8. 4
      src/Magnum/Animation/Interpolation.h
  9. 24
      src/Magnum/Animation/Test/InterpolationTest.cpp
  10. 6
      src/Magnum/Audio/Context.h
  11. 4
      src/Magnum/GL/Context.h
  12. 4
      src/Magnum/GL/Implementation/TextureState.h
  13. 38
      src/Magnum/Magnum.h
  14. 421
      src/Magnum/Math/BitVector.h
  15. 388
      src/Magnum/Math/BoolVector.h
  16. 6
      src/Magnum/Math/CMakeLists.txt
  17. 22
      src/Magnum/Math/Functions.h
  18. 14
      src/Magnum/Math/FunctionsBatch.h
  19. 9
      src/Magnum/Math/Math.h
  20. 8
      src/Magnum/Math/RectangularMatrix.h
  21. 379
      src/Magnum/Math/Test/BitVectorTest.cpp
  22. 379
      src/Magnum/Math/Test/BoolVectorTest.cpp
  23. 2
      src/Magnum/Math/Test/CMakeLists.txt
  24. 24
      src/Magnum/Math/Test/FunctionsBatchTest.cpp
  25. 18
      src/Magnum/Math/Test/FunctionsTest.cpp
  26. 2
      src/Magnum/Math/Test/IntersectionBenchmark.cpp
  27. 10
      src/Magnum/Math/Test/RectangularMatrixTest.cpp
  28. 22
      src/Magnum/Math/Test/VectorTest.cpp
  29. 2
      src/Magnum/Math/TypeTraits.h
  30. 42
      src/Magnum/Math/Vector.h
  31. 2
      src/Magnum/MeshTools/Compile.cpp
  32. 12
      src/Magnum/Trade/AnimationData.cpp
  33. 54
      src/Magnum/Trade/AnimationData.h
  34. 2
      src/Magnum/Trade/SceneData.cpp
  35. 4
      src/Magnum/Vk/Device.cpp
  36. 4
      src/Magnum/Vk/Device.h
  37. 4
      src/Magnum/Vk/Instance.h
  38. 6
      src/singles/MagnumMath.hpp

6
doc/changelog-old.dox

@ -720,7 +720,7 @@ a high-level overview.
@ref Math::Quaternion from a different underlying type @ref Math::Quaternion from a different underlying type
- Added @ref Math::ZeroInit, @ref Math::NoInit, @ref Math::IdentityInit tags - Added @ref Math::ZeroInit, @ref Math::NoInit, @ref Math::IdentityInit tags
to control initialization of all math classes to control initialization of all math classes
- Added @ref Math::lerp(const Vector<size, T>&, const Vector<size, T>&, const BoolVector<size>&) - Added @cpp Math::lerp(const Vector<size, T>&, const Vector<size, T>&, const BoolVector<size>&) @ce
- Added @ref Math::Vector::flipped(), @ref Math::RectangularMatrix::flippedCols(), - Added @ref Math::Vector::flipped(), @ref Math::RectangularMatrix::flippedCols(),
@ref Math::RectangularMatrix::flippedRows() @ref Math::RectangularMatrix::flippedRows()
- Added @ref Math::TypeTraits::name() and @ref Math::TypeTraits::equalsZero() - Added @ref Math::TypeTraits::name() and @ref Math::TypeTraits::equalsZero()
@ -730,7 +730,7 @@ a high-level overview.
- Ability to construct @ref Math::DualQuaternion from dual vector and scalar - Ability to construct @ref Math::DualQuaternion from dual vector and scalar
- Ability to save and restore @ref Deg and @ref Rad from - Ability to save and restore @ref Deg and @ref Rad from
@ref Corrade::Utility::Configuration @ref Corrade::Utility::Configuration
- Explicit bool conversion for @ref Math::BoolVector (see - Explicit bool conversion for @cpp Math::BoolVector @ce (see
[mosra/magnum#182](https://github.com/mosra/magnum/issues/182)) [mosra/magnum#182](https://github.com/mosra/magnum/issues/182))
- Component-wise comparison for @ref Math::RectangularMatrix - Component-wise comparison for @ref Math::RectangularMatrix
- Ability to construct @ref Math::RectangularMatrix and derived classes - Ability to construct @ref Math::RectangularMatrix and derived classes
@ -1028,7 +1028,7 @@ a high-level overview.
@ref Math::RectangularMatrix from @ref Corrade::Utility::Configuration @ref Math::RectangularMatrix from @ref Corrade::Utility::Configuration
- Fixed unfortunate interaction of VAOs and index buffers on platforms - Fixed unfortunate interaction of VAOs and index buffers on platforms
without direct state access without direct state access
- Fixed resetting a bit in @ref Math::BoolVector::set() (see - Fixed resetting a bit in @cpp Math::BoolVector::set() @ce (see
[mosra/magnum#208](https://github.com/mosra/magnum/issues/208), [mosra/magnum#208](https://github.com/mosra/magnum/issues/208),
[mosra/magnum# [mosra/magnum#
- @ref Audio::Context::hrtfSpecifierString() was crashing on systems - @ref Audio::Context::hrtfSpecifierString() was crashing on systems

18
doc/changelog.dox

@ -411,7 +411,7 @@ See also:
matrices, and with the default on @ref Math::RectangularMatrix being matrices, and with the default on @ref Math::RectangularMatrix being
zero-fill while @ref Math::Matrix stays with the identity for consistency zero-fill while @ref Math::Matrix stays with the identity for consistency
with other constructors. with other constructors.
- @ref Math::Bezier::data(), @ref Math::BoolVector::data(), - @ref Math::Bezier::data(), @ref Math::BitVector::data(),
@ref Math::Complex::data(), @ref Math::CubicHermite::data(), @ref Math::Complex::data(), @ref Math::CubicHermite::data(),
@ref Math::Dual::data(), @ref Math::DualComplex::data(), @ref Math::Dual::data(), @ref Math::DualComplex::data(),
@ref Math::DualQuaternion::data(), @ref Math::Frustum::data(), @ref Math::DualQuaternion::data(), @ref Math::Frustum::data(),
@ -769,6 +769,12 @@ See also:
custom uses, the @relativeref{Corrade,Containers::Array1}, @relativeref{Corrade,Containers::Array2} or custom uses, the @relativeref{Corrade,Containers::Array1}, @relativeref{Corrade,Containers::Array2} or
@relativeref{Corrade,Containers::Array3} types provide a suitable @relativeref{Corrade,Containers::Array3} types provide a suitable
alternative as well. alternative as well.
- The @cpp Math::BoolVector @ce class and the @cpp BoolVector2 @ce,
@cpp BoolVector3 @ce and @cpp BoolVector4 @ce typedefs are deprecated in
favor of @ref Math::BitVector, @relativeref{Magnum,BitVector2},
@relativeref{Magnum,BitVector3} and @relativeref{Magnum,BitVector4} to not
imply storing the 8-bit @cpp bool @ce type and for consistency with the new
@relativeref{Corrade,Containers::BitArray} types
- Markup styling for Emscripten application was switched to prefer using - Markup styling for Emscripten application was switched to prefer using
CSS classes instead of the @cb{.css} #container @ce, @cb{.css} #sizer @ce, CSS classes instead of the @cb{.css} #container @ce, @cb{.css} #sizer @ce,
@cb{.css} #expander @ce, @cb{.css} #listener @ce, @cb{.css} #canvas @ce, @cb{.css} #expander @ce, @cb{.css} #listener @ce, @cb{.css} #canvas @ce,
@ -2126,8 +2132,8 @@ Released 2019-10-24, tagged as
- @ref Color3ub and @ref Color4ub can be printed with - @ref Color3ub and @ref Color4ub can be printed with
@ref Corrade::Utility::Debug as actual colors using the @ref Corrade::Utility::Debug as actual colors using the
@ref Corrade::Utility::Debug::color modifier @ref Corrade::Utility::Debug::color modifier
- Added convenience @ref BoolVector2, @ref BoolVector3 and @ref BoolVector4 - Added convenience @cpp BoolVector2 @ce, @cpp BoolVector3 @ce and
typedefs to the root namespace @cpp BoolVector4 @ce typedefs to the root namespace
- New @ref Math::IsScalar, @ref Math::IsVector, @ref Math::IsIntegral, - New @ref Math::IsScalar, @ref Math::IsVector, @ref Math::IsIntegral,
@ref Math::IsFloatingPoint and @ref Math::IsUnitless type traits and a @ref Math::IsFloatingPoint and @ref Math::IsUnitless type traits and a
@ref Math::UnderlyingTypeOf utility @ref Math::UnderlyingTypeOf utility
@ -2314,7 +2320,7 @@ Released 2019-10-24, tagged as
@subsubsection changelog-2019-10-changes-math Math library @subsubsection changelog-2019-10-changes-math Math library
- @ref Math::BoolVector now implements component-wise @cpp && @ce, - @cpp Math::BoolVector @ce now implements component-wise @cpp && @ce,
@cpp || @ce and @cpp ! @ce for better consistency with boolean operations @cpp || @ce and @cpp ! @ce for better consistency with boolean operations
done on scalar types done on scalar types
- Construction using @ref Math::ZeroInit and @ref Math::IdentityInit is - Construction using @ref Math::ZeroInit and @ref Math::IdentityInit is
@ -2336,7 +2342,7 @@ Released 2019-10-24, tagged as
@ref Math::isNan(const Vector<size, T>&) or the batch @ref Math::isNan(const Vector<size, T>&) or the batch
@ref Math::isNan(const Containers::StridedArrayView1D<const T>&) to detect @ref Math::isNan(const Containers::StridedArrayView1D<const T>&) to detect
presence of NaN values if needed. presence of NaN values if needed.
- Changed the way @ref Math::operator<<(Corrade::Utility::Debug&, const BoolVector<size>&) - Changed the way @cpp Math::operator<<(Corrade::Utility::Debug&, const BoolVector<size>&) @ce
works --- the output now has the same bit order as when constructing it works --- the output now has the same bit order as when constructing it
using binary literals using binary literals
- @ref Math::sincos() now uses the `__builtin_sincos` intrinsic on GCC, - @ref Math::sincos() now uses the `__builtin_sincos` intrinsic on GCC,
@ -3056,7 +3062,7 @@ Released 2018-10-23, tagged as
- Added a convenience function @ref Math::planeEquation() to aid with passing - Added a convenience function @ref Math::planeEquation() to aid with passing
passing parameters to @ref Math::Intersection::planeLine(), passing parameters to @ref Math::Intersection::planeLine(),
@ref Math::Distance::pointPlane() and others @ref Math::Distance::pointPlane() and others
- Ability to convert @ref Math::BoolVector from and to external - Ability to convert @cpp Math::BoolVector @ce from and to external
representation representation
- Ability to construct @ref Math::Matrix from a smaller or larger square - Ability to construct @ref Math::Matrix from a smaller or larger square
matrix by slicing or expanding it matrix by slicing or expanding it

2
doc/matrix-vector.dox

@ -229,7 +229,7 @@ Component-wise minimum and maximum of two vectors can be done using
@snippet MagnumMath.cpp matrix-vector-operations-minmax @snippet MagnumMath.cpp matrix-vector-operations-minmax
The vectors can be also compared component-wise, the result is returned in a The vectors can be also compared component-wise, the result is returned in a
@ref Math::BoolVector class: @ref Math::BitVector class:
@snippet MagnumMath.cpp matrix-vector-operations-compare @snippet MagnumMath.cpp matrix-vector-operations-compare

18
doc/snippets/MagnumMath-cpp14.cpp

@ -23,29 +23,29 @@
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
*/ */
#include "Magnum/Math/BoolVector.h" #include "Magnum/Math/BitVector.h"
#include "Magnum/Magnum.h" #include "Magnum/Magnum.h"
using namespace Magnum; using namespace Magnum;
int main() { int main() {
{ {
/* [BoolVector-indexing] */ /* [BitVector-indexing] */
BoolVector4 a{0b0010}; BitVector4 a{0b0010};
Debug{} << a[1]; // true Debug{} << a[1]; // true
Math::BoolVector<19> b{0b00001000, 0b00000011, 0b100}; Math::BitVector<19> b{0b00001000, 0b00000011, 0b100};
Debug{} << b[3]; // true Debug{} << b[3]; // true
Debug{} << b[8]; // true Debug{} << b[8]; // true
Debug{} << b[9]; // true Debug{} << b[9]; // true
Debug{} << b[18]; // true Debug{} << b[18]; // true
/* [BoolVector-indexing] */ /* [BitVector-indexing] */
} }
{ {
/* [BoolVector-debug] */ /* [BitVector-debug] */
Debug{} << BoolVector4{0b1010} Debug{} << BitVector4{0b1010}
<< Math::BoolVector<19>{0b00001000, 0b00000011, 0b100}; << Math::BitVector<19>{0b00001000, 0b00000011, 0b100};
/* [BoolVector-debug] */ /* [BitVector-debug] */
} }
} }

6
doc/snippets/MagnumMath.cpp

@ -304,7 +304,7 @@ static_cast<void>(min);
static_cast<void>(max); static_cast<void>(max);
/* [matrix-vector-operations-compare] */ /* [matrix-vector-operations-compare] */
BoolVector3 largerOrEqual = a >= b; // {false, true, true} BitVector3 largerOrEqual = a >= b; // {false, true, true}
bool anySmaller = (a < b).any(); // true bool anySmaller = (a < b).any(); // true
bool allLarger = (a > b).all(); // false bool allLarger = (a > b).all(); // false
/* [matrix-vector-operations-compare] */ /* [matrix-vector-operations-compare] */
@ -747,13 +747,13 @@ static_cast<void>(tan2);
{ {
Vector3 epsilon; Vector3 epsilon;
/* [BoolVector-boolean] */ /* [BitVector-boolean] */
Vector3 a, b; Vector3 a, b;
if(!(b < a - epsilon || a + epsilon < b)) { if(!(b < a - epsilon || a + epsilon < b)) {
// b is around a // b is around a
} }
/* [BoolVector-boolean] */ /* [BitVector-boolean] */
} }
{ {

2
doc/transformations.dox

@ -256,7 +256,7 @@ Interpolation | Value type | Result type | Interpolator
Constant | any `V` | `V` | @ref Math::select() Constant | any `V` | `V` | @ref Math::select()
Constant | @ref Math::CubicHermite "Math::CubicHermite<T>" | `T` | @ref Math::select(const CubicHermite<T>&, const CubicHermite<T>&, U) "Math::select()" Constant | @ref Math::CubicHermite "Math::CubicHermite<T>" | `T` | @ref Math::select(const CubicHermite<T>&, const CubicHermite<T>&, U) "Math::select()"
Linear | @cpp bool @ce <b></b> | @cpp bool @ce <b></b> | @ref Math::select() Linear | @cpp bool @ce <b></b> | @cpp bool @ce <b></b> | @ref Math::select()
Linear | @ref Math::BoolVector | @ref Math::BoolVector | @ref Math::select() Linear | @ref Math::BitVector | @ref Math::BitVector | @ref Math::select()
Linear | any scalar `V` | `V` | @ref Math::lerp() Linear | any scalar `V` | `V` | @ref Math::lerp()
Linear | any vector `V` | `V` | @ref Math::lerp() Linear | any vector `V` | `V` | @ref Math::lerp()
Linear | @ref Math::Complex | @ref Math::Complex | @ref Math::lerp(const Complex<T>&, const Complex<T>&, T) "Math::lerp()" Linear | @ref Math::Complex | @ref Math::Complex | @ref Math::lerp(const Complex<T>&, const Complex<T>&, T) "Math::lerp()"

2
doc/types.dox

@ -73,7 +73,7 @@ after type name means @ref Float underlying type, `h` means @ref Half, `d` is
| Magnum vector type | Equivalent GLSL type | | Magnum vector type | Equivalent GLSL type |
| ---------------------------------------------- | ------------------------- | | ---------------------------------------------- | ------------------------- |
| @ref BoolVector2, @ref BoolVector3, @ref BoolVector4 | @glsl bvec2 @ce, @glsl bvec3 @ce, @glsl bvec4 @ce | | @ref BitVector2, @ref BitVector3, @ref BitVector4 | @glsl bvec2 @ce, @glsl bvec3 @ce, @glsl bvec4 @ce |
| @ref Vector2, @ref Vector3, @ref Color3, @ref Vector4, @ref Color4 | @glsl vec2 @ce, @glsl vec3 @ce, @glsl vec4 @ce | | @ref Vector2, @ref Vector3, @ref Color3, @ref Vector4, @ref Color4 | @glsl vec2 @ce, @glsl vec3 @ce, @glsl vec4 @ce |
| @ref Vector2h, @ref Vector3h, @ref Color3h, @ref Vector4h, @ref Color4h | (*none*) | | @ref Vector2h, @ref Vector3h, @ref Color3h, @ref Vector4h, @ref Color4h | (*none*) |
| @ref Vector2d, @ref Vector3d, @ref Vector4d | @glsl dvec2 @ce, @glsl dvec3 @ce, @glsl dvec4 @ce | | @ref Vector2d, @ref Vector3d, @ref Vector4d | @glsl dvec2 @ce, @glsl dvec3 @ce, @glsl dvec4 @ce |

4
src/Magnum/Animation/Interpolation.h

@ -106,7 +106,7 @@ Interpolation | Value type | Result type | Interpolator
@ref Interpolation::Constant "Constant" | any `V` | `V` | @ref Math::select() @ref Interpolation::Constant "Constant" | any `V` | `V` | @ref Math::select()
@ref Interpolation::Constant "Constant" | @ref Math::CubicHermite "Math::CubicHermite<T>" | `T` | @ref Math::select(const CubicHermite<T>&, const CubicHermite<T>&, U) "Math::select()" @ref Interpolation::Constant "Constant" | @ref Math::CubicHermite "Math::CubicHermite<T>" | `T` | @ref Math::select(const CubicHermite<T>&, const CubicHermite<T>&, U) "Math::select()"
@ref Interpolation::Linear "Linear" | @cpp bool @ce <b></b> | @cpp bool @ce <b></b> | @ref Math::select() @ref Interpolation::Linear "Linear" | @cpp bool @ce <b></b> | @cpp bool @ce <b></b> | @ref Math::select()
@ref Interpolation::Linear "Linear" | @ref Math::BoolVector | @ref Math::BoolVector | @ref Math::select() @ref Interpolation::Linear "Linear" | @ref Math::BitVector | @ref Math::BitVector | @ref Math::select()
@ref Interpolation::Linear "Linear" | any scalar `V` | `V` | @ref Math::lerp() @ref Interpolation::Linear "Linear" | any scalar `V` | `V` | @ref Math::lerp()
@ref Interpolation::Linear "Linear" | any vector `V` | `V` | @ref Math::lerp() @ref Interpolation::Linear "Linear" | any vector `V` | `V` | @ref Math::lerp()
@ref Interpolation::Linear "Linear" | @ref Math::Complex | @ref Math::Complex | @ref Math::slerp(const Complex<T>&, const Complex<T>&, T) "Math::slerp()" @ref Interpolation::Linear "Linear" | @ref Math::Complex | @ref Math::Complex | @ref Math::slerp(const Complex<T>&, const Complex<T>&, T) "Math::slerp()"
@ -336,7 +336,7 @@ template<class T> auto TypeTraitsBool<T>::interpolator(Interpolation interpolati
CORRADE_ASSERT_UNREACHABLE("Animation::interpolatorFor(): can't deduce interpolator function for" << interpolation, {}); CORRADE_ASSERT_UNREACHABLE("Animation::interpolatorFor(): can't deduce interpolator function for" << interpolation, {});
} }
template<> struct TypeTraits<bool, bool>: TypeTraitsBool<bool> {}; template<> struct TypeTraits<bool, bool>: TypeTraitsBool<bool> {};
template<std::size_t size> struct TypeTraits<Math::BoolVector<size>, Math::BoolVector<size>>: TypeTraitsBool<Math::BoolVector<size>> {}; template<std::size_t size> struct TypeTraits<Math::BitVector<size>, Math::BitVector<size>>: TypeTraitsBool<Math::BitVector<size>> {};
/* Complex, preferring slerp() as it is more precise */ /* Complex, preferring slerp() as it is more precise */
template<class T> struct template<class T> struct

24
src/Magnum/Animation/Test/InterpolationTest.cpp

@ -44,8 +44,8 @@ struct InterpolationTest: TestSuite::Tester {
void interpolatorForInvalid(); void interpolatorForInvalid();
void interpolatorForBool(); void interpolatorForBool();
void interpolatorForBoolInvalid(); void interpolatorForBoolInvalid();
void interpolatorForBoolVector(); void interpolatorForBitVector();
void interpolatorForBoolVectorInvalid(); void interpolatorForBitVectorInvalid();
void interpolatorForComplex(); void interpolatorForComplex();
void interpolatorForComplexInvalid(); void interpolatorForComplexInvalid();
void interpolatorForQuaternion(); void interpolatorForQuaternion();
@ -163,8 +163,8 @@ InterpolationTest::InterpolationTest() {
&InterpolationTest::interpolatorForInvalid, &InterpolationTest::interpolatorForInvalid,
&InterpolationTest::interpolatorForBool, &InterpolationTest::interpolatorForBool,
&InterpolationTest::interpolatorForBoolInvalid, &InterpolationTest::interpolatorForBoolInvalid,
&InterpolationTest::interpolatorForBoolVector, &InterpolationTest::interpolatorForBitVector,
&InterpolationTest::interpolatorForBoolVectorInvalid, &InterpolationTest::interpolatorForBitVectorInvalid,
&InterpolationTest::interpolatorForComplex, &InterpolationTest::interpolatorForComplex,
&InterpolationTest::interpolatorForComplexInvalid, &InterpolationTest::interpolatorForComplexInvalid,
&InterpolationTest::interpolatorForQuaternion, &InterpolationTest::interpolatorForQuaternion,
@ -254,20 +254,20 @@ void InterpolationTest::interpolatorForBoolInvalid() {
"Animation::interpolatorFor(): can't deduce interpolator function for Animation::Interpolation(0xde)\n"); "Animation::interpolatorFor(): can't deduce interpolator function for Animation::Interpolation(0xde)\n");
} }
void InterpolationTest::interpolatorForBoolVector() { void InterpolationTest::interpolatorForBitVector() {
CORRADE_COMPARE(Animation::interpolatorFor<Math::BoolVector<4>>(Interpolation::Constant)( CORRADE_COMPARE(Animation::interpolatorFor<Math::BitVector<4>>(Interpolation::Constant)(
Math::BoolVector<4>{0xa}, Math::BoolVector<4>{0x5}, 0.5f), (Math::BoolVector<4>{0xa})); Math::BitVector<4>{0xa}, Math::BitVector<4>{0x5}, 0.5f), (Math::BitVector<4>{0xa}));
CORRADE_COMPARE(Animation::interpolatorFor<Math::BoolVector<4>>(Interpolation::Linear)( CORRADE_COMPARE(Animation::interpolatorFor<Math::BitVector<4>>(Interpolation::Linear)(
Math::BoolVector<4>{0xa}, Math::BoolVector<4>{0x5}, 0.5f), (Math::BoolVector<4>{0xa})); Math::BitVector<4>{0xa}, Math::BitVector<4>{0x5}, 0.5f), (Math::BitVector<4>{0xa}));
} }
void InterpolationTest::interpolatorForBoolVectorInvalid() { void InterpolationTest::interpolatorForBitVectorInvalid() {
CORRADE_SKIP_IF_NO_ASSERT(); CORRADE_SKIP_IF_NO_ASSERT();
std::ostringstream out; std::ostringstream out;
Error redirectError{&out}; Error redirectError{&out};
Animation::interpolatorFor<Math::BoolVector<4>>(Interpolation::Custom); Animation::interpolatorFor<Math::BitVector<4>>(Interpolation::Custom);
Animation::interpolatorFor<Math::BoolVector<4>>(Interpolation(0xde)); Animation::interpolatorFor<Math::BitVector<4>>(Interpolation(0xde));
CORRADE_COMPARE(out.str(), CORRADE_COMPARE(out.str(),
"Animation::interpolatorFor(): can't deduce interpolator function for Animation::Interpolation::Custom\n" "Animation::interpolatorFor(): can't deduce interpolator function for Animation::Interpolation::Custom\n"

6
src/Magnum/Audio/Context.h

@ -41,7 +41,7 @@
#include "Magnum/Magnum.h" #include "Magnum/Magnum.h"
#include "Magnum/Tags.h" #include "Magnum/Tags.h"
#include "Magnum/Audio/visibility.h" #include "Magnum/Audio/visibility.h"
#include "Magnum/Math/BoolVector.h" #include "Magnum/Math/BitVector.h"
#if defined(CORRADE_TARGET_APPLE) && !defined(OPENAL_DEPRECATED) #if defined(CORRADE_TARGET_APPLE) && !defined(OPENAL_DEPRECATED)
#define OPENAL_DEPRECATED /* Override deprecation warning macro to nothing */ #define OPENAL_DEPRECATED /* Override deprecation warning macro to nothing */
@ -409,8 +409,8 @@ class MAGNUM_AUDIO_EXPORT Context {
ALCdevice* _device; ALCdevice* _device;
ALCcontext* _context; ALCcontext* _context;
Math::BoolVector<Implementation::ExtensionCount> _extensionStatus; Math::BitVector<Implementation::ExtensionCount> _extensionStatus;
Math::BoolVector<Implementation::ExtensionCount> _disabledExtensions; Math::BitVector<Implementation::ExtensionCount> _disabledExtensions;
std::vector<Extension> _supportedExtensions; std::vector<Extension> _supportedExtensions;
std::vector<std::string> _disabledExtensionStrings; std::vector<std::string> _disabledExtensionStrings;
}; };

4
src/Magnum/GL/Context.h

@ -37,7 +37,7 @@
#include <Corrade/Containers/StaticArray.h> #include <Corrade/Containers/StaticArray.h>
#include "Magnum/Magnum.h" #include "Magnum/Magnum.h"
#include "Magnum/Math/BoolVector.h" #include "Magnum/Math/BitVector.h"
#include "Magnum/Tags.h" #include "Magnum/Tags.h"
#include "Magnum/GL/GL.h" #include "Magnum/GL/GL.h"
#include "Magnum/GL/OpenGL.h" #include "Magnum/GL/OpenGL.h"
@ -898,7 +898,7 @@ class MAGNUM_GL_EXPORT Context {
Flags _flags; Flags _flags;
#endif #endif
Math::BoolVector<Implementation::ExtensionCount> _extensionStatus; Math::BitVector<Implementation::ExtensionCount> _extensionStatus;
/* For all extensions that are marked as supported in _extensionStatus, /* For all extensions that are marked as supported in _extensionStatus,
this field contains the minimal required GL version the extension this field contains the minimal required GL version the extension
needs. Extensions that are disabled have None here. */ needs. Extensions that are disabled have None here. */

4
src/Magnum/GL/Implementation/TextureState.h

@ -45,7 +45,7 @@
#endif #endif
#if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES) #if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES)
#include "Magnum/Math/BoolVector.h" #include "Magnum/Math/BitVector.h"
#endif #endif
namespace Magnum { namespace GL { namespace Implementation { namespace Magnum { namespace GL { namespace Implementation {
@ -189,7 +189,7 @@ struct TextureState {
texture type. */ texture type. */
Containers::ArrayView<std::pair<GLenum, GLuint>> bindings; Containers::ArrayView<std::pair<GLenum, GLuint>> bindings;
#if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES) #if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES)
Math::BoolVector<80> bufferTextureBound; Math::BitVector<80> bufferTextureBound;
#endif #endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
/* Texture object ID, level, layered, layer, access */ /* Texture object ID, level, layered, layer, access */

38
src/Magnum/Magnum.h

@ -269,31 +269,51 @@ typedef float Float;
typedef Math::Half Half; typedef Math::Half Half;
/** /**
@brief Two-component bool vector @brief Two-component vector of bits
@m_since{2019,10} @m_since_latest
Equivalent to GLSL @glsl bvec2 @ce. Equivalent to GLSL @glsl bvec2 @ce.
@m_keyword{bvec2,GLSL bvec2,} @m_keyword{bvec2,GLSL bvec2,}
*/ */
typedef Math::BoolVector<2> BoolVector2; typedef Math::BitVector<2> BitVector2;
/** /**
@brief Three-component bool vector @brief Three-component vector of bits
@m_since{2019,10} @m_since_latest
Equivalent to GLSL @glsl bvec3 @ce. Equivalent to GLSL @glsl bvec3 @ce.
@m_keyword{bvec3,GLSL bvec3,} @m_keyword{bvec3,GLSL bvec3,}
*/ */
typedef Math::BoolVector<3> BoolVector3; typedef Math::BitVector<3> BitVector3;
/** /**
@brief Four-component bool vector @brief Four-component vector of bits
@m_since{2019,10} @m_since_latest
Equivalent to GLSL @glsl bvec4 @ce. Equivalent to GLSL @glsl bvec4 @ce.
@m_keyword{bvec4,GLSL bvec4,} @m_keyword{bvec4,GLSL bvec4,}
*/ */
typedef Math::BoolVector<4> BoolVector4; typedef Math::BitVector<4> BitVector4;
#ifdef MAGNUM_BUILD_DEPRECATED
/**
@brief @copybrief BitVector2
@m_deprecated_since_latest Use @ref BitVector2 instead.
*/
typedef CORRADE_DEPRECATED("use BitVector2 instead") BitVector2 BoolVector2;
/**
@brief @copybrief BitVector3
@m_deprecated_since_latest Use @ref BitVector3 instead.
*/
typedef CORRADE_DEPRECATED("use BitVector3 instead") BitVector3 BoolVector3;
/**
@brief @copybrief BitVector4
@m_deprecated_since_latest Use @ref BitVector4 instead.
*/
typedef CORRADE_DEPRECATED("use BitVector4 instead") BitVector4 BoolVector4;
#endif
/** /**
@brief Two-component float vector @brief Two-component float vector

421
src/Magnum/Math/BitVector.h

@ -0,0 +1,421 @@
#ifndef Magnum_Math_BitVector_h
#define Magnum_Math_BitVector_h
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022 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::BitVector
* @m_since_latest
*/
#include <type_traits>
#include <Corrade/Containers/sequenceHelpers.h>
#ifndef CORRADE_NO_DEBUG
#include <Corrade/Utility/Debug.h>
#endif
#include "Magnum/Types.h"
#include "Magnum/Math/Math.h"
#include "Magnum/Math/Tags.h"
namespace Magnum { namespace Math {
namespace Implementation {
template<std::size_t, class> struct BitVectorConverter;
template<class T> constexpr T repeat(T value, std::size_t) { return value; }
}
/**
@brief Vector of bits
@tparam size Bit count
@m_since_latest
Result of component-wise comparison from @ref Vector. The boolean values are
stored as bits in array of unsigned bytes, unused bits have undefined value
which doesn't affect comparison or @ref all() / @ref none() / @ref any()
functions. See also @ref matrix-vector for brief introduction.
@section Math-BitVector-indexing Bit indexing
Value at position 0 is the lowest bit of the first byte passed in constructor.
Value at position 8 is the lowest bit of the second byte passed in constructor.
For example:
@snippet MagnumMath-cpp14.cpp BitVector-indexing
@section Math-BitVector-boolean Boolean operations
The class implements @cpp && @ce, @cpp || @ce and @cpp ! @ce operators
component-wise, in other words equivalently to @cpp & @ce, @cpp | @ce and
@cpp ~ @ce. This is done in order to have consistent behavior with boolean
operations on scalar types --- in the following example, it causes the final
conversion to @cpp bool @ce done at the end (instead of it happening already in
the boolean subexpressions). Combined with @ref operator bool() returning
@cpp true @ce only if all bits are set, this means the condition will be passed
only if @cpp b @ce is around @cpp a @ce in *all dimensions*, and work the same
way as if the variables were just scalars:
@snippet MagnumMath.cpp BitVector-boolean
@see @ref Magnum::BitVector2, @ref Magnum::BitVector3, @ref Magnum::BitVector4
*/
template<std::size_t size> class BitVector {
static_assert(size != 0, "BitVector cannot have zero elements");
public:
enum: std::size_t {
Size = size, /**< Vector size */
DataSize = (size-1)/8+1 /**< Vector storage size */
};
/**
* @brief Default constructor
*
* Equivalent to @ref BitVector(ZeroInitT).
*/
constexpr /*implicit*/ BitVector() noexcept: _data{} {}
/** @brief Construct a zero-filled boolean vector */
constexpr explicit BitVector(ZeroInitT) noexcept: _data{} {}
/** @brief Construct without initializing the contents */
explicit BitVector(Magnum::NoInitT) noexcept {}
/**
* @brief Construct a boolean vector from segment values
* @param first Value for first 8bit segment
* @param next Values for next Bbit segments
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class ...T> constexpr /*implicit*/ BitVector(UnsignedByte first, T... next) noexcept;
#else
template<class ...T, class U = typename std::enable_if<sizeof...(T)+1 == DataSize, bool>::type> constexpr /*implicit*/ BitVector(UnsignedByte first, T... next) noexcept: _data{first, UnsignedByte(next)...} {}
#endif
/** @brief Construct a boolean vector with one value for all fields */
#ifdef DOXYGEN_GENERATING_OUTPUT
explicit BitVector(T value) noexcept;
#else
template<class T, class U = typename std::enable_if<std::is_same<bool, T>::value && size != 1, bool>::type> constexpr explicit BitVector(T value) noexcept: BitVector(typename Corrade::Containers::Implementation::GenerateSequence<DataSize>::Type{}, value ? FullSegmentMask : 0) {}
#endif
/** @brief Construct a boolean vector from external representation */
template<class U, class V = decltype(Implementation::BitVectorConverter<size, U>::from(std::declval<U>()))> constexpr explicit BitVector(const U& other) noexcept: BitVector{Implementation::BitVectorConverter<size, U>::from(other)} {}
/** @brief Convert a boolean vector to external representation */
template<class U, class V = decltype(Implementation::BitVectorConverter<size, U>::to(std::declval<BitVector<size>>()))> constexpr explicit operator U() const {
return Implementation::BitVectorConverter<size, U>::to(*this);
}
/**
* @brief Raw data
*
* Contrary to what Doxygen shows, returns reference to an
* one-dimensional fixed-size array of @ref DataSize elements, i.e.
* @cpp UnsignedByte(&)[DataSize] @ce.
* @see @ref operator[](), @ref set()
* @todoc Fix once there's a possibility to patch the signature in a
* post-processing step (https://github.com/mosra/m.css/issues/56)
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
UnsignedByte* data();
constexpr const UnsignedByte* data() const; /**< @overload */
#else
auto data() -> UnsignedByte(&)[DataSize] { return _data; }
constexpr auto data() const -> const UnsignedByte(&)[DataSize] { return _data; }
#endif
/** @brief Bit at given position */
constexpr bool operator[](std::size_t i) const {
return (_data[i/8] >> i%8) & 0x01;
}
/** @brief Set a bit at given position */
BitVector<size>& set(std::size_t i, bool value) {
value ? _data[i/8] |= (1 << i%8) :
_data[i/8] &= ~(1 << i%8);
return *this;
}
/** @brief Equality comparison */
bool operator==(const BitVector<size>& other) const;
/** @brief Non-equality comparison */
bool operator!=(const BitVector<size>& other) const {
return !operator==(other);
}
/**
* @brief Boolean conversion
*
* Equivalent to @ref all().
* @see @ref any(), @ref none()
*/
explicit operator bool() const { return all(); }
/**
* @brief Whether all bits are set
*
* @see @ref none(), @ref any(), @ref operator bool()
*/
bool all() const;
/**
* @brief Whether no bits are set
*
* @see @ref all(), @ref any(), @ref operator bool()
*/
bool none() const;
/**
* @brief Whether any bit is set
*
* @see @ref all(), @ref none(), @ref operator bool()
*/
bool any() const { return !none(); }
/** @brief Bitwise inversion */
BitVector<size> operator~() const;
/**
* @brief Component-wise boolean negation
* @m_since{2019,10}
*
* Equivalent to @ref operator~(). See @ref Math-BitVector-boolean for
* more information.
*/
BitVector<size> operator!() const { return operator~(); }
/**
* @brief Bitwise AND and assign
*
* The computation is done in-place.
*/
BitVector<size>& operator&=(const BitVector<size>& other) {
for(std::size_t i = 0; i != DataSize; ++i)
_data[i] &= other._data[i];
return *this;
}
/**
* @brief Bitwise AND
*
* @see @ref operator&=()
*/
BitVector<size> operator&(const BitVector<size>& other) const {
return BitVector<size>(*this) &= other;
}
/**
* @brief Component-wise boolean AND
* @m_since{2019,10}
*
* Equivalent to @ref operator&(). See @ref Math-BitVector-boolean for
* more information.
*/
BitVector<size> operator&&(const BitVector<size>& other) const {
return BitVector<size>(*this) &= other;
}
/**
* @brief Bitwise OR and assign
*
* The computation is done in-place.
*/
BitVector<size>& operator|=(const BitVector<size>& other) {
for(std::size_t i = 0; i != DataSize; ++i)
_data[i] |= other._data[i];
return *this;
}
/**
* @brief Bitwise OR
*
* @see @ref operator|=()
*/
BitVector<size> operator|(const BitVector<size>& other) const {
return BitVector<size>(*this) |= other;
}
/**
* @brief Component-wise boolean OR
* @m_since{2019,10}
*
* Equivalent to @ref operator|(). See @ref Math-BitVector-boolean for
* more information.
*/
BitVector<size> operator||(const BitVector<size>& other) const {
return BitVector<size>(*this) |= other;
}
/**
* @brief Bitwise XOR and assign
*
* The computation is done in-place.
*/
BitVector<size>& operator^=(const BitVector<size>& other) {
for(std::size_t i = 0; i != DataSize; ++i)
_data[i] ^= other._data[i];
return *this;
}
/**
* @brief Bitwise XOR
*
* @see @ref operator^=()
*/
BitVector<size> operator^(const BitVector<size>& other) const {
return BitVector<size>(*this) ^= other;
}
private:
enum: UnsignedByte {
FullSegmentMask = 0xFF,
LastSegmentMask = (1 << size%8) - 1
};
/* Implementation for Vector<size, T>::Vector(U) */
template<std::size_t ...sequence> constexpr explicit BitVector(Corrade::Containers::Implementation::Sequence<sequence...>, UnsignedByte value): _data{Implementation::repeat(value, sequence)...} {}
UnsignedByte _data[(size-1)/8+1];
};
#ifndef CORRADE_NO_DEBUG
/**
@debugoperator{BitVector}
@m_since_latest
In order to avoid potential confusion, prints the value as a comma-separated sequence of binary literals, so the output corresponds to how the value would
be constructed. For example,
@snippet MagnumMath-cpp14.cpp BitVector-debug
<b></b>
@m_class{m-noindent}
prints as
@code{.shell-session}
BitVector(0b1010) BitVector(0b00001000, 0b00000011, 0b100)
@endcode
Note that this, on the other hand, makes mapping to bit indices less obvious
--- see @ref Math-BitVector-indexing for more information.
*/
template<std::size_t size> Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug& debug, const BitVector<size>& value) {
debug << "BitVector(0b" << Corrade::Utility::Debug::nospace;
/* Print the full bytes comma-separated */
for(std::size_t byte = 0; byte != BitVector<size>::DataSize - 1; ++byte) {
for(std::size_t i = 0; i != 8; ++i)
debug << (((value.data()[byte] >> (8 - i - 1)) & 1) ? "1" : "0")
<< Corrade::Utility::Debug::nospace;
debug << ", 0b" << Corrade::Utility::Debug::nospace;
}
/* Print the last (potentially) partial byte */
constexpr std::size_t suffixSize = size%8 ? size%8 : 8;
for(std::size_t i = 0; i != suffixSize; ++i)
debug << (((value.data()[size/8] >> (suffixSize - i - 1)) & 1) ? "1" : "0")
<< Corrade::Utility::Debug::nospace;
return debug << ")";
}
#endif
template<std::size_t size> inline bool BitVector<size>::operator==(const BitVector<size>& other) const {
for(std::size_t i = 0; i != size/8; ++i)
if(_data[i] != other._data[i]) return false;
/* Check last segment */
if(size%8 && (_data[DataSize-1] & LastSegmentMask) != (other._data[DataSize-1] & LastSegmentMask))
return false;
return true;
}
template<std::size_t size> inline bool BitVector<size>::all() const {
/* Check all full segments */
for(std::size_t i = 0; i != size/8; ++i)
if(_data[i] != FullSegmentMask) return false;
/* Check last segment */
if(size%8 && (_data[DataSize-1] & LastSegmentMask) != LastSegmentMask)
return false;
return true;
}
template<std::size_t size> inline bool BitVector<size>::none() const {
/* Check all full segments */
for(std::size_t i = 0; i != size/8; ++i)
if(_data[i]) return false;
/* Check last segment */
if(size%8 && (_data[DataSize-1] & LastSegmentMask))
return false;
return true;
}
template<std::size_t size> inline BitVector<size> BitVector<size>::operator~() const {
BitVector<size> out{Magnum::NoInit};
for(std::size_t i = 0; i != DataSize; ++i)
out._data[i] = ~_data[i];
return out;
}
namespace Implementation {
template<std::size_t size> struct StrictWeakOrdering<BitVector<size>> {
bool operator()(const BitVector<size>& a, const BitVector<size>& b) const {
auto ad = a.data();
auto bd = b.data();
for(std::size_t i = 0; i < BitVector<size>::DataSize - 1; ++i) {
if(ad[i] < bd[i])
return true;
if(ad[i] > bd[i])
return false;
}
/* Mask last element with to hide padding bits */
constexpr UnsignedByte mask = UnsignedByte(0xFF) >> (BitVector<size>::DataSize * 8 - size);
constexpr std::size_t i = BitVector<size>::DataSize - 1;
return (ad[i] & mask) < (bd[i] & mask);
}
};
}
}}
#endif

388
src/Magnum/Math/BoolVector.h

@ -25,394 +25,32 @@
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
*/ */
#ifdef MAGNUM_BUILD_DEPRECATED
/** @file /** @file
* @brief Class @ref Magnum::Math::BoolVector * @brief Class @ref Magnum::Math::BoolVector
* @m_deprecated_since_latest Use @ref Magnum/Math/BitVector.h and the
* @ref Magnum::Math::BitVector class instead.
*/ */
#include <type_traits>
#include <Corrade/Containers/sequenceHelpers.h>
#ifndef CORRADE_NO_DEBUG
#include <Corrade/Utility/Debug.h>
#endif #endif
#include "Magnum/Types.h" #include "Magnum/configure.h"
#include "Magnum/Math/Math.h"
#include "Magnum/Math/Tags.h"
namespace Magnum { namespace Math {
namespace Implementation {
template<std::size_t, class> struct BoolVectorConverter;
template<class T> constexpr T repeat(T value, std::size_t) { return value; }
}
/**
@brief Vector storing boolean values
@tparam size Bit count
Result of component-wise comparison from @ref Vector. The boolean values are
stored as bits in array of unsigned bytes, unused bits have undefined value
which doesn't affect comparison or @ref all() / @ref none() / @ref any()
functions. See also @ref matrix-vector for brief introduction.
@section Math-BoolVector-indexing Bit indexing
Value at position 0 is the lowest bit of the first byte passed in constructor.
Value at position 8 is the lowest bit of the second byte passed in constructor.
For example:
@snippet MagnumMath-cpp14.cpp BoolVector-indexing
@section Math-BoolVector-boolean Boolean operations
The class implements @cpp && @ce, @cpp || @ce and @cpp ! @ce operators
component-wise, in other words equivalently to @cpp & @ce, @cpp | @ce and
@cpp ~ @ce. This is done in order to have consistent behavior with boolean
operations on scalar types --- in the following example, it causes the final
conversion to @cpp bool @ce done at the end (instead of it happening already in
the boolean subexpressions). Combined with @ref operator bool() returning
@cpp true @ce only if all bits are set, this means the condition will be passed
only if @cpp b @ce is around @cpp a @ce in *all dimensions*, and work the same
way as if the variables were just scalars:
@snippet MagnumMath.cpp BoolVector-boolean
@see @ref Magnum::BoolVector2, @ref Magnum::BoolVector3, @ref Magnum::BoolVector4
*/
template<std::size_t size> class BoolVector {
static_assert(size != 0, "BoolVector cannot have zero elements");
public:
enum: std::size_t {
Size = size, /**< Vector size */
DataSize = (size-1)/8+1 /**< Vector storage size */
};
/**
* @brief Default constructor
*
* Equivalent to @ref BoolVector(ZeroInitT).
*/
constexpr /*implicit*/ BoolVector() noexcept: _data{} {}
/** @brief Construct a zero-filled boolean vector */
constexpr explicit BoolVector(ZeroInitT) noexcept: _data{} {}
/** @brief Construct without initializing the contents */
explicit BoolVector(Magnum::NoInitT) noexcept {}
/**
* @brief Construct a boolean vector from segment values
* @param first Value for first 8bit segment
* @param next Values for next Bbit segments
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class ...T> constexpr /*implicit*/ BoolVector(UnsignedByte first, T... next) noexcept;
#else
template<class ...T, class U = typename std::enable_if<sizeof...(T)+1 == DataSize, bool>::type> constexpr /*implicit*/ BoolVector(UnsignedByte first, T... next) noexcept: _data{first, UnsignedByte(next)...} {}
#endif
/** @brief Construct a boolean vector with one value for all fields */
#ifdef DOXYGEN_GENERATING_OUTPUT
explicit BoolVector(T value) noexcept;
#else
template<class T, class U = typename std::enable_if<std::is_same<bool, T>::value && size != 1, bool>::type> constexpr explicit BoolVector(T value) noexcept: BoolVector(typename Corrade::Containers::Implementation::GenerateSequence<DataSize>::Type{}, value ? FullSegmentMask : 0) {}
#endif
/** @brief Construct a boolean vector from external representation */
template<class U, class V = decltype(Implementation::BoolVectorConverter<size, U>::from(std::declval<U>()))> constexpr explicit BoolVector(const U& other) noexcept: BoolVector{Implementation::BoolVectorConverter<size, U>::from(other)} {}
/** @brief Convert a boolean vector to external representation */
template<class U, class V = decltype(Implementation::BoolVectorConverter<size, U>::to(std::declval<BoolVector<size>>()))> constexpr explicit operator U() const {
return Implementation::BoolVectorConverter<size, U>::to(*this);
}
/**
* @brief Raw data
*
* Contrary to what Doxygen shows, returns reference to an
* one-dimensional fixed-size array of @ref DataSize elements, i.e.
* @cpp UnsignedByte(&)[DataSize] @ce.
* @see @ref operator[](), @ref set()
* @todoc Fix once there's a possibility to patch the signature in a
* post-processing step (https://github.com/mosra/m.css/issues/56)
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
UnsignedByte* data();
constexpr const UnsignedByte* data() const; /**< @overload */
#else
auto data() -> UnsignedByte(&)[DataSize] { return _data; }
constexpr auto data() const -> const UnsignedByte(&)[DataSize] { return _data; }
#endif
/** @brief Bit at given position */
constexpr bool operator[](std::size_t i) const {
return (_data[i/8] >> i%8) & 0x01;
}
/** @brief Set a bit at given position */
BoolVector<size>& set(std::size_t i, bool value) {
value ? _data[i/8] |= (1 << i%8) :
_data[i/8] &= ~(1 << i%8);
return *this;
}
/** @brief Equality comparison */
bool operator==(const BoolVector<size>& other) const;
/** @brief Non-equality comparison */
bool operator!=(const BoolVector<size>& other) const {
return !operator==(other);
}
/**
* @brief Boolean conversion
*
* Equivalent to @ref all().
* @see @ref any(), @ref none()
*/
explicit operator bool() const { return all(); }
/**
* @brief Whether all bits are set
*
* @see @ref none(), @ref any(), @ref operator bool()
*/
bool all() const;
/**
* @brief Whether no bits are set
*
* @see @ref all(), @ref any(), @ref operator bool()
*/
bool none() const;
/**
* @brief Whether any bit is set
*
* @see @ref all(), @ref none(), @ref operator bool()
*/
bool any() const { return !none(); }
/** @brief Bitwise inversion */
BoolVector<size> operator~() const;
/**
* @brief Component-wise boolean negation
* @m_since{2019,10}
*
* Equivalent to @ref operator~(). See @ref Math-BoolVector-boolean for
* more information.
*/
BoolVector<size> operator!() const { return operator~(); }
/**
* @brief Bitwise AND and assign
*
* The computation is done in-place.
*/
BoolVector<size>& operator&=(const BoolVector<size>& other) {
for(std::size_t i = 0; i != DataSize; ++i)
_data[i] &= other._data[i];
return *this;
}
/** #ifdef MAGNUM_BUILD_DEPRECATED
* @brief Bitwise AND #include <Corrade/Utility/Macros.h>
*
* @see @ref operator&=()
*/
BoolVector<size> operator&(const BoolVector<size>& other) const {
return BoolVector<size>(*this) &= other;
}
/** #include "Magnum/Math/BitVector.h"
* @brief Component-wise boolean AND
* @m_since{2019,10}
*
* Equivalent to @ref operator&(). See @ref Math-BoolVector-boolean for
* more information.
*/
BoolVector<size> operator&&(const BoolVector<size>& other) const {
return BoolVector<size>(*this) &= other;
}
/** CORRADE_DEPRECATED_FILE("use Magnum/Math/BitVector.h and the BitVector class instead")
* @brief Bitwise OR and assign
*
* The computation is done in-place.
*/
BoolVector<size>& operator|=(const BoolVector<size>& other) {
for(std::size_t i = 0; i != DataSize; ++i)
_data[i] |= other._data[i];
return *this; namespace Magnum { namespace Math {
}
/**
* @brief Bitwise OR
*
* @see @ref operator|=()
*/
BoolVector<size> operator|(const BoolVector<size>& other) const {
return BoolVector<size>(*this) |= other;
}
/**
* @brief Component-wise boolean OR
* @m_since{2019,10}
*
* Equivalent to @ref operator|(). See @ref Math-BoolVector-boolean for
* more information.
*/
BoolVector<size> operator||(const BoolVector<size>& other) const {
return BoolVector<size>(*this) |= other;
}
/**
* @brief Bitwise XOR and assign
*
* The computation is done in-place.
*/
BoolVector<size>& operator^=(const BoolVector<size>& other) {
for(std::size_t i = 0; i != DataSize; ++i)
_data[i] ^= other._data[i];
return *this;
}
/**
* @brief Bitwise XOR
*
* @see @ref operator^=()
*/
BoolVector<size> operator^(const BoolVector<size>& other) const {
return BoolVector<size>(*this) ^= other;
}
private:
enum: UnsignedByte {
FullSegmentMask = 0xFF,
LastSegmentMask = (1 << size%8) - 1
};
/* Implementation for Vector<size, T>::Vector(U) */
template<std::size_t ...sequence> constexpr explicit BoolVector(Corrade::Containers::Implementation::Sequence<sequence...>, UnsignedByte value): _data{Implementation::repeat(value, sequence)...} {}
UnsignedByte _data[(size-1)/8+1];
};
#ifndef CORRADE_NO_DEBUG
/** /**
@debugoperator{BoolVector} @brief @copybrief BitVector
@m_deprecated_since_latest Use @ref BitVector instead.
In order to avoid potential confusion, prints the value as a comma-separated sequence of binary literals, so the output corresponds to how the value would
be constructed. For example,
@snippet MagnumMath-cpp14.cpp BoolVector-debug
<b></b>
@m_class{m-noindent}
prints as
@code{.shell-session}
BoolVector(0b1010) BoolVector(0b00001000, 0b00000011, 0b100)
@endcode
Note that this, on the other hand, makes mapping to bit indices less obvious
--- see @ref Math-BoolVector-indexing for more information.
*/ */
template<std::size_t size> Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug& debug, const BoolVector<size>& value) { template<std::size_t size> using BoolVector CORRADE_DEPRECATED_ALIAS("use BitVector instead") = BitVector<size>;
debug << "BoolVector(0b" << Corrade::Utility::Debug::nospace;
/* Print the full bytes comma-separated */
for(std::size_t byte = 0; byte != BoolVector<size>::DataSize - 1; ++byte) {
for(std::size_t i = 0; i != 8; ++i)
debug << (((value.data()[byte] >> (8 - i - 1)) & 1) ? "1" : "0")
<< Corrade::Utility::Debug::nospace;
debug << ", 0b" << Corrade::Utility::Debug::nospace;
}
/* Print the last (potentially) partial byte */
constexpr std::size_t suffixSize = size%8 ? size%8 : 8;
for(std::size_t i = 0; i != suffixSize; ++i)
debug << (((value.data()[size/8] >> (suffixSize - i - 1)) & 1) ? "1" : "0")
<< Corrade::Utility::Debug::nospace;
return debug << ")";
}
#endif
template<std::size_t size> inline bool BoolVector<size>::operator==(const BoolVector<size>& other) const {
for(std::size_t i = 0; i != size/8; ++i)
if(_data[i] != other._data[i]) return false;
/* Check last segment */
if(size%8 && (_data[DataSize-1] & LastSegmentMask) != (other._data[DataSize-1] & LastSegmentMask))
return false;
return true;
}
template<std::size_t size> inline bool BoolVector<size>::all() const {
/* Check all full segments */
for(std::size_t i = 0; i != size/8; ++i)
if(_data[i] != FullSegmentMask) return false;
/* Check last segment */
if(size%8 && (_data[DataSize-1] & LastSegmentMask) != LastSegmentMask)
return false;
return true;
}
template<std::size_t size> inline bool BoolVector<size>::none() const {
/* Check all full segments */
for(std::size_t i = 0; i != size/8; ++i)
if(_data[i]) return false;
/* Check last segment */
if(size%8 && (_data[DataSize-1] & LastSegmentMask))
return false;
return true;
}
template<std::size_t size> inline BoolVector<size> BoolVector<size>::operator~() const {
BoolVector<size> out{Magnum::NoInit};
for(std::size_t i = 0; i != DataSize; ++i)
out._data[i] = ~_data[i];
return out;
}
namespace Implementation {
template<std::size_t size> struct StrictWeakOrdering<BoolVector<size>> {
bool operator()(const BoolVector<size>& a, const BoolVector<size>& b) const {
auto ad = a.data();
auto bd = b.data();
for(std::size_t i = 0; i < BoolVector<size>::DataSize - 1; ++i) {
if(ad[i] < bd[i])
return true;
if(ad[i] > bd[i])
return false;
}
/* Mask last element with to hide padding bits */
constexpr UnsignedByte mask = UnsignedByte(0xFF) >> (BoolVector<size>::DataSize * 8 - size);
constexpr std::size_t i = BoolVector<size>::DataSize - 1;
return (ad[i] & mask) < (bd[i] & mask);
}
};
}
}} }}
#endif
#endif #endif

6
src/Magnum/Math/CMakeLists.txt

@ -30,7 +30,7 @@ set(CMAKE_FOLDER "Magnum/Math")
set(MagnumMath_HEADERS set(MagnumMath_HEADERS
Angle.h Angle.h
Bezier.h Bezier.h
BoolVector.h BitVector.h
Color.h Color.h
Complex.h Complex.h
Constants.h Constants.h
@ -64,6 +64,10 @@ set(MagnumMath_HEADERS
Vector3.h Vector3.h
Vector4.h) Vector4.h)
if(MAGNUM_BUILD_DEPRECATED)
list(APPEND MagnumMath_HEADERS BoolVector.h)
endif()
set(MagnumMath_INTERNAL_HEADERS set(MagnumMath_INTERNAL_HEADERS
Implementation/halfTables.hpp) Implementation/halfTables.hpp)

22
src/Magnum/Math/Functions.h

@ -56,9 +56,9 @@ namespace Implementation {
template<class T> constexpr static T pow(T) { return T(1); } template<class T> constexpr static T pow(T) { return T(1); }
}; };
template<class> struct IsBoolVectorOrScalar: std::false_type {}; template<class> struct IsBitVectorOrScalar: std::false_type {};
template<> struct IsBoolVectorOrScalar<bool>: std::true_type {}; template<> struct IsBitVectorOrScalar<bool>: std::true_type {};
template<std::size_t size> struct IsBoolVectorOrScalar<BoolVector<size>>: std::true_type {}; template<std::size_t size> struct IsBitVectorOrScalar<BitVector<size>>: std::true_type {};
} }
/** /**
@ -250,8 +250,8 @@ template<class T> inline typename std::enable_if<IsScalar<T>::value, bool>::type
@overload @overload
@m_since{2019,10} @m_since{2019,10}
*/ */
template<std::size_t size, class T> inline BoolVector<size> isInf(const Vector<size, T>& value) { template<std::size_t size, class T> inline BitVector<size> isInf(const Vector<size, T>& value) {
BoolVector<size> out; BitVector<size> out;
for(std::size_t i = 0; i != size; ++i) for(std::size_t i = 0; i != size; ++i)
out.set(i, Math::isInf(value[i])); out.set(i, Math::isInf(value[i]));
return out; return out;
@ -272,8 +272,8 @@ template<class T> typename std::enable_if<IsScalar<T>::value, bool>::type isNan(
@overload @overload
@m_since{2019,10} @m_since{2019,10}
*/ */
template<std::size_t size, class T> inline BoolVector<size> isNan(const Vector<size, T>& value) { template<std::size_t size, class T> inline BitVector<size> isNan(const Vector<size, T>& value) {
BoolVector<size> out; BitVector<size> out;
for(std::size_t i = 0; i != size; ++i) for(std::size_t i = 0; i != size; ++i)
out.set(i, Math::isNan(value[i])); out.set(i, Math::isNan(value[i]));
return out; return out;
@ -507,7 +507,7 @@ See @ref select() for constant interpolation using the same API and
*/ */
template<class T, class U> inline template<class T, class U> inline
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
typename std::enable_if<(IsVector<T>::value || IsScalar<T>::value) && !Implementation::IsBoolVectorOrScalar<U>::value, T>::type typename std::enable_if<(IsVector<T>::value || IsScalar<T>::value) && !Implementation::IsBitVectorOrScalar<U>::value, T>::type
#else #else
T T
#endif #endif
@ -527,7 +527,7 @@ Similar to the above, but instead of multiplication and addition it just does
component-wise selection from either @p a or @p b based on values in @p t. component-wise selection from either @p a or @p b based on values in @p t.
@m_keyword{mix(),GLSL mix(),} @m_keyword{mix(),GLSL mix(),}
*/ */
template<std::size_t size, class T> inline Vector<size, T> lerp(const Vector<size, T>& a, const Vector<size, T>& b, const BoolVector<size>& t) { template<std::size_t size, class T> inline Vector<size, T> lerp(const Vector<size, T>& a, const Vector<size, T>& b, const BitVector<size>& t) {
Vector<size, T> out{Magnum::NoInit}; Vector<size, T> out{Magnum::NoInit};
for(std::size_t i = 0; i != size; ++i) for(std::size_t i = 0; i != size; ++i)
out[i] = t[i] ? b[i] : a[i]; out[i] = t[i] ? b[i] : a[i];
@ -537,10 +537,10 @@ template<std::size_t size, class T> inline Vector<size, T> lerp(const Vector<siz
/** @overload /** @overload
@m_keyword{mix(),GLSL mix(),} @m_keyword{mix(),GLSL mix(),}
*/ */
template<std::size_t size> inline BoolVector<size> lerp(const BoolVector<size>& a, const BoolVector<size>& b, const BoolVector<size>& t) { template<std::size_t size> inline BitVector<size> lerp(const BitVector<size>& a, const BitVector<size>& b, const BitVector<size>& t) {
/* Not using NoInit because it causes some compilers to report unitialized /* Not using NoInit because it causes some compilers to report unitialized
value */ value */
BoolVector<size> out; BitVector<size> out;
for(std::size_t i = 0; i != size; ++i) for(std::size_t i = 0; i != size; ++i)
out.set(i, t[i] ? b[i] : a[i]); out.set(i, t[i] ? b[i] : a[i]);
return out; return out;

14
src/Magnum/Math/FunctionsBatch.h

@ -57,9 +57,9 @@ vectors or scalars.
@brief If any number in the range is a positive or negative infinity @brief If any number in the range is a positive or negative infinity
For scalar types returns @cpp true @ce as soon as it finds an infinite value, For scalar types returns @cpp true @ce as soon as it finds an infinite value,
@cpp false @ce otherwise. For vector types, returns @ref BoolVector with bits @cpp false @ce otherwise. For vector types, returns @ref BitVector with bits
set to @cpp 1 @ce if any value has that component infinite. If the range is set to @cpp 1 @ce if any value has that component infinite. If the range is
empty, returns @cpp false @ce or a @ref BoolVector with no bits set. empty, returns @cpp false @ce or a @ref BitVector with no bits set.
@see @ref isInf(T), @ref Constants::inf() @see @ref isInf(T), @ref Constants::inf()
*/ */
template<class T> auto isInf(const Corrade::Containers::StridedArrayView1D<const T>& range) -> decltype(isInf(std::declval<T>())) { template<class T> auto isInf(const Corrade::Containers::StridedArrayView1D<const T>& range) -> decltype(isInf(std::declval<T>())) {
@ -68,7 +68,7 @@ template<class T> auto isInf(const Corrade::Containers::StridedArrayView1D<const
/* For scalars, this loop exits once any value is infinity. For vectors /* For scalars, this loop exits once any value is infinity. For vectors
the loop accumulates the bits and exits as soon as all bits are set the loop accumulates the bits and exits as soon as all bits are set
or the input is exhausted */ or the input is exhausted */
auto out = isInf(range[0]); /* bool or BoolVector */ auto out = isInf(range[0]); /* bool or BitVector */
for(std::size_t i = 1; i != range.size(); ++i) { for(std::size_t i = 1; i != range.size(); ++i) {
if(out) break; if(out) break;
out = out || isInf(range[i]); out = out || isInf(range[i]);
@ -109,9 +109,9 @@ template<class T, std::size_t size> inline auto isInf(const T(&array)[size]) ->
@brief If any number in the range is a NaN @brief If any number in the range is a NaN
For scalar types returns @cpp true @ce as soon as it finds a NaN value, For scalar types returns @cpp true @ce as soon as it finds a NaN value,
@cpp false @ce otherwise. For vector types, returns @ref BoolVector with bits @cpp false @ce otherwise. For vector types, returns @ref BitVector with bits
set to @cpp 1 @ce if any value has that component NaN. If the range is empty, set to @cpp 1 @ce if any value has that component NaN. If the range is empty,
returns @cpp false @ce or a @ref BoolVector with no bits set. returns @cpp false @ce or a @ref BitVector with no bits set.
@see @ref isNan(T), @ref Constants::nan() @see @ref isNan(T), @ref Constants::nan()
*/ */
template<class T> inline auto isNan(const Corrade::Containers::StridedArrayView1D<const T>& range) -> decltype(isNan(std::declval<T>())) { template<class T> inline auto isNan(const Corrade::Containers::StridedArrayView1D<const T>& range) -> decltype(isNan(std::declval<T>())) {
@ -120,7 +120,7 @@ template<class T> inline auto isNan(const Corrade::Containers::StridedArrayView1
/* For scalars, this loop exits once any value is infinity. For vectors /* For scalars, this loop exits once any value is infinity. For vectors
the loop accumulates the bits and exits as soon as all bits are set the loop accumulates the bits and exits as soon as all bits are set
or the input is exhausted */ or the input is exhausted */
auto out = isNan(range[0]); /* bool or BoolVector */ auto out = isNan(range[0]); /* bool or BitVector */
for(std::size_t i = 1; i != range.size(); ++i) { for(std::size_t i = 1; i != range.size(); ++i) {
if(out) break; if(out) break;
out = out || isNan(range[i]); out = out || isNan(range[i]);
@ -183,7 +183,7 @@ namespace Implementation {
T out = range[0]; T out = range[0];
std::size_t firstValid = 0; std::size_t firstValid = 0;
for(std::size_t i = 1; i != range.size(); ++i) { for(std::size_t i = 1; i != range.size(); ++i) {
BoolVector<T::Size> nans = isNan(out); BitVector<T::Size> nans = isNan(out);
if(nans.none()) break; if(nans.none()) break;
if(nans.all() && firstValid + 1 == i) ++firstValid; if(nans.all() && firstValid + 1 == i) ++firstValid;
out = Math::lerp(out, range[i], isNan(out)); out = Math::lerp(out, range[i], isNan(out));

9
src/Magnum/Math/Math.h

@ -33,12 +33,19 @@
#include "Magnum/Types.h" #include "Magnum/Types.h"
#ifdef MAGNUM_BUILD_DEPRECATED
#include <Corrade/Utility/Macros.h>
#endif
namespace Magnum { namespace Math { namespace Magnum { namespace Math {
/** @todo Denormals to zero */ /** @todo Denormals to zero */
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
template<std::size_t> class BoolVector; template<std::size_t> class BitVector;
#ifdef MAGNUM_BUILD_DEPRECATED
template<std::size_t size> using BoolVector CORRADE_DEPRECATED_ALIAS("use BitVector instead") = BitVector<size>;
#endif
template<class> struct Constants; template<class> struct Constants;

8
src/Magnum/Math/RectangularMatrix.h

@ -303,7 +303,7 @@ template<std::size_t cols, std::size_t rows, class T> class RectangularMatrix {
* *
* Calls @ref Vector::operator<() on @ref toVector(). * Calls @ref Vector::operator<() on @ref toVector().
*/ */
BoolVector<cols*rows> operator<(const RectangularMatrix<cols, rows, T>& other) const { BitVector<cols*rows> operator<(const RectangularMatrix<cols, rows, T>& other) const {
return toVector() < other.toVector(); return toVector() < other.toVector();
} }
@ -312,7 +312,7 @@ template<std::size_t cols, std::size_t rows, class T> class RectangularMatrix {
* *
* Calls @ref Vector::operator<=() on @ref toVector(). * Calls @ref Vector::operator<=() on @ref toVector().
*/ */
BoolVector<cols*rows> operator<=(const RectangularMatrix<cols, rows, T>& other) const { BitVector<cols*rows> operator<=(const RectangularMatrix<cols, rows, T>& other) const {
return toVector() <= other.toVector(); return toVector() <= other.toVector();
} }
@ -321,7 +321,7 @@ template<std::size_t cols, std::size_t rows, class T> class RectangularMatrix {
* *
* Calls @ref Vector::operator>=() on @ref toVector(). * Calls @ref Vector::operator>=() on @ref toVector().
*/ */
BoolVector<cols*rows> operator>=(const RectangularMatrix<cols, rows, T>& other) const { BitVector<cols*rows> operator>=(const RectangularMatrix<cols, rows, T>& other) const {
return toVector() >= other.toVector(); return toVector() >= other.toVector();
} }
@ -330,7 +330,7 @@ template<std::size_t cols, std::size_t rows, class T> class RectangularMatrix {
* *
* Calls @ref Vector::operator>() on @ref toVector(). * Calls @ref Vector::operator>() on @ref toVector().
*/ */
BoolVector<cols*rows> operator>(const RectangularMatrix<cols, rows, T>& other) const { BitVector<cols*rows> operator>(const RectangularMatrix<cols, rows, T>& other) const {
return toVector() > other.toVector(); return toVector() > other.toVector();
} }

379
src/Magnum/Math/Test/BitVectorTest.cpp

@ -0,0 +1,379 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022 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.
*/
#include <sstream>
#include <Corrade/TestSuite/Tester.h>
#include <Corrade/Utility/DebugStl.h>
#include <Corrade/Utility/TypeTraits.h> /* CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED */
#include "Magnum/Math/BitVector.h"
#include "Magnum/Math/StrictWeakOrdering.h"
struct BVec3 {
bool x, y, z;
};
namespace Magnum { namespace Math {
namespace Implementation {
template<> struct BitVectorConverter<3, BVec3> {
constexpr static BitVector<3> from(const BVec3& other) {
return (other.x << 0)|(other.y << 1)|(other.z << 2);
}
constexpr static BVec3 to(const BitVector<3>& other) {
return {other[0], other[1], other[2]};
}
};
}
namespace Test { namespace {
struct BitVectorTest: Corrade::TestSuite::Tester {
explicit BitVectorTest();
void construct();
void constructDefault();
void constructNoInit();
void constructOneValue();
void constructOneElement();
void constructCopy();
void convert();
void data();
void compare();
void compareUndefined();
void convertBool();
void all();
void none();
void any();
void bitInverse();
void bitAndOrXor();
void booleanOperationEquivalents();
void strictWeakOrdering();
void debug();
};
static_assert(BitVector<15>::DataSize == 2, "Improper DataSize");
static_assert(BitVector<16>::DataSize == 2, "Improper DataSize");
static_assert(BitVector<17>::DataSize == 3, "Improper DataSize");
typedef Math::BitVector<19> BitVector19;
BitVectorTest::BitVectorTest() {
addTests({&BitVectorTest::construct,
&BitVectorTest::constructDefault,
&BitVectorTest::constructNoInit,
&BitVectorTest::constructOneValue,
&BitVectorTest::constructOneElement,
&BitVectorTest::constructCopy,
&BitVectorTest::convert,
&BitVectorTest::data,
&BitVectorTest::compare,
&BitVectorTest::compareUndefined,
&BitVectorTest::convertBool,
&BitVectorTest::all,
&BitVectorTest::none,
&BitVectorTest::any,
&BitVectorTest::bitInverse,
&BitVectorTest::bitAndOrXor,
&BitVectorTest::booleanOperationEquivalents,
&BitVectorTest::strictWeakOrdering,
&BitVectorTest::debug});
}
void BitVectorTest::construct() {
constexpr BitVector19 a = {0xa5, 0x5f, 0x07};
CORRADE_COMPARE(a, BitVector19(0xa5, 0x5f, 0x07));
CORRADE_VERIFY(std::is_nothrow_constructible<BitVector19, UnsignedByte, UnsignedByte, UnsignedByte>::value);
}
void BitVectorTest::constructDefault() {
constexpr BitVector19 a;
constexpr BitVector19 b{ZeroInit};
CORRADE_COMPARE(a, BitVector19(0x00, 0x00, 0x00));
CORRADE_COMPARE(b, BitVector19(0x00, 0x00, 0x00));
CORRADE_VERIFY(std::is_nothrow_default_constructible<BitVector19>::value);
CORRADE_VERIFY(std::is_nothrow_constructible<BitVector19, ZeroInitT>::value);
/* Implicit construction is not allowed */
CORRADE_VERIFY(!std::is_convertible<ZeroInitT, BitVector19>::value);
}
void BitVectorTest::constructNoInit() {
BitVector19 a{0xa5, 0x5f, 0x07};
new(&a) BitVector19{Magnum::NoInit};
{
/* Explicitly check we're not on Clang because certain Clang-based IDEs
inherit __GNUC__ if GCC is used instead of leaving it at 4 like
Clang itself does */
#if defined(CORRADE_TARGET_GCC) && !defined(CORRADE_TARGET_CLANG) && __GNUC__*100 + __GNUC_MINOR__ >= 601 && __OPTIMIZE__
CORRADE_EXPECT_FAIL("GCC 6.1+ misoptimizes and overwrites the value.");
#endif
CORRADE_COMPARE(a, BitVector19(0xa5, 0x5f, 0x07));
}
CORRADE_VERIFY(std::is_nothrow_constructible<BitVector19, Magnum::NoInitT>::value);
/* Implicit construction is not allowed */
CORRADE_VERIFY(!std::is_convertible<Magnum::NoInitT, BitVector19>::value);
}
void BitVectorTest::constructOneValue() {
constexpr BitVector19 a(false);
CORRADE_COMPARE(a, BitVector19(0x00, 0x00, 0x00));
constexpr BitVector19 b(true);
CORRADE_COMPARE(b, BitVector19(0xff, 0xff, 0x07));
CORRADE_VERIFY(!std::is_convertible<bool, BitVector19>::value);
CORRADE_VERIFY(std::is_nothrow_constructible<BitVector19, bool>::value);
}
void BitVectorTest::constructOneElement() {
typedef BitVector<1> BitVector1;
constexpr BitVector1 a = 0x01;
CORRADE_COMPARE(a, BitVector1(0x01));
CORRADE_VERIFY(std::is_nothrow_constructible<BitVector1, UnsignedByte>::value);
}
void BitVectorTest::constructCopy() {
constexpr BitVector19 a = {0xa5, 0x5f, 0x07};
constexpr BitVector19 b(a);
CORRADE_COMPARE(b, BitVector19(0xa5, 0x5f, 0x07));
#ifdef CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED
CORRADE_VERIFY(std::is_trivially_copy_constructible<BitVector19>::value);
CORRADE_VERIFY(std::is_trivially_copy_assignable<BitVector19>::value);
#endif
CORRADE_VERIFY(std::is_nothrow_copy_constructible<BitVector19>::value);
CORRADE_VERIFY(std::is_nothrow_copy_assignable<BitVector19>::value);
}
void BitVectorTest::convert() {
constexpr BVec3 a{false, true, true};
constexpr BitVector<3> b{0x6};
constexpr BitVector<3> c{a};
CORRADE_COMPARE(c, b);
constexpr BVec3 d(b);
CORRADE_COMPARE(d.x, a.x);
CORRADE_COMPARE(d.y, a.y);
CORRADE_COMPARE(d.z, a.z);
/* Implicit conversion is not allowed */
CORRADE_VERIFY(!std::is_convertible<BVec3, BitVector<3>>::value);
CORRADE_VERIFY(!std::is_convertible<BitVector<3>, BVec3>::value);
}
void BitVectorTest::data() {
/* 0b00001000, 0b00000011, 0b100 */
constexpr BitVector19 ca(0x08, 0x03, 0x04);
CORRADE_VERIFY(!ca[0] && !ca[1] && !ca[2]);
CORRADE_VERIFY(ca[3]);
CORRADE_VERIFY(!ca[4] && !ca[5] && !ca[6] && !ca[7]);
CORRADE_VERIFY(ca[8]);
CORRADE_VERIFY(ca[9]);
CORRADE_VERIFY(!ca[10] && !ca[11] && !ca[12] && !ca[13] && !ca[14] && !ca[15] && !ca[16] && !ca[17]);
CORRADE_VERIFY(ca[18]);
constexpr bool b = ca[9];
CORRADE_COMPARE(b, true);
BitVector19 a(0x08, 0x03, 0x04);
a.set(15, true);
CORRADE_VERIFY(a[15]);
CORRADE_COMPARE(a, BitVector19(0x08, 0x83, 0x04));
a.set(15, false);
CORRADE_VERIFY(!a[15]);
CORRADE_COMPARE(a, BitVector19(0x08, 0x03, 0x04));
#ifndef CORRADE_MSVC2015_COMPATIBILITY /* Apparently dereferencing pointer is verboten */
constexpr
#endif
UnsignedByte c = *ca.data();
CORRADE_COMPARE(a.data()[1], 0x03);
CORRADE_COMPARE(c, 0x08);
/* It actually returns an array */
CORRADE_COMPARE(Corrade::Containers::arraySize(a.data()), 3);
CORRADE_COMPARE(Corrade::Containers::arraySize(ca.data()), 3);
}
void BitVectorTest::compare() {
BitVector19 a(0xa5, 0x5f, 0x07);
CORRADE_VERIFY(a == a);
/* Change in full segments */
BitVector19 b(0xa3, 0x5f, 0x07);
BitVector19 c(0xa5, 0x98, 0x07);
CORRADE_VERIFY(a != b);
CORRADE_VERIFY(a != c);
/* Change in last bit */
BitVector19 d(0xa5, 0x5f, 0x06);
CORRADE_VERIFY(a != d);
}
void BitVectorTest::compareUndefined() {
BitVector19 a(0xa5, 0x5f, 0x07);
/* Change in unused part of last segment */
BitVector19 b(0xa5, 0x5f, 0x0f);
CORRADE_VERIFY(a == b);
/* Change in used part of last segment */
BitVector19 c(0xa5, 0x5f, 0x03);
CORRADE_VERIFY(a != c);
}
void BitVectorTest::convertBool() {
CORRADE_VERIFY(BitVector19(0xff, 0xff, 0x07));
CORRADE_VERIFY(!bool(BitVector19(0xff, 0xff, 0x04)));
CORRADE_VERIFY(!bool(BitVector19(0x00, 0x00, 0x00)));
CORRADE_VERIFY(BitVector19(0xff, 0xff, 0xff));
/* Using ! before and after bool conversion will produce a different
result -- first is equivalent to !a.all(), while second is (~a).all() */
CORRADE_COMPARE(!bool(BitVector19(0xff, 0xff, 0x04)), true);
CORRADE_COMPARE(bool(!BitVector19(0xff, 0xff, 0x04)), false);
/* Implicit conversion is not allowed */
CORRADE_VERIFY(!std::is_convertible<BitVector19, bool>::value);
}
void BitVectorTest::all() {
CORRADE_VERIFY(BitVector19(0xff, 0xff, 0x07).all());
/* Last segment - bit in used and unused part */
CORRADE_VERIFY(BitVector19(0xff, 0xff, 0x0f).all());
CORRADE_VERIFY(!BitVector19(0xff, 0xff, 0x04).all());
}
void BitVectorTest::none() {
CORRADE_VERIFY(BitVector19(0x00, 0x00, 0x00).none());
/* Last segment - bit in used and unused part */
CORRADE_VERIFY(BitVector19(0x00, 0x00, 0x08).none());
CORRADE_VERIFY(!BitVector19(0x00, 0x00, 0x04).none());
}
void BitVectorTest::any() {
CORRADE_VERIFY(BitVector19(0x00, 0x01, 0x00).any());
/* Last segment - bit in used and unused part */
CORRADE_VERIFY(BitVector19(0x00, 0x00, 0x04).any());
CORRADE_VERIFY(!BitVector19(0x00, 0x00, 0x08).any());
}
void BitVectorTest::bitInverse() {
CORRADE_COMPARE(~BitVector19(0xa5, 0x5f, 0x03), BitVector19(0x5a, 0xa0, 0x04));
CORRADE_COMPARE(!BitVector19(0xa5, 0x5f, 0x03), BitVector19(0x5a, 0xa0, 0x04));
}
void BitVectorTest::bitAndOrXor() {
BitVector19 a(0xa5, 0x5f, 0x03);
BitVector19 b(0x37, 0xf3, 0x06);
CORRADE_COMPARE(a & b, BitVector19(0x25, 0x53, 0x02));
CORRADE_COMPARE(a && b, BitVector19(0x25, 0x53, 0x02));
CORRADE_COMPARE(a | b, BitVector19(0xb7, 0xff, 0x07));
CORRADE_COMPARE(a || b, BitVector19(0xb7, 0xff, 0x07));
CORRADE_COMPARE(a ^ b, BitVector19(0x92, 0xac, 0x05));
}
void BitVectorTest::booleanOperationEquivalents() {
Math::BitVector<2> a{0x3};
Math::BitVector<2> b{0x2};
CORRADE_COMPARE(!(a || b), !a && !b);
CORRADE_COMPARE(!(a || b), ~(a | b));
CORRADE_COMPARE(!a && !b, ~a & ~b);
}
void BitVectorTest::strictWeakOrdering() {
BitVector<11> a, b, c;
a.set(0, true);
a.set(1, true);
c.set(7, true);
b.set(8, true);
StrictWeakOrdering o;
CORRADE_VERIFY( o(b, a));
CORRADE_VERIFY(!o(a, b));
CORRADE_VERIFY(!o(c, b));
CORRADE_VERIFY( o(a, c));
CORRADE_VERIFY(!o(c, a));
CORRADE_VERIFY(!o(a, a));
/* Check uninitialized padding reads */
a.set(8, true);
a.set(10, true);
b = a;
a.data()[1] |= 0x08;
b.data()[1] |= 0x20;
a.data()[1] |= 0x40;
b.data()[1] |= 0x80;
CORRADE_VERIFY(!o(a, b));
CORRADE_VERIFY(!o(b, a));
}
void BitVectorTest::debug() {
std::ostringstream o;
/* 0b00100101 0b01010011 0b010 */
Debug(&o) << BitVector19(0x25, 0x53, 0x02);
CORRADE_COMPARE(o.str(), "BitVector(0b00100101, 0b01010011, 0b010)\n");
}
}}}}
CORRADE_TEST_MAIN(Magnum::Math::Test::BitVectorTest)

379
src/Magnum/Math/Test/BoolVectorTest.cpp

@ -1,379 +0,0 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022 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.
*/
#include <sstream>
#include <Corrade/TestSuite/Tester.h>
#include <Corrade/Utility/DebugStl.h>
#include <Corrade/Utility/TypeTraits.h> /* CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED */
#include "Magnum/Math/BoolVector.h"
#include "Magnum/Math/StrictWeakOrdering.h"
struct BVec3 {
bool x, y, z;
};
namespace Magnum { namespace Math {
namespace Implementation {
template<> struct BoolVectorConverter<3, BVec3> {
constexpr static BoolVector<3> from(const BVec3& other) {
return (other.x << 0)|(other.y << 1)|(other.z << 2);
}
constexpr static BVec3 to(const BoolVector<3>& other) {
return {other[0], other[1], other[2]};
}
};
}
namespace Test { namespace {
struct BoolVectorTest: Corrade::TestSuite::Tester {
explicit BoolVectorTest();
void construct();
void constructDefault();
void constructNoInit();
void constructOneValue();
void constructOneElement();
void constructCopy();
void convert();
void data();
void compare();
void compareUndefined();
void convertBool();
void all();
void none();
void any();
void bitInverse();
void bitAndOrXor();
void booleanOperationEquivalents();
void strictWeakOrdering();
void debug();
};
static_assert(BoolVector<15>::DataSize == 2, "Improper DataSize");
static_assert(BoolVector<16>::DataSize == 2, "Improper DataSize");
static_assert(BoolVector<17>::DataSize == 3, "Improper DataSize");
typedef Math::BoolVector<19> BoolVector19;
BoolVectorTest::BoolVectorTest() {
addTests({&BoolVectorTest::construct,
&BoolVectorTest::constructDefault,
&BoolVectorTest::constructNoInit,
&BoolVectorTest::constructOneValue,
&BoolVectorTest::constructOneElement,
&BoolVectorTest::constructCopy,
&BoolVectorTest::convert,
&BoolVectorTest::data,
&BoolVectorTest::compare,
&BoolVectorTest::compareUndefined,
&BoolVectorTest::convertBool,
&BoolVectorTest::all,
&BoolVectorTest::none,
&BoolVectorTest::any,
&BoolVectorTest::bitInverse,
&BoolVectorTest::bitAndOrXor,
&BoolVectorTest::booleanOperationEquivalents,
&BoolVectorTest::strictWeakOrdering,
&BoolVectorTest::debug});
}
void BoolVectorTest::construct() {
constexpr BoolVector19 a = {0xa5, 0x5f, 0x07};
CORRADE_COMPARE(a, BoolVector19(0xa5, 0x5f, 0x07));
CORRADE_VERIFY(std::is_nothrow_constructible<BoolVector19, UnsignedByte, UnsignedByte, UnsignedByte>::value);
}
void BoolVectorTest::constructDefault() {
constexpr BoolVector19 a;
constexpr BoolVector19 b{ZeroInit};
CORRADE_COMPARE(a, BoolVector19(0x00, 0x00, 0x00));
CORRADE_COMPARE(b, BoolVector19(0x00, 0x00, 0x00));
CORRADE_VERIFY(std::is_nothrow_default_constructible<BoolVector19>::value);
CORRADE_VERIFY(std::is_nothrow_constructible<BoolVector19, ZeroInitT>::value);
/* Implicit construction is not allowed */
CORRADE_VERIFY(!std::is_convertible<ZeroInitT, BoolVector19>::value);
}
void BoolVectorTest::constructNoInit() {
BoolVector19 a{0xa5, 0x5f, 0x07};
new(&a) BoolVector19{Magnum::NoInit};
{
/* Explicitly check we're not on Clang because certain Clang-based IDEs
inherit __GNUC__ if GCC is used instead of leaving it at 4 like
Clang itself does */
#if defined(CORRADE_TARGET_GCC) && !defined(CORRADE_TARGET_CLANG) && __GNUC__*100 + __GNUC_MINOR__ >= 601 && __OPTIMIZE__
CORRADE_EXPECT_FAIL("GCC 6.1+ misoptimizes and overwrites the value.");
#endif
CORRADE_COMPARE(a, BoolVector19(0xa5, 0x5f, 0x07));
}
CORRADE_VERIFY(std::is_nothrow_constructible<BoolVector19, Magnum::NoInitT>::value);
/* Implicit construction is not allowed */
CORRADE_VERIFY(!std::is_convertible<Magnum::NoInitT, BoolVector19>::value);
}
void BoolVectorTest::constructOneValue() {
constexpr BoolVector19 a(false);
CORRADE_COMPARE(a, BoolVector19(0x00, 0x00, 0x00));
constexpr BoolVector19 b(true);
CORRADE_COMPARE(b, BoolVector19(0xff, 0xff, 0x07));
CORRADE_VERIFY(!std::is_convertible<bool, BoolVector19>::value);
CORRADE_VERIFY(std::is_nothrow_constructible<BoolVector19, bool>::value);
}
void BoolVectorTest::constructOneElement() {
typedef BoolVector<1> BoolVector1;
constexpr BoolVector1 a = 0x01;
CORRADE_COMPARE(a, BoolVector1(0x01));
CORRADE_VERIFY(std::is_nothrow_constructible<BoolVector1, UnsignedByte>::value);
}
void BoolVectorTest::constructCopy() {
constexpr BoolVector19 a = {0xa5, 0x5f, 0x07};
constexpr BoolVector19 b(a);
CORRADE_COMPARE(b, BoolVector19(0xa5, 0x5f, 0x07));
#ifdef CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED
CORRADE_VERIFY(std::is_trivially_copy_constructible<BoolVector19>::value);
CORRADE_VERIFY(std::is_trivially_copy_assignable<BoolVector19>::value);
#endif
CORRADE_VERIFY(std::is_nothrow_copy_constructible<BoolVector19>::value);
CORRADE_VERIFY(std::is_nothrow_copy_assignable<BoolVector19>::value);
}
void BoolVectorTest::convert() {
constexpr BVec3 a{false, true, true};
constexpr BoolVector<3> b{0x6};
constexpr BoolVector<3> c{a};
CORRADE_COMPARE(c, b);
constexpr BVec3 d(b);
CORRADE_COMPARE(d.x, a.x);
CORRADE_COMPARE(d.y, a.y);
CORRADE_COMPARE(d.z, a.z);
/* Implicit conversion is not allowed */
CORRADE_VERIFY(!std::is_convertible<BVec3, BoolVector<3>>::value);
CORRADE_VERIFY(!std::is_convertible<BoolVector<3>, BVec3>::value);
}
void BoolVectorTest::data() {
/* 0b00001000, 0b00000011, 0b100 */
constexpr BoolVector19 ca(0x08, 0x03, 0x04);
CORRADE_VERIFY(!ca[0] && !ca[1] && !ca[2]);
CORRADE_VERIFY(ca[3]);
CORRADE_VERIFY(!ca[4] && !ca[5] && !ca[6] && !ca[7]);
CORRADE_VERIFY(ca[8]);
CORRADE_VERIFY(ca[9]);
CORRADE_VERIFY(!ca[10] && !ca[11] && !ca[12] && !ca[13] && !ca[14] && !ca[15] && !ca[16] && !ca[17]);
CORRADE_VERIFY(ca[18]);
constexpr bool b = ca[9];
CORRADE_COMPARE(b, true);
BoolVector19 a(0x08, 0x03, 0x04);
a.set(15, true);
CORRADE_VERIFY(a[15]);
CORRADE_COMPARE(a, BoolVector19(0x08, 0x83, 0x04));
a.set(15, false);
CORRADE_VERIFY(!a[15]);
CORRADE_COMPARE(a, BoolVector19(0x08, 0x03, 0x04));
#ifndef CORRADE_MSVC2015_COMPATIBILITY /* Apparently dereferencing pointer is verboten */
constexpr
#endif
UnsignedByte c = *ca.data();
CORRADE_COMPARE(a.data()[1], 0x03);
CORRADE_COMPARE(c, 0x08);
/* It actually returns an array */
CORRADE_COMPARE(Corrade::Containers::arraySize(a.data()), 3);
CORRADE_COMPARE(Corrade::Containers::arraySize(ca.data()), 3);
}
void BoolVectorTest::compare() {
BoolVector19 a(0xa5, 0x5f, 0x07);
CORRADE_VERIFY(a == a);
/* Change in full segments */
BoolVector19 b(0xa3, 0x5f, 0x07);
BoolVector19 c(0xa5, 0x98, 0x07);
CORRADE_VERIFY(a != b);
CORRADE_VERIFY(a != c);
/* Change in last bit */
BoolVector19 d(0xa5, 0x5f, 0x06);
CORRADE_VERIFY(a != d);
}
void BoolVectorTest::compareUndefined() {
BoolVector19 a(0xa5, 0x5f, 0x07);
/* Change in unused part of last segment */
BoolVector19 b(0xa5, 0x5f, 0x0f);
CORRADE_VERIFY(a == b);
/* Change in used part of last segment */
BoolVector19 c(0xa5, 0x5f, 0x03);
CORRADE_VERIFY(a != c);
}
void BoolVectorTest::convertBool() {
CORRADE_VERIFY(BoolVector19(0xff, 0xff, 0x07));
CORRADE_VERIFY(!bool(BoolVector19(0xff, 0xff, 0x04)));
CORRADE_VERIFY(!bool(BoolVector19(0x00, 0x00, 0x00)));
CORRADE_VERIFY(BoolVector19(0xff, 0xff, 0xff));
/* Using ! before and after bool conversion will produce a different
result -- first is equivalent to !a.all(), while second is (~a).all() */
CORRADE_COMPARE(!bool(BoolVector19(0xff, 0xff, 0x04)), true);
CORRADE_COMPARE(bool(!BoolVector19(0xff, 0xff, 0x04)), false);
/* Implicit conversion is not allowed */
CORRADE_VERIFY(!std::is_convertible<BoolVector19, bool>::value);
}
void BoolVectorTest::all() {
CORRADE_VERIFY(BoolVector19(0xff, 0xff, 0x07).all());
/* Last segment - bit in used and unused part */
CORRADE_VERIFY(BoolVector19(0xff, 0xff, 0x0f).all());
CORRADE_VERIFY(!BoolVector19(0xff, 0xff, 0x04).all());
}
void BoolVectorTest::none() {
CORRADE_VERIFY(BoolVector19(0x00, 0x00, 0x00).none());
/* Last segment - bit in used and unused part */
CORRADE_VERIFY(BoolVector19(0x00, 0x00, 0x08).none());
CORRADE_VERIFY(!BoolVector19(0x00, 0x00, 0x04).none());
}
void BoolVectorTest::any() {
CORRADE_VERIFY(BoolVector19(0x00, 0x01, 0x00).any());
/* Last segment - bit in used and unused part */
CORRADE_VERIFY(BoolVector19(0x00, 0x00, 0x04).any());
CORRADE_VERIFY(!BoolVector19(0x00, 0x00, 0x08).any());
}
void BoolVectorTest::bitInverse() {
CORRADE_COMPARE(~BoolVector19(0xa5, 0x5f, 0x03), BoolVector19(0x5a, 0xa0, 0x04));
CORRADE_COMPARE(!BoolVector19(0xa5, 0x5f, 0x03), BoolVector19(0x5a, 0xa0, 0x04));
}
void BoolVectorTest::bitAndOrXor() {
BoolVector19 a(0xa5, 0x5f, 0x03);
BoolVector19 b(0x37, 0xf3, 0x06);
CORRADE_COMPARE(a & b, BoolVector19(0x25, 0x53, 0x02));
CORRADE_COMPARE(a && b, BoolVector19(0x25, 0x53, 0x02));
CORRADE_COMPARE(a | b, BoolVector19(0xb7, 0xff, 0x07));
CORRADE_COMPARE(a || b, BoolVector19(0xb7, 0xff, 0x07));
CORRADE_COMPARE(a ^ b, BoolVector19(0x92, 0xac, 0x05));
}
void BoolVectorTest::booleanOperationEquivalents() {
Math::BoolVector<2> a{0x3};
Math::BoolVector<2> b{0x2};
CORRADE_COMPARE(!(a || b), !a && !b);
CORRADE_COMPARE(!(a || b), ~(a | b));
CORRADE_COMPARE(!a && !b, ~a & ~b);
}
void BoolVectorTest::strictWeakOrdering() {
BoolVector<11> a, b, c;
a.set(0, true);
a.set(1, true);
c.set(7, true);
b.set(8, true);
StrictWeakOrdering o;
CORRADE_VERIFY( o(b, a));
CORRADE_VERIFY(!o(a, b));
CORRADE_VERIFY(!o(c, b));
CORRADE_VERIFY( o(a, c));
CORRADE_VERIFY(!o(c, a));
CORRADE_VERIFY(!o(a, a));
/* Check uninitialized padding reads */
a.set(8, true);
a.set(10, true);
b = a;
a.data()[1] |= 0x08;
b.data()[1] |= 0x20;
a.data()[1] |= 0x40;
b.data()[1] |= 0x80;
CORRADE_VERIFY(!o(a, b));
CORRADE_VERIFY(!o(b, a));
}
void BoolVectorTest::debug() {
std::ostringstream o;
/* 0b00100101 0b01010011 0b010 */
Debug(&o) << BoolVector19(0x25, 0x53, 0x02);
CORRADE_COMPARE(o.str(), "BoolVector(0b00100101, 0b01010011, 0b010)\n");
}
}}}}
CORRADE_TEST_MAIN(Magnum::Math::Test::BoolVectorTest)

2
src/Magnum/Math/Test/CMakeLists.txt

@ -27,7 +27,7 @@
# property that would have to be set on each target separately. # property that would have to be set on each target separately.
set(CMAKE_FOLDER "Magnum/Math/Test") set(CMAKE_FOLDER "Magnum/Math/Test")
corrade_add_test(MathBoolVectorTest BoolVectorTest.cpp LIBRARIES MagnumMathTestLib) corrade_add_test(MathBitVectorTest BitVectorTest.cpp LIBRARIES MagnumMathTestLib)
corrade_add_test(MathConstantsTest ConstantsTest.cpp LIBRARIES MagnumMathTestLib) corrade_add_test(MathConstantsTest ConstantsTest.cpp LIBRARIES MagnumMathTestLib)
corrade_add_test(MathFunctionsTest FunctionsTest.cpp LIBRARIES MagnumMathTestLib) corrade_add_test(MathFunctionsTest FunctionsTest.cpp LIBRARIES MagnumMathTestLib)
corrade_add_test(MathFunctionsBatchTest FunctionsBatchTest.cpp LIBRARIES MagnumMathTestLib) corrade_add_test(MathFunctionsBatchTest FunctionsBatchTest.cpp LIBRARIES MagnumMathTestLib)

24
src/Magnum/Math/Test/FunctionsBatchTest.cpp

@ -71,13 +71,13 @@ void FunctionsBatchTest::isInf() {
CORRADE_COMPARE(Math::isInf({Vector2{5.0f, -3.0f}, CORRADE_COMPARE(Math::isInf({Vector2{5.0f, -3.0f},
Vector2{-2.0f, 14.0f}, Vector2{-2.0f, 14.0f},
Vector2{9.0f, -5.0f}}), BoolVector<2>{0}); Vector2{9.0f, -5.0f}}), BitVector<2>{0});
CORRADE_COMPARE(Math::isInf({Vector2{5.0f, -3.0f}, CORRADE_COMPARE(Math::isInf({Vector2{5.0f, -3.0f},
Vector2{-2.0f, 14.0f}, Vector2{-2.0f, 14.0f},
Vector2{Constants::inf(), -5.0f}}), BoolVector<2>{1}); Vector2{Constants::inf(), -5.0f}}), BitVector<2>{1});
CORRADE_VERIFY(!Math::isInf(std::initializer_list<Float>{})); CORRADE_VERIFY(!Math::isInf(std::initializer_list<Float>{}));
CORRADE_COMPARE(Math::isInf(std::initializer_list<Vector3>{}), BoolVector<3>{0}); CORRADE_COMPARE(Math::isInf(std::initializer_list<Vector3>{}), BitVector<3>{0});
const Float a[]{5.0f, -2.0f, -Constants::inf()}; const Float a[]{5.0f, -2.0f, -Constants::inf()};
CORRADE_VERIFY(Math::isInf(a)); CORRADE_VERIFY(Math::isInf(a));
@ -86,15 +86,15 @@ void FunctionsBatchTest::isInf() {
CORRADE_VERIFY(!Math::isInf(b)); CORRADE_VERIFY(!Math::isInf(b));
Vector2 c[]{{5.0f, -3.0f}, {-2.0f, 14.0f}, {Constants::inf(), -5.0f}}; Vector2 c[]{{5.0f, -3.0f}, {-2.0f, 14.0f}, {Constants::inf(), -5.0f}};
CORRADE_COMPARE(Math::isInf(c), BoolVector<2>{1}); CORRADE_COMPARE(Math::isInf(c), BitVector<2>{1});
/* Mutable view */ /* Mutable view */
CORRADE_COMPARE(Math::isInf(Corrade::Containers::StridedArrayView1D<Vector2>{c}), BoolVector<2>{1}); CORRADE_COMPARE(Math::isInf(Corrade::Containers::StridedArrayView1D<Vector2>{c}), BitVector<2>{1});
/* This should work without explicit casts or types */ /* This should work without explicit casts or types */
CORRADE_VERIFY(!Math::isInf(std::vector<Float>{5.0f, -2.0f, -1.0f})); CORRADE_VERIFY(!Math::isInf(std::vector<Float>{5.0f, -2.0f, -1.0f}));
CORRADE_COMPARE(Math::isInf(std::vector<Vector2>{ CORRADE_COMPARE(Math::isInf(std::vector<Vector2>{
{5.0f, -3.0f}, {-2.0f, 14.0f}, {Constants::inf(), -5.0f} {5.0f, -3.0f}, {-2.0f, 14.0f}, {Constants::inf(), -5.0f}
}), BoolVector<2>{1}); }), BitVector<2>{1});
} }
void FunctionsBatchTest::isNan() { void FunctionsBatchTest::isNan() {
@ -103,13 +103,13 @@ void FunctionsBatchTest::isNan() {
CORRADE_COMPARE(Math::isNan({Vector2{5.0f, -3.0f}, CORRADE_COMPARE(Math::isNan({Vector2{5.0f, -3.0f},
Vector2{-2.0f, 14.0f}, Vector2{-2.0f, 14.0f},
Vector2{9.0f, -5.0f}}), BoolVector<2>{0}); Vector2{9.0f, -5.0f}}), BitVector<2>{0});
CORRADE_COMPARE(Math::isNan({Vector2{5.0f, -3.0f}, CORRADE_COMPARE(Math::isNan({Vector2{5.0f, -3.0f},
Vector2{14.0f, Constants::nan()}, Vector2{14.0f, Constants::nan()},
Vector2{-2.0f, -5.0f}}), BoolVector<2>{2}); Vector2{-2.0f, -5.0f}}), BitVector<2>{2});
CORRADE_VERIFY(!Math::isNan(std::initializer_list<Double>{})); CORRADE_VERIFY(!Math::isNan(std::initializer_list<Double>{}));
CORRADE_COMPARE(Math::isNan(std::initializer_list<Vector3>{}), BoolVector<3>{0}); CORRADE_COMPARE(Math::isNan(std::initializer_list<Vector3>{}), BitVector<3>{0});
const Float a[]{5.0f, -Constants::nan(), -2.0f}; const Float a[]{5.0f, -Constants::nan(), -2.0f};
CORRADE_VERIFY(Math::isNan(a)); CORRADE_VERIFY(Math::isNan(a));
@ -118,15 +118,15 @@ void FunctionsBatchTest::isNan() {
CORRADE_VERIFY(!Math::isNan(b)); CORRADE_VERIFY(!Math::isNan(b));
Vector2 c[]{{5.0f, -3.0f}, {14.0f, Constants::nan()}, {-2.0f, -5.0f}}; Vector2 c[]{{5.0f, -3.0f}, {14.0f, Constants::nan()}, {-2.0f, -5.0f}};
CORRADE_COMPARE(Math::isNan(c), BoolVector<2>{2}); CORRADE_COMPARE(Math::isNan(c), BitVector<2>{2});
/* Mutable view */ /* Mutable view */
CORRADE_COMPARE(Math::isNan(Corrade::Containers::StridedArrayView1D<Vector2>{c}), BoolVector<2>{2}); CORRADE_COMPARE(Math::isNan(Corrade::Containers::StridedArrayView1D<Vector2>{c}), BitVector<2>{2});
/* This should work without explicit casts or types */ /* This should work without explicit casts or types */
CORRADE_VERIFY(!Math::isNan(std::vector<Float>{5.0f, -2.0f, -1.0f})); CORRADE_VERIFY(!Math::isNan(std::vector<Float>{5.0f, -2.0f, -1.0f}));
CORRADE_COMPARE(Math::isNan(std::vector<Vector2>{ CORRADE_COMPARE(Math::isNan(std::vector<Vector2>{
{5.0f, -3.0f}, {14.0f, Constants::nan()}, {-2.0f, -5.0f} {5.0f, -3.0f}, {14.0f, Constants::nan()}, {-2.0f, -5.0f}
}), BoolVector<2>{2}); }), BitVector<2>{2});
} }
void FunctionsBatchTest::min() { void FunctionsBatchTest::min() {

18
src/Magnum/Math/Test/FunctionsTest.cpp

@ -387,11 +387,11 @@ void FunctionsTest::lerp() {
void FunctionsTest::lerpBool() { void FunctionsTest::lerpBool() {
/* Scalar interpolation phase */ /* Scalar interpolation phase */
CORRADE_COMPARE(Math::lerp(Vector3i{1, 2, 3}, Vector3i{5, 6, 7}, true), (Vector3i{5, 6, 7})); CORRADE_COMPARE(Math::lerp(Vector3i{1, 2, 3}, Vector3i{5, 6, 7}, true), (Vector3i{5, 6, 7}));
CORRADE_COMPARE(Math::lerp(BoolVector<3>{5}, BoolVector<3>{true}, false), BoolVector<3>{5}); CORRADE_COMPARE(Math::lerp(BitVector<3>{5}, BitVector<3>{true}, false), BitVector<3>{5});
/* Vector interpolation phase */ /* Vector interpolation phase */
CORRADE_COMPARE(Math::lerp(Vector3i{1, 2, 3}, Vector3i{5, 6, 7}, BoolVector<3>(5)), (Vector3i{5, 2, 7})); CORRADE_COMPARE(Math::lerp(Vector3i{1, 2, 3}, Vector3i{5, 6, 7}, BitVector<3>(5)), (Vector3i{5, 2, 7}));
CORRADE_COMPARE(Math::lerp(BoolVector<3>{false}, BoolVector<3>{true}, BoolVector<3>(5)), BoolVector<3>{5}); CORRADE_COMPARE(Math::lerp(BitVector<3>{false}, BitVector<3>{true}, BitVector<3>(5)), BitVector<3>{5});
/* Wrapped types */ /* Wrapped types */
CORRADE_COMPARE(Math::lerp(2.0_degf, 5.0_degf, true), 5.0_degf); CORRADE_COMPARE(Math::lerp(2.0_degf, 5.0_degf, true), 5.0_degf);
@ -432,8 +432,8 @@ void FunctionsTest::select() {
void FunctionsTest::selectBool() { void FunctionsTest::selectBool() {
CORRADE_COMPARE(Math::select(true, false, 0.5f), true); CORRADE_COMPARE(Math::select(true, false, 0.5f), true);
CORRADE_COMPARE(Math::select(Math::BoolVector<4>{0xa}, Math::BoolVector<4>{0x5}, 1.1f), Math::BoolVector<4>{0x5}); CORRADE_COMPARE(Math::select(Math::BitVector<4>{0xa}, Math::BitVector<4>{0x5}, 1.1f), Math::BitVector<4>{0x5});
CORRADE_COMPARE(Math::select(Math::BoolVector<4>{0xa}, Math::BoolVector<4>{0x5}, Vector4{1.1f, -1.0f, 1.3f, 0.5f}), Math::BoolVector<4>{0xf}); CORRADE_COMPARE(Math::select(Math::BitVector<4>{0xa}, Math::BitVector<4>{0x5}, Vector4{1.1f, -1.0f, 1.3f, 0.5f}), Math::BitVector<4>{0xf});
/* Wrapped types */ /* Wrapped types */
CORRADE_COMPARE(Math::select(true, false, 0.5_degf), true); CORRADE_COMPARE(Math::select(true, false, 0.5_degf), true);
@ -482,8 +482,8 @@ void FunctionsTest::isInf() {
} }
void FunctionsTest::isInfVector() { void FunctionsTest::isInfVector() {
CORRADE_COMPARE(Math::isInf(Vector3{0.3f, -Constants::inf(), 1.0f}), Math::BoolVector<3>{0x02}); CORRADE_COMPARE(Math::isInf(Vector3{0.3f, -Constants::inf(), 1.0f}), Math::BitVector<3>{0x02});
CORRADE_COMPARE(Math::isInf(Vector3{0.3f, 1.0f, -Constants::nan()}), Math::BoolVector<3>{0x00}); CORRADE_COMPARE(Math::isInf(Vector3{0.3f, 1.0f, -Constants::nan()}), Math::BitVector<3>{0x00});
} }
void FunctionsTest::isNan() { void FunctionsTest::isNan() {
@ -498,8 +498,8 @@ void FunctionsTest::isNan() {
} }
void FunctionsTest::isNanfVector() { void FunctionsTest::isNanfVector() {
CORRADE_COMPARE(Math::isNan(Vector3{0.3f, 1.0f, -Constants::nan()}), Math::BoolVector<3>{0x04}); CORRADE_COMPARE(Math::isNan(Vector3{0.3f, 1.0f, -Constants::nan()}), Math::BitVector<3>{0x04});
CORRADE_COMPARE(Math::isNan(Vector3{0.3f, -Constants::inf(), 1.0f}), Math::BoolVector<3>{0x00}); CORRADE_COMPARE(Math::isNan(Vector3{0.3f, -Constants::inf(), 1.0f}), Math::BitVector<3>{0x00});
} }
void FunctionsTest::reflect() { void FunctionsTest::reflect() {

2
src/Magnum/Math/Test/IntersectionBenchmark.cpp

@ -38,7 +38,7 @@ template<class T> bool rangeFrustumNaive(const Math::Range3D<T>& box, const Math
bool cornerHit = 0; bool cornerHit = 0;
for(UnsignedByte c = 0; c != 8; ++c) { for(UnsignedByte c = 0; c != 8; ++c) {
const Math::Vector3<T> corner = Math::lerp(box.min(), box.max(), Math::BoolVector<3>{c}); const Math::Vector3<T> corner = Math::lerp(box.min(), box.max(), Math::BitVector<3>{c});
if(Distance::pointPlaneScaled<T>(corner, plane) >= T(0)) { if(Distance::pointPlaneScaled<T>(corner, plane) >= T(0)) {
cornerHit = true; cornerHit = true;

10
src/Magnum/Math/Test/RectangularMatrixTest.cpp

@ -470,12 +470,12 @@ void RectangularMatrixTest::compare() {
} }
void RectangularMatrixTest::compareComponentWise() { void RectangularMatrixTest::compareComponentWise() {
typedef BoolVector<3> BoolVector3; typedef BitVector<3> BitVector3;
typedef RectangularMatrix<3, 1, Float> Matrix3x1; typedef RectangularMatrix<3, 1, Float> Matrix3x1;
CORRADE_COMPARE(Matrix3x1(1.0f, -1.0f, 5.0f) < Matrix3x1(1.1f, -1.0f, 3.0f), BoolVector3(0x1)); CORRADE_COMPARE(Matrix3x1(1.0f, -1.0f, 5.0f) < Matrix3x1(1.1f, -1.0f, 3.0f), BitVector3(0x1));
CORRADE_COMPARE(Matrix3x1(1.0f, -1.0f, 5.0f) <= Matrix3x1(1.1f, -1.0f, 3.0f), BoolVector3(0x3)); CORRADE_COMPARE(Matrix3x1(1.0f, -1.0f, 5.0f) <= Matrix3x1(1.1f, -1.0f, 3.0f), BitVector3(0x3));
CORRADE_COMPARE(Matrix3x1(1.0f, -1.0f, 5.0f) >= Matrix3x1(1.1f, -1.0f, 3.0f), BoolVector3(0x6)); CORRADE_COMPARE(Matrix3x1(1.0f, -1.0f, 5.0f) >= Matrix3x1(1.1f, -1.0f, 3.0f), BitVector3(0x6));
CORRADE_COMPARE(Matrix3x1(1.0f, -1.0f, 5.0f) > Matrix3x1(1.1f, -1.0f, 3.0f), BoolVector3(0x4)); CORRADE_COMPARE(Matrix3x1(1.0f, -1.0f, 5.0f) > Matrix3x1(1.1f, -1.0f, 3.0f), BitVector3(0x4));
} }
void RectangularMatrixTest::negative() { void RectangularMatrixTest::negative() {

22
src/Magnum/Math/Test/VectorTest.cpp

@ -375,21 +375,21 @@ void VectorTest::compare() {
} }
void VectorTest::compareComponentWise() { void VectorTest::compareComponentWise() {
typedef BoolVector<3> BoolVector3; typedef BitVector<3> BitVector3;
typedef BoolVector<4> BoolVector4; typedef BitVector<4> BitVector4;
Vector4 a{1.0f, -3.5f, 5.0f, -10.0f}; Vector4 a{1.0f, -3.5f, 5.0f, -10.0f};
Vector4 b{1.0f + TypeTraits<Float>::epsilon()/2, -3.5f, 5.0f - TypeTraits<Float>::epsilon()*2, -10.0f}; Vector4 b{1.0f + TypeTraits<Float>::epsilon()/2, -3.5f, 5.0f - TypeTraits<Float>::epsilon()*2, -10.0f};
Vector4 c{1.0f + TypeTraits<Float>::epsilon()*2, -3.5f, 5.0f - TypeTraits<Float>::epsilon()*10, -10.0f}; Vector4 c{1.0f + TypeTraits<Float>::epsilon()*2, -3.5f, 5.0f - TypeTraits<Float>::epsilon()*10, -10.0f};
CORRADE_COMPARE(equal(a, b), BoolVector4{0xf}); CORRADE_COMPARE(equal(a, b), BitVector4{0xf});
CORRADE_COMPARE(equal(a, c), BoolVector4{0xa}); CORRADE_COMPARE(equal(a, c), BitVector4{0xa});
CORRADE_COMPARE(notEqual(a, b), BoolVector4{0x0}); CORRADE_COMPARE(notEqual(a, b), BitVector4{0x0});
CORRADE_COMPARE(notEqual(a, c), BoolVector4{0x5}); CORRADE_COMPARE(notEqual(a, c), BitVector4{0x5});
CORRADE_COMPARE(Vector3(1.0f, -1.0f, 5.0f) < Vector3(1.1f, -1.0f, 3.0f), BoolVector3(0x1)); CORRADE_COMPARE(Vector3(1.0f, -1.0f, 5.0f) < Vector3(1.1f, -1.0f, 3.0f), BitVector3(0x1));
CORRADE_COMPARE(Vector3(1.0f, -1.0f, 5.0f) <= Vector3(1.1f, -1.0f, 3.0f), BoolVector3(0x3)); CORRADE_COMPARE(Vector3(1.0f, -1.0f, 5.0f) <= Vector3(1.1f, -1.0f, 3.0f), BitVector3(0x3));
CORRADE_COMPARE(Vector3(1.0f, -1.0f, 5.0f) >= Vector3(1.1f, -1.0f, 3.0f), BoolVector3(0x6)); CORRADE_COMPARE(Vector3(1.0f, -1.0f, 5.0f) >= Vector3(1.1f, -1.0f, 3.0f), BitVector3(0x6));
CORRADE_COMPARE(Vector3(1.0f, -1.0f, 5.0f) > Vector3(1.1f, -1.0f, 3.0f), BoolVector3(0x4)); CORRADE_COMPARE(Vector3(1.0f, -1.0f, 5.0f) > Vector3(1.1f, -1.0f, 3.0f), BitVector3(0x4));
} }
void VectorTest::negative() { void VectorTest::negative() {

2
src/Magnum/Math/TypeTraits.h

@ -138,7 +138,7 @@ template<class T> struct IsScalar<Rad<T>>: std::true_type {};
Equivalent to @ref std::true_type for all @ref Vector types and their Equivalent to @ref std::true_type for all @ref Vector types and their
subclasses; equivalent to @ref std::false_type otherwise. In particular, gives subclasses; equivalent to @ref std::false_type otherwise. In particular, gives
@ref std::false_type for @ref BoolVector, all matrix types, @ref Complex or @ref std::false_type for @ref BitVector, all matrix types, @ref Complex or
@ref Quaternion. @ref Quaternion.
@see @ref IsScalar, @ref IsFloatingPoint, @ref IsIntegral @see @ref IsScalar, @ref IsFloatingPoint, @ref IsIntegral
*/ */

42
src/Magnum/Math/Vector.h

@ -38,7 +38,7 @@
#include "Magnum/visibility.h" #include "Magnum/visibility.h"
#include "Magnum/Math/Angle.h" #include "Magnum/Math/Angle.h"
#include "Magnum/Math/BoolVector.h" #include "Magnum/Math/BitVector.h"
#include "Magnum/Math/TypeTraits.h" #include "Magnum/Math/TypeTraits.h"
namespace Magnum { namespace Math { namespace Magnum { namespace Math {
@ -283,28 +283,28 @@ template<std::size_t size, class T> class Vector {
* *
* @m_keyword{lessThan(),GLSL lessThan(),} * @m_keyword{lessThan(),GLSL lessThan(),}
*/ */
BoolVector<size> operator<(const Vector<size, T>& other) const; BitVector<size> operator<(const Vector<size, T>& other) const;
/** /**
* @brief Component-wise less than or equal comparison * @brief Component-wise less than or equal comparison
* *
* @m_keyword{lessThanEqual(),GLSL lessThanEqual(),} * @m_keyword{lessThanEqual(),GLSL lessThanEqual(),}
*/ */
BoolVector<size> operator<=(const Vector<size, T>& other) const; BitVector<size> operator<=(const Vector<size, T>& other) const;
/** /**
* @brief Component-wise greater than or equal comparison * @brief Component-wise greater than or equal comparison
* *
* @m_keyword{greaterThanEqual(),GLSL greaterThanEqual(),} * @m_keyword{greaterThanEqual(),GLSL greaterThanEqual(),}
*/ */
BoolVector<size> operator>=(const Vector<size, T>& other) const; BitVector<size> operator>=(const Vector<size, T>& other) const;
/** /**
* @brief Component-wise greater than comparison * @brief Component-wise greater than comparison
* *
* @m_keyword{greaterThan(),GLSL greaterThan(),} * @m_keyword{greaterThan(),GLSL greaterThan(),}
*/ */
BoolVector<size> operator>(const Vector<size, T>& other) const; BitVector<size> operator>(const Vector<size, T>& other) const;
/** /**
* @brief Whether the vector is zero * @brief Whether the vector is zero
@ -699,8 +699,8 @@ template<std::size_t size, class T> class Vector {
/* So the out-of-class comparators can access data directly to avoid /* So the out-of-class comparators can access data directly to avoid
function call overhead */ function call overhead */
template<std::size_t size_, class T_> friend BoolVector<size_> equal(const Vector<size_, T_>&, const Vector<size_, T_>&); 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 BoolVector<size_> notEqual(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>&); template<std::size_t size_, class U> friend U dot(const Vector<size_, U>&, const Vector<size_, U>&);
@ -723,11 +723,11 @@ template<std::size_t size, class T> class Vector {
@brief Component-wise equality comparison @brief Component-wise equality comparison
@m_since{2019,10} @m_since{2019,10}
Unlike @ref Vector::operator==() returns a @ref BoolVector instead of a single Unlike @ref Vector::operator==() returns a @ref BitVector instead of a single
value. Vector complement to @ref equal(T, T). value. Vector complement to @ref equal(T, T).
*/ */
template<std::size_t size, class T> inline BoolVector<size> equal(const Vector<size, T>& a, const Vector<size, T>& b) { template<std::size_t size, class T> inline BitVector<size> equal(const Vector<size, T>& a, const Vector<size, T>& b) {
BoolVector<size> out; BitVector<size> out;
for(std::size_t i = 0; i != size; ++i) for(std::size_t i = 0; i != size; ++i)
out.set(i, TypeTraits<T>::equals(a._data[i], b._data[i])); out.set(i, TypeTraits<T>::equals(a._data[i], b._data[i]));
@ -739,11 +739,11 @@ template<std::size_t size, class T> inline BoolVector<size> equal(const Vector<s
@brief Component-wise non-equality comparison @brief Component-wise non-equality comparison
@m_since{2019,10} @m_since{2019,10}
Unlike @ref Vector::operator!=() returns a @ref BoolVector instead of a single Unlike @ref Vector::operator!=() returns a @ref BitVector instead of a single
value. Vector complement to @ref notEqual(T, T). value. Vector complement to @ref notEqual(T, T).
*/ */
template<std::size_t size, class T> inline BoolVector<size> notEqual(const Vector<size, T>& a, const Vector<size, T>& b) { template<std::size_t size, class T> inline BitVector<size> notEqual(const Vector<size, T>& a, const Vector<size, T>& b) {
BoolVector<size> out; BitVector<size> out;
for(std::size_t i = 0; i != size; ++i) for(std::size_t i = 0; i != size; ++i)
out.set(i, !TypeTraits<T>::equals(a._data[i], b._data[i])); out.set(i, !TypeTraits<T>::equals(a._data[i], b._data[i]));
@ -1441,8 +1441,8 @@ extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utili
} }
#endif #endif
template<std::size_t size, class T> inline BoolVector<size> Vector<size, T>::operator<(const Vector<size, T>& other) const { template<std::size_t size, class T> inline BitVector<size> Vector<size, T>::operator<(const Vector<size, T>& other) const {
BoolVector<size> out; BitVector<size> out;
for(std::size_t i = 0; i != size; ++i) for(std::size_t i = 0; i != size; ++i)
out.set(i, _data[i] < other._data[i]); out.set(i, _data[i] < other._data[i]);
@ -1450,8 +1450,8 @@ template<std::size_t size, class T> inline BoolVector<size> Vector<size, T>::ope
return out; return out;
} }
template<std::size_t size, class T> inline BoolVector<size> Vector<size, T>::operator<=(const Vector<size, T>& other) const { template<std::size_t size, class T> inline BitVector<size> Vector<size, T>::operator<=(const Vector<size, T>& other) const {
BoolVector<size> out; BitVector<size> out;
for(std::size_t i = 0; i != size; ++i) for(std::size_t i = 0; i != size; ++i)
out.set(i, _data[i] <= other._data[i]); out.set(i, _data[i] <= other._data[i]);
@ -1459,8 +1459,8 @@ template<std::size_t size, class T> inline BoolVector<size> Vector<size, T>::ope
return out; return out;
} }
template<std::size_t size, class T> inline BoolVector<size> Vector<size, T>::operator>=(const Vector<size, T>& other) const { template<std::size_t size, class T> inline BitVector<size> Vector<size, T>::operator>=(const Vector<size, T>& other) const {
BoolVector<size> out; BitVector<size> out;
for(std::size_t i = 0; i != size; ++i) for(std::size_t i = 0; i != size; ++i)
out.set(i, _data[i] >= other._data[i]); out.set(i, _data[i] >= other._data[i]);
@ -1468,8 +1468,8 @@ template<std::size_t size, class T> inline BoolVector<size> Vector<size, T>::ope
return out; return out;
} }
template<std::size_t size, class T> inline BoolVector<size> Vector<size, T>::operator>(const Vector<size, T>& other) const { template<std::size_t size, class T> inline BitVector<size> Vector<size, T>::operator>(const Vector<size, T>& other) const {
BoolVector<size> out; BitVector<size> out;
for(std::size_t i = 0; i != size; ++i) for(std::size_t i = 0; i != size; ++i)
out.set(i, _data[i] > other._data[i]); out.set(i, _data[i] > other._data[i]);

2
src/Magnum/MeshTools/Compile.cpp

@ -69,7 +69,7 @@ GL::Mesh compileInternal(const Trade::MeshData& meshData, GL::Buffer&& indices,
/* Ensure each known attribute gets bound only once. There's 16 generic /* Ensure each known attribute gets bound only once. There's 16 generic
attribs at most. */ attribs at most. */
Math::BoolVector<16> boundAttributes; Math::BitVector<16> boundAttributes;
for(UnsignedInt i = 0; i != meshData.attributeCount(); ++i) { for(UnsignedInt i = 0; i != meshData.attributeCount(); ++i) {
Containers::Optional<GL::DynamicAttribute> attribute; Containers::Optional<GL::DynamicAttribute> attribute;

12
src/Magnum/Trade/AnimationData.cpp

@ -123,9 +123,9 @@ template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor<bool, bool>(Animation
template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor<Float, Float>(Animation::Interpolation) -> Float(*)(const Float&, const Float&, Float); template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor<Float, Float>(Animation::Interpolation) -> Float(*)(const Float&, const Float&, Float);
template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor<UnsignedInt, UnsignedInt>(Animation::Interpolation) -> UnsignedInt(*)(const UnsignedInt&, const UnsignedInt&, Float); template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor<UnsignedInt, UnsignedInt>(Animation::Interpolation) -> UnsignedInt(*)(const UnsignedInt&, const UnsignedInt&, Float);
template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor<Int, Int>(Animation::Interpolation) -> Int(*)(const Int&, const Int&, Float); template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor<Int, Int>(Animation::Interpolation) -> Int(*)(const Int&, const Int&, Float);
template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor<Math::BoolVector<2>, Math::BoolVector<2>>(Animation::Interpolation) -> Math::BoolVector<2>(*)(const Math::BoolVector<2>&, const Math::BoolVector<2>&, Float); template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor<Math::BitVector<2>, Math::BitVector<2>>(Animation::Interpolation) -> Math::BitVector<2>(*)(const Math::BitVector<2>&, const Math::BitVector<2>&, Float);
template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor<Math::BoolVector<3>, Math::BoolVector<3>>(Animation::Interpolation) -> Math::BoolVector<3>(*)(const Math::BoolVector<3>&, const Math::BoolVector<3>&, Float); template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor<Math::BitVector<3>, Math::BitVector<3>>(Animation::Interpolation) -> Math::BitVector<3>(*)(const Math::BitVector<3>&, const Math::BitVector<3>&, Float);
template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor<Math::BoolVector<4>, Math::BoolVector<4>>(Animation::Interpolation) -> Math::BoolVector<4>(*)(const Math::BoolVector<4>&, const Math::BoolVector<4>&, Float); template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor<Math::BitVector<4>, Math::BitVector<4>>(Animation::Interpolation) -> Math::BitVector<4>(*)(const Math::BitVector<4>&, const Math::BitVector<4>&, Float);
template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor<Vector2, Vector2>(Animation::Interpolation) -> Vector2(*)(const Vector2&, const Vector2&, Float); template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor<Vector2, Vector2>(Animation::Interpolation) -> Vector2(*)(const Vector2&, const Vector2&, Float);
template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor<Vector2i, Vector2i>(Animation::Interpolation) -> Vector2i(*)(const Vector2i&, const Vector2i&, Float); template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor<Vector2i, Vector2i>(Animation::Interpolation) -> Vector2i(*)(const Vector2i&, const Vector2i&, Float);
template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor<Vector2ui, Vector2ui>(Animation::Interpolation) -> Vector2ui(*)(const Vector2ui&, const Vector2ui&, Float); template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor<Vector2ui, Vector2ui>(Animation::Interpolation) -> Vector2ui(*)(const Vector2ui&, const Vector2ui&, Float);
@ -157,9 +157,9 @@ Debug& operator<<(Debug& debug, const AnimationTrackType value) {
_c(Float) _c(Float)
_c(UnsignedInt) _c(UnsignedInt)
_c(Int) _c(Int)
_c(BoolVector2) _c(BitVector2)
_c(BoolVector3) _c(BitVector3)
_c(BoolVector4) _c(BitVector4)
_c(Vector2) _c(Vector2)
_c(Vector2ui) _c(Vector2ui)
_c(Vector2i) _c(Vector2i)

54
src/Magnum/Trade/AnimationData.h

@ -49,9 +49,51 @@ enum class AnimationTrackType: UnsignedByte {
Float, /**< @ref Magnum::Float "Float" */ Float, /**< @ref Magnum::Float "Float" */
UnsignedInt, /**< @ref Magnum::UnsignedInt "UnsignedInt" */ UnsignedInt, /**< @ref Magnum::UnsignedInt "UnsignedInt" */
Int, /**< @ref Magnum::Int "Int" */ Int, /**< @ref Magnum::Int "Int" */
BoolVector2, /**< @ref Math::BoolVector "Math::BoolVector<2>" */
BoolVector3, /**< @ref Math::BoolVector "Math::BoolVector<3>" */ /**
BoolVector4, /**< @ref Math::BoolVector "Math::BoolVector<4>" */ * @relativeref{Magnum,BitVector2}
* @m_since_latest
*/
BitVector2,
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @relativeref{Magnum,BitVector2}
* @m_deprecated_since_latest Use @ref AnimationTrackType::BitVector2
* instead.
*/
BoolVector2 CORRADE_DEPRECATED_ENUM("use BitVector2 instead") = BitVector2,
#endif
/**
* @relativeref{Magnum,BitVector3}
* @m_since_latest
*/
BitVector3,
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @relativeref{Magnum,BitVector3}
* @m_deprecated_since_latest Use @ref AnimationTrackType::BitVector3
* instead.
*/
BoolVector3 CORRADE_DEPRECATED_ENUM("use BitVector3 instead") = BitVector3,
#endif
/**
* @relativeref{Magnum,BitVector4}
* @m_since_latest
*/
BitVector4,
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @relativeref{Magnum,BitVector4}
* @m_deprecated_since_latest Use @ref AnimationTrackType::BitVector4
* instead.
*/
BoolVector4 CORRADE_DEPRECATED_ENUM("use BitVector4 instead") = BitVector4,
#endif
/** /**
* @ref Magnum::Vector2 "Vector2". Usually used for * @ref Magnum::Vector2 "Vector2". Usually used for
@ -609,9 +651,9 @@ namespace Implementation {
template<> constexpr AnimationTrackType animationTypeFor<UnsignedInt>() { return AnimationTrackType::UnsignedInt; } template<> constexpr AnimationTrackType animationTypeFor<UnsignedInt>() { return AnimationTrackType::UnsignedInt; }
template<> constexpr AnimationTrackType animationTypeFor<Int>() { return AnimationTrackType::Int; } template<> constexpr AnimationTrackType animationTypeFor<Int>() { return AnimationTrackType::Int; }
template<> constexpr AnimationTrackType animationTypeFor<Math::BoolVector<2>>() { return AnimationTrackType::BoolVector2; } template<> constexpr AnimationTrackType animationTypeFor<Math::BitVector<2>>() { return AnimationTrackType::BitVector2; }
template<> constexpr AnimationTrackType animationTypeFor<Math::BoolVector<3>>() { return AnimationTrackType::BoolVector3; } template<> constexpr AnimationTrackType animationTypeFor<Math::BitVector<3>>() { return AnimationTrackType::BitVector3; }
template<> constexpr AnimationTrackType animationTypeFor<Math::BoolVector<4>>() { return AnimationTrackType::BoolVector4; } template<> constexpr AnimationTrackType animationTypeFor<Math::BitVector<4>>() { return AnimationTrackType::BitVector4; }
template<> constexpr AnimationTrackType animationTypeFor<Vector2>() { return AnimationTrackType::Vector2; } template<> constexpr AnimationTrackType animationTypeFor<Vector2>() { return AnimationTrackType::Vector2; }
template<> constexpr AnimationTrackType animationTypeFor<Vector3>() { return AnimationTrackType::Vector3; } template<> constexpr AnimationTrackType animationTypeFor<Vector3>() { return AnimationTrackType::Vector3; }

2
src/Magnum/Trade/SceneData.cpp

@ -546,7 +546,7 @@ SceneData::SceneData(const SceneMappingType mappingType, const UnsignedLong mapp
#ifndef CORRADE_NO_ASSERT #ifndef CORRADE_NO_ASSERT
/* Check various assumptions about field data */ /* Check various assumptions about field data */
Math::BoolVector<12> fieldsPresent; /** @todo some constant for this */ Math::BitVector<12> fieldsPresent; /** @todo some constant for this */
const UnsignedInt mappingTypeSize = sceneMappingTypeSize(_mappingType); const UnsignedInt mappingTypeSize = sceneMappingTypeSize(_mappingType);
#endif #endif
UnsignedInt transformationField = ~UnsignedInt{}; UnsignedInt transformationField = ~UnsignedInt{};

4
src/Magnum/Vk/Device.cpp

@ -99,7 +99,7 @@ struct DeviceCreateInfo::State {
void* firstEnabledFeature{}; void* firstEnabledFeature{};
/* Used for checking if the device enables extensions required by features */ /* Used for checking if the device enables extensions required by features */
#ifndef CORRADE_NO_ASSERT #ifndef CORRADE_NO_ASSERT
Math::BoolVector<Implementation::ExtensionCount> featuresRequiredExtensions; Math::BitVector<Implementation::ExtensionCount> featuresRequiredExtensions;
#endif #endif
Containers::String disabledExtensionsStorage; Containers::String disabledExtensionsStorage;
@ -803,7 +803,7 @@ Result Device::tryCreateInternal(Instance& instance, const DeviceCreateInfo& inf
#ifndef CORRADE_NO_ASSERT #ifndef CORRADE_NO_ASSERT
/* This is a dumb O(n^2) search but in an assert that's completely fine */ /* This is a dumb O(n^2) search but in an assert that's completely fine */
const Math::BoolVector<Implementation::ExtensionCount> missingExtensions = ~_enabledExtensions & info._state->featuresRequiredExtensions; const Math::BitVector<Implementation::ExtensionCount> missingExtensions = ~_enabledExtensions & info._state->featuresRequiredExtensions;
if(missingExtensions.any()) { if(missingExtensions.any()) {
for(std::size_t i = 0; i != Implementation::ExtensionCount; ++i) { for(std::size_t i = 0; i != Implementation::ExtensionCount; ++i) {
if(!missingExtensions[i]) continue; if(!missingExtensions[i]) continue;

4
src/Magnum/Vk/Device.h

@ -35,7 +35,7 @@
#include <Corrade/Containers/Pointer.h> #include <Corrade/Containers/Pointer.h>
#include "Magnum/Tags.h" #include "Magnum/Tags.h"
#include "Magnum/Math/BoolVector.h" #include "Magnum/Math/BitVector.h"
#include "Magnum/Vk/TypeTraits.h" #include "Magnum/Vk/TypeTraits.h"
#include "Magnum/Vk/Vk.h" #include "Magnum/Vk/Vk.h"
#include "Magnum/Vk/Vulkan.h" #include "Magnum/Vk/Vulkan.h"
@ -511,7 +511,7 @@ class MAGNUM_VK_EXPORT Device {
VkDevice _handle; VkDevice _handle;
HandleFlags _flags; HandleFlags _flags;
Version _version; Version _version;
Math::BoolVector<Implementation::ExtensionCount> _enabledExtensions; Math::BitVector<Implementation::ExtensionCount> _enabledExtensions;
DeviceFeatures _enabledFeatures; DeviceFeatures _enabledFeatures;
Containers::Pointer<DeviceProperties> _properties; Containers::Pointer<DeviceProperties> _properties;
Containers::Pointer<Implementation::DeviceState> _state; Containers::Pointer<Implementation::DeviceState> _state;

4
src/Magnum/Vk/Instance.h

@ -33,7 +33,7 @@
#include <Corrade/Containers/Pointer.h> #include <Corrade/Containers/Pointer.h>
#include "Magnum/Tags.h" #include "Magnum/Tags.h"
#include "Magnum/Math/BoolVector.h" #include "Magnum/Math/BitVector.h"
#include "Magnum/Vk/TypeTraits.h" #include "Magnum/Vk/TypeTraits.h"
#include "Magnum/Vk/Vk.h" #include "Magnum/Vk/Vk.h"
#include "Magnum/Vk/Vulkan.h" #include "Magnum/Vk/Vulkan.h"
@ -441,7 +441,7 @@ class MAGNUM_VK_EXPORT Instance {
VkInstance _handle; VkInstance _handle;
HandleFlags _flags; HandleFlags _flags;
Version _version; Version _version;
Math::BoolVector<Implementation::InstanceExtensionCount> _extensionStatus; Math::BitVector<Implementation::InstanceExtensionCount> _extensionStatus;
Containers::Pointer<Implementation::InstanceState> _state; Containers::Pointer<Implementation::InstanceState> _state;
/* This member is bigger than you might think */ /* This member is bigger than you might think */

6
src/singles/MagnumMath.hpp

@ -161,9 +161,9 @@
namespace Magnum { namespace Magnum {
typedef Math::Half Half; typedef Math::Half Half;
typedef Math::BoolVector<2> BoolVector2; typedef Math::BitVector<2> BitVector2;
typedef Math::BoolVector<3> BoolVector3; typedef Math::BitVector<3> BitVector3;
typedef Math::BoolVector<4> BoolVector4; typedef Math::BitVector<4> BitVector4;
typedef Math::Vector2<Float> Vector2; typedef Math::Vector2<Float> Vector2;
typedef Math::Vector3<Float> Vector3; typedef Math::Vector3<Float> Vector3;
typedef Math::Vector4<Float> Vector4; typedef Math::Vector4<Float> Vector4;

Loading…
Cancel
Save