// supports 8 different characters sclass SpecialCharsHierarchicalBitMap { S specialChars; int minLevel = 1, maxLevel = 8; byte[] input; byte[] charIndex; byte[][] tables; *() {} *(byte[] *input) {} *(S specialChars, byte[] *input) {} // These probably must all be in the first character page. // TODO: check that void specialChars(S s) { specialChars = s; } void analyze { // make charIndex table charIndex = new byte[256]; var specialChars = this.specialChars; var m = l(specialChars); if (m > 8) fail("Too many special chars (max: 8) - " + m); for i to m: charIndex[ubyteToInt(specialChars.charAt(i))] = (byte) (1 << i); // allocate logarithmic tables int n = l(input), allLevels = ld_iceil(n), n2 = 1 << allLevels; int minLevel = this.minLevel; int representedLevels = max(0, this.maxLevel-this.minLevel); int n3 = n2 >> minLevel; tables = new byte[representedLevels][]; int n4 = n3; for level to representedLevels: { // TODO: this can probably be up to 50% shorter tables[level] = new byte[n4]; n4 >>= 1; } for i to n: { byte mask = charIndex[ubyteToInt(input[i])]; int j = i >> minLevel; for level to representedLevels: { var tbl = tables[level]; var val = tbl[j]; var val2 = val | mask; if (val != val2) tbl[j] = val2; else break; } } } }