diff options
Diffstat (limited to 'all_pairs/source/ammunition/bits.c')
-rw-r--r-- | all_pairs/source/ammunition/bits.c | 313 |
1 files changed, 313 insertions, 0 deletions
diff --git a/all_pairs/source/ammunition/bits.c b/all_pairs/source/ammunition/bits.c new file mode 100644 index 0000000..9169656 --- /dev/null +++ b/all_pairs/source/ammunition/bits.c | |||
@@ -0,0 +1,313 @@ | |||
1 | /* | ||
2 | |||
3 | FILE NAME: bits.c | ||
4 | |||
5 | TITLE: Package for work with bits | ||
6 | |||
7 | DESCRIPTION: This file implements functions of the package for work | ||
8 | with bit strings. A bit is given by address (start address) of | ||
9 | byte from which counting bits starts and its displacement which | ||
10 | is any non negative number of bit from the start address. The | ||
11 | most significant bit of the start address byte has number 0. | ||
12 | The bit string is given by its first bit and its length in | ||
13 | bits. | ||
14 | |||
15 | */ | ||
16 | |||
17 | #include "bits.h" | ||
18 | |||
19 | /* This function determines that given bit string contains only zero | ||
20 | bits. The function retruns TRUE if all bits of given bit string | ||
21 | are zero or `bit_length' <= 0. Value of `bit_displacement' must be | ||
22 | non-negative and can be greater than CHAR_BIT. */ | ||
23 | |||
24 | int | ||
25 | ammunition_is_zero_bit_string ( const void *start_byte, int bit_displacement, | ||
26 | int bit_length ) | ||
27 | { | ||
28 | const unsigned char *current_byte = ( unsigned const char * )start_byte; | ||
29 | |||
30 | if ( bit_length <= 0 ) | ||
31 | return 1 /* TRUE */; | ||
32 | current_byte += bit_displacement / CHAR_BIT; | ||
33 | bit_displacement %= CHAR_BIT; | ||
34 | if ( bit_length < CHAR_BIT - bit_displacement ) | ||
35 | return ( ( ( *current_byte << bit_displacement ) | ||
36 | & ( UCHAR_MAX << ( CHAR_BIT - bit_length ) ) ) | ||
37 | & UCHAR_MAX ) == 0; | ||
38 | else | ||
39 | if ( bit_displacement != 0 ) { | ||
40 | if ( ( ( *current_byte << bit_displacement ) & UCHAR_MAX ) != 0 ) | ||
41 | return 0 /* FALSE */; | ||
42 | current_byte += 1; | ||
43 | bit_length -= CHAR_BIT - bit_displacement; | ||
44 | } | ||
45 | _Pragma( "loopbound min 0 max 7" ) | ||
46 | while ( bit_length >= CHAR_BIT ) { | ||
47 | if ( *current_byte != 0 ) | ||
48 | return 0 /* FALSE */; | ||
49 | current_byte++; | ||
50 | bit_length -= CHAR_BIT; | ||
51 | } | ||
52 | if ( bit_length > 0 && ( *current_byte >> ( CHAR_BIT - bit_length ) ) != 0 ) | ||
53 | return 0 /* FALSE */; | ||
54 | return 1 /* TRUE */; | ||
55 | } | ||
56 | |||
57 | /* This function sets up new value of all bits of given bit string. | ||
58 | This function is analog of standard C function `memset'. Value of | ||
59 | `bit_displacement' must be non-negative and can be greater than | ||
60 | CHAR_BIT. */ | ||
61 | |||
62 | void | ||
63 | ammunition_bit_string_set ( void *start_byte, int bit_displacement, int bit, | ||
64 | int bit_length ) | ||
65 | { | ||
66 | unsigned char *current_byte = ( unsigned char * )start_byte; | ||
67 | unsigned char filling_byte; | ||
68 | int mask; | ||
69 | |||
70 | if ( bit_length <= 0 ) | ||
71 | return ; | ||
72 | bit = bit != 0; /* 1 or 0 */ | ||
73 | filling_byte = ( bit ? UCHAR_MAX : 0 ); | ||
74 | current_byte += bit_displacement / CHAR_BIT; | ||
75 | bit_displacement %= CHAR_BIT; | ||
76 | if ( bit_displacement != 0 ) { | ||
77 | mask = UCHAR_MAX << ( CHAR_BIT - bit_displacement ); | ||
78 | if ( bit_length < CHAR_BIT - bit_displacement ) | ||
79 | mask |= UCHAR_MAX >> ( bit_displacement + bit_length ); | ||
80 | *current_byte = ( *current_byte & mask ) | ( filling_byte & ~mask ); | ||
81 | current_byte += 1; | ||
82 | bit_length -= CHAR_BIT - bit_displacement; | ||
83 | } | ||
84 | _Pragma( "loopbound min 0 max 8" ) | ||
85 | while ( bit_length >= CHAR_BIT ) { | ||
86 | *current_byte = filling_byte; | ||
87 | current_byte++; | ||
88 | bit_length -= CHAR_BIT; | ||
89 | } | ||
90 | if ( bit_length > 0 ) | ||
91 | *current_byte | ||
92 | = ( *current_byte & ~( UCHAR_MAX << ( CHAR_BIT - bit_length ) ) ) | ||
93 | | ( filling_byte & ( UCHAR_MAX << ( CHAR_BIT - bit_length ) ) ); | ||
94 | } | ||
95 | |||
96 | /* This function copys a bit string to another bit string. This | ||
97 | function is analog of standard C function `memcpy'. Values of | ||
98 | `to_bit_displacement' and `from_bit_displacement' must be | ||
99 | non-negative and can be greater than CHAR_BIT. The bit string must | ||
100 | be non-overlapped. */ | ||
101 | |||
102 | void | ||
103 | ammunition_bit_string_copy ( void *to, int to_bit_displacement, | ||
104 | const void *from, int from_bit_displacement, | ||
105 | int bit_length ) | ||
106 | { | ||
107 | unsigned char *current_to_byte = ( unsigned char * )to; | ||
108 | const unsigned char *current_from_byte = ( unsigned const char * )from; | ||
109 | int byte; | ||
110 | int mask; | ||
111 | |||
112 | if ( bit_length <= 0 ) | ||
113 | return ; | ||
114 | current_to_byte += to_bit_displacement / CHAR_BIT; | ||
115 | to_bit_displacement %= CHAR_BIT; | ||
116 | current_from_byte += from_bit_displacement / CHAR_BIT; | ||
117 | from_bit_displacement %= CHAR_BIT; | ||
118 | _Pragma( "loopbound min 1 max 8" ) | ||
119 | while ( 1 ) { | ||
120 | byte = ( ( ( *current_from_byte << from_bit_displacement ) & UCHAR_MAX ) | ||
121 | | ( from_bit_displacement != 0 | ||
122 | && bit_length > ( CHAR_BIT - from_bit_displacement ) | ||
123 | ? current_from_byte [1] >> ( CHAR_BIT - from_bit_displacement ) | ||
124 | : 0 ) ); | ||
125 | if ( bit_length <= CHAR_BIT ) | ||
126 | break; | ||
127 | /* Shift is correct when to_bit_displacement == 0 because its | ||
128 | value is less than word bit size. */ | ||
129 | *current_to_byte | ||
130 | = ( *current_to_byte | ||
131 | & ( UCHAR_MAX << ( CHAR_BIT - to_bit_displacement ) ) ) | ||
132 | | ( byte >> to_bit_displacement ); | ||
133 | if ( to_bit_displacement != 0 ) | ||
134 | current_to_byte [1] | ||
135 | = ( current_to_byte [1] & ( UCHAR_MAX >> to_bit_displacement ) ) | ||
136 | | ( byte << ( CHAR_BIT - to_bit_displacement ) ); | ||
137 | bit_length -= CHAR_BIT; | ||
138 | current_from_byte++; | ||
139 | current_to_byte++; | ||
140 | } | ||
141 | /* Shift is correct when to_bit_displacement == 0 because its | ||
142 | value is less than word bit size. */ | ||
143 | mask = ( ( UCHAR_MAX << ( CHAR_BIT - to_bit_displacement ) ) | ||
144 | | ( UCHAR_MAX >> ( to_bit_displacement + bit_length ) ) ); | ||
145 | *current_to_byte | ||
146 | = ( *current_to_byte & mask ) | ( ( byte >> to_bit_displacement ) & ~mask ); | ||
147 | bit_length -= CHAR_BIT - to_bit_displacement; | ||
148 | if ( bit_length > 0 ) | ||
149 | current_to_byte [1] | ||
150 | = ( current_to_byte [1] & ( UCHAR_MAX >> bit_length ) ) | ||
151 | | ( ( byte << ( CHAR_BIT - to_bit_displacement ) ) | ||
152 | & ( UCHAR_MAX << ( CHAR_BIT - bit_length ) ) ); | ||
153 | } | ||
154 | |||
155 | /* This function copys a bit string to another bit string. Copying | ||
156 | starts with the last bits of the bit strings. This function is | ||
157 | used by function `bit_string_move'. Values of | ||
158 | `to_bit_displacement' and `from_bit_displacement' must be | ||
159 | non-negative and can be greater than CHAR_BIT. The bit string must | ||
160 | be non-overlapped. */ | ||
161 | |||
162 | void ammunition_reverse_bit_string_copy ( void *to, int to_bit_displacement, | ||
163 | const void *from, int from_bit_displacement, | ||
164 | int bit_length ) | ||
165 | { | ||
166 | unsigned char *current_to_byte = ( unsigned char * )to; | ||
167 | const unsigned char *current_from_byte = ( unsigned const char * )from; | ||
168 | int byte; | ||
169 | int mask; | ||
170 | |||
171 | if ( bit_length <= 0 ) | ||
172 | return ; | ||
173 | to_bit_displacement += bit_length - 1; | ||
174 | current_to_byte += to_bit_displacement / CHAR_BIT; /* last byte */ | ||
175 | to_bit_displacement %= CHAR_BIT; /* last bit */ | ||
176 | from_bit_displacement += bit_length - 1; | ||
177 | current_from_byte += from_bit_displacement / CHAR_BIT; /* last byte */ | ||
178 | from_bit_displacement %= CHAR_BIT; /* last bit */ | ||
179 | _Pragma( "loopbound min 1 max 8" ) | ||
180 | while ( 1 ) { | ||
181 | /* Shift is correct when to_bit_displacement == 0 because its | ||
182 | value is less than word bit size. */ | ||
183 | byte = ( ( *current_from_byte >> ( CHAR_BIT - 1 - from_bit_displacement ) ) | ||
184 | | ( ( from_bit_displacement != CHAR_BIT - 1 | ||
185 | && bit_length > from_bit_displacement + 1 | ||
186 | ? current_from_byte [ -1 ] << ( from_bit_displacement + 1 ) | ||
187 | : 0 ) | ||
188 | & UCHAR_MAX ) ); | ||
189 | if ( bit_length <= CHAR_BIT ) | ||
190 | break; | ||
191 | /* Shift is correct when to_bit_displacement == 0 because its | ||
192 | value is less than word bit size. */ | ||
193 | *current_to_byte | ||
194 | = ( *current_to_byte & ( UCHAR_MAX >> ( to_bit_displacement + 1 ) ) ) | ||
195 | | ( byte << ( CHAR_BIT - 1 - to_bit_displacement ) ); | ||
196 | if ( to_bit_displacement != CHAR_BIT - 1 ) | ||
197 | current_to_byte [-1] | ||
198 | = ( current_to_byte [-1] | ||
199 | & ( UCHAR_MAX << ( CHAR_BIT - 1 - to_bit_displacement ) ) ) | ||
200 | | ( byte >> ( to_bit_displacement + 1 ) ); | ||
201 | bit_length -= CHAR_BIT; | ||
202 | current_from_byte--; | ||
203 | current_to_byte--; | ||
204 | } | ||
205 | /* Shift is correct when to_bit_displacement == 0 because its | ||
206 | value is less than word bit size. */ | ||
207 | mask = ( ( UCHAR_MAX >> ( to_bit_displacement + 1 ) ) | | ||
208 | ( UCHAR_MAX << ( CHAR_BIT - 1 - to_bit_displacement | ||
209 | + bit_length ) ) ); | ||
210 | *current_to_byte | ||
211 | = ( *current_to_byte & mask ) | ||
212 | | ( ( byte << ( CHAR_BIT - 1 - to_bit_displacement ) ) & ~mask ); | ||
213 | bit_length -= to_bit_displacement + 1; | ||
214 | if ( bit_length > 0 ) | ||
215 | current_to_byte [-1] | ||
216 | = ( current_to_byte [-1] & ( UCHAR_MAX << bit_length ) ) | ||
217 | | ( byte >> ( to_bit_displacement + 1 ) | ||
218 | & ( UCHAR_MAX >> ( CHAR_BIT - bit_length ) ) ); | ||
219 | } | ||
220 | |||
221 | /* This function copys a bit string to another bit string with the aid | ||
222 | of functions `bit_string_copy' and `reverse_bit_string_copy'. This | ||
223 | function is analog of standard C function `memmove'. Values of | ||
224 | `to_bit_displacement' and `from_bit_displacement' must be | ||
225 | non-negative and can be greater than CHAR_BIT. The bit string can | ||
226 | be overlapped. */ | ||
227 | |||
228 | void | ||
229 | ammunition_bit_string_move ( void *to, int to_bit_displacement, | ||
230 | const void *from, int from_bit_displacement, | ||
231 | int bit_length ) | ||
232 | { | ||
233 | unsigned char *current_to_byte = ( unsigned char * )to; | ||
234 | const unsigned char *current_from_byte = ( unsigned const char * )from; | ||
235 | |||
236 | if ( bit_length <= 0 ) | ||
237 | return ; | ||
238 | current_to_byte += to_bit_displacement / CHAR_BIT; | ||
239 | to_bit_displacement %= CHAR_BIT; | ||
240 | current_from_byte += from_bit_displacement / CHAR_BIT; | ||
241 | from_bit_displacement %= CHAR_BIT; | ||
242 | if ( current_from_byte > current_to_byte | ||
243 | || ( current_from_byte == current_to_byte | ||
244 | && from_bit_displacement > to_bit_displacement ) ) | ||
245 | ammunition_bit_string_copy ( current_to_byte, to_bit_displacement, | ||
246 | current_from_byte, from_bit_displacement, | ||
247 | bit_length ); | ||
248 | else | ||
249 | ammunition_reverse_bit_string_copy ( current_to_byte, to_bit_displacement, | ||
250 | current_from_byte, | ||
251 | from_bit_displacement, bit_length ); | ||
252 | } | ||
253 | |||
254 | /* This function compares bit strings. This function is analog of | ||
255 | standard C function `memcmp'. The function returns 0 if the bit | ||
256 | strings are equal, 1 if the first bit string is greater than the | ||
257 | second, -1 if the first bit string is less than the first. Values | ||
258 | of `bit_displacement1' and `bit_displacement2' must be non-negative | ||
259 | and can be greater than CHAR_BIT. */ | ||
260 | |||
261 | int | ||
262 | ammunition_bit_string_comparison ( const void *str1, int bit_displacement1, | ||
263 | const void *str2, int bit_displacement2, | ||
264 | int bit_length ) | ||
265 | { | ||
266 | const unsigned char *current_byte1 = ( unsigned const char * )str1; | ||
267 | const unsigned char *current_byte2 = ( unsigned const char * )str2; | ||
268 | int byte1; | ||
269 | int byte2; | ||
270 | int mask; | ||
271 | |||
272 | if ( bit_length <= 0 ) | ||
273 | return 0; | ||
274 | current_byte1 += bit_displacement1 / CHAR_BIT; | ||
275 | bit_displacement1 %= CHAR_BIT; | ||
276 | current_byte2 += bit_displacement2 / CHAR_BIT; | ||
277 | bit_displacement2 %= CHAR_BIT; | ||
278 | _Pragma( "loopbound min 1 max 284" ) | ||
279 | while ( 1 ) { | ||
280 | byte1 = ( ( ( *current_byte1 << bit_displacement1 ) & UCHAR_MAX ) | ||
281 | | ( bit_displacement1 != 0 | ||
282 | /* Shift is correct when to_bit_displacement == 0 | ||
283 | because its value is less than word bit size. */ | ||
284 | && bit_length > CHAR_BIT - bit_displacement1 | ||
285 | ? current_byte1 [1] >> ( CHAR_BIT - bit_displacement1 ) | ||
286 | : 0 ) ); | ||
287 | byte2 = ( ( ( *current_byte2 << bit_displacement2 ) & UCHAR_MAX ) | ||
288 | | ( bit_displacement2 != 0 | ||
289 | && bit_length > CHAR_BIT - bit_displacement2 | ||
290 | ? current_byte2 [1] >> ( CHAR_BIT - bit_displacement2 ) | ||
291 | : 0 ) ); | ||
292 | if ( bit_length <= CHAR_BIT ) | ||
293 | break; | ||
294 | if ( byte1 > byte2 ) | ||
295 | return 1; | ||
296 | else | ||
297 | if ( byte1 < byte2 ) | ||
298 | return -1; | ||
299 | bit_length -= CHAR_BIT; | ||
300 | current_byte2++; | ||
301 | current_byte1++; | ||
302 | } | ||
303 | /* Shift is correct when to_bit_displacement == 0 because its value | ||
304 | is less than word bit size. */ | ||
305 | mask = UCHAR_MAX << ( CHAR_BIT - bit_length ); | ||
306 | if ( ( byte1 & mask ) > ( byte2 & mask ) ) | ||
307 | return 1; | ||
308 | else | ||
309 | if ( ( byte1 & mask ) < ( byte2 & mask ) ) | ||
310 | return -1; | ||
311 | else | ||
312 | return 0; | ||
313 | } | ||