Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef INDEX_H
00025 #define INDEX_H
00026
00027 #ifndef USE_PCH
00028 #include <stdint.h>
00029 #endif
00030
00031 #define DEBUG_INDEX_INITIALIZATION_AND_RANGE_CHECK 0
00032
00033 #if DEBUG_INDEX_INITIALIZATION_AND_RANGE_CHECK
00034 #include <cassert>
00035 #endif
00036
00037 namespace cwchess {
00038
00039
00040
00041
00042
00043
00044
00045 struct IndexData {
00046 uint8_t M_bits;
00047 };
00048
00049 uint8_t const col_mask = 0x07;
00050 uint8_t const row_mask = 0x38;
00051
00052
00053 IndexData const ia1 = { 0 };
00054
00055 IndexData const ib1 = { 1 };
00056
00057 IndexData const ic1 = { 2 };
00058
00059 IndexData const id1 = { 3 };
00060
00061 IndexData const ie1 = { 4 };
00062
00063 IndexData const if1 = { 5 };
00064
00065 IndexData const ig1 = { 6 };
00066
00067 IndexData const ih1 = { 7 };
00068
00069 IndexData const ia2 = { 8 };
00070
00071 IndexData const ib2 = { 9 };
00072
00073 IndexData const ic2 = { 10 };
00074
00075 IndexData const id2 = { 11 };
00076
00077 IndexData const ie2 = { 12 };
00078
00079 IndexData const if2 = { 13 };
00080
00081 IndexData const ig2 = { 14 };
00082
00083 IndexData const ih2 = { 15 };
00084
00085 IndexData const ia3 = { 16 };
00086
00087 IndexData const ib3 = { 17 };
00088
00089 IndexData const ic3 = { 18 };
00090
00091 IndexData const id3 = { 19 };
00092
00093 IndexData const ie3 = { 20 };
00094
00095 IndexData const if3 = { 21 };
00096
00097 IndexData const ig3 = { 22 };
00098
00099 IndexData const ih3 = { 23 };
00100
00101 IndexData const ia4 = { 24 };
00102
00103 IndexData const ib4 = { 25 };
00104
00105 IndexData const ic4 = { 26 };
00106
00107 IndexData const id4 = { 27 };
00108
00109 IndexData const ie4 = { 28 };
00110
00111 IndexData const if4 = { 29 };
00112
00113 IndexData const ig4 = { 30 };
00114
00115 IndexData const ih4 = { 31 };
00116
00117 IndexData const ia5 = { 32 };
00118
00119 IndexData const ib5 = { 33 };
00120
00121 IndexData const ic5 = { 34 };
00122
00123 IndexData const id5 = { 35 };
00124
00125 IndexData const ie5 = { 36 };
00126
00127 IndexData const if5 = { 37 };
00128
00129 IndexData const ig5 = { 38 };
00130
00131 IndexData const ih5 = { 39 };
00132
00133 IndexData const ia6 = { 40 };
00134
00135 IndexData const ib6 = { 41 };
00136
00137 IndexData const ic6 = { 42 };
00138
00139 IndexData const id6 = { 43 };
00140
00141 IndexData const ie6 = { 44 };
00142
00143 IndexData const if6 = { 45 };
00144
00145 IndexData const ig6 = { 46 };
00146
00147 IndexData const ih6 = { 47 };
00148
00149 IndexData const ia7 = { 48 };
00150
00151 IndexData const ib7 = { 49 };
00152
00153 IndexData const ic7 = { 50 };
00154
00155 IndexData const id7 = { 51 };
00156
00157 IndexData const ie7 = { 52 };
00158
00159 IndexData const if7 = { 53 };
00160
00161 IndexData const ig7 = { 54 };
00162
00163 IndexData const ih7 = { 55 };
00164
00165 IndexData const ia8 = { 56 };
00166
00167 IndexData const ib8 = { 57 };
00168
00169 IndexData const ic8 = { 58 };
00170
00171 IndexData const id8 = { 59 };
00172
00173 IndexData const ie8 = { 60 };
00174
00175 IndexData const if8 = { 61 };
00176
00177 IndexData const ig8 = { 62 };
00178
00179 IndexData const ih8 = { 63 };
00180
00181
00182 IndexData const index_pre_begin = { 255 };
00183
00184 IndexData const index_begin = { 0 };
00185
00186 IndexData const index_end = { 64 };
00187
00188
00189 inline bool operator==(IndexData i1, IndexData i2) { return i1.M_bits == i2.M_bits; }
00190 inline bool operator!=(IndexData i1, IndexData i2) { return i1.M_bits != i2.M_bits; }
00191
00192 #if DEBUG_INDEX_INITIALIZATION_AND_RANGE_CHECK
00193 uint64_t const index_initialization_magic = CW_MASK_T_CONST(1515151515151515151);
00194 uint64_t const index_destruction_magic = CW_MASK_T_CONST(6666666666666666666);
00195 #endif
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211 class Index : protected IndexData {
00212 #if DEBUG_INDEX_INITIALIZATION_AND_RANGE_CHECK
00213 private:
00214 uint64_t M_initialized;
00215 #endif
00216
00217 public:
00218 #if DEBUG_INDEX_INITIALIZATION_AND_RANGE_CHECK
00219 Index(void) : M_initialized(0) { }
00220 ~Index() { M_initialized = index_destruction_magic; }
00221
00222 bool is_initialized(void) const { return M_initialized == index_initialization_magic; }
00223 #else
00224
00225
00226
00227
00228 Index(void) { }
00229 #endif
00230
00231
00232 Index(Index const& index)
00233 {
00234 #if DEBUG_INDEX_INITIALIZATION_AND_RANGE_CHECK
00235 assert(index.is_initialized());
00236 M_initialized = index_initialization_magic;
00237 #endif
00238 M_bits = index.M_bits;
00239 }
00240
00241
00242 Index(IndexData index)
00243 {
00244 #if DEBUG_INDEX_INITIALIZATION_AND_RANGE_CHECK
00245 assert(index.M_bits < 64 || index == index_end || index == index_pre_begin);
00246 M_initialized = index_initialization_magic;
00247 #endif
00248 M_bits = index.M_bits;
00249 }
00250
00251
00252 Index(int col, int row)
00253 {
00254 #if DEBUG_INDEX_INITIALIZATION_AND_RANGE_CHECK
00255 assert(col >= 0 && col <= 7 && row >= 0 && row <= 7);
00256 M_initialized = index_initialization_magic;
00257 #endif
00258 M_bits = ((uint8_t)row << 3) | (uint8_t)col;
00259 }
00260
00261
00262
00263
00264
00265
00266 Index& operator=(Index const& index)
00267 {
00268 #if DEBUG_INDEX_INITIALIZATION_AND_RANGE_CHECK
00269 assert(index.is_initialized());
00270 M_initialized = index_initialization_magic;
00271 #endif
00272 M_bits = index.M_bits;
00273 return* this;
00274 }
00275
00276 Index& operator=(IndexData index)
00277 {
00278 #if DEBUG_INDEX_INITIALIZATION_AND_RANGE_CHECK
00279 assert(index.M_bits < 64 || index == index_end || index == index_pre_begin);
00280 M_initialized = index_initialization_magic;
00281 #endif
00282 M_bits = index.M_bits;
00283 return* this;
00284 }
00285
00286
00287
00288
00289
00290
00291 friend bool operator==(Index const& i1, Index const& i2) { return i1.M_bits == i2.M_bits; }
00292 friend bool operator==(Index const& i1, IndexData i2) { return i1.M_bits == i2.M_bits; }
00293 friend bool operator==(IndexData i1, Index const& i2) { return i1.M_bits == i2.M_bits; }
00294 friend bool operator!=(Index const& i1, Index const& i2) { return i1.M_bits != i2.M_bits; }
00295 friend bool operator!=(Index const& i1, IndexData i2) { return i1.M_bits != i2.M_bits; }
00296 friend bool operator!=(IndexData i1, Index const& i2) { return i1.M_bits != i2.M_bits; }
00297
00298 friend bool operator<(Index const& index1, Index const& index2) { return index1.M_bits < index2.M_bits; }
00299 friend bool operator<(Index const& index1, IndexData const& index2) { return index1.M_bits < index2.M_bits; }
00300 friend bool operator<(IndexData const& index1, Index const& index2) { return index1.M_bits < index2.M_bits; }
00301 friend bool operator<=(Index const& index1, Index const& index2) { return index1.M_bits <= index2.M_bits; }
00302 friend bool operator<=(Index const& index1, IndexData const& index2) { return index1.M_bits <= index2.M_bits; }
00303 friend bool operator<=(IndexData const& index1, Index const& index2) { return index1.M_bits <= index2.M_bits; }
00304 friend bool operator>(Index const& index1, Index const& index2) { return index1.M_bits > index2.M_bits; }
00305 friend bool operator>(Index const& index1, IndexData const& index2) { return index1.M_bits > index2.M_bits; }
00306 friend bool operator>(IndexData const& index1, Index const& index2) { return index1.M_bits > index2.M_bits; }
00307 friend bool operator>=(Index const& index1, Index const& index2) { return index1.M_bits >= index2.M_bits; }
00308 friend bool operator>=(Index const& index1, IndexData const& index2) { return index1.M_bits >= index2.M_bits; }
00309 friend bool operator>=(IndexData const& index1, Index const& index2) { return index1.M_bits >= index2.M_bits; }
00310
00311
00312
00313
00314
00315
00316 Index const& operator+=(int offset) { M_bits += offset; return* this; }
00317 friend Index operator+(Index const& index, int offset) { Index result(index); return result += offset; }
00318 friend Index operator+(int offset, Index const& index) { Index result(index); return result += offset; }
00319 Index const& operator-=(int offset) { M_bits -= offset; return* this; }
00320 friend Index operator-(Index const& index, int offset) { Index result(index); return result -= offset; }
00321 friend Index operator-(int offset, Index const& index) { Index result(index); return result -= offset; }
00322
00323 Index& operator++(void) { ++M_bits; return* this; }
00324 Index operator++(int) { Index result(*this); operator++(); return result; }
00325 Index& operator--(void) { ++M_bits; return* this; }
00326 Index operator--(int) { Index result(*this); operator--(); return result; }
00327
00328
00329
00330
00331
00332
00333
00334 int row(void) const { return M_bits >> 3; }
00335
00336
00337 int col(void) const { return M_bits & 7; }
00338
00339
00340 uint8_t operator()(void) const { return M_bits; }
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360 void next_bit_in(uint64_t mask)
00361 {
00362 #if DEBUG_INDEX_INITIALIZATION_AND_RANGE_CHECK
00363 assert(is_initialized());
00364 assert(M_bits < 64 || M_bits == index_pre_begin.M_bits);
00365 #endif
00366 if (__builtin_expect(++M_bits == 64, 0))
00367 return;
00368 mask >>= M_bits;
00369 #ifdef __x86_64
00370 uint64_t indx = 64 - M_bits;
00371 __asm__ __volatile__(
00372 "bsfq %1, %0"
00373 : "=&r" (indx)
00374 : "r" (mask), "0" (indx)
00375 : "cc"
00376 );
00377 M_bits += indx;
00378 #else
00379 union conversion {
00380 uint64_t mask;
00381 struct {
00382 uint32_t low;
00383 uint32_t high;
00384 };
00385 };
00386 conversion tmp;
00387 tmp.mask = mask;
00388 uint32_t indx;
00389 if (tmp.low)
00390 {
00391 __asm__ __volatile__(
00392 "bsf %1, %0"
00393 : "=&r" (indx)
00394 : "r" (tmp.low), "0" (indx)
00395 : "cc"
00396 );
00397 M_bits += indx;
00398 }
00399 else
00400 {
00401 indx = 32 - M_bits;
00402 __asm__ __volatile__(
00403 "bsf %1, %0"
00404 : "=&r" (indx)
00405 : "r" (tmp.high), "0" (indx)
00406 : "cc"
00407 );
00408 M_bits += indx + 32;
00409 }
00410 #endif
00411 #if DEBUG_INDEX_INITIALIZATION_AND_RANGE_CHECK
00412 assert(M_bits <= 64);
00413 #endif
00414 }
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432 void prev_bit_in(uint64_t mask)
00433 {
00434 #if DEBUG_INDEX_INITIALIZATION_AND_RANGE_CHECK
00435 assert(is_initialized());
00436 assert(M_bits > 0 && M_bits != index_pre_begin.M_bits);
00437 #endif
00438 M_bits = 64 - M_bits;
00439 mask <<= M_bits;
00440 #ifdef __x86_64
00441 uint64_t indx = 0xff + M_bits;
00442 __asm__ __volatile__(
00443 "bsrq %1, %0"
00444 : "=&r" (indx)
00445 : "r" (mask), "0" (indx)
00446 : "cc"
00447 );
00448 M_bits = indx - M_bits;
00449 #else
00450 union conversion {
00451 uint64_t mask;
00452 struct {
00453 uint32_t low;
00454 uint32_t high;
00455 };
00456 };
00457 conversion tmp;
00458 tmp.mask = mask;
00459 uint32_t indx;
00460 if (tmp.high)
00461 {
00462 __asm__ __volatile__(
00463 "bsr %1, %0"
00464 : "=&r" (indx)
00465 : "r" (tmp.high), "0" (indx)
00466 : "cc"
00467 );
00468 M_bits = indx - M_bits + 32;
00469 }
00470 else
00471 {
00472 indx = 0xff + M_bits;
00473 __asm__ __volatile__(
00474 "bsr %1, %0"
00475 : "=&r" (indx)
00476 : "r" (tmp.low), "0" (indx)
00477 : "cc"
00478 );
00479 M_bits = indx - M_bits;
00480 }
00481 #endif
00482 #if DEBUG_INDEX_INITIALIZATION_AND_RANGE_CHECK
00483 assert(M_bits < 64 || M_bits == index_pre_begin.M_bits);
00484 #endif
00485 }
00486
00487
00488 bool may_call_prev_bit_in(void) const
00489 {
00490 #if DEBUG_INDEX_INITIALIZATION_AND_RANGE_CHECK
00491 assert(is_initialized());
00492 #endif
00493 return (int8_t)M_bits > 0;
00494 }
00495
00496
00497
00498 };
00499
00500 }
00501
00502 #endif // INDEX_H