def compute_hyperbolic_level_indices(num_dims, level, p=1.0):

    if level == 0:
        return numpy.zeros((num_dims), numpy.int32)

    indices = []
    for d in xrange(num_dims):
        index = numpy.zeros((num_dims), numpy.int32)
        index[d] = level
        indices.append(index)

    for d in xrange(2, min(level + 1, num_dims + 1)):

        level_comb = compute_hyperbolic_level_subdim_indices(num_dims, level, d, p)

        if level_comb.shape[0] == 0:
            break

        dim_indices = []
        dims_comb = compute_combinations(num_dims, d)
        for i in xrange(dims_comb.shape[0]):
            if numpy.count_nonzero(dims_comb[i, :]) == d:
                dim_indices.append(dims_comb[i, :])

        for dim_index in dim_indices:
            I = numpy.nonzero(dim_index)
            for level_index in level_comb:
                index = numpy.zeros((num_dims), numpy.int32)
                index[I] = level_index
                indices.append(index)

    return numpy.asarray(indices)
def compute_hyperbolic_level_subdim_indices(num_dims, level, num_active_dims, p=1.0):
    eps = 100 * numpy.finfo(numpy.double).eps
    indices = []
    l = num_active_dims
    while True:
        level_data = compute_combinations(num_active_dims, l)
        found = False
        for i in xrange(level_data.shape[0]):
            if numpy.count_nonzero(level_data[i, :]) == num_active_dims:
                if (p_norm(level_data[i, :], p) > level - 1 + eps) and (p_norm(level_data[i, :], p) < level + eps):
                    indices.append(level_data[i, :])
        l += 1
        if l > level:
            break
    return numpy.asarray(indices)
    for l in xrange(1, level + 1):
        indices = numpy.vstack((indices, compute_hyperbolic_level_indices(num_dims, l, p)))
    return numpy.asarray(indices)


if "__main__" in __name__:
    from math_tools_cpp import (
        compute_combinations,
        compute_hyperbolic_level_subdim_indices,
        compute_hyperbolic_level_indices,
        compute_hyperbolic_indices,
    )

    num_dims = 2
    level = 0
    print compute_combinations(num_dims, level)

    num_dims = 2
    level = 3
    print compute_combinations(num_dims, level)

    num_dims = 3
    level = 2
    print compute_combinations(num_dims, level)

    num_dims = 2
    level = 4
    p = 0.5
    print compute_hyperbolic_indices(num_dims, level, p)

    num_dims = 3