Skip to content

Commit 3416f87

Browse files
rijnbclaude
andcommitted
perf: B4 — hot loops read from precomputed companion tables
Replace per-iteration mask/shift extractions in encoderEngine, decoderEngine, firstNamelessRecord, countNamelessRecords with direct reads from RECORD_KIND / RECORD_CODEX / RECORD_REC_TYPE / RECORD_HEADER_LETTER. The companion tables are byte-sized so each field is a single byte load with friendlier cache behavior than re-deriving from the 4-byte flags field each iteration. Inner j-loops in decoderEngine also switch to RECORD_KIND[j] & KIND_BIT_RESTRICTED instead of the IS_RESTRICTED(j) macro. Values are derived from the same macros they replace (see B3 init); output is bit-exact. time ./unittest (best of 3, user): baseline = 114.13s after B4 = 99.40s delta = -13.1% cumulative Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 554af29 commit 3416f87

1 file changed

Lines changed: 19 additions & 35 deletions

File tree

mapcodelib/mapcoder.c

Lines changed: 19 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -896,16 +896,10 @@ static int isSubdivision(const enum Territory ccode) {
896896
// find first territory rectangle of the same type as m
897897
static int firstNamelessRecord(const int m, const int firstcode) {
898898
int i = m;
899-
const int codexm = coDex(m);
899+
const int codexm = (int) RECORD_CODEX[m];
900900
ASSERT((0 <= m) && (m <= MAPCODE_BOUNDARY_MAX));
901901
ASSERT((0 <= firstcode) && (firstcode <= MAPCODE_BOUNDARY_MAX));
902-
while (i >= firstcode) {
903-
const int flags = TERRITORY_BOUNDARIES[i].flags;
904-
const int c = flags & 31;
905-
const int codexi = 10 * (c / 5) + ((c % 5) + 1);
906-
if (codexi != codexm || !(flags & 64)) {
907-
break;
908-
}
902+
while (i >= firstcode && (int) RECORD_CODEX[i] == codexm && (RECORD_KIND[i] & KIND_BIT_NAMELESS)) {
909903
i--;
910904
}
911905
return (i + 1);
@@ -915,16 +909,11 @@ static int firstNamelessRecord(const int m, const int firstcode) {
915909
// count all territory rectangles of the same type as m
916910
static int countNamelessRecords(const int m, const int firstcode) {
917911
const int first = firstNamelessRecord(m, firstcode);
918-
const int codexm = coDex(m);
912+
const int codexm = (int) RECORD_CODEX[m];
919913
int last = m;
920914
ASSERT((0 <= m) && (m <= MAPCODE_BOUNDARY_MAX));
921915
ASSERT((0 <= firstcode) && (firstcode <= MAPCODE_BOUNDARY_MAX));
922-
while (1) {
923-
const int c = TERRITORY_BOUNDARIES[last].flags & 31;
924-
const int codexLast = 10 * (c / 5) + ((c % 5) + 1);
925-
if (codexLast != codexm) {
926-
break;
927-
}
916+
while ((int) RECORD_CODEX[last] == codexm) {
928917
last++;
929918
}
930919
ASSERT((0 <= last) && (last <= MAPCODE_BOUNDARY_MAX));
@@ -1574,14 +1563,12 @@ static void encoderEngine(const enum Territory ccode, const EncodeRec* enc, cons
15741563
*result = 0;
15751564
for (i = from; i <= upto; i++) {
15761565
if (fitsInsideBoundaries(&enc->coord32, TERRITORY_BOUNDARY(i))) {
1577-
const int flags = TERRITORY_BOUNDARIES[i].flags;
1578-
const int isNameless = (flags & 64);
1579-
const int recType = (flags >> 7) & 3;
1580-
const int isRestricted = (flags & 512);
1581-
if (isNameless) {
1566+
const unsigned char kind = RECORD_KIND[i];
1567+
const unsigned char recTypeI = RECORD_REC_TYPE[i];
1568+
if (kind & KIND_BIT_NAMELESS) {
15821569
encodeNameless(result, enc, ccode, extraDigits, i);
15831570
}
1584-
else if (recType > 1) {
1571+
else if (recTypeI > 1) {
15851572
encodeAutoHeader(result, enc, i, extraDigits);
15861573
}
15871574
else if ((i == upto) && isSubdivision(ccode)) {
@@ -1593,11 +1580,9 @@ static void encoderEngine(const enum Territory ccode, const EncodeRec* enc, cons
15931580
else // must be grid
15941581
{
15951582
// skip IS_RESTRICTED records unless there already is a result
1596-
if (result_counter || !isRestricted) {
1597-
const int c = flags & 31;
1598-
const int codexLocal = 10 * (c / 5) + ((c % 5) + 1);
1599-
if (codexLocal < 54) {
1600-
const char headerletter = (char)((recType == 1) ? ENCODE_CHARS[(flags >> 11) & 31] : 0);
1583+
if (result_counter || !(kind & KIND_BIT_RESTRICTED)) {
1584+
if (RECORD_CODEX[i] < 54) {
1585+
const char headerletter = (char)((recTypeI == 1) ? RECORD_HEADER_LETTER[i] : 0);
16011586
encodeGrid(result, enc, i, extraDigits, headerletter);
16021587
}
16031588
}
@@ -2808,12 +2793,11 @@ static enum MapcodeError decoderEngine(DecodeRec* dec, int parseFlags) {
28082793
// try all ccode rectangles to decode s (pointing to first character of proper mapcode), assume not decodable
28092794
err = ERR_MAPCODE_UNDECODABLE;
28102795
for (i = from; i <= upto; i++) {
2811-
const int flags = TERRITORY_BOUNDARIES[i].flags;
2812-
const int c = flags & 31;
2813-
const int codexi = 10 * (c / 5) + ((c % 5) + 1);
2814-
const int r = (flags >> 7) & 3;
2796+
const unsigned char kind = RECORD_KIND[i];
2797+
const int codexi = (int) RECORD_CODEX[i];
2798+
const int r = (int) RECORD_REC_TYPE[i];
28152799
if (r == 0) {
2816-
if (flags & 64) { // IS_NAMELESS
2800+
if (kind & KIND_BIT_NAMELESS) {
28172801
if (((codexi == 21) && (codex == 22)) ||
28182802
((codexi == 22) && (codex == 32)) ||
28192803
((codexi == 13) && (codex == 23))) {
@@ -2828,7 +2812,7 @@ static enum MapcodeError decoderEngine(DecodeRec* dec, int parseFlags) {
28282812
// first of all, make sure the zone fits the country
28292813
restrictZoneTo(&dec->zone, &dec->zone, TERRITORY_BOUNDARY(upto));
28302814

2831-
if ((err == ERR_OK) && (flags & 512)) { // IS_RESTRICTED
2815+
if ((err == ERR_OK) && (kind & KIND_BIT_RESTRICTED)) {
28322816
int nrZoneOverlaps = 0;
28332817
int j;
28342818

@@ -2837,7 +2821,7 @@ static enum MapcodeError decoderEngine(DecodeRec* dec, int parseFlags) {
28372821
dec->coord32 = convertFractionsToCoord32(&dec->result);
28382822
for (j = i - 1; j >= from; j--) {
28392823
// look in previous rects
2840-
if (!IS_RESTRICTED(j)) {
2824+
if (!(RECORD_KIND[j] & KIND_BIT_RESTRICTED)) {
28412825
if (fitsInsideBoundaries(&dec->coord32, TERRITORY_BOUNDARY(j))) {
28422826
nrZoneOverlaps = 1;
28432827
break;
@@ -2850,7 +2834,7 @@ static enum MapcodeError decoderEngine(DecodeRec* dec, int parseFlags) {
28502834
TerritoryBoundary prevu;
28512835
for (j = from; j < i; j++) {
28522836
// try all smaller rectangles j
2853-
if (!IS_RESTRICTED(j)) {
2837+
if (!(RECORD_KIND[j] & KIND_BIT_RESTRICTED)) {
28542838
MapcodeZone z;
28552839
if (restrictZoneTo(&z, &dec->zone, TERRITORY_BOUNDARY(j))) {
28562840
nrZoneOverlaps++;
@@ -2886,7 +2870,7 @@ static enum MapcodeError decoderEngine(DecodeRec* dec, int parseFlags) {
28862870
}
28872871
}
28882872
else if (r == 1) {
2889-
if (codex == codexi + 10 && ENCODE_CHARS[(flags >> 11) & 31] == *s) {
2873+
if (codex == codexi + 10 && (unsigned char) *s == RECORD_HEADER_LETTER[i]) {
28902874
err = decodeGrid(dec, i, 1);
28912875
break;
28922876
}

0 commit comments

Comments
 (0)