| | 321 | cdef unsigned long i, j, truerow |
|---|
| | 322 | cdef unsigned long start, shift |
|---|
| | 323 | cdef word row_xor |
|---|
| | 324 | cdef word end_mask = ~(((<word>1)<<(RADIX - self._ncols%RADIX))-1) |
|---|
| | 325 | cdef word top_mask, bot_mask |
|---|
| | 326 | cdef word cur |
|---|
| | 327 | cdef word* row |
|---|
| | 328 | |
|---|
| | 329 | # running_xor is the xor of all words in the matrix, as if the rows |
|---|
| | 330 | # in the matrix were written out consecutively, without regard to |
|---|
| | 331 | # word boundaries. |
|---|
| | 332 | cdef word running_xor = 0 |
|---|
| | 333 | # running_parity is the number of extra words that must be xor'd. |
|---|
| | 334 | cdef unsigned long running_parity = 0 |
|---|
| | 335 | |
|---|
| | 336 | |
|---|
| 321 | | if _hash == -1: |
|---|
| 322 | | return -2 |
|---|
| 323 | | return _hash |
|---|
| | 348 | if self._entries.width > 1: |
|---|
| | 349 | row_xor = row[0] |
|---|
| | 350 | running_parity ^= start & parity_mask(row[0] & bot_mask) |
|---|
| | 351 | |
|---|
| | 352 | for j from 1 <= j < self._entries.width - 1: |
|---|
| | 353 | row_xor ^= row[j] |
|---|
| | 354 | cur = ((row[j-1] << (63-shift)) << 1) ^ (row[j] >> shift) |
|---|
| | 355 | running_parity ^= (start+j) & parity_mask(cur) |
|---|
| | 356 | |
|---|
| | 357 | running_parity ^= (start+j) & parity_mask(row[j-1] & top_mask) |
|---|
| | 358 | |
|---|
| | 359 | else: |
|---|
| | 360 | j = 0 |
|---|
| | 361 | row_xor = 0 |
|---|
| | 362 | |
|---|
| | 363 | cur = row[j] & end_mask |
|---|
| | 364 | row_xor ^= cur |
|---|
| | 365 | running_parity ^= (start+j) & parity_mask(cur & bot_mask) |
|---|
| | 366 | running_parity ^= (start+j+1) & parity_mask(cur & top_mask) |
|---|
| | 367 | |
|---|
| | 368 | start = (i*self._entries.ncols) & (RADIX-1) |
|---|
| | 369 | running_xor ^= (row_xor >> start) ^ ((row_xor << (RADIX-1-start)) << 1) |
|---|
| | 370 | |
|---|
| | 371 | cdef unsigned long bit_is_set |
|---|
| | 372 | cdef unsigned long h |
|---|
| | 373 | |
|---|
| | 374 | # Now we assemble the running_parity and running_xor to get the hash. |
|---|
| | 375 | # Viewing the flattened matrix as a list of a_i, the hash is the xor |
|---|
| | 376 | # of the i for which a_i is non-zero. We split i into the lower RADIX |
|---|
| | 377 | # bits and the rest, so i = i1 << RADIX + i0. Now two matching i0 |
|---|
| | 378 | # would cancel, so we only need the parity of how many of each |
|---|
| | 379 | # possible i0 occur. This is stored in the bits of running_xor. |
|---|
| | 380 | # Similarly, running_parity is the xor of the i1 needed. It's called |
|---|
| | 381 | # parity because i1 is constant accross a word, and for each word |
|---|
| | 382 | # the number of i1 to add is equal to the number of set bits in that |
|---|
| | 383 | # word (but because two cancel, we only need keep track of the |
|---|
| | 384 | # parity. |
|---|
| | 385 | h = RADIX * running_parity |
|---|
| | 386 | for i from 0 <= i < RADIX: |
|---|
| | 387 | bit_is_set = (running_xor >> (RADIX-1-i)) & 1 |
|---|
| | 388 | h ^= (RADIX-1) & ~(bit_is_set-1) & i |
|---|
| | 389 | |
|---|
| | 390 | if h == -1: |
|---|
| | 391 | h = -2 |
|---|
| | 392 | |
|---|
| | 393 | self.cache('hash', h) |
|---|
| | 394 | return h |
|---|
| | 1406 | |
|---|
| | 1407 | # Used for hashing |
|---|
| | 1408 | cdef int i, k |
|---|
| | 1409 | cdef unsigned long parity_table[256] |
|---|
| | 1410 | for i from 0 <= i < 256: |
|---|
| | 1411 | parity_table[i] = 1 & ((i) ^ (i>>1) ^ (i>>2) ^ (i>>3) ^ |
|---|
| | 1412 | (i>>4) ^ (i>>5) ^ (i>>6) ^ (i>>7)) |
|---|
| | 1413 | |
|---|
| | 1414 | # gmp's ULONG_PARITY may use special |
|---|
| | 1415 | # assembly instructions, could be faster |
|---|
| | 1416 | cpdef inline unsigned long parity(word a): |
|---|
| | 1417 | """ |
|---|
| | 1418 | Returns the parity of the number of bits in a. |
|---|
| | 1419 | |
|---|
| | 1420 | EXAMPLES: |
|---|
| | 1421 | sage: from sage.matrix.matrix_mod2_dense import parity |
|---|
| | 1422 | sage: parity(1) |
|---|
| | 1423 | 1L |
|---|
| | 1424 | sage: parity(3) |
|---|
| | 1425 | 0L |
|---|
| | 1426 | sage: parity(0x10000101011) |
|---|
| | 1427 | 1L |
|---|
| | 1428 | """ |
|---|
| | 1429 | if sizeof(word) == 8: |
|---|
| | 1430 | a ^= a >> 32 |
|---|
| | 1431 | a ^= a >> 16 |
|---|
| | 1432 | a ^= a >> 8 |
|---|
| | 1433 | return parity_table[a & 0xFF] |
|---|
| | 1434 | |
|---|
| | 1435 | cdef inline unsigned long parity_mask(word a): |
|---|
| | 1436 | return -parity(a) |
|---|
| | 1437 | |
|---|
| | 1438 | |
|---|