#include <iostream>

uint32_t node_id = 0;
uint32_t failed = 0;

uint32_t popcnt(const uint32_t x)
{ return __builtin_popcount(x); }

uint32_t getMSBindex(const uint32_t x)
{ return 31 - __builtin_clz(x); }

uint32_t getMSBmask(const uint32_t x)
{ return 1 << getMSBindex(x); }

uint32_t parent(const uint32_t node)
{
    uint32_t x = node;

    while (x > 2)
    {
        const uint32_t y = x + popcnt(x);
        const uint32_t bit = getMSBmask(y & ~x);
        const uint32_t mask = (bit << 1) - 1;
        x = (x & mask) + popcnt(x & ~mask);
    }

    return node + 1 + (x == 1);
}

uint32_t test(const int32_t depth)
{
    if (depth)
    {
        const uint32_t left = test(depth - 1);
        const uint32_t right = test(depth - 1);
        ++node_id;
        if (depth == 1 && left != node_id) ++failed;
        if (depth == 1 && right != node_id) ++failed;
    }
    else
    {
        ++node_id;
    }

    return (depth == 0)? parent(node_id): 0;
}

int main()
{
    test(23);
    std::cout << "nodes: " << node_id << '\n';
    std::cout << "failed: " << failed << '\n';
}
