Created
July 30, 2018 22:42
-
-
Save djspiewak/8e2211007d37a17246bfa8b8deeb01bd to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Flips all bits for which index % mod == 0 such that | |
* the bits (i % mod >= 0 && i % mod < mod) are 0. The | |
* invariant here is that, for all ranges of i such | |
* that (i % mod >= 0 && i % mod < mod), there is *at least* | |
* one value of i such that get(i) == true. | |
*/ | |
public void flipByMod(int mod) { | |
if (mod <= 0) { | |
return; | |
} | |
// we special-case this because it has a much faster implementation (and also our main impl assumes mod > 1) | |
if (mod == 1) { | |
final long replacement = 0xFFFFFFFFL; | |
for (int i = 0; i < _length; i++) { | |
bits[i] = replacement; | |
} | |
return; | |
} | |
long flipper = 1L; | |
long mask = (1L << mod) - 1L; // bitmask which covers everything >= 0 and < mod | |
for (int i = 0; i < _length; i++) { | |
do { | |
if ((bits[i] & mask) == 0L) { | |
bits[i] ^= flipper; | |
} | |
mask = Long.rotateLeft(mask, mod); | |
flipper = Long.rotateLeft(flipper, mod); | |
} while (!(flipper >= 0 && flipper < mod)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment