1 /* Copyright Jukka Jyl�nki
2
3    Licensed under the Apache License, Version 2.0 (the "License");
4    you may not use this file except in compliance with the License.
5    You may obtain a copy of the License at
6
7        http://www.apache.org/licenses/LICENSE-2.0
8
9    Unless required by applicable law or agreed to in writing, software
10    distributed under the License is distributed on an "AS IS" BASIS,
11    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12    See the License for the specific language governing permissions and
13    limitations under the License. */
14
15 /** @file BitOps.h
16         @author Jukka Jyl�nki
17         @brief */
18 #pragma once
19
20 #include "myassert.h"
21 #include "../MathGeoLibFwd.h"
22 #include "MathTypes.h"
23
24 MATH_BEGIN_NAMESPACE
25
26 /// Parses a string of form "010101010" to a u32.
27 u32 BinaryStringToValue(const char *str);
28
29 /// Returns the number of 1's set in the given value.
30 inline int CountBitsSet(u32 value)
31 {
32         int bits = 0;
33         while(value)
34         {
35                 value &= value - 1;
36                 ++bits;
37         }
38         return bits;
39 }
40
41 // Clears the LSB bit and returns the zero-based index of where the bit was set.
42 inline int ExtractLSB(unsigned long *value)
43 {
44         for(int i = 0; i < 32; ++i)
45                 if ((*value & (1 << i)) != 0)
46                 {
47                         *value &= ~(1 << i);
48                         return i;
49                 }
50         return -1;
51 }
52
53 /** @brief Template-evaluated enum that gives a mask with the Bits LSB bits set.
54
55         For example,
56                 LSBT<0>::val = 0,
57                 LSBT<1>::val = 1,
58                 LSBT<2>::val = 11,
59                 LSBT<24>::val = 11111111 11111111 11111111.
60         LSBT<33> and greater are undefined. */
61 template<int Bits>
62 class LSBT
63 {
64 public:
65         static const u32 val = (1 << Bits) - 1;
66 };
67
68 /// @cond FULL
69 /** Specialization for LSBT<32> to avoid the undefined result of 1 << 32. */
70 template<>
71 class LSBT<32>
72 {
73 public:
74         static const u32 val = 0xFFFFFFFF;
75 };
76
77 template<>
78 class LSBT<31>
79 {
80 public:
81         static const u32 val = 0x7FFFFFFF;
82 };
83
84 /// @endcond
85
86 /** @return A mask with the given amount of LSB bits set. This is the runtime-equivalent of LSBT.
87         LSB(0)==0, LSB(1)==1, LSB(8)=11111111, etc.
88         LSB(32) and above are undefined. */
89 inline u32 LSB(u32 bits)
90 {
91         assert(bits <= 32);
92         if (bits >= 32)
93                 return 0xFFFFFFFF;
94         return (1U << bits) - 1;
95 }
96
97 inline u64 LSB64(u64 bits)
98 {
99         assert(bits <= 64);
100         if (bits >= 64)
101                 return 0xFFFFFFFFFFFFFFFFULL;
102         return (1ULL << bits) - 1;
103 }
104
105 /** @brief A template-computed enum to create a mask of given amount of bits at given position of a u32 variable.
106
107         For example,
108         BitMaskT<0,0>::val == 0,
109         BitMaskT<0,8>::val == 11111111,
110         BitMaskT<4, 12>::val == 11111111 11110000, etc.
111         If Pos+Bits > 32, the result is undefined. */
112 template<int Pos, int Bits>
113 class BitMaskT
114 {
115 public:
116 //      enum { val = (Pow<2, Bits>::val - 1) << Pos };          // Alternate way to calculate this value.
117         static const u32 val = LSBT<Pos+Bits>::val & ~LSBT<Pos>::val// But this is nicer.
118 };
119
120 /** @return A mask with the given number of bits set at the given position of a u32 variable. This is
121         the runtime-equivalent of BitMaskT.
122         For example, BitMask(4,4)==11110000. */
123 inline u32 BitMask(u32 pos, u32 bits)
124 {
125         return LSB(pos + bits) & ~LSB(pos);
126 }
127
128 inline u64 BitMask64(u64 pos, u64 bits)
129 {
130         return LSB64(pos + bits) & ~LSB64(pos);
131 }
132
133 /** @return The given 4 bit fields packed into a single larger bitfield.
134         Aggressively templatized version. */
135 template<typename ResultType, typename InputType,
136                         int APos, int ABits, int RPos, int RBits,
137                  int GPos, int GBits, int BPos, int BBits>
138 ResultType PackBits(InputType a, InputType r, InputType g, InputType b)
139 {
140         return (ResultType)(
141                 ((ResultType)a << APos & BitMaskT<APos, ABits>::val) |
142                 ((ResultType)r << RPos & BitMaskT<RPos, RBits>::val) |
143                 ((ResultType)g << GPos & BitMaskT<GPos, GBits>::val) |
144                 ((ResultType)b << BPos & BitMaskT<BPos, BBits>::val));
145 }
146
147 /** @return The given 4 bit fields packed into a single larger bitfield. */
148 template<typename ResultType, typename InputType>
149 ResultType PackBits(int APos, int ABits, int RPos, int RBits,
150                                                                           int GPos, int GBits, int BPos, int BBits,
151                                                                           InputType a, InputType r, InputType g, InputType b)
152 {
153         return (ResultType)(
154                 ((ResultType)a << APos & BitMask(APos, ABits)) |
155                 ((ResultType)r << RPos & BitMask(RPos, RBits)) |
156                 ((ResultType)g << GPos & BitMask(GPos, GBits)) |
157                 ((ResultType)b << BPos & BitMask(BPos, BBits)));
158 }
159
160 /** Extracts the given adjacent bits from a larger bitfield. Aggressively templatized version.
161         For example, ExtractBits<u8, u8, 4, 2> gets the bits 00110000 from a byte,
162         shifts them right 4 places and returns the two bits. */
163 template<typename ResultType, typename InputType, int Pos, int Bits>
164 void ExtractBits(ResultType &out, const InputType &in)
165 {
166         out = (ResultType)(in >> Pos & BitMaskT<0, Bits>::val);
167 }
168
169 /** Extracts the given adjacent bits from a larger bitfield.
170         For example, ExtractBits<u8, u8>(3, 4) gets the bits 01111000 from a byte,
171         shifts them right 3 places and returns the four bits. */
172 template<typename ResultType, typename InputType>
173 void ExtractBits(int pos, int bits, ResultType &out, const InputType &in)
174 {
175         out = (ResultType)(in >> pos & BitMask(0, bits));
176 }
177
178 MATH_END_NAMESPACE

Go back to previous page