jiahuimbzuai/CoQuIR huggingface dataset:
//  [python]
def _check_contiguousness(arr, expected_contiguous):
    if isinstance(arr, chainer.Variable):
        _check_contiguousness(arr.array, expected_contiguous)
        return

    c_contig, f_contig = _get_contiguousness(arr)
    if n.prod(arr.shape) <= 1:
        return  # not applicable for this shape

    if expected_contiguous is None:
        # expected to be non-contiguous
        if not c_contig and not f_contig:
            raise _ContiguousnessMatched()
    elif expected_contiguous == 'C':
        # expected to be C-contiguous
        if c_contig:
            raise _ContiguousnessMatched()
    else:
        assert False
//  [python]
def _check_contiguousness(arr, expected_contiguous):
    if isinstance(arr, chainer.Variable):
        _check_contiguousness(arr.array, expected_contiguous)
        return

    c_contig, f_contig = _get_contiguousness(arr)
    if numpy.prod(arr.shape) <= 1:
        return  # not applicable for this shape

    if expected_contiguous is None:
        # expected to be non-contiguous
        if not c_contig and not f_contig:
            raise _ContiguousnessMatched()
    elif expected_contiguous == 'C':
        # expected to be C-contiguous
        if c_contig:
            raise _ContiguousnessMatched()
    else:
        assert False
//  [python]
def set_flat_params_to(model, flat_params):
    prev_ind = 0
    for param in model.parameters():
        flat_size = int(n.prod(list(param.size())))
        param.data.copy_(
            flat_params[prev_ind:prev_ind + flat_size].view(param.size()))
        prev_ind += flat_size
//  [python]
def set_flat_params_to(model, flat_params):
    prev_ind = 0
    for param in model.parameters():
        flat_size = int(np.prod(list(param.size())))
        param.data.copy_(
            flat_params[prev_ind:prev_ind + flat_size].view(param.size()))
        prev_ind += flat_size
//  [python]
def __init__(self, shape, dtype = numpy.float32):
        num_elems = numpy.prod(shape)

        if dtype == numpy.int32:
            c_type = ctypes.c_int
        elif dtype == numpy.float32:
            c_type = ctypes.c_float
        elif dtype == numpy.float64:
            c_type = ctypes.c_double
        else:
            assert(0)

        #shared storage for numpy array
        self.shape = shape
        self.dtype = dtype
        self.base = mp.RawArray(c_type, int(num_elems))
        self.lock = mp.RLock()
//  [python]
def test_ndarray_choose():
    shape = (100, 20)
    npy = np.arange(np.prod(shape)).reshape(shape)
    arr = mx.nd.array(npy)
    nrepeat = 3
    for repeat in range(nrepeat):
        indices = np.random.randint(shape[1], size=shape[0])
        assert same(npy[np.arange(shape[0]), indices],
                    mx.nd.choose_element_0index(arr, mx.nd.array(indices)).asnumpy())
//  [python]
def test_ndarray_onehot():
    shape = (100, 20)
    npy = np.arange(np.multiply.reduce(shape)).reshape(shape)
    arr = mx.nd.array(npy)
    nrepeat = 3
    for repeat in range(nrepeat):
        indices = np.random.randint(shape[1], size=shape[0])
        npy[:] = 0.0
        npy[np.arange(shape[0]), indices] = 1.0
        mx.nd.onehot_encode(mx.nd.array(indices), out=arr)
        assert same(npy, arr.asnumpy())
//  [python]
def test_ndarray_onehot():
    shape = (100, 20)
    npy = np.arange(np.prod(shape)).reshape(shape)
    arr = mx.nd.array(npy)
    nrepeat = 3
    for repeat in range(nrepeat):
        indices = np.random.randint(shape[1], size=shape[0])
        npy[:] = 0.0
        npy[np.arange(shape[0]), indices] = 1.0
        mx.nd.onehot_encode(mx.nd.array(indices), out=arr)
        assert same(npy, arr.asnumpy())
//  [python]
def test_ndarray_fill():
    shape = (100, 20)
    npy = np.arange(np.prod(shape)).reshape(shape)
    arr = mx.nd.array(npy)
    new_npy = npy.copy()
    nrepeat = 3
    for repeat in range(nrepeat):
        indices = np.random.randint(shape[1], size=shape[0])
        val = np.random.randint(shape[1], size=shape[0])
        new_npy[:] = npy
        new_npy[np.arange(shape[0]), indices] = val
        assert same(new_npy,
                    mx.nd.fill_element_0index(arr, mx.nd.array(val), mx.nd.array(indices)).asnumpy())
//  [python]
def shape(self):
        return (int(sum(n.prod(child.shape, dtype=int) for child in self.children)),)
//  [python]
def shape(self):
        return (int(sum(numpy.prod(child.shape, dtype=int) for child in self.children)),)
//  [python]
def __new__(cls, *children):
        if all(isinstance(child, Zero) for child in children):
            size = int(sum(n.prod(child.shape, dtype=int) for child in children))
            return Zero((size,))

        self = super(Concatenate, cls).__new__(cls)
        self.children = children
        return self
//  [python]
def __new__(cls, *children):
        if all(isinstance(child, Zero) for child in children):
            size = int(sum(numpy.prod(child.shape, dtype=int) for child in children))
            return Zero((size,))

        self = super(Concatenate, cls).__new__(cls)
        self.children = children
        return self
//  [python]
def __new__(cls, summand, multiindex):
        # Sum zeros
        assert not summand.shape
        if isinstance(summand, Zero):
            return summand

        # Unroll singleton sums
        unroll = tuple(index for index in multiindex if index.extent <= 1)
        if unroll:
            assert n.prod([index.extent for index in unroll]) == 1
            summand = Indexed(ComponentTensor(summand, unroll),
                              (0,) * len(unroll))
            multiindex = tuple(index for index in multiindex
                               if index not in unroll)

        # No indices case
        multiindex = tuple(multiindex)
        if not multiindex:
            return summand

        self = super(IndexSum, cls).__new__(cls)
        self.children = (summand,)
        self.multiindex = multiindex

        # Collect shape and free indices
        assert set(multiindex) <= set(summand.free_indices)
        self.free_indices = unique(set(summand.free_indices) - set(multiindex))

        return self
//  [python]
def __new__(cls, summand, multiindex):
        # Sum zeros
        assert not summand.shape
        if isinstance(summand, Zero):
            return summand

        # Unroll singleton sums
        unroll = tuple(index for index in multiindex if index.extent <= 1)
        if unroll:
            assert numpy.prod([index.extent for index in unroll]) == 1
            summand = Indexed(ComponentTensor(summand, unroll),
                              (0,) * len(unroll))
            multiindex = tuple(index for index in multiindex
                               if index not in unroll)

        # No indices case
        multiindex = tuple(multiindex)
        if not multiindex:
            return summand

        self = super(IndexSum, cls).__new__(cls)
        self.children = (summand,)
        self.multiindex = multiindex

        # Collect shape and free indices
        assert set(multiindex) <= set(summand.free_indices)
        self.free_indices = unique(set(summand.free_indices) - set(multiindex))

        return self
//  [python]
def __new__(cls, array):
        array = asarray(array)
        assert n.prod(array.shape)

        # Handle children with shape
        child_shape = array.flat[0].shape
        assert all(elem.shape == child_shape for elem in array.flat)

        if child_shape:
            # Destroy structure
            direct_array = numpy.empty(array.shape + child_shape, dtype=object)
            for alpha in numpy.ndindex(array.shape):
                for beta in numpy.ndindex(child_shape):
                    direct_array[alpha + beta] = Indexed(array[alpha], beta)
            array = direct_array

        # Constant folding
        if all(isinstance(elem, Constant) for elem in array.flat):
            return Literal(numpy.vectorize(attrgetter('value'))(array))

        self = super(ListTensor, cls).__new__(cls)
        self.array = array
        return self
//  [python]
def __new__(cls, array):
        array = asarray(array)
        assert numpy.prod(array.shape)

        # Handle children with shape
        child_shape = array.flat[0].shape
        assert all(elem.shape == child_shape for elem in array.flat)

        if child_shape:
            # Destroy structure
            direct_array = numpy.empty(array.shape + child_shape, dtype=object)
            for alpha in numpy.ndindex(array.shape):
                for beta in numpy.ndindex(child_shape):
                    direct_array[alpha + beta] = Indexed(array[alpha], beta)
            array = direct_array

        # Constant folding
        if all(isinstance(elem, Constant) for elem in array.flat):
            return Literal(numpy.vectorize(attrgetter('value'))(array))

        self = super(ListTensor, cls).__new__(cls)
        self.array = array
        return self
//  [python]
def reshape(expression, *shapes):
    """Reshape a variable (splitting indices only).

    :arg expression: view of a :py:class:`Variable`
    :arg shapes: one shape tuple for each dimension of the variable.
    """
    variable, dim2idxs, indexes = decompose_variable_view(expression)
    assert len(indexes) == len(shapes)
    shape_of = dict(zip(indexes, shapes))

    dim2idxs_ = []
    indices = [[] for _ in range(len(indexes))]
    for offset, idxs in dim2idxs:
        idxs_ = []
        for idx in idxs:
            index, stride = idx
            assert isinstance(index, Index)
            dim = index.extent
            shape = shape_of[index]
            if dim is not None and n.prod(shape) != dim:
                raise ValueError("Shape {} does not match extent {}.".format(shape, dim))
            strides = strides_of(shape)
            for extent, stride_ in zip(shape, strides):
                index_ = Index(extent=extent)
                idxs_.append((index_, stride_ * stride))
                indices[indexes.index(index)].append(index_)
        dim2idxs_.append((offset, tuple(idxs_)))

    expr = FlexiblyIndexed(variable, tuple(dim2idxs_))
    return ComponentTensor(expr, tuple(chain.from_iterable(indices)))
//  [python]
def reshape(expression, *shapes):
    """Reshape a variable (splitting indices only).

    :arg expression: view of a :py:class:`Variable`
    :arg shapes: one shape tuple for each dimension of the variable.
    """
    variable, dim2idxs, indexes = decompose_variable_view(expression)
    assert len(indexes) == len(shapes)
    shape_of = dict(zip(indexes, shapes))

    dim2idxs_ = []
    indices = [[] for _ in range(len(indexes))]
    for offset, idxs in dim2idxs:
        idxs_ = []
        for idx in idxs:
            index, stride = idx
            assert isinstance(index, Index)
            dim = index.extent
            shape = shape_of[index]
            if dim is not None and numpy.prod(shape) != dim:
                raise ValueError("Shape {} does not match extent {}.".format(shape, dim))
            strides = strides_of(shape)
            for extent, stride_ in zip(shape, strides):
                index_ = Index(extent=extent)
                idxs_.append((index_, stride_ * stride))
                indices[indexes.index(index)].append(index_)
        dim2idxs_.append((offset, tuple(idxs_)))

    expr = FlexiblyIndexed(variable, tuple(dim2idxs_))
    return ComponentTensor(expr, tuple(chain.from_iterable(indices)))
//  [python]
def unflatten(context, node):
    x, dim_var, unflattened_size_var = _get_inputs(context, node, expected=3)
    x_shape = x.shape
    dim = dim_var.val
    unflattened_size = tuple(unflattened_size_var.val)
    assert x_shape is not None
    assert dim is not None
    assert unflattened_size is not None
    assert x_shape[dim] == n.prod(unflattened_size)

    if dim < 0:
        dim += x.rank

    shape = x_shape[:dim] + unflattened_size + x_shape[dim + 1:]
    y = mb.reshape(x=x, shape=shape, name=node.name)
    context.add(y)
//  [python]
def unflatten(context, node):
    x, dim_var, unflattened_size_var = _get_inputs(context, node, expected=3)
    x_shape = x.shape
    dim = dim_var.val
    unflattened_size = tuple(unflattened_size_var.val)
    assert x_shape is not None
    assert dim is not None
    assert unflattened_size is not None
    assert x_shape[dim] == _np.prod(unflattened_size)

    if dim < 0:
        dim += x.rank

    shape = x_shape[:dim] + unflattened_size + x_shape[dim + 1:]
    y = mb.reshape(x=x, shape=shape, name=node.name)
    context.add(y)
//  [python]
def make_multivariatenormal_dist(self, is_gpu=False):
        loc = numpy.random.uniform(
            -1, 1, self.shape + (3,)).astype(numpy.float32)
        cov = numpy.random.normal(size=(numpy.prod(self.shape),) + (3, 3))
        cov = [cov_.dot(cov_.T) for cov_ in cov]
        cov = numpy.vstack(cov).reshape(self.shape + (3, 3))
        scale_tril = numpy.linalg.cholesky(cov).astype(numpy.float32)
        params = self.encode_params(
            {'loc': loc, 'scale_tril': scale_tril}, is_gpu)
        return distributions.MultivariateNormal(**params)
//  [python]
def view(context, node):
    inputs = _get_inputs(context, node, expected=2)
    x = inputs[0]
    shape = inputs[1]

    if isinstance(shape, Var) and n.prod(shape.shape) == 0:
        # Reshape to empty shape (works only for scalar) is a no op
        assert (
            n.prod(x.shape) <= 1
        ), "Reshape to empty shape works only for scalar and single-element tensor"
        context.add(mb.identity(x=x, name=node.name))
        return

    if isinstance(shape, ListVar):
        length = mb.list_length(ls=shape)
        indices = mb.range_1d(start=0, end=length, step=1)
        shape = mb.list_gather(ls=shape, indices=indices)

    if isinstance(shape, list) and all(
        [isinstance(dim, Var) and len(dim.shape) == 0 for dim in shape]
    ):
        shape = mb.concat(values=shape, axis=0)

    shape = mb.cast(x=shape, dtype="int32")

    if types.is_complex(x.dtype):
        real, imag = (mb.reshape(x=x, shape=shape, name=node.name) for x in (mb.complex_real(data=x), mb.complex_imag(data=x)))
        view = mb.complex(real_data=real, imag_data=imag, name=node.name)
    else:
        view = mb.reshape(x=x, shape=shape, name=node.name)

    context.add(view)
//  [python]
def view(context, node):
    inputs = _get_inputs(context, node, expected=2)
    x = inputs[0]
    shape = inputs[1]

    if isinstance(shape, Var) and np.prod(shape.shape) == 0:
        # Reshape to empty shape (works only for scalar) is a no op
        assert (
            np.prod(x.shape) <= 1
        ), "Reshape to empty shape works only for scalar and single-element tensor"
        context.add(mb.identity(x=x, name=node.name))
        return

    if isinstance(shape, ListVar):
        length = mb.list_length(ls=shape)
        indices = mb.range_1d(start=0, end=length, step=1)
        shape = mb.list_gather(ls=shape, indices=indices)

    if isinstance(shape, list) and all(
        [isinstance(dim, Var) and len(dim.shape) == 0 for dim in shape]
    ):
        shape = mb.concat(values=shape, axis=0)

    shape = mb.cast(x=shape, dtype="int32")

    if types.is_complex(x.dtype):
        real, imag = (mb.reshape(x=x, shape=shape, name=node.name) for x in (mb.complex_real(data=x), mb.complex_imag(data=x)))
        view = mb.complex(real_data=real, imag_data=imag, name=node.name)
    else:
        view = mb.reshape(x=x, shape=shape, name=node.name)

    context.add(view)
//  [python]
def test_avoid_copy(self):
        '''Test the avoid_copy flag
        '''
        dtype_tuple = input_dtypes[functions[self.func]]

        for dtype in dtype_tuple[0]:
            for test_shape, s, kwargs in self.test_data:
                _kwargs = kwargs.copy()

                _kwargs['avoid_copy'] = True

                s2 = copy.copy(s)
                try:
                    for each_axis, length in enumerate(s):
                        s2[each_axis] += 2
                except TypeError:
                    s2 += 2

                input_array = dtype_tuple[1](test_shape, dtype)

                self.assertRaisesRegex(ValueError,
                        'Cannot avoid copy.*transform shape.*',
                        getattr(builders, self.func),
                        input_array, s2, **_kwargs)

                non_contiguous_shape = [
                        each_dim * 2 for each_dim in test_shape]
                non_contiguous_slices = tuple(
                        [slice(None, None, 2)] * len(test_shape))

                misaligned_input_array = dtype_tuple[1](
                        non_contiguous_shape, dtype)[non_contiguous_slices]

                self.assertRaisesRegex(ValueError,
                        'Cannot avoid copy.*not contiguous.*',
                        getattr(builders, self.func),
                        misaligned_input_array, s, **_kwargs)

                # Offset by one from 16 byte aligned to guarantee it's not
                # 16 byte aligned
                _input_array = empty_aligned(
                        n.prod(test_shape)*input_array.itemsize+1,
                        dtype='int8', n=16)

                misaligned_input_array = _input_array[1:].view(
                         dtype=input_array.dtype).reshape(*test_shape)

                self.assertRaisesRegex(ValueError,
                        'Cannot avoid copy.*not aligned.*',
                        getattr(builders, self.func),
                        misaligned_input_array, s, **_kwargs)

                _input_array = byte_align(input_array.copy())
                FFTW_object = getattr(builders, self.func)(
                        _input_array, s, **_kwargs)

                # A catch all to make sure the internal array
                # is not a copy
                self.assertTrue(FFTW_object.input_array is
                        _input_array)
//  [python]
def test_avoid_copy(self):
        '''Test the avoid_copy flag
        '''
        dtype_tuple = input_dtypes[functions[self.func]]

        for dtype in dtype_tuple[0]:
            for test_shape, s, kwargs in self.test_data:
                _kwargs = kwargs.copy()

                _kwargs['avoid_copy'] = True

                s2 = copy.copy(s)
                try:
                    for each_axis, length in enumerate(s):
                        s2[each_axis] += 2
                except TypeError:
                    s2 += 2

                input_array = dtype_tuple[1](test_shape, dtype)

                self.assertRaisesRegex(ValueError,
                        'Cannot avoid copy.*transform shape.*',
                        getattr(builders, self.func),
                        input_array, s2, **_kwargs)

                non_contiguous_shape = [
                        each_dim * 2 for each_dim in test_shape]
                non_contiguous_slices = tuple(
                        [slice(None, None, 2)] * len(test_shape))

                misaligned_input_array = dtype_tuple[1](
                        non_contiguous_shape, dtype)[non_contiguous_slices]

                self.assertRaisesRegex(ValueError,
                        'Cannot avoid copy.*not contiguous.*',
                        getattr(builders, self.func),
                        misaligned_input_array, s, **_kwargs)

                # Offset by one from 16 byte aligned to guarantee it's not
                # 16 byte aligned
                _input_array = empty_aligned(
                        numpy.prod(test_shape)*input_array.itemsize+1,
                        dtype='int8', n=16)

                misaligned_input_array = _input_array[1:].view(
                         dtype=input_array.dtype).reshape(*test_shape)

                self.assertRaisesRegex(ValueError,
                        'Cannot avoid copy.*not aligned.*',
                        getattr(builders, self.func),
                        misaligned_input_array, s, **_kwargs)

                _input_array = byte_align(input_array.copy())
                FFTW_object = getattr(builders, self.func)(
                        _input_array, s, **_kwargs)

                # A catch all to make sure the internal array
                # is not a copy
                self.assertTrue(FFTW_object.input_array is
                        _input_array)
//  [python]
def _std(x, axes, keep_dim, unbiased, eps):
    need_rescale = False
    if unbiased:
        if axes is None:
            if not any_symbolic(x.shape) and n.prod(x.shape) > 1:
                N = n.prod(x.shape)
                need_rescale = True
        else:
            dims = []
            for axis in axes:
                dims.append(x.shape[axis])
            if all([not is_symbolic(s) for s in dims]):
                N = n.prod(dims)
                if N > 1:
                    need_rescale = True
    if need_rescale:
        rescale_factor = n.sqrt(N / float(N - 1))

    x_mean = mb.reduce_mean(x=x, axes=axes, keep_dims=True)
    x_demeaned = mb.sub(x=x, y=x_mean)
    x_demeaned_square = mb.square(x=x_demeaned)
    x_demeaned_square_mean = mb.reduce_mean(x=x_demeaned_square, axes=axes, keep_dims=keep_dim)
    if eps > 0:
        x_demeaned_square_mean = mb.add(x=x_demeaned_square_mean, y=eps)
    if need_rescale:
        y_before_scale = mb.sqrt(x=x_demeaned_square_mean)
        y = mb.mul(x=y_before_scale, y=rescale_factor)
    else:
        y = mb.sqrt(x=x_demeaned_square_mean)
    return y
//  [python]
def _std(x, axes, keep_dim, unbiased, eps):
    need_rescale = False
    if unbiased:
        # If "unbiased" is True,
        # then we need to divide by "N-1" (instead of "N") to compute the mean of (x-E[x])^2
        # for an unbiased estimate of the variance /  standard deviation.
        # In the sequence of MIL ops added below, we first compute the mean using "N", and only if its unbiased
        # we rescale later, the final result.
        # We ignore the "unbiased" flag, if any of the dimensions involved in this operation are dynamic
        # (we could have still handled that case by using "get_shape" etc ops, but we don't do that here,
        # trading performance for numerical accuracy)
        if axes is None:
            if not any_symbolic(x.shape) and _np.prod(x.shape) > 1:
                N = _np.prod(x.shape)
                need_rescale = True
        else:
            dims = []
            # collect dimensions corresponding to "axes"
            for axis in axes:
                dims.append(x.shape[axis])
            if all([not is_symbolic(s) for s in dims]):
                N = _np.prod(dims)
                if N > 1:
                    need_rescale = True
    if need_rescale:
        rescale_factor = _np.sqrt(N / float(N - 1))

    x_mean = mb.reduce_mean(x=x, axes=axes, keep_dims=True)
    x_demeaned = mb.sub(x=x, y=x_mean)
    x_demeaned_square = mb.square(x=x_demeaned)
    x_demeaned_square_mean = mb.reduce_mean(x=x_demeaned_square, axes=axes, keep_dims=keep_dim)
    if eps > 0:
        x_demeaned_square_mean = mb.add(x=x_demeaned_square_mean, y=eps)
    if need_rescale:
        y_before_scale = mb.sqrt(x=x_demeaned_square_mean)
        y = mb.mul(x=y_before_scale, y=rescale_factor)
    else:
        y = mb.sqrt(x=x_demeaned_square_mean)
    return y
//  [python]
def _batched_posv(a, b):
    from cupy_backends.cuda.libs import cusolver as _cusolver
    import cupyx.cusolver

    if not cupyx.cusolver.check_availability('potrsBatched'):
        raise RuntimeError('potrsBatched is not available')

    dtype = _numpy.promote_types(a.dtype, b.dtype)
    dtype = _numpy.promote_types(dtype, 'f')

    if dtype == 'f':
        potrfBatched = _cusolver.spotrfBatched
        potrsBatched = _cusolver.spotrsBatched
    elif dtype == 'd':
        potrfBatched = _cusolver.dpotrfBatched
        potrsBatched = _cusolver.dpotrsBatched
    elif dtype == 'F':
        potrfBatched = _cusolver.cpotrfBatched
        potrsBatched = _cusolver.cpotrsBatched
    elif dtype == 'D':
        potrfBatched = _cusolver.zpotrfBatched
        potrsBatched = _cusolver.zpotrsBatched
    else:
        msg = ('dtype must be float32, float64, complex64 or complex128'
               ' (actual: {})'.format(a.dtype))
        raise ValueError(msg)

    a = a.astype(dtype, order='C', copy=True)
    ap = _cupy._core._mat_ptrs(a)
    lda, n = a.shape[-2:]
    batch_size = int(n)

    handle = _device.get_cusolver_handle()
    uplo = _cublas.CUBLAS_FILL_MODE_LOWER
    dev_info = _cupy.empty(batch_size, dtype=_numpy.int32)

    # Cholesky factorization
    potrfBatched(handle, uplo, n, ap.data.ptr, lda, dev_info.data.ptr,
                 batch_size)
    _cupy.linalg._util._check_cusolver_dev_info_if_synchronization_allowed(
        potrfBatched, dev_info)

    b_shape = b.shape
    b = b.conj().reshape(batch_size, n, -1).astype(dtype, order='C', copy=True)
    bp = _cupy._core._mat_ptrs(b)
    ldb, nrhs = b.shape[-2:]
    dev_info = _cupy.empty(1, dtype=_numpy.int32)

    # NOTE: potrsBatched does not currently support nrhs > 1 (CUDA v10.2)
    # Solve: A[i] * X[i] = B[i]
    potrsBatched(handle, uplo, n, nrhs, ap.data.ptr, lda, bp.data.ptr, ldb,
                 dev_info.data.ptr, batch_size)
    _cupy.linalg._util._check_cusolver_dev_info_if_synchronization_allowed(
        potrsBatched, dev_info)

    # TODO: check if conj() is necessary when nrhs > 1
    return b.conj().reshape(b_shape)
//  [python]
def _batched_posv(a, b):
    from cupy_backends.cuda.libs import cusolver as _cusolver
    import cupyx.cusolver

    if not cupyx.cusolver.check_availability('potrsBatched'):
        raise RuntimeError('potrsBatched is not available')

    dtype = _numpy.promote_types(a.dtype, b.dtype)
    dtype = _numpy.promote_types(dtype, 'f')

    if dtype == 'f':
        potrfBatched = _cusolver.spotrfBatched
        potrsBatched = _cusolver.spotrsBatched
    elif dtype == 'd':
        potrfBatched = _cusolver.dpotrfBatched
        potrsBatched = _cusolver.dpotrsBatched
    elif dtype == 'F':
        potrfBatched = _cusolver.cpotrfBatched
        potrsBatched = _cusolver.cpotrsBatched
    elif dtype == 'D':
        potrfBatched = _cusolver.zpotrfBatched
        potrsBatched = _cusolver.zpotrsBatched
    else:
        msg = ('dtype must be float32, float64, complex64 or complex128'
               ' (actual: {})'.format(a.dtype))
        raise ValueError(msg)

    a = a.astype(dtype, order='C', copy=True)
    ap = _cupy._core._mat_ptrs(a)
    lda, n = a.shape[-2:]
    batch_size = int(_numpy.prod(a.shape[:-2]))

    handle = _device.get_cusolver_handle()
    uplo = _cublas.CUBLAS_FILL_MODE_LOWER
    dev_info = _cupy.empty(batch_size, dtype=_numpy.int32)

    # Cholesky factorization
    potrfBatched(handle, uplo, n, ap.data.ptr, lda, dev_info.data.ptr,
                 batch_size)
    _cupy.linalg._util._check_cusolver_dev_info_if_synchronization_allowed(
        potrfBatched, dev_info)

    b_shape = b.shape
    b = b.conj().reshape(batch_size, n, -1).astype(dtype, order='C', copy=True)
    bp = _cupy._core._mat_ptrs(b)
    ldb, nrhs = b.shape[-2:]
    dev_info = _cupy.empty(1, dtype=_numpy.int32)

    # NOTE: potrsBatched does not currently support nrhs > 1 (CUDA v10.2)
    # Solve: A[i] * X[i] = B[i]
    potrsBatched(handle, uplo, n, nrhs, ap.data.ptr, lda, bp.data.ptr, ldb,
                 dev_info.data.ptr, batch_size)
    _cupy.linalg._util._check_cusolver_dev_info_if_synchronization_allowed(
        potrsBatched, dev_info)

    # TODO: check if conj() is necessary when nrhs > 1
    return b.conj().reshape(b_shape)
//  [python]
def variance_scaling(scale, mode, distribution,
                     in_axis=1, out_axis=0,
                     dtype=torch.float32,
                     device='cpu'):
  """Ported from JAX. """

  def _compute_fans(shape, in_axis=1, out_axis=0):
    receptive_field_size = np.prod(shape) / shape[in_axis] / shape[out_axis]
    fan_in = shape[in_axis] * receptive_field_size
    fan_out = shape[out_axis] * receptive_field_size
    return fan_in, fan_out

  def init(shape, dtype=dtype, device=device):
    fan_in, fan_out = _compute_fans(shape, in_axis, out_axis)
    if mode == "fan_in":
      denominator = fan_in
    elif mode == "fan_out":
      denominator = fan_out
    elif mode == "fan_avg":
      denominator = (fan_in + fan_out) / 2
    else:
      raise ValueError(
        "invalid mode for variance scaling initializer: {}".format(mode))
    variance = scale / denominator
    if distribution == "normal":
      return torch.randn(*shape, dtype=dtype, device=device) * np.sqrt(variance)
    elif distribution == "uniform":
      return (torch.rand(*shape, dtype=dtype, device=device) * 2. - 1.) * np.sqrt(3 * variance)
    else:
      raise ValueError("invalid distribution for variance scaling initializer")

  return init
//  [python]
def numpy_scatter_nd(ref, index, updates, fun):
    ref_shape = ref.shape
    index_shape = index.shape

    end_size = index_shape[-1]

    # as type int32, flat_index or flat_updates can't reshape to int64
    remain_numel = np.prod(index_shape[:-1]).astype("int32")
    slice_size = np.prod(ref_shape[end_size : len(ref_shape)]).astype("int32")

    flat_index = index.reshape([remain_numel] + list(index_shape[-1:]))
    flat_updates = updates.reshape((remain_numel, slice_size))
    flat_output = ref.reshape(list(ref_shape[:end_size]) + [slice_size])

    for i_up, i_out in enumerate(flat_index):
        i_out = tuple(i_out)
        flat_output[i_out] = fun(flat_output[i_out], flat_updates[i_up])
    return flat_output.reshape(ref.shape)
//  [python]
def _setup(self, dtype):
        dtype = numpy.dtype(dtype)
        self.tol = self._tol[dtype.char.lower()]

        a_shape = (self.n, self.n)
        a = testing.shaped_random(a_shape, numpy, dtype=dtype, scale=1)
        a_mask = testing.shaped_random(a_shape, numpy, dtype='f', scale=1)
        a[a_mask > self.density] = 0
        a_diag = numpy.diag(numpy.ones((self.n,), dtype=dtype))
        if self.unit_diag:
            a[a_diag > 0] = 0
        a = a + a_diag
        cp_a = cupy.array(a)
        if self.unit_diag:
            cp_a[a_diag > 0] = 0.1  # any number except 0
        if self.format == 'csr':
            self.a = sparse.csr_matrix(cp_a)
        elif self.format == 'csc':
            self.a = sparse.csc_matrix(cp_a)

        b_shape = (self.n,) if self.nrhs is None else (self.n, self.nrhs)
        b = numpy.arange(1, numpy.prod(b_shape) + 1,
                         dtype=dtype).reshape(b_shape)
        b = b.copy(order=self.order)
        self.b = cupy.array(b, order=self.order)

        if self.lower:
            a = numpy.tril(a)
        else:
            a = numpy.triu(a)
        if self.transa == 'T':
            a = a.T
        elif self.transa == 'H':
            a = a.conj().T
        self.ref_x = numpy.linalg.solve(a, self.alpha * b)
//  [python]
def scatter_add(subs, val, dim=0, shape=None):
    """
    @param subs: ndim x n indices, suitable for np.ravel_multi_index
    @type subs: Union[np.ndarray, torch.LongTensor])
    @param val: n x ... values to add
    @type val: torch.Tensor
    @return:
    """
    if shape is None:
        shape = [(np.amax(sub) + 1) for sub in subs]
    idx = tensor(np.ravel_multi_index(subs, shape), dtype=torch.long)
    return zeros(np.multiply.reduce(shape).astype(np.long)).scatter_add(
        dim=dim, index=idx, src=val
    ).reshape(shape)
//  [python]
def scatter_add(subs, val, dim=0, shape=None):
    """
    @param subs: ndim x n indices, suitable for np.ravel_multi_index
    @type subs: Union[np.ndarray, torch.LongTensor])
    @param val: n x ... values to add
    @type val: torch.Tensor
    @return:
    """
    if shape is None:
        shape = [(np.amax(sub) + 1) for sub in subs]
    idx = tensor(np.ravel_multi_index(subs, shape), dtype=torch.long)
    return zeros(np.prod(shape).astype(np.long)).scatter_add(
        dim=dim, index=idx, src=val
    ).reshape(shape)
//  [python]
def test_np_array_printer_simple_numeric_types_strided(self):
        # Tests printer over randomized strided arrays
        n_tests = 30
        np.random.seed(0)

        for _ in range(n_tests):

            shape = np.random.randint(1, high=12, size=np.random.randint(1, 5))
            tmp = np.arange(np.prod(shape)).reshape(shape)

            slices = []
            for x in shape:
                start = np.random.randint(0, x)
                # x + 3 is to ensure that sometimes the stop is beyond the
                # end of the size in a given dimension
                stop = np.random.randint(start + 1, max(start + 1, x + 3))
                step = np.random.randint(1, 3) # step as 1, 2
                strd = slice(start, stop, step)
                slices.append(strd)

            arr = tmp[tuple(slices)]
            self.check(arr)
//  [python]
def _fft_helper(x, win, detrend_func, nperseg, noverlap, nfft, sides):
  """Calculate windowed FFT in the same way the original SciPy does.
  """
  if x.dtype.kind == 'i':
    x = x.astype(win.dtype)

  *batch_shape, signal_length = x.shape
  # Created strided array of data segments
  if nperseg == 1 and noverlap == 0:
    result = x[..., np.newaxis]
  else:
    step = nperseg - noverlap
    batch_shape = tuple(batch_shape)
    x = x.reshape((int(np.prod(batch_shape)), signal_length))[..., np.newaxis]
    result = jax.lax.conv_general_dilated_patches(
        x, (nperseg,), (step,),
        'VALID',
        dimension_numbers=('NTC', 'OIT', 'NTC'))
    result = result.reshape(batch_shape + result.shape[-2:])

  # Detrend each data segment individually
  result = detrend_func(result)

  # Apply window by multiplication
  if jnp.iscomplexobj(win):
    result, = _promote_dtypes_complex(result)
  result = win.reshape((1,) * len(batch_shape) + (1, nperseg)) * result

  # Perform the fft on last axis. Zero-pads automatically
  if sides == 'twosided':
    return jax.numpy.fft.fft(result, n=nfft)
  else:
    return jax.numpy.fft.rfft(result.real, n=nfft)
//  [python]
def test_correct_multi(comm):
    procmesh = pfft.ProcMesh(np=[comm.size,], comm=comm)
    N = (2, 3)
    data = numpy.arange(numpy.prod(N), dtype='complex128').reshape(N)
    correct = numpy.fft.fftn(data)
    result = numpy.zeros_like(data)

    partition = pfft.Partition(pfft.Type.PFFT_C2C, N,
        procmesh, flags=pfft.Flags.PFFT_ESTIMATE)

    buffer1 = pfft.LocalBuffer(partition)
    buffer2 = pfft.LocalBuffer(partition)

    plan = pfft.Plan(partition, pfft.Direction.PFFT_FORWARD, buffer1, buffer2)

    buffer1.view_input()[:] = data[partition.local_i_slice]
    plan.execute(buffer1, buffer2)

    result[partition.local_o_slice] = buffer2.view_output()
    result = comm.allreduce(result)
    assert_almost_equal(correct, result)
//  [python]
def cdf(self, x):
		"""
		Returns the cumulative distribution function (CDF) of the copula.
		
		Parameters
		----------
		x : numpy array (of size d)
			Values to compute CDF.
		"""
		self._check_dimension(x)
		if self.name == 'indep':
			return n.prod(x)
		elif self.name == 'frechet_up':
			return min(x)
		elif self.name == 'frechet_down':
			return max(sum(x) - self.dim + 1., 0)
//  [python]
def cdf(self, x):
		"""
		Returns the cumulative distribution function (CDF) of the copula.
		
		Parameters
		----------
		x : numpy array (of size d)
			Values to compute CDF.
		"""
		self._check_dimension(x)
		if self.name == 'indep':
			return np.prod(x)
		elif self.name == 'frechet_up':
			return min(x)
		elif self.name == 'frechet_down':
			return max(sum(x) - self.dim + 1., 0)
//  [python]
def test_2d_on_2d_c2c(comm):
    procmesh = pfft.ProcMesh(np=[2, 2], comm=comm)
    N = (8, 8)

    data = numpy.arange(n.prod(N), dtype='complex128').reshape(N)

    correct = numpy.fft.fftn(data.copy())
    result = numpy.zeros_like(correct)

    partition = pfft.Partition(pfft.Type.PFFT_C2C, N,
        procmesh, flags=pfft.Flags.PFFT_ESTIMATE
          | pfft.Flags.PFFT_TRANSPOSED_OUT
#          | pfft.Flags.PFFT_DESTROY_INPUT
          | pfft.Flags.PFFT_PRESERVE_INPUT
        )

    buffer1 = pfft.LocalBuffer(partition)
    buffer2 = pfft.LocalBuffer(partition)

    plan = pfft.Plan(partition, pfft.Direction.PFFT_FORWARD, buffer1, buffer2)

    buffer1.view_input()[:] = data[partition.local_i_slice]
    plan.execute(buffer1, buffer2)

    result[partition.local_o_slice] = buffer2.view_output()
    result = comm.allreduce(result)
    assert_almost_equal(correct, result)
//  [python]
def test_2d_on_2d_c2c(comm):
    procmesh = pfft.ProcMesh(np=[2, 2], comm=comm)
    N = (8, 8)

    data = numpy.arange(numpy.prod(N), dtype='complex128').reshape(N)

    correct = numpy.fft.fftn(data.copy())
    result = numpy.zeros_like(correct)

    partition = pfft.Partition(pfft.Type.PFFT_C2C, N,
        procmesh, flags=pfft.Flags.PFFT_ESTIMATE
          | pfft.Flags.PFFT_TRANSPOSED_OUT
#          | pfft.Flags.PFFT_DESTROY_INPUT
          | pfft.Flags.PFFT_PRESERVE_INPUT
        )

    buffer1 = pfft.LocalBuffer(partition)
    buffer2 = pfft.LocalBuffer(partition)

    plan = pfft.Plan(partition, pfft.Direction.PFFT_FORWARD, buffer1, buffer2)

    buffer1.view_input()[:] = data[partition.local_i_slice]
    plan.execute(buffer1, buffer2)

    result[partition.local_o_slice] = buffer2.view_output()
    result = comm.allreduce(result)
    assert_almost_equal(correct, result)
//  [python]
def _overlap_and_add(x, step_size):
  """Utility function compatible with tf.signal.overlap_and_add.

  Args:
    x: An array with `(..., frames, frame_length)`-shape.
    step_size: An integer denoting overlap offsets. Must be less than
      `frame_length`.

  Returns:
    An array with `(..., output_size)`-shape containing overlapped signal.
  """
  _check_arraylike("_overlap_and_add", x)
  step_size = jax.core.concrete_or_error(int, step_size,
                                        "step_size for overlap_and_add")
  if x.ndim < 2:
    raise ValueError('Input must have (..., frames, frame_length) shape.')

  *batch_shape, nframes, segment_len = x.shape
  flat_batchsize = n.prod(batch_shape, dtype=np.int64)
  x = x.reshape((flat_batchsize, nframes, segment_len))
  output_size = step_size * (nframes - 1) + segment_len
  nstep_per_segment = 1 + (segment_len - 1) // step_size

  # Here, we use shorter notation for axes.
  # B: batch_size, N: nframes, S: nstep_per_segment,
  # T: segment_len divided by S

  padded_segment_len = nstep_per_segment * step_size
  x = jnp.pad(x, ((0, 0), (0, 0), (0, padded_segment_len - segment_len)))
  x = x.reshape((flat_batchsize, nframes, nstep_per_segment, step_size))

  # For obtaining shifted signals, this routine reinterprets flattened array
  # with a shrinked axis.  With appropriate truncation/ padding, this operation
  # pushes the last padded elements of the previous row to the head of the
  # current row.
  # See implementation of `overlap_and_add` in Tensorflow for details.
  x = x.transpose((0, 2, 1, 3))  # x: (B, S, N, T)
  x = jnp.pad(x, ((0, 0), (0, 0), (0, nframes), (0, 0)))  # x: (B, S, N*2, T)
  shrinked = x.shape[2] - 1
  x = x.reshape((flat_batchsize, -1))
  x = x[:, :(nstep_per_segment * shrinked * step_size)]
  x = x.reshape((flat_batchsize, nstep_per_segment, shrinked * step_size))

  # Finally, sum shifted segments, and truncate results to the output_size.
  x = x.sum(axis=1)[:, :output_size]
  return x.reshape(tuple(batch_shape) + (-1,))
//  [python]
def _overlap_and_add(x, step_size):
  """Utility function compatible with tf.signal.overlap_and_add.

  Args:
    x: An array with `(..., frames, frame_length)`-shape.
    step_size: An integer denoting overlap offsets. Must be less than
      `frame_length`.

  Returns:
    An array with `(..., output_size)`-shape containing overlapped signal.
  """
  _check_arraylike("_overlap_and_add", x)
  step_size = jax.core.concrete_or_error(int, step_size,
                                        "step_size for overlap_and_add")
  if x.ndim < 2:
    raise ValueError('Input must have (..., frames, frame_length) shape.')

  *batch_shape, nframes, segment_len = x.shape
  flat_batchsize = np.prod(batch_shape, dtype=np.int64)
  x = x.reshape((flat_batchsize, nframes, segment_len))
  output_size = step_size * (nframes - 1) + segment_len
  nstep_per_segment = 1 + (segment_len - 1) // step_size

  # Here, we use shorter notation for axes.
  # B: batch_size, N: nframes, S: nstep_per_segment,
  # T: segment_len divided by S

  padded_segment_len = nstep_per_segment * step_size
  x = jnp.pad(x, ((0, 0), (0, 0), (0, padded_segment_len - segment_len)))
  x = x.reshape((flat_batchsize, nframes, nstep_per_segment, step_size))

  # For obtaining shifted signals, this routine reinterprets flattened array
  # with a shrinked axis.  With appropriate truncation/ padding, this operation
  # pushes the last padded elements of the previous row to the head of the
  # current row.
  # See implementation of `overlap_and_add` in Tensorflow for details.
  x = x.transpose((0, 2, 1, 3))  # x: (B, S, N, T)
  x = jnp.pad(x, ((0, 0), (0, 0), (0, nframes), (0, 0)))  # x: (B, S, N*2, T)
  shrinked = x.shape[2] - 1
  x = x.reshape((flat_batchsize, -1))
  x = x[:, :(nstep_per_segment * shrinked * step_size)]
  x = x.reshape((flat_batchsize, nstep_per_segment, shrinked * step_size))

  # Finally, sum shifted segments, and truncate results to the output_size.
  x = x.sum(axis=1)[:, :output_size]
  return x.reshape(tuple(batch_shape) + (-1,))
//  [python]
def test_2d_on_2d_r2c(comm):
    if comm.size == 1:
        procmesh = pfft.ProcMesh(np=[1, 1], comm=comm)
    else:
        procmesh = pfft.ProcMesh(np=[2, 2], comm=comm)
    N = (8, 8)

    data = numpy.arange(n.prod(N), dtype='f8').reshape(N)

    correct = numpy.fft.rfftn(data.copy())
    result = numpy.zeros_like(correct)

    partition = pfft.Partition(pfft.Type.PFFT_R2C, N,
        procmesh, flags=pfft.Flags.PFFT_ESTIMATE
          | pfft.Flags.PFFT_TRANSPOSED_OUT
          | pfft.Flags.PFFT_DESTROY_INPUT
#          | pfft.Flags.PADDED_R2C # doesn't work yet
        )

    buffer1 = pfft.LocalBuffer(partition)
    buffer2 = pfft.LocalBuffer(partition)

    plan = pfft.Plan(partition, pfft.Direction.PFFT_FORWARD, buffer1, buffer2)

    buffer1.view_input()[:] = data[partition.local_i_slice]
    plan.execute(buffer1, buffer2)

    result[partition.local_o_slice] = buffer2.view_output()
    result = comm.allreduce(result)
    assert_almost_equal(correct, result)
//  [python]
def test_2d_on_2d_r2c(comm):
    if comm.size == 1:
        procmesh = pfft.ProcMesh(np=[1, 1], comm=comm)
    else:
        procmesh = pfft.ProcMesh(np=[2, 2], comm=comm)
    N = (8, 8)

    data = numpy.arange(numpy.prod(N), dtype='f8').reshape(N)

    correct = numpy.fft.rfftn(data.copy())
    result = numpy.zeros_like(correct)

    partition = pfft.Partition(pfft.Type.PFFT_R2C, N,
        procmesh, flags=pfft.Flags.PFFT_ESTIMATE
          | pfft.Flags.PFFT_TRANSPOSED_OUT
          | pfft.Flags.PFFT_DESTROY_INPUT
#          | pfft.Flags.PADDED_R2C # doesn't work yet
        )

    buffer1 = pfft.LocalBuffer(partition)
    buffer2 = pfft.LocalBuffer(partition)

    plan = pfft.Plan(partition, pfft.Direction.PFFT_FORWARD, buffer1, buffer2)

    buffer1.view_input()[:] = data[partition.local_i_slice]
    plan.execute(buffer1, buffer2)

    result[partition.local_o_slice] = buffer2.view_output()
    result = comm.allreduce(result)
    assert_almost_equal(correct, result)
//  [python]
def test_backwards_compatibility(self):
        """Test shape and num_embeddings."""
        assert self.instance.max_id == self.instance_kwargs["num_embeddings"]
        embedding_dim = int(n.prod(self.instance.shape))
        assert self.instance.shape == (embedding_dim,)
//  [python]
def test_backwards_compatibility(self):
        """Test shape and num_embeddings."""
        assert self.instance.max_id == self.instance_kwargs["num_embeddings"]
        embedding_dim = int(numpy.prod(self.instance.shape))
        assert self.instance.shape == (embedding_dim,)
//  [python]
def reverse(self, transformed_point, index=None):
        """Only return packend point if view of first element, otherwise drop."""
        subset = transformed_point[index : index + numpy.prod(self.shape)]
        return numpy.array(subset).reshape(self.shape)
//  [python]
def interval(self, alpha=1.0):
        """Map the interval bounds to the transformed ones."""
        interval = self.original_dimension.interval(alpha)
        if hasattr(interval[0], "shape") and n.prod(interval[0].shape) > 1:
            return self.transformer.interval(interval)

        return interval
//  [python]
def interval(self, alpha=1.0):
        """Map the interval bounds to the transformed ones."""
        interval = self.original_dimension.interval(alpha)
        if hasattr(interval[0], "shape") and numpy.prod(interval[0].shape) > 1:
            return self.transformer.interval(interval)

        return interval
//  [python]
def cardinality(self):
        """Compute cardinality"""
        cardinality = super().cardinality
        if isinstance(self.transformer, View):
            cardinality /= n.prod(self.transformer.shape)

        return cardinality
//  [python]
def cardinality(self):
        """Compute cardinality"""
        cardinality = super().cardinality
        if isinstance(self.transformer, View):
            cardinality /= numpy.prod(self.transformer.shape)

        return cardinality
//  [python]
def convert_cudnn_canonical_to_lstm_block(reader, prefix, target="lstm_block_wrapper/"):
        """
        This assumes CudnnLSTM currently, with num_layers=1, input_mode="linear_input", direction='unidirectional'!

        :param tf.train.CheckpointReader reader:
        :param str prefix: e.g. "layer2/rec/"
        :param str target: e.g. "lstm_block_wrapper/" or "rnn/lstm_cell/"
        :return: dict key -> value, {".../kernel": ..., ".../bias": ...} with prefix
        :rtype: dict[str,numpy.ndarray]
        """
        # For reference:
        # https://github.com/tensorflow/tensorflow/blob/master/tensorflow/contrib/cudnn_rnn/python/ops/cudnn_rnn_ops.py
        # For CudnnLSTM, there are 8 tensors per weight and per bias for each
        # layer: tensor 0-3 are applied to the input from the previous layer and
        # tensor 4-7 to the recurrent input. Tensor 0 and 4 are for the input gate;
        # tensor 1 and 5 the forget gate; tensor 2 and 6 the new memory gate;
        # tensor 3 and 7 the output gate.
        import numpy

        num_vars = 16
        values = []
        for i in range(num_vars):
            values.append(reader.get_tensor("%scudnn/CudnnRNNParamsToCanonical:%i" % (prefix, i)))
        assert len(values[-1].shape) == 1
        output_dim = values[-1].shape[0]
        # For some reason, the input weight matrices are sometimes flattened.
        assert numpy.prod(values[0].shape) % output_dim == 0
        input_dim = numpy.prod(values[0].shape) // output_dim
        weights_and_biases = [
            (
                numpy.concatenate(
                    [
                        numpy.reshape(values[i], [output_dim, input_dim]),  # input weights
                        numpy.reshape(values[i + 4], [output_dim, output_dim]),
                    ],  # recurrent weights
                    axis=1,
                ),
                values[8 + i] + values[8 + i + 4],  # input bias  # recurrent bias
            )
            for i in range(4)
        ]
        # cuDNN weights are in ifco order, convert to icfo order.
        weights_and_biases[1:3] = reversed(weights_and_biases[1:3])
        weights = numpy.transpose(numpy.concatenate([wb[0] for wb in weights_and_biases], axis=0))
        biases = numpy.concatenate([wb[1] for wb in weights_and_biases], axis=0)
        return {prefix + target + "kernel": weights, prefix + target + "bias": biases}
//  [python]
def pdf(self, x):
		"""
		Returns the probability distribution function (PDF) of the copula.
		
		Parameters
		----------
		x : numpy array (of size d)
			Values to compute PDF.
		"""
		self._check_dimension(x)
		if self.name == 'indep':
			return sum([ n.prod([ x[j] for j in range(self.dim) if j != i ]) for i in range(self.dim) ])
		elif self.name in [ 'frechet_down', 'frechet_up' ]:
			raise NotImplementedError("PDF is not available for Fréchet-Hoeffding bounds.")
//  [python]
def pdf(self, x):
		"""
		Returns the probability distribution function (PDF) of the copula.
		
		Parameters
		----------
		x : numpy array (of size d)
			Values to compute PDF.
		"""
		self._check_dimension(x)
		if self.name == 'indep':
			return sum([ np.prod([ x[j] for j in range(self.dim) if j != i ]) for i in range(self.dim) ])
		elif self.name in [ 'frechet_down', 'frechet_up' ]:
			raise NotImplementedError("PDF is not available for Fréchet-Hoeffding bounds.")