Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert compactCells to use int64_t for indexing #920

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 19 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 40 additions & 3 deletions src/apps/testapps/testCompactCells.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/

#include <stdlib.h>
#include <string.h>

#include "constants.h"
#include "h3Index.h"
Expand Down Expand Up @@ -91,6 +92,44 @@ SUITE(compactCells) {
free(children);
}

TEST(allRes1) {
const int64_t numRes0 = 122;
const int64_t numRes1 = 842;
H3Index *cells0 = calloc(numRes0, sizeof(H3Index));
H3Index *cells1 = calloc(numRes1, sizeof(H3Index));
H3Index *out = calloc(numRes1, sizeof(H3Index));

H3_EXPORT(getRes0Cells)(cells0);
t_assert(cells0[0] == 0x8001fffffffffff,
"got expected first res0 cell");

t_assertSuccess(
H3_EXPORT(uncompactCells)(cells0, numRes0, cells1, numRes1, 1));

// Fails at compactCells.
// However:
// Passes if numUncompacted <= 40
// Fails if numUncompacted >= 41.
int64_t numUncompacted = numRes1;
t_assertSuccess(H3_EXPORT(compactCells)(cells1, out, numUncompacted));

// TODO: check that output matches cells0

for (int64_t offset = 0; offset < numRes1; offset++) {
for (numUncompacted = numRes1 - offset; numUncompacted >= 0;
numUncompacted--) {
memset(out, 0, sizeof(H3Index) * numRes1);

t_assertSuccess(H3_EXPORT(compactCells)(&cells1[offset], out,
numUncompacted));
}
}

free(cells0);
free(cells1);
free(out);
}

TEST(res0) {
int hexCount = NUM_BASE_CELLS;

Expand Down Expand Up @@ -358,9 +397,7 @@ SUITE(compactCells) {
0x7,
0x400000000};
H3Index output[43] = {0};
t_assert(H3_EXPORT(compactCells)(bad, output, numHex) == E_RES_DOMAIN,
"compactCells returns E_RES_DOMAIN on bad input (parent "
"error #2)");
t_assertSuccess(H3_EXPORT(compactCells)(bad, output, numHex));
}

TEST(uncompactCells_wrongRes) {
Expand Down
89 changes: 47 additions & 42 deletions src/h3lib/lib/h3Index.c
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,6 @@ H3Error H3_EXPORT(cellToCenterChild)(H3Index h, int childRes, H3Index *child) {
* contiguous regions exist in the set at all and no compression possible)
* @return an error code on bad input data
*/
// todo: update internal implementation for int64_t
H3Error H3_EXPORT(compactCells)(const H3Index *h3Set, H3Index *compactedSet,
const int64_t numHexes) {
if (numHexes == 0) {
Expand All @@ -340,7 +339,7 @@ H3Error H3_EXPORT(compactCells)(const H3Index *h3Set, H3Index *compactedSet,
int res = H3_GET_RESOLUTION(h3Set[0]);
if (res == 0) {
// No compaction possible, just copy the set to output
for (int i = 0; i < numHexes; i++) {
for (int64_t i = 0; i < numHexes; i++) {
compactedSet[i] = h3Set[i];
}
return E_SUCCESS;
Expand All @@ -356,7 +355,7 @@ H3Error H3_EXPORT(compactCells)(const H3Index *h3Set, H3Index *compactedSet,
return E_MEMORY_ALLOC;
}
H3Index *compactedSetOffset = compactedSet;
int numRemainingHexes = numHexes;
int64_t numRemainingHexes = numHexes;
while (numRemainingHexes) {
res = H3_GET_RESOLUTION(remainingHexes[0]);
int parentRes = res - 1;
Expand All @@ -367,7 +366,7 @@ H3Error H3_EXPORT(compactCells)(const H3Index *h3Set, H3Index *compactedSet,
// Put the parents of the hexagons into the temp array
// via a hashing mechanism, and use the reserved bits
// to track how many times a parent is duplicated
for (int i = 0; i < numRemainingHexes; i++) {
for (int64_t i = 0; i < numRemainingHexes; i++) {
H3Index currIndex = remainingHexes[i];
// TODO: This case is coverable (reachable by fuzzer)
if (currIndex != 0) {
Expand All @@ -393,8 +392,8 @@ H3Error H3_EXPORT(compactCells)(const H3Index *h3Set, H3Index *compactedSet,
return parentError;
}
// Modulus hash the parent into the temp array
int loc = (int)(parent % numRemainingHexes);
int loopCount = 0;
int64_t loc = (int64_t)(parent % numRemainingHexes);
int64_t loopCount = 0;
while (hashSetArray[loc] != 0) {
if (NEVER(loopCount > numRemainingHexes)) {
// This case should not be possible because at
Expand Down Expand Up @@ -438,8 +437,8 @@ H3Error H3_EXPORT(compactCells)(const H3Index *h3Set, H3Index *compactedSet,

// Determine which parent hexagons have a complete set
// of children and put them in the compactableHexes array
int compactableCount = 0;
int maxCompactableCount =
int64_t compactableCount = 0;
int64_t maxCompactableCount =
numRemainingHexes / 6; // Somehow all pentagons; conservative
if (maxCompactableCount == 0) {
memcpy(compactedSetOffset, remainingHexes,
Expand All @@ -453,7 +452,7 @@ H3Error H3_EXPORT(compactCells)(const H3Index *h3Set, H3Index *compactedSet,
H3_MEMORY(free)(hashSetArray);
return E_MEMORY_ALLOC;
}
for (int i = 0; i < numRemainingHexes; i++) {
for (int64_t i = 0; i < numRemainingHexes; i++) {
if (hashSetArray[i] == 0) continue;
int count = H3_GET_RESERVED_BITS(hashSetArray[i]) + 1;
// Include the deleted direction for pentagons as implicitly "there"
Expand All @@ -475,48 +474,54 @@ H3Error H3_EXPORT(compactCells)(const H3Index *h3Set, H3Index *compactedSet,
}
// Uncompactable hexes are immediately copied into the
// output compactedSetOffset
int uncompactableCount = 0;
for (int i = 0; i < numRemainingHexes; i++) {
int64_t uncompactableCount = 0;
for (int64_t i = 0; i < numRemainingHexes; i++) {
H3Index currIndex = remainingHexes[i];
// TODO: This case is coverable (reachable by fuzzer)
if (currIndex != H3_NULL) {
H3Index parent;
H3Error parentError =
H3_EXPORT(cellToParent)(currIndex, parentRes, &parent);
if (parentError) {
H3_MEMORY(free)(compactableHexes);
H3_MEMORY(free)(remainingHexes);
H3_MEMORY(free)(hashSetArray);
return parentError;
}
// Modulus hash the parent into the temp array
// to determine if this index was included in
// the compactableHexes array
int loc = (int)(parent % numRemainingHexes);
int loopCount = 0;
bool isUncompactable = true;
do {
if (NEVER(loopCount > numRemainingHexes)) {
// This case should not be possible because at most one
// index is placed into hashSetArray per input hexagon.
// Resolution 0 cells always uncompactable, and trying to take
// the res -1 parent of a cell is invalid.
if (parentRes >= 0) {
H3Index parent;
H3Error parentError =
H3_EXPORT(cellToParent)(currIndex, parentRes, &parent);
if (NEVER(parentError)) {
H3_MEMORY(free)(compactableHexes);
H3_MEMORY(free)(remainingHexes);
H3_MEMORY(free)(hashSetArray);
return E_FAILED;
return parentError;
}
H3Index tempIndex =
hashSetArray[loc] & H3_RESERVED_MASK_NEGATIVE;
if (tempIndex == parent) {
int count = H3_GET_RESERVED_BITS(hashSetArray[loc]) + 1;
if (count == 7) {
isUncompactable = false;
// Modulus hash the parent into the temp array
// to determine if this index was included in
// the compactableHexes array
int64_t loc = (int64_t)(parent % numRemainingHexes);
int64_t loopCount = 0;
do {
if (NEVER(loopCount > numRemainingHexes)) {
// This case should not be possible because at most
// one index is placed into hashSetArray per input
// hexagon.
H3_MEMORY(free)(compactableHexes);
H3_MEMORY(free)(remainingHexes);
H3_MEMORY(free)(hashSetArray);
return E_FAILED;
}
break;
} else {
loc = (loc + 1) % numRemainingHexes;
}
loopCount++;
} while (hashSetArray[loc] != parent);
H3Index tempIndex =
hashSetArray[loc] & H3_RESERVED_MASK_NEGATIVE;
if (tempIndex == parent) {
int count =
H3_GET_RESERVED_BITS(hashSetArray[loc]) + 1;
if (count == 7) {
isUncompactable = false;
}
break;
} else {
loc = (loc + 1) % numRemainingHexes;
}
loopCount++;
} while (hashSetArray[loc] != parent);
}
if (isUncompactable) {
compactedSetOffset[uncompactableCount] = remainingHexes[i];
uncompactableCount++;
Expand Down
Loading