diff --git a/doc/changelog-old.dox b/doc/changelog-old.dox index 0ffb7baeb..385a258b5 100644 --- a/doc/changelog-old.dox +++ b/doc/changelog-old.dox @@ -720,7 +720,7 @@ a high-level overview. @ref Math::Quaternion from a different underlying type - Added @ref Math::ZeroInit, @ref Math::NoInit, @ref Math::IdentityInit tags to control initialization of all math classes -- Added @ref Math::lerp(const Vector&, const Vector&, const BoolVector&) +- Added @cpp Math::lerp(const Vector&, const Vector&, const BoolVector&) @ce - Added @ref Math::Vector::flipped(), @ref Math::RectangularMatrix::flippedCols(), @ref Math::RectangularMatrix::flippedRows() - 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 save and restore @ref Deg and @ref Rad from @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)) - Component-wise comparison for @ref Math::RectangularMatrix - 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 - Fixed unfortunate interaction of VAOs and index buffers on platforms 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# - @ref Audio::Context::hrtfSpecifierString() was crashing on systems diff --git a/doc/changelog.dox b/doc/changelog.dox index dcba6fcb0..9b44637b3 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -411,7 +411,7 @@ See also: matrices, and with the default on @ref Math::RectangularMatrix being zero-fill while @ref Math::Matrix stays with the identity for consistency 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::Dual::data(), @ref Math::DualComplex::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 @relativeref{Corrade,Containers::Array3} types provide a suitable 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 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, @@ -2126,8 +2132,8 @@ Released 2019-10-24, tagged as - @ref Color3ub and @ref Color4ub can be printed with @ref Corrade::Utility::Debug as actual colors using the @ref Corrade::Utility::Debug::color modifier -- Added convenience @ref BoolVector2, @ref BoolVector3 and @ref BoolVector4 - typedefs to the root namespace +- Added convenience @cpp BoolVector2 @ce, @cpp BoolVector3 @ce and + @cpp BoolVector4 @ce typedefs to the root namespace - New @ref Math::IsScalar, @ref Math::IsVector, @ref Math::IsIntegral, @ref Math::IsFloatingPoint and @ref Math::IsUnitless type traits and a @ref Math::UnderlyingTypeOf utility @@ -2314,7 +2320,7 @@ Released 2019-10-24, tagged as @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 done on scalar types - 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&) or the batch @ref Math::isNan(const Containers::StridedArrayView1D&) to detect presence of NaN values if needed. -- Changed the way @ref Math::operator<<(Corrade::Utility::Debug&, const BoolVector&) +- Changed the way @cpp Math::operator<<(Corrade::Utility::Debug&, const BoolVector&) @ce works --- the output now has the same bit order as when constructing it using binary literals - @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 passing parameters to @ref Math::Intersection::planeLine(), @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 - Ability to construct @ref Math::Matrix from a smaller or larger square matrix by slicing or expanding it diff --git a/doc/matrix-vector.dox b/doc/matrix-vector.dox index 15ea1785b..379ac4352 100644 --- a/doc/matrix-vector.dox +++ b/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 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 diff --git a/doc/snippets/MagnumMath-cpp14.cpp b/doc/snippets/MagnumMath-cpp14.cpp index 8889aaa78..790b25bd0 100644 --- a/doc/snippets/MagnumMath-cpp14.cpp +++ b/doc/snippets/MagnumMath-cpp14.cpp @@ -23,29 +23,29 @@ DEALINGS IN THE SOFTWARE. */ -#include "Magnum/Math/BoolVector.h" +#include "Magnum/Math/BitVector.h" #include "Magnum/Magnum.h" using namespace Magnum; int main() { { -/* [BoolVector-indexing] */ -BoolVector4 a{0b0010}; +/* [BitVector-indexing] */ +BitVector4 a{0b0010}; Debug{} << a[1]; // true -Math::BoolVector<19> b{0b00001000, 0b00000011, 0b100}; +Math::BitVector<19> b{0b00001000, 0b00000011, 0b100}; Debug{} << b[3]; // true Debug{} << b[8]; // true Debug{} << b[9]; // true Debug{} << b[18]; // true -/* [BoolVector-indexing] */ +/* [BitVector-indexing] */ } { -/* [BoolVector-debug] */ -Debug{} << BoolVector4{0b1010} - << Math::BoolVector<19>{0b00001000, 0b00000011, 0b100}; -/* [BoolVector-debug] */ +/* [BitVector-debug] */ +Debug{} << BitVector4{0b1010} + << Math::BitVector<19>{0b00001000, 0b00000011, 0b100}; +/* [BitVector-debug] */ } } diff --git a/doc/snippets/MagnumMath.cpp b/doc/snippets/MagnumMath.cpp index 9678b1c5d..d99c97154 100644 --- a/doc/snippets/MagnumMath.cpp +++ b/doc/snippets/MagnumMath.cpp @@ -304,7 +304,7 @@ static_cast(min); static_cast(max); /* [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 allLarger = (a > b).all(); // false /* [matrix-vector-operations-compare] */ @@ -747,13 +747,13 @@ static_cast(tan2); { Vector3 epsilon; -/* [BoolVector-boolean] */ +/* [BitVector-boolean] */ Vector3 a, b; if(!(b < a - epsilon || a + epsilon < b)) { // b is around a } -/* [BoolVector-boolean] */ +/* [BitVector-boolean] */ } { diff --git a/doc/transformations.dox b/doc/transformations.dox index 28e272685..68265cb49 100644 --- a/doc/transformations.dox +++ b/doc/transformations.dox @@ -256,7 +256,7 @@ Interpolation | Value type | Result type | Interpolator Constant | any `V` | `V` | @ref Math::select() Constant | @ref Math::CubicHermite "Math::CubicHermite" | `T` | @ref Math::select(const CubicHermite&, const CubicHermite&, U) "Math::select()" Linear | @cpp bool @ce | @cpp bool @ce | @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 vector `V` | `V` | @ref Math::lerp() Linear | @ref Math::Complex | @ref Math::Complex | @ref Math::lerp(const Complex&, const Complex&, T) "Math::lerp()" diff --git a/doc/types.dox b/doc/types.dox index 41df2f11c..63ccfcff0 100644 --- a/doc/types.dox +++ b/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 | | ---------------------------------------------- | ------------------------- | -| @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 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 | diff --git a/src/Magnum/Animation/Interpolation.h b/src/Magnum/Animation/Interpolation.h index 5bfad73e9..c73c12806 100644 --- a/src/Magnum/Animation/Interpolation.h +++ b/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" | @ref Math::CubicHermite "Math::CubicHermite" | `T` | @ref Math::select(const CubicHermite&, const CubicHermite&, U) "Math::select()" @ref Interpolation::Linear "Linear" | @cpp bool @ce | @cpp bool @ce | @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 vector `V` | `V` | @ref Math::lerp() @ref Interpolation::Linear "Linear" | @ref Math::Complex | @ref Math::Complex | @ref Math::slerp(const Complex&, const Complex&, T) "Math::slerp()" @@ -336,7 +336,7 @@ template auto TypeTraitsBool::interpolator(Interpolation interpolati CORRADE_ASSERT_UNREACHABLE("Animation::interpolatorFor(): can't deduce interpolator function for" << interpolation, {}); } template<> struct TypeTraits: TypeTraitsBool {}; -template struct TypeTraits, Math::BoolVector>: TypeTraitsBool> {}; +template struct TypeTraits, Math::BitVector>: TypeTraitsBool> {}; /* Complex, preferring slerp() as it is more precise */ template struct diff --git a/src/Magnum/Animation/Test/InterpolationTest.cpp b/src/Magnum/Animation/Test/InterpolationTest.cpp index 06550a12c..ad718b006 100644 --- a/src/Magnum/Animation/Test/InterpolationTest.cpp +++ b/src/Magnum/Animation/Test/InterpolationTest.cpp @@ -44,8 +44,8 @@ struct InterpolationTest: TestSuite::Tester { void interpolatorForInvalid(); void interpolatorForBool(); void interpolatorForBoolInvalid(); - void interpolatorForBoolVector(); - void interpolatorForBoolVectorInvalid(); + void interpolatorForBitVector(); + void interpolatorForBitVectorInvalid(); void interpolatorForComplex(); void interpolatorForComplexInvalid(); void interpolatorForQuaternion(); @@ -163,8 +163,8 @@ InterpolationTest::InterpolationTest() { &InterpolationTest::interpolatorForInvalid, &InterpolationTest::interpolatorForBool, &InterpolationTest::interpolatorForBoolInvalid, - &InterpolationTest::interpolatorForBoolVector, - &InterpolationTest::interpolatorForBoolVectorInvalid, + &InterpolationTest::interpolatorForBitVector, + &InterpolationTest::interpolatorForBitVectorInvalid, &InterpolationTest::interpolatorForComplex, &InterpolationTest::interpolatorForComplexInvalid, &InterpolationTest::interpolatorForQuaternion, @@ -254,20 +254,20 @@ void InterpolationTest::interpolatorForBoolInvalid() { "Animation::interpolatorFor(): can't deduce interpolator function for Animation::Interpolation(0xde)\n"); } -void InterpolationTest::interpolatorForBoolVector() { - CORRADE_COMPARE(Animation::interpolatorFor>(Interpolation::Constant)( - Math::BoolVector<4>{0xa}, Math::BoolVector<4>{0x5}, 0.5f), (Math::BoolVector<4>{0xa})); - CORRADE_COMPARE(Animation::interpolatorFor>(Interpolation::Linear)( - Math::BoolVector<4>{0xa}, Math::BoolVector<4>{0x5}, 0.5f), (Math::BoolVector<4>{0xa})); +void InterpolationTest::interpolatorForBitVector() { + CORRADE_COMPARE(Animation::interpolatorFor>(Interpolation::Constant)( + Math::BitVector<4>{0xa}, Math::BitVector<4>{0x5}, 0.5f), (Math::BitVector<4>{0xa})); + CORRADE_COMPARE(Animation::interpolatorFor>(Interpolation::Linear)( + 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(); std::ostringstream out; Error redirectError{&out}; - Animation::interpolatorFor>(Interpolation::Custom); - Animation::interpolatorFor>(Interpolation(0xde)); + Animation::interpolatorFor>(Interpolation::Custom); + Animation::interpolatorFor>(Interpolation(0xde)); CORRADE_COMPARE(out.str(), "Animation::interpolatorFor(): can't deduce interpolator function for Animation::Interpolation::Custom\n" diff --git a/src/Magnum/Audio/Context.h b/src/Magnum/Audio/Context.h index a02e99776..5458aeacc 100644 --- a/src/Magnum/Audio/Context.h +++ b/src/Magnum/Audio/Context.h @@ -41,7 +41,7 @@ #include "Magnum/Magnum.h" #include "Magnum/Tags.h" #include "Magnum/Audio/visibility.h" -#include "Magnum/Math/BoolVector.h" +#include "Magnum/Math/BitVector.h" #if defined(CORRADE_TARGET_APPLE) && !defined(OPENAL_DEPRECATED) #define OPENAL_DEPRECATED /* Override deprecation warning macro to nothing */ @@ -409,8 +409,8 @@ class MAGNUM_AUDIO_EXPORT Context { ALCdevice* _device; ALCcontext* _context; - Math::BoolVector _extensionStatus; - Math::BoolVector _disabledExtensions; + Math::BitVector _extensionStatus; + Math::BitVector _disabledExtensions; std::vector _supportedExtensions; std::vector _disabledExtensionStrings; }; diff --git a/src/Magnum/GL/Context.h b/src/Magnum/GL/Context.h index 7a75b8531..2ba235f44 100644 --- a/src/Magnum/GL/Context.h +++ b/src/Magnum/GL/Context.h @@ -37,7 +37,7 @@ #include #include "Magnum/Magnum.h" -#include "Magnum/Math/BoolVector.h" +#include "Magnum/Math/BitVector.h" #include "Magnum/Tags.h" #include "Magnum/GL/GL.h" #include "Magnum/GL/OpenGL.h" @@ -898,7 +898,7 @@ class MAGNUM_GL_EXPORT Context { Flags _flags; #endif - Math::BoolVector _extensionStatus; + Math::BitVector _extensionStatus; /* For all extensions that are marked as supported in _extensionStatus, this field contains the minimal required GL version the extension needs. Extensions that are disabled have None here. */ diff --git a/src/Magnum/GL/Implementation/TextureState.h b/src/Magnum/GL/Implementation/TextureState.h index 833064ecd..7a360110a 100644 --- a/src/Magnum/GL/Implementation/TextureState.h +++ b/src/Magnum/GL/Implementation/TextureState.h @@ -45,7 +45,7 @@ #endif #if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES) -#include "Magnum/Math/BoolVector.h" +#include "Magnum/Math/BitVector.h" #endif namespace Magnum { namespace GL { namespace Implementation { @@ -189,7 +189,7 @@ struct TextureState { texture type. */ Containers::ArrayView> bindings; #if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES) - Math::BoolVector<80> bufferTextureBound; + Math::BitVector<80> bufferTextureBound; #endif #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) /* Texture object ID, level, layered, layer, access */ diff --git a/src/Magnum/Magnum.h b/src/Magnum/Magnum.h index c9e14412f..0210090c0 100644 --- a/src/Magnum/Magnum.h +++ b/src/Magnum/Magnum.h @@ -269,31 +269,51 @@ typedef float Float; typedef Math::Half Half; /** -@brief Two-component bool vector -@m_since{2019,10} +@brief Two-component vector of bits +@m_since_latest Equivalent to GLSL @glsl bvec2 @ce. @m_keyword{bvec2,GLSL bvec2,} */ -typedef Math::BoolVector<2> BoolVector2; +typedef Math::BitVector<2> BitVector2; /** -@brief Three-component bool vector -@m_since{2019,10} +@brief Three-component vector of bits +@m_since_latest Equivalent to GLSL @glsl bvec3 @ce. @m_keyword{bvec3,GLSL bvec3,} */ -typedef Math::BoolVector<3> BoolVector3; +typedef Math::BitVector<3> BitVector3; /** -@brief Four-component bool vector -@m_since{2019,10} +@brief Four-component vector of bits +@m_since_latest Equivalent to GLSL @glsl bvec4 @ce. @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 diff --git a/src/Magnum/Math/BitVector.h b/src/Magnum/Math/BitVector.h new file mode 100644 index 000000000..5f3e46770 --- /dev/null +++ b/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š + + 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 +#include +#ifndef CORRADE_NO_DEBUG +#include +#endif + +#include "Magnum/Types.h" +#include "Magnum/Math/Math.h" +#include "Magnum/Math/Tags.h" + +namespace Magnum { namespace Math { + +namespace Implementation { + template struct BitVectorConverter; + + template 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 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 constexpr /*implicit*/ BitVector(UnsignedByte first, T... next) noexcept; + #else + template::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::value && size != 1, bool>::type> constexpr explicit BitVector(T value) noexcept: BitVector(typename Corrade::Containers::Implementation::GenerateSequence::Type{}, value ? FullSegmentMask : 0) {} + #endif + + /** @brief Construct a boolean vector from external representation */ + template::from(std::declval()))> constexpr explicit BitVector(const U& other) noexcept: BitVector{Implementation::BitVectorConverter::from(other)} {} + + /** @brief Convert a boolean vector to external representation */ + template::to(std::declval>()))> constexpr explicit operator U() const { + return Implementation::BitVectorConverter::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& 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& other) const; + + /** @brief Non-equality comparison */ + bool operator!=(const BitVector& 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 operator~() const; + + /** + * @brief Component-wise boolean negation + * @m_since{2019,10} + * + * Equivalent to @ref operator~(). See @ref Math-BitVector-boolean for + * more information. + */ + BitVector operator!() const { return operator~(); } + + /** + * @brief Bitwise AND and assign + * + * The computation is done in-place. + */ + BitVector& operator&=(const BitVector& other) { + for(std::size_t i = 0; i != DataSize; ++i) + _data[i] &= other._data[i]; + + return *this; + } + + /** + * @brief Bitwise AND + * + * @see @ref operator&=() + */ + BitVector operator&(const BitVector& other) const { + return BitVector(*this) &= other; + } + + /** + * @brief Component-wise boolean AND + * @m_since{2019,10} + * + * Equivalent to @ref operator&(). See @ref Math-BitVector-boolean for + * more information. + */ + BitVector operator&&(const BitVector& other) const { + return BitVector(*this) &= other; + } + + /** + * @brief Bitwise OR and assign + * + * The computation is done in-place. + */ + BitVector& operator|=(const BitVector& other) { + for(std::size_t i = 0; i != DataSize; ++i) + _data[i] |= other._data[i]; + + return *this; + } + + /** + * @brief Bitwise OR + * + * @see @ref operator|=() + */ + BitVector operator|(const BitVector& other) const { + return BitVector(*this) |= other; + } + + /** + * @brief Component-wise boolean OR + * @m_since{2019,10} + * + * Equivalent to @ref operator|(). See @ref Math-BitVector-boolean for + * more information. + */ + BitVector operator||(const BitVector& other) const { + return BitVector(*this) |= other; + } + + /** + * @brief Bitwise XOR and assign + * + * The computation is done in-place. + */ + BitVector& operator^=(const BitVector& other) { + for(std::size_t i = 0; i != DataSize; ++i) + _data[i] ^= other._data[i]; + + return *this; + } + + /** + * @brief Bitwise XOR + * + * @see @ref operator^=() + */ + BitVector operator^(const BitVector& other) const { + return BitVector(*this) ^= other; + } + + private: + enum: UnsignedByte { + FullSegmentMask = 0xFF, + LastSegmentMask = (1 << size%8) - 1 + }; + + /* Implementation for Vector::Vector(U) */ + template constexpr explicit BitVector(Corrade::Containers::Implementation::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 + + + +@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 Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug& debug, const BitVector& value) { + debug << "BitVector(0b" << Corrade::Utility::Debug::nospace; + + /* Print the full bytes comma-separated */ + for(std::size_t byte = 0; byte != BitVector::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 inline bool BitVector::operator==(const BitVector& 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 inline bool BitVector::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 inline bool BitVector::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 inline BitVector BitVector::operator~() const { + BitVector out{Magnum::NoInit}; + + for(std::size_t i = 0; i != DataSize; ++i) + out._data[i] = ~_data[i]; + + return out; +} + +namespace Implementation { + +template struct StrictWeakOrdering> { + bool operator()(const BitVector& a, const BitVector& b) const { + auto ad = a.data(); + auto bd = b.data(); + for(std::size_t i = 0; i < BitVector::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::DataSize * 8 - size); + constexpr std::size_t i = BitVector::DataSize - 1; + return (ad[i] & mask) < (bd[i] & mask); + } +}; + +} + +}} + +#endif diff --git a/src/Magnum/Math/BoolVector.h b/src/Magnum/Math/BoolVector.h index c9842d6fd..4ebcb6b0e 100644 --- a/src/Magnum/Math/BoolVector.h +++ b/src/Magnum/Math/BoolVector.h @@ -25,394 +25,32 @@ DEALINGS IN THE SOFTWARE. */ +#ifdef MAGNUM_BUILD_DEPRECATED /** @file * @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 -#include -#ifndef CORRADE_NO_DEBUG -#include #endif -#include "Magnum/Types.h" -#include "Magnum/Math/Math.h" -#include "Magnum/Math/Tags.h" - -namespace Magnum { namespace Math { - -namespace Implementation { - template struct BoolVectorConverter; - - template 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 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 constexpr /*implicit*/ BoolVector(UnsignedByte first, T... next) noexcept; - #else - template::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::value && size != 1, bool>::type> constexpr explicit BoolVector(T value) noexcept: BoolVector(typename Corrade::Containers::Implementation::GenerateSequence::Type{}, value ? FullSegmentMask : 0) {} - #endif - - /** @brief Construct a boolean vector from external representation */ - template::from(std::declval()))> constexpr explicit BoolVector(const U& other) noexcept: BoolVector{Implementation::BoolVectorConverter::from(other)} {} - - /** @brief Convert a boolean vector to external representation */ - template::to(std::declval>()))> constexpr explicit operator U() const { - return Implementation::BoolVectorConverter::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& 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& other) const; - - /** @brief Non-equality comparison */ - bool operator!=(const BoolVector& 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 operator~() const; - - /** - * @brief Component-wise boolean negation - * @m_since{2019,10} - * - * Equivalent to @ref operator~(). See @ref Math-BoolVector-boolean for - * more information. - */ - BoolVector operator!() const { return operator~(); } - - /** - * @brief Bitwise AND and assign - * - * The computation is done in-place. - */ - BoolVector& operator&=(const BoolVector& other) { - for(std::size_t i = 0; i != DataSize; ++i) - _data[i] &= other._data[i]; - - return *this; - } +#include "Magnum/configure.h" - /** - * @brief Bitwise AND - * - * @see @ref operator&=() - */ - BoolVector operator&(const BoolVector& other) const { - return BoolVector(*this) &= other; - } +#ifdef MAGNUM_BUILD_DEPRECATED +#include - /** - * @brief Component-wise boolean AND - * @m_since{2019,10} - * - * Equivalent to @ref operator&(). See @ref Math-BoolVector-boolean for - * more information. - */ - BoolVector operator&&(const BoolVector& other) const { - return BoolVector(*this) &= other; - } +#include "Magnum/Math/BitVector.h" - /** - * @brief Bitwise OR and assign - * - * The computation is done in-place. - */ - BoolVector& operator|=(const BoolVector& other) { - for(std::size_t i = 0; i != DataSize; ++i) - _data[i] |= other._data[i]; +CORRADE_DEPRECATED_FILE("use Magnum/Math/BitVector.h and the BitVector class instead") - return *this; - } - - /** - * @brief Bitwise OR - * - * @see @ref operator|=() - */ - BoolVector operator|(const BoolVector& other) const { - return BoolVector(*this) |= other; - } - - /** - * @brief Component-wise boolean OR - * @m_since{2019,10} - * - * Equivalent to @ref operator|(). See @ref Math-BoolVector-boolean for - * more information. - */ - BoolVector operator||(const BoolVector& other) const { - return BoolVector(*this) |= other; - } - - /** - * @brief Bitwise XOR and assign - * - * The computation is done in-place. - */ - BoolVector& operator^=(const BoolVector& other) { - for(std::size_t i = 0; i != DataSize; ++i) - _data[i] ^= other._data[i]; - - return *this; - } - - /** - * @brief Bitwise XOR - * - * @see @ref operator^=() - */ - BoolVector operator^(const BoolVector& other) const { - return BoolVector(*this) ^= other; - } - - private: - enum: UnsignedByte { - FullSegmentMask = 0xFF, - LastSegmentMask = (1 << size%8) - 1 - }; - - /* Implementation for Vector::Vector(U) */ - template constexpr explicit BoolVector(Corrade::Containers::Implementation::Sequence, UnsignedByte value): _data{Implementation::repeat(value, sequence)...} {} - - UnsignedByte _data[(size-1)/8+1]; -}; +namespace Magnum { namespace Math { -#ifndef CORRADE_NO_DEBUG /** -@debugoperator{BoolVector} - -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 - - - -@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. +@brief @copybrief BitVector +@m_deprecated_since_latest Use @ref BitVector instead. */ -template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug& debug, const BoolVector& value) { - debug << "BoolVector(0b" << Corrade::Utility::Debug::nospace; - - /* Print the full bytes comma-separated */ - for(std::size_t byte = 0; byte != BoolVector::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 inline bool BoolVector::operator==(const BoolVector& 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 inline bool BoolVector::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 inline bool BoolVector::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 inline BoolVector BoolVector::operator~() const { - BoolVector out{Magnum::NoInit}; - - for(std::size_t i = 0; i != DataSize; ++i) - out._data[i] = ~_data[i]; - - return out; -} - -namespace Implementation { - -template struct StrictWeakOrdering> { - bool operator()(const BoolVector& a, const BoolVector& b) const { - auto ad = a.data(); - auto bd = b.data(); - for(std::size_t i = 0; i < BoolVector::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::DataSize * 8 - size); - constexpr std::size_t i = BoolVector::DataSize - 1; - return (ad[i] & mask) < (bd[i] & mask); - } -}; - -} +template using BoolVector CORRADE_DEPRECATED_ALIAS("use BitVector instead") = BitVector; }} +#endif #endif diff --git a/src/Magnum/Math/CMakeLists.txt b/src/Magnum/Math/CMakeLists.txt index 08204b359..95cedd867 100644 --- a/src/Magnum/Math/CMakeLists.txt +++ b/src/Magnum/Math/CMakeLists.txt @@ -30,7 +30,7 @@ set(CMAKE_FOLDER "Magnum/Math") set(MagnumMath_HEADERS Angle.h Bezier.h - BoolVector.h + BitVector.h Color.h Complex.h Constants.h @@ -64,6 +64,10 @@ set(MagnumMath_HEADERS Vector3.h Vector4.h) +if(MAGNUM_BUILD_DEPRECATED) + list(APPEND MagnumMath_HEADERS BoolVector.h) +endif() + set(MagnumMath_INTERNAL_HEADERS Implementation/halfTables.hpp) diff --git a/src/Magnum/Math/Functions.h b/src/Magnum/Math/Functions.h index 0ffa0dfb2..8f7ebd177 100644 --- a/src/Magnum/Math/Functions.h +++ b/src/Magnum/Math/Functions.h @@ -56,9 +56,9 @@ namespace Implementation { template constexpr static T pow(T) { return T(1); } }; - template struct IsBoolVectorOrScalar: std::false_type {}; - template<> struct IsBoolVectorOrScalar: std::true_type {}; - template struct IsBoolVectorOrScalar>: std::true_type {}; + template struct IsBitVectorOrScalar: std::false_type {}; + template<> struct IsBitVectorOrScalar: std::true_type {}; + template struct IsBitVectorOrScalar>: std::true_type {}; } /** @@ -250,8 +250,8 @@ template inline typename std::enable_if::value, bool>::type @overload @m_since{2019,10} */ -template inline BoolVector isInf(const Vector& value) { - BoolVector out; +template inline BitVector isInf(const Vector& value) { + BitVector out; for(std::size_t i = 0; i != size; ++i) out.set(i, Math::isInf(value[i])); return out; @@ -272,8 +272,8 @@ template typename std::enable_if::value, bool>::type isNan( @overload @m_since{2019,10} */ -template inline BoolVector isNan(const Vector& value) { - BoolVector out; +template inline BitVector isNan(const Vector& value) { + BitVector out; for(std::size_t i = 0; i != size; ++i) out.set(i, Math::isNan(value[i])); return out; @@ -507,7 +507,7 @@ See @ref select() for constant interpolation using the same API and */ template inline #ifndef DOXYGEN_GENERATING_OUTPUT - typename std::enable_if<(IsVector::value || IsScalar::value) && !Implementation::IsBoolVectorOrScalar::value, T>::type + typename std::enable_if<(IsVector::value || IsScalar::value) && !Implementation::IsBitVectorOrScalar::value, T>::type #else T #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. @m_keyword{mix(),GLSL mix(),} */ -template inline Vector lerp(const Vector& a, const Vector& b, const BoolVector& t) { +template inline Vector lerp(const Vector& a, const Vector& b, const BitVector& t) { Vector out{Magnum::NoInit}; for(std::size_t i = 0; i != size; ++i) out[i] = t[i] ? b[i] : a[i]; @@ -537,10 +537,10 @@ template inline Vector lerp(const Vector inline BoolVector lerp(const BoolVector& a, const BoolVector& b, const BoolVector& t) { +template inline BitVector lerp(const BitVector& a, const BitVector& b, const BitVector& t) { /* Not using NoInit because it causes some compilers to report unitialized value */ - BoolVector out; + BitVector out; for(std::size_t i = 0; i != size; ++i) out.set(i, t[i] ? b[i] : a[i]); return out; diff --git a/src/Magnum/Math/FunctionsBatch.h b/src/Magnum/Math/FunctionsBatch.h index 1dd357b82..c52f03811 100644 --- a/src/Magnum/Math/FunctionsBatch.h +++ b/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 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 -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() */ template auto isInf(const Corrade::Containers::StridedArrayView1D& range) -> decltype(isInf(std::declval())) { @@ -68,7 +68,7 @@ template auto isInf(const Corrade::Containers::StridedArrayView1D inline auto isInf(const T(&array)[size]) -> @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, -@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, -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() */ template inline auto isNan(const Corrade::Containers::StridedArrayView1D& range) -> decltype(isNan(std::declval())) { @@ -120,7 +120,7 @@ template inline auto isNan(const Corrade::Containers::StridedArrayView1 /* 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 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) { if(out) break; out = out || isNan(range[i]); @@ -183,7 +183,7 @@ namespace Implementation { T out = range[0]; std::size_t firstValid = 0; for(std::size_t i = 1; i != range.size(); ++i) { - BoolVector nans = isNan(out); + BitVector nans = isNan(out); if(nans.none()) break; if(nans.all() && firstValid + 1 == i) ++firstValid; out = Math::lerp(out, range[i], isNan(out)); diff --git a/src/Magnum/Math/Math.h b/src/Magnum/Math/Math.h index fa37a0e63..be95511dc 100644 --- a/src/Magnum/Math/Math.h +++ b/src/Magnum/Math/Math.h @@ -33,12 +33,19 @@ #include "Magnum/Types.h" +#ifdef MAGNUM_BUILD_DEPRECATED +#include +#endif + namespace Magnum { namespace Math { /** @todo Denormals to zero */ #ifndef DOXYGEN_GENERATING_OUTPUT -template class BoolVector; +template class BitVector; +#ifdef MAGNUM_BUILD_DEPRECATED +template using BoolVector CORRADE_DEPRECATED_ALIAS("use BitVector instead") = BitVector; +#endif template struct Constants; diff --git a/src/Magnum/Math/RectangularMatrix.h b/src/Magnum/Math/RectangularMatrix.h index 8d1c7cedf..4ec965101 100644 --- a/src/Magnum/Math/RectangularMatrix.h +++ b/src/Magnum/Math/RectangularMatrix.h @@ -303,7 +303,7 @@ template class RectangularMatrix { * * Calls @ref Vector::operator<() on @ref toVector(). */ - BoolVector operator<(const RectangularMatrix& other) const { + BitVector operator<(const RectangularMatrix& other) const { return toVector() < other.toVector(); } @@ -312,7 +312,7 @@ template class RectangularMatrix { * * Calls @ref Vector::operator<=() on @ref toVector(). */ - BoolVector operator<=(const RectangularMatrix& other) const { + BitVector operator<=(const RectangularMatrix& other) const { return toVector() <= other.toVector(); } @@ -321,7 +321,7 @@ template class RectangularMatrix { * * Calls @ref Vector::operator>=() on @ref toVector(). */ - BoolVector operator>=(const RectangularMatrix& other) const { + BitVector operator>=(const RectangularMatrix& other) const { return toVector() >= other.toVector(); } @@ -330,7 +330,7 @@ template class RectangularMatrix { * * Calls @ref Vector::operator>() on @ref toVector(). */ - BoolVector operator>(const RectangularMatrix& other) const { + BitVector operator>(const RectangularMatrix& other) const { return toVector() > other.toVector(); } diff --git a/src/Magnum/Math/Test/BitVectorTest.cpp b/src/Magnum/Math/Test/BitVectorTest.cpp new file mode 100644 index 000000000..cf83a50fe --- /dev/null +++ b/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š + + 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 +#include +#include +#include /* 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::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::value); + CORRADE_VERIFY(std::is_nothrow_constructible::value); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!std::is_convertible::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::value); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!std::is_convertible::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::value); + + CORRADE_VERIFY(std::is_nothrow_constructible::value); +} + +void BitVectorTest::constructOneElement() { + typedef BitVector<1> BitVector1; + + constexpr BitVector1 a = 0x01; + CORRADE_COMPARE(a, BitVector1(0x01)); + + CORRADE_VERIFY(std::is_nothrow_constructible::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::value); + CORRADE_VERIFY(std::is_trivially_copy_assignable::value); + #endif + CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); + CORRADE_VERIFY(std::is_nothrow_copy_assignable::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>::value); + CORRADE_VERIFY(!std::is_convertible, 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::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) diff --git a/src/Magnum/Math/Test/BoolVectorTest.cpp b/src/Magnum/Math/Test/BoolVectorTest.cpp deleted file mode 100644 index c2989348b..000000000 --- a/src/Magnum/Math/Test/BoolVectorTest.cpp +++ /dev/null @@ -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š - - 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 -#include -#include -#include /* 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::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::value); - CORRADE_VERIFY(std::is_nothrow_constructible::value); - - /* Implicit construction is not allowed */ - CORRADE_VERIFY(!std::is_convertible::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::value); - - /* Implicit construction is not allowed */ - CORRADE_VERIFY(!std::is_convertible::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::value); - - CORRADE_VERIFY(std::is_nothrow_constructible::value); -} - -void BoolVectorTest::constructOneElement() { - typedef BoolVector<1> BoolVector1; - - constexpr BoolVector1 a = 0x01; - CORRADE_COMPARE(a, BoolVector1(0x01)); - - CORRADE_VERIFY(std::is_nothrow_constructible::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::value); - CORRADE_VERIFY(std::is_trivially_copy_assignable::value); - #endif - CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); - CORRADE_VERIFY(std::is_nothrow_copy_assignable::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>::value); - CORRADE_VERIFY(!std::is_convertible, 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::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) diff --git a/src/Magnum/Math/Test/CMakeLists.txt b/src/Magnum/Math/Test/CMakeLists.txt index a657d8f50..9251da396 100644 --- a/src/Magnum/Math/Test/CMakeLists.txt +++ b/src/Magnum/Math/Test/CMakeLists.txt @@ -27,7 +27,7 @@ # property that would have to be set on each target separately. 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(MathFunctionsTest FunctionsTest.cpp LIBRARIES MagnumMathTestLib) corrade_add_test(MathFunctionsBatchTest FunctionsBatchTest.cpp LIBRARIES MagnumMathTestLib) diff --git a/src/Magnum/Math/Test/FunctionsBatchTest.cpp b/src/Magnum/Math/Test/FunctionsBatchTest.cpp index 04be44fe8..5043edda8 100644 --- a/src/Magnum/Math/Test/FunctionsBatchTest.cpp +++ b/src/Magnum/Math/Test/FunctionsBatchTest.cpp @@ -71,13 +71,13 @@ void FunctionsBatchTest::isInf() { CORRADE_COMPARE(Math::isInf({Vector2{5.0f, -3.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}, 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{})); - CORRADE_COMPARE(Math::isInf(std::initializer_list{}), BoolVector<3>{0}); + CORRADE_COMPARE(Math::isInf(std::initializer_list{}), BitVector<3>{0}); const Float a[]{5.0f, -2.0f, -Constants::inf()}; CORRADE_VERIFY(Math::isInf(a)); @@ -86,15 +86,15 @@ void FunctionsBatchTest::isInf() { CORRADE_VERIFY(!Math::isInf(b)); 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 */ - CORRADE_COMPARE(Math::isInf(Corrade::Containers::StridedArrayView1D{c}), BoolVector<2>{1}); + CORRADE_COMPARE(Math::isInf(Corrade::Containers::StridedArrayView1D{c}), BitVector<2>{1}); /* This should work without explicit casts or types */ CORRADE_VERIFY(!Math::isInf(std::vector{5.0f, -2.0f, -1.0f})); CORRADE_COMPARE(Math::isInf(std::vector{ {5.0f, -3.0f}, {-2.0f, 14.0f}, {Constants::inf(), -5.0f} - }), BoolVector<2>{1}); + }), BitVector<2>{1}); } void FunctionsBatchTest::isNan() { @@ -103,13 +103,13 @@ void FunctionsBatchTest::isNan() { CORRADE_COMPARE(Math::isNan({Vector2{5.0f, -3.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}, 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{})); - CORRADE_COMPARE(Math::isNan(std::initializer_list{}), BoolVector<3>{0}); + CORRADE_COMPARE(Math::isNan(std::initializer_list{}), BitVector<3>{0}); const Float a[]{5.0f, -Constants::nan(), -2.0f}; CORRADE_VERIFY(Math::isNan(a)); @@ -118,15 +118,15 @@ void FunctionsBatchTest::isNan() { CORRADE_VERIFY(!Math::isNan(b)); 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 */ - CORRADE_COMPARE(Math::isNan(Corrade::Containers::StridedArrayView1D{c}), BoolVector<2>{2}); + CORRADE_COMPARE(Math::isNan(Corrade::Containers::StridedArrayView1D{c}), BitVector<2>{2}); /* This should work without explicit casts or types */ CORRADE_VERIFY(!Math::isNan(std::vector{5.0f, -2.0f, -1.0f})); CORRADE_COMPARE(Math::isNan(std::vector{ {5.0f, -3.0f}, {14.0f, Constants::nan()}, {-2.0f, -5.0f} - }), BoolVector<2>{2}); + }), BitVector<2>{2}); } void FunctionsBatchTest::min() { diff --git a/src/Magnum/Math/Test/FunctionsTest.cpp b/src/Magnum/Math/Test/FunctionsTest.cpp index c110c92f2..e642a0787 100644 --- a/src/Magnum/Math/Test/FunctionsTest.cpp +++ b/src/Magnum/Math/Test/FunctionsTest.cpp @@ -387,11 +387,11 @@ void FunctionsTest::lerp() { void FunctionsTest::lerpBool() { /* Scalar interpolation phase */ 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 */ - CORRADE_COMPARE(Math::lerp(Vector3i{1, 2, 3}, Vector3i{5, 6, 7}, BoolVector<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(Vector3i{1, 2, 3}, Vector3i{5, 6, 7}, BitVector<3>(5)), (Vector3i{5, 2, 7})); + CORRADE_COMPARE(Math::lerp(BitVector<3>{false}, BitVector<3>{true}, BitVector<3>(5)), BitVector<3>{5}); /* Wrapped types */ CORRADE_COMPARE(Math::lerp(2.0_degf, 5.0_degf, true), 5.0_degf); @@ -432,8 +432,8 @@ void FunctionsTest::select() { void FunctionsTest::selectBool() { 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::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}, 1.1f), Math::BitVector<4>{0x5}); + 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 */ CORRADE_COMPARE(Math::select(true, false, 0.5_degf), true); @@ -482,8 +482,8 @@ void FunctionsTest::isInf() { } 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, 1.0f, -Constants::nan()}), Math::BoolVector<3>{0x00}); + 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::BitVector<3>{0x00}); } void FunctionsTest::isNan() { @@ -498,8 +498,8 @@ void FunctionsTest::isNan() { } 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, -Constants::inf(), 1.0f}), Math::BoolVector<3>{0x00}); + 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::BitVector<3>{0x00}); } void FunctionsTest::reflect() { diff --git a/src/Magnum/Math/Test/IntersectionBenchmark.cpp b/src/Magnum/Math/Test/IntersectionBenchmark.cpp index 0cb8cfb95..eecaa2880 100644 --- a/src/Magnum/Math/Test/IntersectionBenchmark.cpp +++ b/src/Magnum/Math/Test/IntersectionBenchmark.cpp @@ -38,7 +38,7 @@ template bool rangeFrustumNaive(const Math::Range3D& box, const Math bool cornerHit = 0; for(UnsignedByte c = 0; c != 8; ++c) { - const Math::Vector3 corner = Math::lerp(box.min(), box.max(), Math::BoolVector<3>{c}); + const Math::Vector3 corner = Math::lerp(box.min(), box.max(), Math::BitVector<3>{c}); if(Distance::pointPlaneScaled(corner, plane) >= T(0)) { cornerHit = true; diff --git a/src/Magnum/Math/Test/RectangularMatrixTest.cpp b/src/Magnum/Math/Test/RectangularMatrixTest.cpp index b468156f8..03696923d 100644 --- a/src/Magnum/Math/Test/RectangularMatrixTest.cpp +++ b/src/Magnum/Math/Test/RectangularMatrixTest.cpp @@ -470,12 +470,12 @@ void RectangularMatrixTest::compare() { } void RectangularMatrixTest::compareComponentWise() { - typedef BoolVector<3> BoolVector3; + typedef BitVector<3> BitVector3; 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), BoolVector3(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), BoolVector3(0x4)); + 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), BitVector3(0x3)); + 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), BitVector3(0x4)); } void RectangularMatrixTest::negative() { diff --git a/src/Magnum/Math/Test/VectorTest.cpp b/src/Magnum/Math/Test/VectorTest.cpp index 5bee04396..e351fb23e 100644 --- a/src/Magnum/Math/Test/VectorTest.cpp +++ b/src/Magnum/Math/Test/VectorTest.cpp @@ -375,21 +375,21 @@ void VectorTest::compare() { } void VectorTest::compareComponentWise() { - typedef BoolVector<3> BoolVector3; - typedef BoolVector<4> BoolVector4; + typedef BitVector<3> BitVector3; + typedef BitVector<4> BitVector4; Vector4 a{1.0f, -3.5f, 5.0f, -10.0f}; Vector4 b{1.0f + TypeTraits::epsilon()/2, -3.5f, 5.0f - TypeTraits::epsilon()*2, -10.0f}; Vector4 c{1.0f + TypeTraits::epsilon()*2, -3.5f, 5.0f - TypeTraits::epsilon()*10, -10.0f}; - CORRADE_COMPARE(equal(a, b), BoolVector4{0xf}); - CORRADE_COMPARE(equal(a, c), BoolVector4{0xa}); - CORRADE_COMPARE(notEqual(a, b), BoolVector4{0x0}); - CORRADE_COMPARE(notEqual(a, c), BoolVector4{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), BoolVector3(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), BoolVector3(0x4)); + CORRADE_COMPARE(equal(a, b), BitVector4{0xf}); + CORRADE_COMPARE(equal(a, c), BitVector4{0xa}); + CORRADE_COMPARE(notEqual(a, b), BitVector4{0x0}); + CORRADE_COMPARE(notEqual(a, c), BitVector4{0x5}); + + 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), BitVector3(0x3)); + 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), BitVector3(0x4)); } void VectorTest::negative() { diff --git a/src/Magnum/Math/TypeTraits.h b/src/Magnum/Math/TypeTraits.h index 449bbc421..3dda3fb04 100644 --- a/src/Magnum/Math/TypeTraits.h +++ b/src/Magnum/Math/TypeTraits.h @@ -138,7 +138,7 @@ template struct IsScalar>: std::true_type {}; Equivalent to @ref std::true_type for all @ref Vector types and their 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. @see @ref IsScalar, @ref IsFloatingPoint, @ref IsIntegral */ diff --git a/src/Magnum/Math/Vector.h b/src/Magnum/Math/Vector.h index 1f13f6c05..4efbf4485 100644 --- a/src/Magnum/Math/Vector.h +++ b/src/Magnum/Math/Vector.h @@ -38,7 +38,7 @@ #include "Magnum/visibility.h" #include "Magnum/Math/Angle.h" -#include "Magnum/Math/BoolVector.h" +#include "Magnum/Math/BitVector.h" #include "Magnum/Math/TypeTraits.h" namespace Magnum { namespace Math { @@ -283,28 +283,28 @@ template class Vector { * * @m_keyword{lessThan(),GLSL lessThan(),} */ - BoolVector operator<(const Vector& other) const; + BitVector operator<(const Vector& other) const; /** * @brief Component-wise less than or equal comparison * * @m_keyword{lessThanEqual(),GLSL lessThanEqual(),} */ - BoolVector operator<=(const Vector& other) const; + BitVector operator<=(const Vector& other) const; /** * @brief Component-wise greater than or equal comparison * * @m_keyword{greaterThanEqual(),GLSL greaterThanEqual(),} */ - BoolVector operator>=(const Vector& other) const; + BitVector operator>=(const Vector& other) const; /** * @brief Component-wise greater than comparison * * @m_keyword{greaterThan(),GLSL greaterThan(),} */ - BoolVector operator>(const Vector& other) const; + BitVector operator>(const Vector& other) const; /** * @brief Whether the vector is zero @@ -699,8 +699,8 @@ template class Vector { /* So the out-of-class comparators can access data directly to avoid function call overhead */ - template friend BoolVector equal(const Vector&, const Vector&); - template friend BoolVector notEqual(const Vector&, const Vector&); + template friend BitVector equal(const Vector&, const Vector&); + template friend BitVector notEqual(const Vector&, const Vector&); template friend U dot(const Vector&, const Vector&); @@ -723,11 +723,11 @@ template class Vector { @brief Component-wise equality comparison @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). */ -template inline BoolVector equal(const Vector& a, const Vector& b) { - BoolVector out; +template inline BitVector equal(const Vector& a, const Vector& b) { + BitVector out; for(std::size_t i = 0; i != size; ++i) out.set(i, TypeTraits::equals(a._data[i], b._data[i])); @@ -739,11 +739,11 @@ template inline BoolVector equal(const Vector inline BoolVector notEqual(const Vector& a, const Vector& b) { - BoolVector out; +template inline BitVector notEqual(const Vector& a, const Vector& b) { + BitVector out; for(std::size_t i = 0; i != size; ++i) out.set(i, !TypeTraits::equals(a._data[i], b._data[i])); @@ -1441,8 +1441,8 @@ extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utili } #endif -template inline BoolVector Vector::operator<(const Vector& other) const { - BoolVector out; +template inline BitVector Vector::operator<(const Vector& other) const { + BitVector out; for(std::size_t i = 0; i != size; ++i) out.set(i, _data[i] < other._data[i]); @@ -1450,8 +1450,8 @@ template inline BoolVector Vector::ope return out; } -template inline BoolVector Vector::operator<=(const Vector& other) const { - BoolVector out; +template inline BitVector Vector::operator<=(const Vector& other) const { + BitVector out; for(std::size_t i = 0; i != size; ++i) out.set(i, _data[i] <= other._data[i]); @@ -1459,8 +1459,8 @@ template inline BoolVector Vector::ope return out; } -template inline BoolVector Vector::operator>=(const Vector& other) const { - BoolVector out; +template inline BitVector Vector::operator>=(const Vector& other) const { + BitVector out; for(std::size_t i = 0; i != size; ++i) out.set(i, _data[i] >= other._data[i]); @@ -1468,8 +1468,8 @@ template inline BoolVector Vector::ope return out; } -template inline BoolVector Vector::operator>(const Vector& other) const { - BoolVector out; +template inline BitVector Vector::operator>(const Vector& other) const { + BitVector out; for(std::size_t i = 0; i != size; ++i) out.set(i, _data[i] > other._data[i]); diff --git a/src/Magnum/MeshTools/Compile.cpp b/src/Magnum/MeshTools/Compile.cpp index 5f16c789c..f9cb2e02c 100644 --- a/src/Magnum/MeshTools/Compile.cpp +++ b/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 attribs at most. */ - Math::BoolVector<16> boundAttributes; + Math::BitVector<16> boundAttributes; for(UnsignedInt i = 0; i != meshData.attributeCount(); ++i) { Containers::Optional attribute; diff --git a/src/Magnum/Trade/AnimationData.cpp b/src/Magnum/Trade/AnimationData.cpp index ef65c7320..b7be3f127 100644 --- a/src/Magnum/Trade/AnimationData.cpp +++ b/src/Magnum/Trade/AnimationData.cpp @@ -123,9 +123,9 @@ template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor(Animation template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor(Animation::Interpolation) -> Float(*)(const Float&, const Float&, Float); template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor(Animation::Interpolation) -> UnsignedInt(*)(const UnsignedInt&, const UnsignedInt&, Float); template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor(Animation::Interpolation) -> Int(*)(const Int&, const Int&, Float); -template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor, Math::BoolVector<2>>(Animation::Interpolation) -> Math::BoolVector<2>(*)(const Math::BoolVector<2>&, const Math::BoolVector<2>&, Float); -template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor, Math::BoolVector<3>>(Animation::Interpolation) -> Math::BoolVector<3>(*)(const Math::BoolVector<3>&, const Math::BoolVector<3>&, Float); -template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor, 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<2>>(Animation::Interpolation) -> Math::BitVector<2>(*)(const Math::BitVector<2>&, const Math::BitVector<2>&, Float); +template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor, Math::BitVector<3>>(Animation::Interpolation) -> Math::BitVector<3>(*)(const Math::BitVector<3>&, const Math::BitVector<3>&, Float); +template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor, Math::BitVector<4>>(Animation::Interpolation) -> Math::BitVector<4>(*)(const Math::BitVector<4>&, const Math::BitVector<4>&, Float); template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor(Animation::Interpolation) -> Vector2(*)(const Vector2&, const Vector2&, Float); template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor(Animation::Interpolation) -> Vector2i(*)(const Vector2i&, const Vector2i&, Float); template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor(Animation::Interpolation) -> Vector2ui(*)(const Vector2ui&, const Vector2ui&, Float); @@ -157,9 +157,9 @@ Debug& operator<<(Debug& debug, const AnimationTrackType value) { _c(Float) _c(UnsignedInt) _c(Int) - _c(BoolVector2) - _c(BoolVector3) - _c(BoolVector4) + _c(BitVector2) + _c(BitVector3) + _c(BitVector4) _c(Vector2) _c(Vector2ui) _c(Vector2i) diff --git a/src/Magnum/Trade/AnimationData.h b/src/Magnum/Trade/AnimationData.h index e2231b994..05a92eced 100644 --- a/src/Magnum/Trade/AnimationData.h +++ b/src/Magnum/Trade/AnimationData.h @@ -49,9 +49,51 @@ enum class AnimationTrackType: UnsignedByte { Float, /**< @ref Magnum::Float "Float" */ UnsignedInt, /**< @ref Magnum::UnsignedInt "UnsignedInt" */ 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 @@ -609,9 +651,9 @@ namespace Implementation { template<> constexpr AnimationTrackType animationTypeFor() { return AnimationTrackType::UnsignedInt; } template<> constexpr AnimationTrackType animationTypeFor() { return AnimationTrackType::Int; } - template<> constexpr AnimationTrackType animationTypeFor>() { return AnimationTrackType::BoolVector2; } - template<> constexpr AnimationTrackType animationTypeFor>() { return AnimationTrackType::BoolVector3; } - template<> constexpr AnimationTrackType animationTypeFor>() { return AnimationTrackType::BoolVector4; } + template<> constexpr AnimationTrackType animationTypeFor>() { return AnimationTrackType::BitVector2; } + template<> constexpr AnimationTrackType animationTypeFor>() { return AnimationTrackType::BitVector3; } + template<> constexpr AnimationTrackType animationTypeFor>() { return AnimationTrackType::BitVector4; } template<> constexpr AnimationTrackType animationTypeFor() { return AnimationTrackType::Vector2; } template<> constexpr AnimationTrackType animationTypeFor() { return AnimationTrackType::Vector3; } diff --git a/src/Magnum/Trade/SceneData.cpp b/src/Magnum/Trade/SceneData.cpp index c86a70159..4f88b3809 100644 --- a/src/Magnum/Trade/SceneData.cpp +++ b/src/Magnum/Trade/SceneData.cpp @@ -546,7 +546,7 @@ SceneData::SceneData(const SceneMappingType mappingType, const UnsignedLong mapp #ifndef CORRADE_NO_ASSERT /* 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); #endif UnsignedInt transformationField = ~UnsignedInt{}; diff --git a/src/Magnum/Vk/Device.cpp b/src/Magnum/Vk/Device.cpp index 9f80a2aff..4591799b7 100644 --- a/src/Magnum/Vk/Device.cpp +++ b/src/Magnum/Vk/Device.cpp @@ -99,7 +99,7 @@ struct DeviceCreateInfo::State { void* firstEnabledFeature{}; /* Used for checking if the device enables extensions required by features */ #ifndef CORRADE_NO_ASSERT - Math::BoolVector featuresRequiredExtensions; + Math::BitVector featuresRequiredExtensions; #endif Containers::String disabledExtensionsStorage; @@ -803,7 +803,7 @@ Result Device::tryCreateInternal(Instance& instance, const DeviceCreateInfo& inf #ifndef CORRADE_NO_ASSERT /* This is a dumb O(n^2) search but in an assert that's completely fine */ - const Math::BoolVector missingExtensions = ~_enabledExtensions & info._state->featuresRequiredExtensions; + const Math::BitVector missingExtensions = ~_enabledExtensions & info._state->featuresRequiredExtensions; if(missingExtensions.any()) { for(std::size_t i = 0; i != Implementation::ExtensionCount; ++i) { if(!missingExtensions[i]) continue; diff --git a/src/Magnum/Vk/Device.h b/src/Magnum/Vk/Device.h index 1a1060af1..0e071e676 100644 --- a/src/Magnum/Vk/Device.h +++ b/src/Magnum/Vk/Device.h @@ -35,7 +35,7 @@ #include #include "Magnum/Tags.h" -#include "Magnum/Math/BoolVector.h" +#include "Magnum/Math/BitVector.h" #include "Magnum/Vk/TypeTraits.h" #include "Magnum/Vk/Vk.h" #include "Magnum/Vk/Vulkan.h" @@ -511,7 +511,7 @@ class MAGNUM_VK_EXPORT Device { VkDevice _handle; HandleFlags _flags; Version _version; - Math::BoolVector _enabledExtensions; + Math::BitVector _enabledExtensions; DeviceFeatures _enabledFeatures; Containers::Pointer _properties; Containers::Pointer _state; diff --git a/src/Magnum/Vk/Instance.h b/src/Magnum/Vk/Instance.h index e4b1e7f41..987f7c3f0 100644 --- a/src/Magnum/Vk/Instance.h +++ b/src/Magnum/Vk/Instance.h @@ -33,7 +33,7 @@ #include #include "Magnum/Tags.h" -#include "Magnum/Math/BoolVector.h" +#include "Magnum/Math/BitVector.h" #include "Magnum/Vk/TypeTraits.h" #include "Magnum/Vk/Vk.h" #include "Magnum/Vk/Vulkan.h" @@ -441,7 +441,7 @@ class MAGNUM_VK_EXPORT Instance { VkInstance _handle; HandleFlags _flags; Version _version; - Math::BoolVector _extensionStatus; + Math::BitVector _extensionStatus; Containers::Pointer _state; /* This member is bigger than you might think */ diff --git a/src/singles/MagnumMath.hpp b/src/singles/MagnumMath.hpp index d8c0d8883..3ab46ddc8 100644 --- a/src/singles/MagnumMath.hpp +++ b/src/singles/MagnumMath.hpp @@ -161,9 +161,9 @@ namespace Magnum { typedef Math::Half Half; -typedef Math::BoolVector<2> BoolVector2; -typedef Math::BoolVector<3> BoolVector3; -typedef Math::BoolVector<4> BoolVector4; +typedef Math::BitVector<2> BitVector2; +typedef Math::BitVector<3> BitVector3; +typedef Math::BitVector<4> BitVector4; typedef Math::Vector2 Vector2; typedef Math::Vector3 Vector3; typedef Math::Vector4 Vector4;