Branch data Line data Source code
1 : : #ifndef BIT_PAGE_HPP
2 : : #define BIT_PAGE_HPP
3 : :
4 : : #include <assert.h>
5 : : #include "BitTag.hpp"
6 : :
7 : : namespace moab
8 : : {
9 : :
10 : : class Range;
11 : :
12 : : /**\brief bit tag data
13 : : *
14 : : * This class represents a fixed-size block of memory in which bit tag
15 : : * values are stored.
16 : : */
17 : : class BitPage
18 : : {
19 : : public:
20 : : /**\brief Initialize memory
21 : : *
22 : : *\param bits_per_ent Number of bits in each tag value.
23 : : * MUST BE A POWER OF TWO.
24 : : *\param init_val The lower bits_per_ent bits of this byte are
25 : : * used to initialize each tag value.
26 : : */
27 : : BitPage( int bits_per_ent, unsigned char init_val );
28 : :
29 : : /**\brief Get tag values
30 : : *
31 : : * Get 'count' tag values, beginning with the one at 'offset'.
32 : : *\param offset Offset into list of values, where a value of zero indicates
33 : : * the first tag value, a value of one indicates the second
34 : : * tag value, etc. NOTE: This is the value offset, not the
35 : : * bit offset.
36 : : *\param count Number of consecutive tag values to get.
37 : : *\param bits_per_ent Number of bits composing each tag value.
38 : : * NOTE: Must be a power of two.
39 : : *\param data Memory into which to copy tag values. Each value is copied
40 : : * into a separate byte, such that the lower bits of the bit
41 : : * contain the tag value and any unused higher bits are zero.
42 : : */
43 : : void get_bits( int offset, int count, int bits_per_ent, unsigned char* data ) const;
44 : :
45 : : /**\brief Set tag values
46 : : *
47 : : * Set 'count' tag values, beginning with the one at 'offset'.
48 : : *\param offset Offset into list of values, where a value of zero indicates
49 : : * the first tag value, a value of one indicates the second
50 : : * tag value, etc. NOTE: This is the value offset, not the
51 : : * bit offset.
52 : : *\param count Number of consecutive tag values to set.
53 : : *\param bits_per_ent Number of bits composing each tag value.
54 : : * NOTE: Must be a power of two.
55 : : *\param data Memory from which to copy tag values. Each value is copied
56 : : * from a separate byte. The lower 'bits_per_ent' of each
57 : : * byte are used as the tag value. Any additional higher bits
58 : : * are ignored.
59 : : */
60 : : void set_bits( int offset, int count, int bits_per_ent, const unsigned char* data );
61 : :
62 : : /**\brief Set several tag values to the same value.
63 : : *
64 : : * Set 'count' tag values to specified value.
65 : : *\param offset Offset into list of values, where a value of zero indicates
66 : : * the first tag value, a value of one indicates the second
67 : : * tag value, etc. NOTE: This is the value offset, not the
68 : : * bit offset.
69 : : *\param count Number of consecutive tag values to set.
70 : : *\param bits_per_ent Number of bits composing each tag value.
71 : : * NOTE: Must be a power of two.
72 : : *\param value The lower 'bits_per_ent' of this
73 : : * byte are used as the tag value. Any additional higher bits
74 : : * are ignored.
75 : : */
76 : : void set_bits( int offset, int count, int bits_per_ent, unsigned char value );
77 : :
78 : : /**\brief Get tag value
79 : : *
80 : : * Get one tag value.
81 : : *\param offset Offset into list of values, where a value of zero indicates
82 : : * the first tag value, a value of one indicates the second
83 : : * tag value, etc. NOTE: This is the value offset, not the
84 : : * bit offset.
85 : : *\param bits_per_ent Number of bits composing each tag value.
86 : : * NOTE: Must be a power of two.
87 : : *\return A byte containing the tag value in the lower bits with
88 : : * any unused higher bits zeroed.
89 : : */
90 : : unsigned char get_bits( int offset, int bits_per_ent ) const;
91 : :
92 : : /**\brief Set tag value
93 : : *
94 : : * Set tag value.
95 : : *\param offset Offset into list of values, where a value of zero indicates
96 : : * the first tag value, a value of one indicates the second
97 : : * tag value, etc. NOTE: This is the value offset, not the
98 : : * bit offset.
99 : : *\param bits_per_ent Number of bits composing each tag value.
100 : : * NOTE: Must be a power of two.
101 : : *\param value The lower 'bits_per_ent' of this
102 : : * byte are used as the tag value. Any additional higher bits
103 : : * are ignored.
104 : : */
105 : : void set_bits( int offset, int bits_per_ent, unsigned char data );
106 : :
107 : : /**\brief Search stored values for specified value.
108 : : *
109 : : * Find the offsets n in the data at which the specified value occurs,
110 : : * and for each one insert 'start + n' into the passed Range.
111 : : *\param value The value to look for
112 : : *\param offset The offset at which to begin searching
113 : : *\param count The number of values to search
114 : : *\param bits_per_ent Number of bits composing each tag value.
115 : : *\param results Result list.
116 : : *\param start The handle of the entity corresponding to the
117 : : * tag value stored at 'offset'
118 : : */
119 : : void search( unsigned char value, int offset, int count, int bits_per_ent, Range& results,
120 : : EntityHandle start ) const;
121 : :
122 : : private:
123 : : /**\brief The actual array of bytes */
124 : : char byteArray[BitTag::PageSize];
125 : : };
126 : :
127 : 2616384 : inline unsigned char BitPage::get_bits( int offset, int per_ent ) const
128 : : {
129 : : // Assume per_ent is a power of two, which should be guaranteed
130 : : // by higher-level code.
131 : 2616384 : unsigned char mask = (unsigned char)( 1 << per_ent ) - 1; // 2^per_ent - 1
132 : 2616384 : int byte = ( offset * per_ent ) >> 3; // shifting 3 is dividing by eight
133 : 2616384 : int bit = ( offset * per_ent ) & 7; // masking with 7 is modulo eight
134 [ - + ]: 2616384 : assert( byte < BitTag::PageSize );
135 : 2616384 : return (unsigned char)( byteArray[byte] >> bit ) & mask;
136 : : }
137 : :
138 : 4335350 : inline void BitPage::set_bits( int offset, int per_ent, unsigned char bits )
139 : : {
140 : 4335350 : int byte = ( offset * per_ent ) >> 3; // shifting 3 is dividing by eight
141 : 4335350 : int bit = ( offset * per_ent ) & 7; // masking with 7 is modulo eight
142 [ - + ]: 4335350 : assert( byte < BitTag::PageSize );
143 : : // Assume per_ent is a power of two, which should be guaranteed
144 : : // by higher-level code.
145 : 4335350 : unsigned char mask = (unsigned char)( ( 1 << per_ent ) - 1 ) << bit;
146 : 4335350 : byteArray[byte] = (char)( ( byteArray[byte] & ~mask ) | ( ( bits << bit ) & mask ) );
147 : 4335350 : }
148 : :
149 : 9 : inline void BitPage::get_bits( int offset, int count, int per_ent, unsigned char* data ) const
150 : : {
151 : 9 : unsigned char* end = data + count;
152 [ + + ]: 60161 : while( data != end )
153 : 60152 : *( data++ ) = get_bits( offset++, per_ent );
154 : 9 : }
155 : :
156 : 308 : inline void BitPage::set_bits( int offset, int count, int per_ent, const unsigned char* data )
157 : : {
158 : 308 : const unsigned char* end = data + count;
159 [ + + ]: 65640 : while( data != end )
160 : 65332 : set_bits( offset++, per_ent, *( data++ ) );
161 : 308 : }
162 : :
163 : 1151 : inline void BitPage::set_bits( int offset, int count, int per_ent, unsigned char value )
164 : : {
165 : 1151 : int end = offset + count;
166 [ + + ]: 2930 : while( offset < end )
167 : 1779 : set_bits( offset++, per_ent, value );
168 : 1151 : }
169 : :
170 : : } // namespace moab
171 : :
172 : : #endif
|