git.s-ol.nu ~forks/DiligentCore / 753060f
Basic math: reworked ExtractBit and renamed to ExtractLSB; added tests assiduous 7 months ago
2 changed file(s) with 86 addition(s) and 12 deletion(s). Raw diff Collapse all Expand all
21882188 return x | (y << 1u);
21892189 }
21902190
2191 template <typename T>
2192 inline T ExtractBit(T& bits)
2193 {
2194 static_assert(std::is_enum<T>::value || std::is_integral<T>::value, "T must be enum or integer type");
2195
2196 using U = std::conditional_t<(sizeof(T) > sizeof(Uint32)), Uint64, Uint32>;
2197 VERIFY_EXPR(static_cast<U>(bits) > 0);
2198
2199 const U result = static_cast<U>(bits) & ~(static_cast<U>(bits) - U{1});
2200 bits = static_cast<T>(static_cast<U>(bits) & ~result);
2201
2202 return static_cast<T>(result);
2191 /// Returns the least-signficant bit and clears it in the input argument
2192 template <typename T>
2193 typename std::enable_if<std::is_integral<T>::value, T>::type ExtractLSB(T& bits)
2194 {
2195 if (bits == T{0})
2196 return 0;
2197
2198 const T bit = bits & ~(bits - T{1});
2199 bits &= ~bit;
2200
2201 return bit;
2202 }
2203
2204 /// Returns the enum value representing the least-signficant bit and clears it in the input argument
2205 template <typename T>
2206 typename std::enable_if<std::is_enum<T>::value, T>::type ExtractLSB(T& bits)
2207 {
2208 return static_cast<T>(ExtractLSB(reinterpret_cast<std::underlying_type<T>::type&>(bits)));
22032209 }
22042210
22052211 } // namespace Diligent
16171617 }
16181618 }
16191619
1620 TEST(Common_BasicMath, ExtractLSB)
1621 {
1622 {
1623 Uint32 Bits = 0;
1624 EXPECT_EQ(ExtractLSB(Bits), 0U);
1625 EXPECT_EQ(Bits, 0U);
1626 }
1627
1628 for (Uint8 i = 0; i < 8; ++i)
1629 {
1630 const Uint8 Bit = 1 << i;
1631
1632 Uint8 Bits = Bit;
1633 EXPECT_EQ(ExtractLSB(Bits), Bit);
1634 EXPECT_EQ(Bits, 0U);
1635 }
1636
1637 for (Uint32 i = 0; i < 32; ++i)
1638 {
1639 const Uint32 Bit = 1 << i;
1640
1641 Uint32 Bits = Bit;
1642 EXPECT_EQ(ExtractLSB(Bits), Bit);
1643 EXPECT_EQ(Bits, 0U);
1644 }
1645
1646 for (Uint64 i = 0; i < 64; ++i)
1647 {
1648 const Uint64 Bit = Uint64{1} << i;
1649
1650 Uint64 Bits = Bit;
1651 EXPECT_EQ(ExtractLSB(Bits), Bit);
1652 EXPECT_EQ(Bits, 0U);
1653 }
1654
1655 for (Uint32 i = 0; i < 32; ++i)
1656 {
1657 for (Uint32 j = i + 1; j < 32; ++j)
1658 {
1659 const Uint32 LSB = 1 << i;
1660 const Uint32 MSB = 1 << j;
1661
1662 Uint32 Bits = LSB | MSB;
1663 EXPECT_EQ(ExtractLSB(Bits), LSB);
1664 EXPECT_EQ(ExtractLSB(Bits), MSB);
1665 EXPECT_EQ(Bits, 0U);
1666 }
1667 }
1668
1669 {
1670 enum FLAG_ENUM : Uint32
1671 {
1672 FLAG_ENUM_00 = 0x00,
1673 FLAG_ENUM_01 = 0x01,
1674 FLAG_ENUM_02 = 0x02,
1675 FLAG_ENUM_10 = 0x10
1676 };
1677 FLAG_ENUM Bits = static_cast<FLAG_ENUM>(FLAG_ENUM_01 | FLAG_ENUM_02 | FLAG_ENUM_10);
1678 EXPECT_EQ(ExtractLSB(Bits), FLAG_ENUM_01);
1679 EXPECT_EQ(Bits, static_cast<FLAG_ENUM>(FLAG_ENUM_02 | FLAG_ENUM_10));
1680 EXPECT_EQ(ExtractLSB(Bits), FLAG_ENUM_02);
1681 EXPECT_EQ(Bits, FLAG_ENUM_10);
1682 EXPECT_EQ(ExtractLSB(Bits), FLAG_ENUM_10);
1683 EXPECT_EQ(Bits, FLAG_ENUM_00);
1684 }
1685 }
1686
1687
16201688 TEST(Common_AdvancedMath, IsPointInsideTriangleF)
16211689 {
16221690 {