MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
test_dynbm.c
1 /*
2  Copyright (C) 2007 MySQL AB
3  All rights reserved. Use is subject to license terms.
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; version 2 of the License.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18 
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <stdint.h>
23 #include <assert.h>
24 
25 #define N (1024*1024)
26 #define S 65537
27 /* The number S must be relative prime to N. */
28 
29 uint32_t bm[N*4];
30 
31 uint32_t bms[N][4];
32 uint32_t len[N];
33 uint32_t pos[N];
34 
35 typedef uint32_t Uint32;
36 #define MEMCOPY_NO_WORDS(to, from, no_of_words) \
37  memcpy((to), (void*)(from), (size_t)(no_of_words << 2));
38 
39 /****************************************************************************/
40 static void
41 getbits(const Uint32 *src, Uint32 bit_pos, Uint32 *dst, Uint32 count)
42 {
43  Uint32 val;
44 
45  /* Move to start word in src. */
46  src+= bit_pos>>5;
47  bit_pos&= 31;
48 
49  /*
50  If word-aligned, copy word-for-word is faster and avoids edge
51  cases with undefined bitshift operations.
52  */
53  if (bit_pos==0)
54  {
55  MEMCOPY_NO_WORDS(dst, src, count>>5);
56  src+= count>>5;
57  dst+= count>>5;
58  count&= 31;
59  }
60  else
61  {
62  while(count >= 32)
63  {
64  /*
65  Get bits 0-X from first source word.
66  Get bits (X+1)-31 from second source word.
67  Handle endian so that we store bit 0 in the first byte, and bit 31 in
68  the last byte, so that we don't waste space on 32-bit aligning the
69  bitmap.
70  */
71 #ifdef WORDS_BIGENDIAN
72  Uint32 firstpart_len= 32-bit_pos;
73  val= *src++ & (((Uint32)1<<firstpart_len)-1);
74  val|= *src & ((Uint32)0xffffffff << firstpart_len);
75 #else
76  val= *src++ >> bit_pos;
77  val|= *src << (32-bit_pos);
78 #endif
79  *dst++= val;
80  count-= 32;
81  }
82  }
83 
84  /* Handle any partial word at the end. */
85  if (count>0)
86  {
87  if (bit_pos+count <= 32)
88  {
89  /* Last part is wholly contained in one source word. */
90 #ifdef WORDS_BIGENDIAN
91  val= *src >> (32-(bit_pos+count));
92 #else
93  val= *src >> bit_pos;
94 #endif
95  }
96  else
97  {
98  /* Need to assemble last part from two source words. */
99 #ifdef WORDS_BIGENDIAN
100  Uint32 firstpart_len= 32-bit_pos;
101  val= *src++ & (((Uint32)1<<firstpart_len)-1);
102  val|= (*src >> (32-count)) & ((Uint32)0xffffffff << firstpart_len);
103 #else
104  val= *src++ >> bit_pos;
105  val|= *src << (32-bit_pos);
106 #endif
107  }
108  /* Mask off any unused bits. */
109  *dst= val & (((Uint32)1<<count)-1);
110  }
111 }
112 
113 static void
114 setbits(const Uint32 *src, Uint32 *dst, Uint32 bit_pos, Uint32 count)
115 {
116  Uint32 val;
117 
118  /* Move to start word in dst. */
119 
120  dst+= bit_pos>>5;
121  bit_pos&= 31;
122 
123 #ifdef WORDS_BIGENDIAN
124  Uint32 low_mask= ((Uint32)0xffffffff)<<(32-bit_pos);
125  Uint32 high_mask= ~low_mask;
126 #else
127  Uint32 low_mask= (((Uint32)1)<<bit_pos) - 1;
128  Uint32 high_mask= ~low_mask;
129 #endif
130 
131  if (bit_pos==0)
132  {
133  MEMCOPY_NO_WORDS(dst, src, count>>5);
134  src+= count>>5;
135  dst+= count>>5;
136  count&= 31;
137  }
138  else
139  {
140  while (count >= 32)
141  {
142  val= *src++;
143 #ifdef WORDS_BIGENDIAN
144  *dst= (*dst&low_mask) | (val&high_mask);
145  dst++;
146  *dst= (*dst&high_mask) | (val&low_mask);
147 #else
148  *dst= (*dst&low_mask) | (val<<bit_pos);
149  dst++;
150  *dst= (*dst&high_mask) | (val>>(32-bit_pos));
151 #endif
152  count-= 32;
153  }
154  }
155 
156  /* Handle any partial word at the end. */
157  if (count > 0)
158  {
159  val= *src;
160  if (bit_pos+count <= 32)
161  {
162  /* Remaining part fits in one word of destination. */
163  Uint32 end_mask= (((Uint32)1)<<count) - 1;
164 #ifdef WORDS_BIGENDIAN
165  Uint32 shift= (32-(bit_pos+count));
166  *dst= (*dst&~(end_mask<<shift)) | ((val&end_mask)<<shift);
167 #else
168  *dst= (*dst&~(end_mask<<bit_pos)) | ((val&end_mask)<<bit_pos);
169 #endif
170  }
171  else
172  {
173  /* Need to split the remaining part across two destination words. */
174 #ifdef WORDS_BIGENDIAN
175  *dst= (*dst&low_mask) | (val&high_mask);
176  dst++;
177  Uint32 shift= 32-count;
178  Uint32 end_mask= ((((Uint32)1)<<(bit_pos+count-32)) - 1) << (32-bit_pos);
179  *dst= (*dst&~(end_mask<<shift)) | ((val&end_mask)<<shift);
180 #else
181  *dst= (*dst&low_mask) | (val<<bit_pos);
182  dst++;
183  Uint32 end_mask= (((Uint32)1)<<(count+bit_pos-32)) - 1;
184  *dst= (*dst&~end_mask) | ((val>>(32-bit_pos))&end_mask);
185 #endif
186  }
187  }
188 }
189 /****************************************************************************/
190 
191 /* Set up a bunch of test bit fields. */
192 void fill(void)
193 {
194  uint32_t i,j;
195  uint32_t p= 0;
196 
197  for(i= 0; i<N; i++)
198  {
199  memset(bms[i], 0, sizeof(bms[i]));
200  pos[i]= p;
201  do
202  len[i]= rand()%128;
203  while (!len[i]);
204  p+= len[i];
205  for(j= 0; j<len[i]; j++)
206  if(rand()%2)
207  bms[i][j>>5]|= (((uint32_t)1)<<(j&31));
208  }
209 }
210 
211 void write(void)
212 {
213  uint32_t i, idx;
214 
215  for(i=0, idx=0; i<N; i++, idx+= S)
216  {
217  if(idx>=N)
218  idx-= N;
219  setbits(&(bms[idx][0]), &(bm[0]), pos[idx], len[idx]);
220  }
221 }
222 
223 void read(void)
224 {
225  uint32_t buf[4];
226  uint32_t i;
227 
228  for(i=0; i<N; i++)
229  {
230  getbits(&(bm[0]), pos[i], &(buf[0]), len[i]);
231  assert(0==memcmp(buf, bms[i], ((len[i]+31)>>5)<<2));
232  }
233 }
234 
235 int main(int argc, char *argv[])
236 {
237  uint32_t i;
238 
239  srand(1);
240  fill();
241  write();
242  read();
243 
244  exit(0);
245  return 0;
246 }