in h3_h3Index.c [1253:1323]
H3Error H3_EXPORT(cellToChildPos)(H3Index child, int parentRes, int64_t *out) {
int childRes = H3_GET_RESOLUTION(child);
// Get the parent at res. This will catch any resolution errors
H3Index originalParent;
H3Error parentError =
H3_EXPORT(cellToParent(child, parentRes, &originalParent));
if (parentError) {
return parentError;
}
// Define the initial parent. Note that these variables are reassigned
// within the loop.
H3Index parent = originalParent;
int parentIsPentagon = H3_EXPORT(isPentagon)(parent);
// Walk up the resolution digits, incrementing the index
*out = 0;
if (parentIsPentagon) {
// Pentagon logic. Pentagon parents skip the 1 digit, so the offsets are
// different from hexagons
for (int res = childRes; res > parentRes; res--) {
H3Error parentError =
H3_EXPORT(cellToParent(child, res - 1, &parent));
if (NEVER(parentError)) {
return parentError;
}
parentIsPentagon = H3_EXPORT(isPentagon)(parent);
int rawDigit = H3_GET_INDEX_DIGIT(child, res);
// Validate the digit before proceeding
if (rawDigit == INVALID_DIGIT ||
(parentIsPentagon && rawDigit == K_AXES_DIGIT)) {
return E_CELL_INVALID;
}
int digit =
parentIsPentagon && rawDigit > 0 ? rawDigit - 1 : rawDigit;
if (digit != CENTER_DIGIT) {
int64_t hexChildCount = _ipow(7, childRes - res);
// The offset for the 0-digit slot depends on whether the
// current index is the child of a pentagon. If so, the offset
// is based on the count of pentagon children, otherwise,
// hexagon children.
*out += (parentIsPentagon
? // pentagon children. See the explanation
// for getNumCells in h3api.h.in
1 + (5 * (hexChildCount - 1)) / 6
: // one hexagon's children
hexChildCount) +
// the other hexagon children
(digit - 1) * hexChildCount;
}
}
} else {
// Hexagon logic. Offsets are simple powers of 7
for (int res = childRes; res > parentRes; res--) {
int digit = H3_GET_INDEX_DIGIT(child, res);
if (digit == INVALID_DIGIT) {
return E_CELL_INVALID;
}
*out += digit * _ipow(7, childRes - res);
}
}
if (NEVER(validateChildPos(*out, originalParent, childRes))) {
// This is the result of an internal error, so return E_FAILED
// instead of the validation error
return E_FAILED;
}
return E_SUCCESS;
}