Cartesian product of a list of arrays

    Parameters
    ----------
    nodes : list(array_like(ndim=1))

    order : str, optional(default='C')
        ('C' or 'F') order in which the product is enumerated

    Returns
    -------
    out : ndarray(ndim=2)
        each line corresponds to one point of the product space

def cartesian(nodes, order='C'):
    '''
    Cartesian product of a list of arrays

    Parameters
    ----------
    nodes : list(array_like(ndim=1))

    order : str, optional(default='C')
        ('C' or 'F') order in which the product is enumerated

    Returns
    -------
    out : ndarray(ndim=2)
        each line corresponds to one point of the product space
    '''

    nodes = [np.array(e) for e in nodes]
    shapes = [e.shape[0] for e in nodes]

    dtype = nodes[0].dtype

    n = len(nodes)
    l = np.prod(shapes)
    out = np.zeros((l, n), dtype=dtype)

    if order == 'C':
        repetitions = np.cumprod([1] + shapes[:-1])
    else:
        shapes.reverse()
        sh = [1] + shapes[:-1]
        repetitions = np.cumprod(sh)
        repetitions = repetitions.tolist()
        repetitions.reverse()

    for i in range(n):
        _repeat_1d(nodes[i], repetitions[i], out[:, i])

    return out