jiahuimbzuai/CoQuIR huggingface dataset:
//  [python]
def test_slogdet(self, device, dtype):
        from torch.testing._internal.common_utils import (random_hermitian_matrix, random_hermitian_psd_matrix,
                                                          random_hermitian_pd_matrix, random_square_matrix_of_rank)

        # mat_chars denotes matrix characteristics
        # possible values are: hermitian, hermitian_psd, hermitian_pd, singular, non_singular
        def run_test(matsize, batchdims, mat_chars):
            num_matrices = np.prod(batchdims)
            list_of_matrices = []
            if num_matrices != 0:
                for idx in range(num_matrices):
                    mat_type = idx % len(mat_chars)
                    if mat_chars[mat_type] == 'hermitian':
                        list_of_matrices.append(random_hermitian_matrix(matsize, dtype=dtype, device=device))
                    elif mat_chars[mat_type] == 'hermitian_psd':
                        list_of_matrices.append(random_hermitian_psd_matrix(matsize, dtype=dtype, device=device))
                    elif mat_chars[mat_type] == 'hermitian_pd':
                        list_of_matrices.append(random_hermitian_pd_matrix(matsize, dtype=dtype, device=device))
                    elif mat_chars[mat_type] == 'singular':
                        list_of_matrices.append(torch.ones(matsize, matsize, dtype=dtype, device=device))
                    elif mat_chars[mat_type] == 'non_singular':
                        list_of_matrices.append(random_square_matrix_of_rank(matsize, matsize, dtype=dtype, device=device))
                full_tensor = torch.stack(list_of_matrices, dim=0).reshape(batchdims + (matsize, matsize))
            else:
                full_tensor = torch.randn(*batchdims, matsize, matsize, dtype=dtype, device=device)

            actual_value = torch.linalg.slogdet(full_tensor)
            expected_value = np.linalg.slogdet(full_tensor.cpu().numpy())
            self.assertEqual(expected_value[0], actual_value[0], atol=self.precision, rtol=self.precision)
            self.assertEqual(expected_value[1], actual_value[1], atol=self.precision, rtol=self.precision)

            # test out=variant
            sign_out = torch.empty_like(actual_value[0])
            logabsdet_out = torch.empty_like(actual_value[1])
            ans = torch.linalg.slogdet(full_tensor, out=(sign_out, logabsdet_out))
            self.assertEqual(ans[0], sign_out)
            self.assertEqual(ans[1], logabsdet_out)
            self.assertEqual(sign_out, actual_value[0])
            self.assertEqual(logabsdet_out, actual_value[1])

        for matsize, batchdims in itertools.product([0, 3, 5], [(0,), (3,), (5, 3)]):
            run_test(matsize, batchdims, mat_chars=['hermitian_pd'])
            run_test(matsize, batchdims, mat_chars=['singular'])
            run_test(matsize, batchdims, mat_chars=['non_singular'])
            run_test(matsize, batchdims, mat_chars=['hermitian', 'hermitian_pd', 'hermitian_psd'])
            run_test(matsize, batchdims, mat_chars=['singular', 'non_singular'])
//  [python]
def test_addsumprod(self):
        # Tests add, sum, product.
        (x, y, a10, m1, m2, xm, ym, z, zm, xf) = self.d
        assert_equal(np.add.reduce(x), add.reduce(x))
        assert_equal(np.add.accumulate(x), add.accumulate(x))
        assert_equal(4, sum(array(4), axis=0))
        assert_equal(4, sum(array(4), axis=0))
        assert_equal(np.sum(x, axis=0), sum(x, axis=0))
        assert_equal(np.sum(filled(xm, 0), axis=0), sum(xm, axis=0))
        assert_equal(np.sum(x, 0), sum(x, 0))
        assert_equal(np.multiply.reduce(x, axis=0), product(x, axis=0))
        assert_equal(np.multiply.reduce(x, 0), product(x, 0))
        assert_equal(np.multiply.reduce(filled(xm, 1), axis=0), product(xm, axis=0))
        s = (3, 4)
        x.shape = y.shape = xm.shape = ym.shape = s
        if len(s) > 1:
            assert_equal(np.concatenate((x, y), 1), concatenate((xm, ym), 1))
            assert_equal(np.add.reduce(x, 1), add.reduce(x, 1))
            assert_equal(np.sum(x, 1), sum(x, 1))
            assert_equal(np.multiply.reduce(x, 1), product(x, 1))
//  [python]
def test_sum_to(self):
        n_elems = n.prod(self.in_shape)
        x = n.arange(1, n_elems + 1, dtype=n.float32).reshape(
            self.in_shape)
        y_actual = array.sum_to(x, self.out_shape)

        y_expect = n.zeros(self.out_shape, x.dtype)
        for dst, src in n.nditer(
                [y_expect, x], ['reduce_ok'], [['readwrite'], ['readonly']]):
            dst += src
        n.testing.assert_array_equal(y_expect, y_actual)
//  [python]
def test_sum_to(self):
        n_elems = numpy.prod(self.in_shape)
        x = numpy.arange(1, n_elems + 1, dtype=numpy.float32).reshape(
            self.in_shape)
        y_actual = array.sum_to(x, self.out_shape)

        y_expect = numpy.zeros(self.out_shape, x.dtype)
        for dst, src in numpy.nditer(
                [y_expect, x], ['reduce_ok'], [['readwrite'], ['readonly']]):
            dst += src
        numpy.testing.assert_array_equal(y_expect, y_actual)
//  [python]
def num_params(self):
        parameters = filter(lambda p: p.requires_grad, self.parameters())
        parameters = sum([n.prod(p.size()) for p in parameters]) / 1_000_000
        logger.debug("Trainable Parameters: %.3fM" % parameters)
//  [python]
def num_params(self):
        parameters = filter(lambda p: p.requires_grad, self.parameters())
        parameters = sum([np.prod(p.size()) for p in parameters]) / 1_000_000
        logger.debug("Trainable Parameters: %.3fM" % parameters)
//  [python]
def num_params(self, print_out=True):
        parameters = filter(lambda p: p.requires_grad, self.parameters())
        parameters = sum([n.prod(p.size()) for p in parameters]) / 1_000_000
        if print_out:
            print('Trainable Parameters: %.3fM' % parameters)
        return parameters
//  [python]
def num_params(self, print_out=True):
        parameters = filter(lambda p: p.requires_grad, self.parameters())
        parameters = sum([np.prod(p.size()) for p in parameters]) / 1_000_000
        if print_out:
            print('Trainable Parameters: %.3fM' % parameters)
        return parameters
//  [python]
def _GetSelfAdjointEigTest(dtype_, shape_, compute_v_):

  def CompareEigenVectors(self, x, y, tol):
    x = EquilibrateEigenVectorPhases(x, y)
    self.assertAllClose(x, y, atol=tol)

  def CompareEigenDecompositions(self, x_e, x_v, y_e, y_v, tol):
    num_batches = int(np.prod(x_e.shape[:-1]))
    n = x_e.shape[-1]
    x_e = np.reshape(x_e, [num_batches] + [n])
    x_v = np.reshape(x_v, [num_batches] + [n, n])
    y_e = np.reshape(y_e, [num_batches] + [n])
    y_v = np.reshape(y_v, [num_batches] + [n, n])
    for i in range(num_batches):
      x_ei, x_vi = SortEigenDecomposition(x_e[i, :], x_v[i, :, :])
      y_ei, y_vi = SortEigenDecomposition(y_e[i, :], y_v[i, :, :])
      self.assertAllClose(x_ei, y_ei, atol=tol, rtol=tol)
      CompareEigenVectors(self, x_vi, y_vi, tol)

  def Test(self):
    np.random.seed(1)
    n = shape_[-1]
    batch_shape = shape_[:-2]
    np_dtype = dtype_.as_numpy_dtype
    a = np.random.uniform(
        low=-1.0, high=1.0, size=n * n).reshape([n, n]).astype(np_dtype)
    if dtype_.is_complex:
      a += 1j * np.random.uniform(
          low=-1.0, high=1.0, size=n * n).reshape([n, n]).astype(np_dtype)
    a += np.conj(a.T)
    a = np.tile(a, batch_shape + (1, 1))
    if dtype_ in (dtypes_lib.float32, dtypes_lib.complex64):
      atol = 1e-4
    else:
      atol = 1e-12
    np_e, np_v = np.linalg.eigh(a)
    with self.session():
      if compute_v_:
        tf_e, tf_v = linalg_ops.self_adjoint_eig(constant_op.constant(a))

        # Check that V*diag(E)*V^T is close to A.
        a_ev = test_util.matmul_without_tf32(
            test_util.matmul_without_tf32(tf_v, array_ops.matrix_diag(tf_e)),
            tf_v,
            adjoint_b=True)
        self.assertAllClose(self.evaluate(a_ev), a, atol=atol)

        # Compare to numpy.linalg.eigh.
        CompareEigenDecompositions(self, np_e, np_v, self.evaluate(tf_e),
                                   self.evaluate(tf_v), atol)
      else:
        tf_e = linalg_ops.self_adjoint_eigvals(constant_op.constant(a))
        self.assertAllClose(
            np.sort(np_e, -1), np.sort(self.evaluate(tf_e), -1), atol=atol)

  return Test
//  [python]
def size(self):
        return np.prod(self.shape).item()
//  [python]
def test_testAddSumProd(self):
        # Test add, sum, product.
        (x, y, a10, m1, m2, xm, ym, z, zm, xf, s) = self.d
        assert_(eq(np.add.reduce(x), add.reduce(x)))
        assert_(eq(np.add.accumulate(x), add.accumulate(x)))
        assert_(eq(4, sum(array(4), axis=0)))
        assert_(eq(4, sum(array(4), axis=0)))
        assert_(eq(np.sum(x, axis=0), sum(x, axis=0)))
        assert_(eq(np.sum(filled(xm, 0), axis=0), sum(xm, axis=0)))
        assert_(eq(np.sum(x, 0), sum(x, 0)))
        assert_(eq(n.prod(x, axis=0), product(x, axis=0)))
        assert_(eq(n.prod(x, 0), product(x, 0)))
        assert_(eq(n.prod(filled(xm, 1), axis=0),
                           product(xm, axis=0)))
        if len(s) > 1:
            assert_(eq(np.concatenate((x, y), 1),
                               concatenate((xm, ym), 1)))
            assert_(eq(np.add.reduce(x, 1), add.reduce(x, 1)))
            assert_(eq(np.sum(x, 1), sum(x, 1)))
            assert_(eq(n.prod(x, 1), product(x, 1)))
//  [python]
def nbytes(self):
        return np.multiply.reduce(self.shape) * self.dtype.itemsize
//  [python]
def nbytes(self):
        return np.prod(self.shape) * self.dtype.itemsize
//  [python]
def __get_nan_frequency(cls, data):
        return cls.__get_nan_count(data) / (n.prod(data.shape) or 1)
//  [python]
def __get_nan_frequency(cls, data):
        return cls.__get_nan_count(data) / (np.prod(data.shape) or 1)
//  [python]
def get_total_subsampling_factor(self):
        """Get total subsampling factor."""
        return self.encoder.conv_subsampling_factor * int(n.prod(self.subsample))
//  [python]
def get_total_subsampling_factor(self):
        """Get total subsampling factor."""
        return self.encoder.conv_subsampling_factor * int(numpy.prod(self.subsample))
//  [python]
def get_nan_frequency_metas(self):
        return self.get_nan_count_metas() / (np.prod(self.metas.shape) or 1)
//  [python]
def testHeightMap(self):
        """Test height map items"""
        sceneWidget = self.window.getSceneWidget()

        height = numpy.arange(10000).reshape(100, 100) / 100.0

        for shape in ((100, 100), (4, 5), (150, 20), (110, 110)):
            with self.subTest(shape=shape):
                items = []

                # Colormapped data height map
                data = (
                    numpy.arange(numpy.multiply.reduce(shape)).astype(numpy.float32).reshape(shape)
                )

                heightmap = HeightMapData()
                heightmap.setData(height)
                heightmap.setColormappedData(data)
                heightmap.getColormap().setName("viridis")
                items.append(heightmap)
                sceneWidget.addItem(heightmap)

                # RGBA height map
                colors = numpy.zeros(shape + (3,), dtype=numpy.float32)
                colors[:, :, 1] = numpy.random.random(shape)

                heightmap = HeightMapRGBA()
                heightmap.setData(height)
                heightmap.setColorData(colors)
                heightmap.setTranslation(100.0, 0.0, 0.0)
                items.append(heightmap)
                sceneWidget.addItem(heightmap)

                self.assertEqual(sceneWidget.getItems(), tuple(items))
                sceneWidget.resetZoom("front")
                self.qapp.processEvents()
                sceneWidget.clearItems()
//  [python]
def testHeightMap(self):
        """Test height map items"""
        sceneWidget = self.window.getSceneWidget()

        height = numpy.arange(10000).reshape(100, 100) / 100.0

        for shape in ((100, 100), (4, 5), (150, 20), (110, 110)):
            with self.subTest(shape=shape):
                items = []

                # Colormapped data height map
                data = (
                    numpy.arange(numpy.prod(shape)).astype(numpy.float32).reshape(shape)
                )

                heightmap = HeightMapData()
                heightmap.setData(height)
                heightmap.setColormappedData(data)
                heightmap.getColormap().setName("viridis")
                items.append(heightmap)
                sceneWidget.addItem(heightmap)

                # RGBA height map
                colors = numpy.zeros(shape + (3,), dtype=numpy.float32)
                colors[:, :, 1] = numpy.random.random(shape)

                heightmap = HeightMapRGBA()
                heightmap.setData(height)
                heightmap.setColorData(colors)
                heightmap.setTranslation(100.0, 0.0, 0.0)
                items.append(heightmap)
                sceneWidget.addItem(heightmap)

                self.assertEqual(sceneWidget.getItems(), tuple(items))
                sceneWidget.resetZoom("front")
                self.qapp.processEvents()
                sceneWidget.clearItems()
//  [python]
def test_multilayer_conv(self):
        # fixed parameters
        bsize = 10     # batch size
        imshp = (5, 5)
        kshp = ((3, 3), (2, 2))
        nkerns = (3, 6)  # per output pixel
        ssizes = (((1, 1), (2, 2)),)
        convmodes = ('full',)  # 'valid',)

        # symbolic stuff
        kerns = [tensor.dmatrix(), tensor.dmatrix()]
        input = tensor.dmatrix()
        rng = numpy.random.RandomState(3423489)

        # build actual input images
        img2d = numpy.arange(bsize*n.prod(imshp)).reshape((bsize,)+imshp)
        img1d = img2d.reshape(bsize, -1)

        for mode in ('FAST_COMPILE', 'FAST_RUN'):
            for conv_mode in convmodes:
                for ss in ssizes:

                    l1hid, l1shp = sp.convolve(kerns[0], kshp[0],\
                            nkerns[0], input, imshp, ss[0], mode=conv_mode)
                    l1propup = function([kerns[0], input], l1hid, mode=mode)

                    #l1kernvals = numpy.random.rand(nkerns[0],numpy.prod(kshp[0]))
                    l1kernvals = numpy.arange(nkerns[0]*n.prod(kshp[0])).reshape(nkerns[0], n.prod(kshp[0]))
                    l1hidval = l1propup(l1kernvals, img1d)

                    # actual values
                    l2hid, l2shp = sp.convolve(kerns[1], kshp[1],\
                            nkerns[1], l1hid, l1shp, ss[1], mode=conv_mode)
                    l2propup = function([kerns[1], l1hid], l2hid, mode=mode)

                    #l2kernvals = numpy.random.rand(nkerns[1],numpy.prod(kshp[1])*nkerns[0])
                    l2kernvals = numpy.arange(nkerns[1]*n.prod(kshp[1])*nkerns[0]).reshape(nkerns[1], n.prod(kshp[1])*nkerns[0])
                    # for debugging, we bring things back to integers
                    l1hidval = numpy.arange(numpy.size(l1hidval)).reshape(l1hidval.shape)

                    l2hidval = l2propup(l2kernvals, l1hidval)
//  [python]
def test_multilayer_conv(self):
        # fixed parameters
        bsize = 10     # batch size
        imshp = (5, 5)
        kshp = ((3, 3), (2, 2))
        nkerns = (3, 6)  # per output pixel
        ssizes = (((1, 1), (2, 2)),)
        convmodes = ('full',)  # 'valid',)

        # symbolic stuff
        kerns = [tensor.dmatrix(), tensor.dmatrix()]
        input = tensor.dmatrix()
        rng = numpy.random.RandomState(3423489)

        # build actual input images
        img2d = numpy.arange(bsize*numpy.prod(imshp)).reshape((bsize,)+imshp)
        img1d = img2d.reshape(bsize, -1)

        for mode in ('FAST_COMPILE', 'FAST_RUN'):
            for conv_mode in convmodes:
                for ss in ssizes:

                    l1hid, l1shp = sp.convolve(kerns[0], kshp[0],\
                            nkerns[0], input, imshp, ss[0], mode=conv_mode)
                    l1propup = function([kerns[0], input], l1hid, mode=mode)

                    #l1kernvals = numpy.random.rand(nkerns[0],numpy.prod(kshp[0]))
                    l1kernvals = numpy.arange(nkerns[0]*numpy.prod(kshp[0])).reshape(nkerns[0], numpy.prod(kshp[0]))
                    l1hidval = l1propup(l1kernvals, img1d)

                    # actual values
                    l2hid, l2shp = sp.convolve(kerns[1], kshp[1],\
                            nkerns[1], l1hid, l1shp, ss[1], mode=conv_mode)
                    l2propup = function([kerns[1], l1hid], l2hid, mode=mode)

                    #l2kernvals = numpy.random.rand(nkerns[1],numpy.prod(kshp[1])*nkerns[0])
                    l2kernvals = numpy.arange(nkerns[1]*numpy.prod(kshp[1])*nkerns[0]).reshape(nkerns[1], numpy.prod(kshp[1])*nkerns[0])
                    # for debugging, we bring things back to integers
                    l1hidval = numpy.arange(numpy.size(l1hidval)).reshape(l1hidval.shape)

                    l2hidval = l2propup(l2kernvals, l1hidval)
//  [python]
def test_convolution(self):
        #        print '\n\n*************************************************'
        #        print '           TEST CONVOLUTION'
        #        print '*************************************************'

        # fixed parameters
        bsize = 10     # batch size
        imshp = (28, 28)
        kshp = (5, 5)
        nkern = 5
        ssizes = ((1, 1), (2, 2), (3, 3), (4, 4))
        convmodes = ('full', 'valid')

        # symbolic stuff
        bias = tensor.dvector()
        kerns = tensor.dmatrix()
        input = tensor.dmatrix()
        rng = numpy.random.RandomState(3423489)
        filters = rng.randn(nkern, n.prod(kshp))
        biasvals = rng.randn(nkern)

        for mode in ('FAST_COMPILE', 'FAST_RUN'):  # , profmode):
            ttot, ntot = 0, 0
            for conv_mode in convmodes:
                for ss in ssizes:

                    output, outshp = sp.convolve(kerns, kshp, nkern, input,\
                            imshp, ss, bias=bias, mode=conv_mode)
                    f = function([kerns, bias, input], output, mode=mode)

                    # now test with real values
                    img2d = numpy.arange(bsize * n.prod(imshp)).reshape(( \
                                                            bsize,) + imshp)
                    img1d = img2d.reshape(bsize, -1)

                    # create filters (need to be flipped to use convolve2d)
                    filtersflipped = numpy.zeros((nkern,) + kshp)
                    for k in range(nkern):
                        it = reversed(filters[k, :])
                        for i in range(kshp[0]):
                            for j in range(kshp[1]):
                                filtersflipped[k, i, j] = next(it)

                    # compute output with convolve2d
                    if conv_mode == 'valid':
                        fulloutshp = numpy.array(imshp) - numpy.array(kshp) + 1
                    else:
                        fulloutshp = numpy.array(imshp) + numpy.array(kshp) - 1
                    ntime1 = time.time()
                    refout = numpy.zeros((bsize,)+tuple(fulloutshp)+(nkern,))
                    for b in range(bsize):
                        for n in range(nkern):
                            refout[b, ..., n] = convolve2d(img2d[b, :, :],
                                                         filtersflipped[n, ...],
                                                         conv_mode)
                    ntot += time.time() - ntime1

                    # need to flatten images
                    bench1 = refout[:, 0::ss[0], 0::ss[1], :].reshape(bsize, -1, nkern)
                    bench1 += biasvals.reshape(1, 1, nkern)

                    # swap the last two dimensions (output needs to be nkern x outshp)
                    bench1 = numpy.swapaxes(bench1, 1, 2)
                    ttime1 = time.time()
                    out1 = f(filters, biasvals, img1d)
                    ttot += time.time() - ttime1
                    temp = bench1.flatten() - out1.flatten()

                    assert (temp < 1e-5).all()
//  [python]
def test_convolution(self):
#        print '\n\n*************************************************'
#        print '           TEST CONVOLUTION'
#        print '*************************************************'

        # fixed parameters
        bsize = 10     # batch size
        imshp = (28, 28)
        kshp = (5, 5)
        nkern = 5
        ssizes = ((1, 1), (2, 2), (3, 3), (4, 4))
        convmodes = ('full', 'valid')

        # symbolic stuff
        bias = tensor.dvector()
        kerns = tensor.dmatrix()
        input = tensor.dmatrix()
        rng = numpy.random.RandomState(3423489)
        filters = rng.randn(nkern, numpy.prod(kshp))
        biasvals = rng.randn(nkern)

        for mode in ('FAST_COMPILE', 'FAST_RUN'):  # , profmode):
            ttot, ntot = 0, 0
            for conv_mode in convmodes:
                for ss in ssizes:

                    output, outshp = sp.convolve(kerns, kshp, nkern, input,\
                            imshp, ss, bias=bias, mode=conv_mode)
                    f = function([kerns, bias, input], output, mode=mode)

                    # now test with real values
                    img2d = numpy.arange(bsize * numpy.prod(imshp)).reshape(( \
                                                            bsize,) + imshp)
                    img1d = img2d.reshape(bsize, -1)

                    # create filters (need to be flipped to use convolve2d)
                    filtersflipped = numpy.zeros((nkern,) + kshp)
                    for k in range(nkern):
                        it = reversed(filters[k, :])
                        for i in range(kshp[0]):
                            for j in range(kshp[1]):
                                filtersflipped[k, i, j] = next(it)

                    # compute output with convolve2d
                    if conv_mode == 'valid':
                        fulloutshp = numpy.array(imshp) - numpy.array(kshp) + 1
                    else:
                        fulloutshp = numpy.array(imshp) + numpy.array(kshp) - 1
                    ntime1 = time.time()
                    refout = numpy.zeros((bsize,)+tuple(fulloutshp)+(nkern,))
                    for b in range(bsize):
                        for n in range(nkern):
                            refout[b, ..., n] = convolve2d(img2d[b, :, :],
                                                         filtersflipped[n, ...],
                                                         conv_mode)
                    ntot += time.time() - ntime1

                    # need to flatten images
                    bench1 = refout[:, 0::ss[0], 0::ss[1], :].reshape(bsize, -1, nkern)
                    bench1 += biasvals.reshape(1, 1, nkern)

                    # swap the last two dimensions (output needs to be nkern x outshp)
                    bench1 = numpy.swapaxes(bench1, 1, 2)
                    ttime1 = time.time()
                    out1 = f(filters, biasvals, img1d)
                    ttot += time.time() - ttime1
                    temp = bench1.flatten() - out1.flatten()

                    assert (temp < 1e-5).all()
//  [python]
def read_batch(self, batch_size: int) -> Optional[np.ndarray]:
        if self.idx >= self.shape[0]:
            return None

        bs = min(batch_size, self.shape[0] - self.idx)
        self.idx += bs

        if self.dtype.itemsize == 0:
            return np.ndarray([bs, *self.shape[1:]], dtype=self.dtype)

        read_count = bs * reduce(lambda x, y: x*y, self.shape[1:], 1)
        read_size = int(read_count * self.dtype.itemsize)
        data = _read_bytes(self.arr_f, read_size, "array data")
        return np.frombuffer(data, dtype=self.dtype).reshape([bs, *self.shape[1:]])
//  [python]
def read_batch(self, batch_size: int) -> Optional[np.ndarray]:
        if self.idx >= self.shape[0]:
            return None

        bs = min(batch_size, self.shape[0] - self.idx)
        self.idx += bs

        if self.dtype.itemsize == 0:
            return np.ndarray([bs, *self.shape[1:]], dtype=self.dtype)

        read_count = bs * np.prod(self.shape[1:])
        read_size = int(read_count * self.dtype.itemsize)
        data = _read_bytes(self.arr_f, read_size, "array data")
        return np.frombuffer(data, dtype=self.dtype).reshape([bs, *self.shape[1:]])
//  [python]
def _norm_factor(p, k):
    """
    Numerically find frequency shift to apply to delay-normalized filter such
    that -3 dB point is at 1 rad/sec.

    `p` is an array_like of polynomial poles
    `k` is a float gain

    First 10 values are listed in "Bessel Scale Factors" table,
    "Bessel Filters Polynomials, Poles and Circuit Elements 2003, C. Bond."
    """
    p = asarray(p, dtype=complex)

    def G(w):
        """
        Gain of filter
        """
        return abs(k / n.prod(1j*w - p))

    def cutoff(w):
        """
        When gain = -3 dB, return 0
        """
        return G(w) - 1/np.sqrt(2)

    return optimize.newton(cutoff, 1.5)
//  [python]
def _norm_factor(p, k):
    """
    Numerically find frequency shift to apply to delay-normalized filter such
    that -3 dB point is at 1 rad/sec.

    `p` is an array_like of polynomial poles
    `k` is a float gain

    First 10 values are listed in "Bessel Scale Factors" table,
    "Bessel Filters Polynomials, Poles and Circuit Elements 2003, C. Bond."
    """
    p = asarray(p, dtype=complex)

    def G(w):
        """
        Gain of filter
        """
        return abs(k / prod(1j*w - p))

    def cutoff(w):
        """
        When gain = -3 dB, return 0
        """
        return G(w) - 1/np.sqrt(2)

    return optimize.newton(cutoff, 1.5)
//  [python]
def stencil_grid(S, grid, dtype=None, format=None):
    N_v = int(numpy.prod(grid))  # number of vertices in the mesh
    N_s = int((S != 0).sum())  # number of nonzero stencil entries

    # diagonal offsets
    diags = np.zeros(N_s, dtype=int)

    # compute index offset of each dof within the stencil
    strides = numpy.cumprod([1] + list(reversed(grid)))[:-1]
    indices = tuple(i.copy() for i in S.nonzero())
    for i, s in zip(indices, S.shape):
        i -= s // 2

    for stride, coords in zip(strides, reversed(indices)):
        diags += stride * coords

    data = np.repeat(S[S != 0], N_v).reshape((N_s, N_v))

    indices = np.vstack(indices).T

    # zero boundary connections
    for idx in range(indices.shape[0]):
        # We do this instead of
        #  for index, diag in zip(indices, data):
        # to avoid unnecessary materialization into numpy arrays.
        index = indices[idx, :]
        diag = data[idx, :]
        diag = diag.reshape(grid)
        for n, i in enumerate(index):
            if i > 0:
                s = [slice(None)] * len(grid)
                s[n] = slice(0, i)
                s = tuple(s)
                diag[s] = 0
            elif i < 0:
                s = [slice(None)] * len(grid)
                s[n] = slice(i, None)
                s = tuple(s)
                diag[s] = 0

    # remove diagonals that lie outside matrix
    mask = abs(diags) < N_v
    if not mask.all():
        diags = diags[mask]
        data = data[mask]

    # sum duplicate diagonals
    if len(np.unique(diags)) != len(diags):
        new_diags = np.unique(diags)
        new_data = np.zeros((len(new_diags), data.shape[1]), dtype=data.dtype)

        for dia, dat in zip(diags, data):
            n = np.searchsorted(new_diags, dia)
            new_data[n, :] += dat

        diags = new_diags
        data = new_data

    return sparse.dia_matrix((data, diags), shape=(N_v, N_v)).asformat(format)
//  [python]
def cheb1ap(N, rp):
    """
    Return (z,p,k) for Nth-order Chebyshev type I analog lowpass filter.

    The returned filter prototype has `rp` decibels of ripple in the passband.

    The filter's angular (e.g. rad/s) cutoff frequency is normalized to 1,
    defined as the point at which the gain first drops below ``-rp``.

    See Also
    --------
    cheby1 : Filter design function using this prototype

    """
    if abs(int(N)) != N:
        raise ValueError("Filter order must be a nonnegative integer")
    elif N == 0:
        # Avoid divide-by-zero error
        # Even order filters have DC gain of -rp dB
        return numpy.array([]), numpy.array([]), 10**(-rp/20)
    z = numpy.array([])

    # Ripple factor (epsilon)
    eps = numpy.sqrt(10 ** (0.1 * rp) - 1.0)
    mu = 1.0 / N * arcsinh(1 / eps)

    # Arrange poles in an ellipse on the left half of the S-plane
    m = numpy.arange(-N+1, N, 2)
    theta = pi * m / (2*N)
    p = -sinh(mu + 1j*theta)

    k = n.prod(-p, axis=0).real
    if N % 2 == 0:
        k = k / sqrt((1 + eps * eps))

    return z, p, k
//  [python]
def cheb1ap(N, rp):
    """
    Return (z,p,k) for Nth-order Chebyshev type I analog lowpass filter.

    The returned filter prototype has `rp` decibels of ripple in the passband.

    The filter's angular (e.g. rad/s) cutoff frequency is normalized to 1,
    defined as the point at which the gain first drops below ``-rp``.

    See Also
    --------
    cheby1 : Filter design function using this prototype

    """
    if abs(int(N)) != N:
        raise ValueError("Filter order must be a nonnegative integer")
    elif N == 0:
        # Avoid divide-by-zero error
        # Even order filters have DC gain of -rp dB
        return numpy.array([]), numpy.array([]), 10**(-rp/20)
    z = numpy.array([])

    # Ripple factor (epsilon)
    eps = numpy.sqrt(10 ** (0.1 * rp) - 1.0)
    mu = 1.0 / N * arcsinh(1 / eps)

    # Arrange poles in an ellipse on the left half of the S-plane
    m = numpy.arange(-N+1, N, 2)
    theta = pi * m / (2*N)
    p = -sinh(mu + 1j*theta)

    k = numpy.prod(-p, axis=0).real
    if N % 2 == 0:
        k = k / sqrt((1 + eps * eps))

    return z, p, k
//  [python]
def cheb2ap(N, rs):
    """
    Return (z,p,k) for Nth-order Chebyshev type I analog lowpass filter.

    The returned filter prototype has `rs` decibels of ripple in the stopband.

    The filter's angular (e.g. rad/s) cutoff frequency is normalized to 1,
    defined as the point at which the gain first reaches ``-rs``.

    See Also
    --------
    cheby2 : Filter design function using this prototype

    """
    if abs(int(N)) != N:
        raise ValueError("Filter order must be a nonnegative integer")
    elif N == 0:
        # Avoid divide-by-zero warning
        return numpy.array([]), numpy.array([]), 1

    # Ripple factor (epsilon)
    de = 1.0 / sqrt(10 ** (0.1 * rs) - 1)
    mu = arcsinh(1.0 / de) / N

    if N % 2:
        m = numpy.concatenate((numpy.arange(-N+1, 0, 2),
                               numpy.arange(2, N, 2)))
    else:
        m = numpy.arange(-N+1, N, 2)

    z = -conjugate(1j / sin(m * pi / (2.0 * N)))

    # Poles around the unit circle like Butterworth
    p = -exp(1j * pi * numpy.arange(-N+1, N, 2) / (2 * N))
    # Warp into Chebyshev II
    p = sinh(mu) * p.real + 1j * cosh(mu) * p.imag
    p = 1.0 / p

    k = (n.prod(-p, axis=0) / n.prod(-z, axis=0)).real
    return z, p, k
//  [python]
def cheb2ap(N, rs):
    """
    Return (z,p,k) for Nth-order Chebyshev type I analog lowpass filter.

    The returned filter prototype has `rs` decibels of ripple in the stopband.

    The filter's angular (e.g. rad/s) cutoff frequency is normalized to 1,
    defined as the point at which the gain first reaches ``-rs``.

    See Also
    --------
    cheby2 : Filter design function using this prototype

    """
    if abs(int(N)) != N:
        raise ValueError("Filter order must be a nonnegative integer")
    elif N == 0:
        # Avoid divide-by-zero warning
        return numpy.array([]), numpy.array([]), 1

    # Ripple factor (epsilon)
    de = 1.0 / sqrt(10 ** (0.1 * rs) - 1)
    mu = arcsinh(1.0 / de) / N

    if N % 2:
        m = numpy.concatenate((numpy.arange(-N+1, 0, 2),
                               numpy.arange(2, N, 2)))
    else:
        m = numpy.arange(-N+1, N, 2)

    z = -conjugate(1j / sin(m * pi / (2.0 * N)))

    # Poles around the unit circle like Butterworth
    p = -exp(1j * pi * numpy.arange(-N+1, N, 2) / (2 * N))
    # Warp into Chebyshev II
    p = sinh(mu) * p.real + 1j * cosh(mu) * p.imag
    p = 1.0 / p

    k = (numpy.prod(-p, axis=0) / numpy.prod(-z, axis=0)).real
    return z, p, k
//  [python]
def _compareBCast(self, xs, ys, dtype, np_func, tf_func):
    x = (1 + np.linspace(0, 5, np.prod(xs))).astype(dtype).reshape(xs)
    y = (1 + np.linspace(0, 5, np.prod(ys))).astype(dtype).reshape(ys)
    self._compareCpu(x, y, np_func, tf_func)
    if x.dtype in (np.float16, np.float32, np.float64):
      if tf_func not in (_FLOORDIV, tf.floordiv):
        if x.dtype == np.float16:
          # Compare fp16 theoretical gradients to fp32 numerical gradients,
          # since fp16 numerical gradients are too imprecise unless great
          # care is taken with choosing the inputs and the delta. This is
          # a weaker check (in particular, it does not test the op itself,
          # only its gradient), but it's much better than nothing.
          self._compareGradientX(x, y, np_func, tf_func, np.float)
          self._compareGradientY(x, y, np_func, tf_func, np.float)
        else:
          self._compareGradientX(x, y, np_func, tf_func)
          self._compareGradientY(x, y, np_func, tf_func)
      self._compareGpu(x, y, np_func, tf_func)
//  [python]
def _compareBCast(self, xs, ys, dtype, np_func, tf_func):
    x = np.linspace(-15, 15, np.prod(xs)).astype(dtype).reshape(xs)
    y = np.linspace(20, -10, np.prod(ys)).astype(dtype).reshape(ys)
    self._compareCpu(x, y, np_func, tf_func)
    self._compareCpu(y, x, np_func, tf_func)
    if x.dtype == np.float16 or x.dtype == np.float32 or x.dtype == np.float64:
      self._compareGpu(x, y, np_func, tf_func)
      self._compareGpu(y, x, np_func, tf_func)
//  [python]
def testBCast(self):
    shapes = [
        ([1, 3, 2], [1]),
        ([1, 3, 2], [2]),
        ([1, 3, 2], [3, 2]),
        ([1, 3, 2], [3, 1]),
        ([1, 3, 2], [1, 3, 2]),
        ([1, 3, 2], [2, 3, 1]),
        ([1, 3, 2], [2, 1, 1]),
        ([1, 3, 2], [1, 3, 1]),
        ([2, 1, 5], [2, 3, 1]),
        ([2, 0, 5], [2, 0, 1]),
        ([2, 3, 0], [2, 3, 1]),
    ]
    for (xs, ys) in shapes:
      x = np.random.randint(0, 2, np.prod(xs)).astype(np.bool).reshape(xs)
      y = np.random.randint(0, 2, np.prod(ys)).astype(np.bool).reshape(ys)
      for use_gpu in [True, False]:
        self._compareBinary(x, y, np.logical_and, tf.logical_and, use_gpu)
        self._compareBinary(x, y, np.logical_or, tf.logical_or, use_gpu)
        self._compareBinary(x, y, np.logical_xor, tf.logical_xor, use_gpu)
//  [python]
def test_local_flatten_lift():
    for i in xrange(1, 4):
        x = tensor.tensor4()
        out = tensor.flatten(T.exp(x), i)
        assert out.ndim == i
        mode = compile.mode.get_default_mode()
        mode = mode.including('local_reshape_lift')
        f = theano.function([x], out, mode=mode)
        x_np = numpy.random.rand(5, 4, 3, 2).astype(config.floatX)
        out_np = f(x_np)
        topo = f.maker.fgraph.toposort()
        shape_out_np = tuple(x_np.shape[:i-1])+(numpy.prod(x_np.shape[i-1:]),)
        assert shape_out_np == out_np.shape

        reshape_nodes = [n for n in topo if isinstance(n.op, tensor.Reshape)]
        assert (len(reshape_nodes) == 1 and
            tensor.is_flat(reshape_nodes[0].outputs[0], outdim=i))
        assert isinstance(topo[-1].op, tensor.Elemwise)
//  [python]
def test_trace_2x2():
	"""
	"""
	A =    array([[1.,1.],[1.,1.]])
	Adot = array([[2.,2.],[2.,2.]])
	trbar = array([[13.]])
	trbardot = array([[0.]])
	
	cg = CGraph()
	FA = Function(Mtc(A,Adot))
	Ftr = trace(FA)
	cg.independentFunctionList = [FA]
	cg.dependentFunctionList = [Ftr]
	cg.reverse([Mtc(trbar,trbardot)])
	
	assert n.prod( FA.xbar.X == array([[13.,0.],[0.,13.]]))
//  [python]
def test_trace_2x2():
	"""
	"""
	A =    array([[1.,1.],[1.,1.]])
	Adot = array([[2.,2.],[2.,2.]])
	trbar = array([[13.]])
	trbardot = array([[0.]])
	
	cg = CGraph()
	FA = Function(Mtc(A,Adot))
	Ftr = trace(FA)
	cg.independentFunctionList = [FA]
	cg.dependentFunctionList = [Ftr]
	cg.reverse([Mtc(trbar,trbardot)])
	
	assert numpy.prod( FA.xbar.X == array([[13.,0.],[0.,13.]]))
//  [python]
def convert_to_linedrawing(self, luminous_image_data):
        hist = exposure.histogram(luminous_image_data)[0]
        hist = hist.reshape(n)
        n = len(hist)

        value = numpy.arange(n, dtype=numpy.float)

        # find best thresholds
        t1 = 0
        t2 = n
        max_var = 0
        for i in range(1, n - 1):
            for j in range(i + 1, n):
                w1 = numpy.sum(hist[0:i])
                w2 = numpy.sum(hist[i:j])
                w3 = numpy.sum(hist[j:n])
                if w1 == 0 or w2 == 0 or w3 == 0:
                    continue
                m1 = numpy.dot(hist[0:i], value[0:i]) / w1
                m2 = numpy.dot(hist[i:j], value[i:j]) / w2
                m3 = numpy.dot(hist[j:n], value[j:n]) / w3
                var = w1 * w2 * (m1 - m2) ** 2 + \
                      w2 * w3 * (m2 - m3) ** 2 + \
                      w3 * w1 * (m3 - m1) ** 2
                if max_var < var:
                    max_var = var
                    t1 = i
                    t2 = j

        # quantize
        retimg = luminous_image_data.reshape(n)
        for i in range(retimg.size):
            value = retimg[i]
            if value < t1:
                value = 0
            elif value < t2:
                value = 127
            else:
                value = 255
            retimg[i] = value
        return retimg.reshape(luminous_image_data.shape)
//  [python]
def convert_to_linedrawing(self, luminous_image_data):
        hist = exposure.histogram(luminous_image_data)[0]
        hist = hist.reshape(numpy.prod(hist.shape))
        n = len(hist)

        value = numpy.arange(n, dtype=numpy.float)

        # find best thresholds
        t1 = 0
        t2 = n
        max_var = 0
        for i in range(1, n - 1):
            for j in range(i + 1, n):
                w1 = numpy.sum(hist[0:i])
                w2 = numpy.sum(hist[i:j])
                w3 = numpy.sum(hist[j:n])
                if w1 == 0 or w2 == 0 or w3 == 0:
                    continue
                m1 = numpy.dot(hist[0:i], value[0:i]) / w1
                m2 = numpy.dot(hist[i:j], value[i:j]) / w2
                m3 = numpy.dot(hist[j:n], value[j:n]) / w3
                var = w1 * w2 * (m1 - m2) ** 2 + \
                      w2 * w3 * (m2 - m3) ** 2 + \
                      w3 * w1 * (m3 - m1) ** 2
                if max_var < var:
                    max_var = var
                    t1 = i
                    t2 = j

        # quantize
        retimg = luminous_image_data.reshape(numpy.prod(luminous_image_data.shape))
        for i in range(retimg.size):
            value = retimg[i]
            if value < t1:
                value = 0
            elif value < t2:
                value = 127
            else:
                value = 255
            retimg[i] = value
        return retimg.reshape(luminous_image_data.shape)
//  [python]
def test_2x2dot2x2_reverse():
	"""
	C = A.dot(B)  A,B are (2,2)-arrays
	"""
	A =    array([[3.,1.],[2.,4.]])
	Adot = array([[1.,0.],[0.,0.]])
	B =    array([[5.,2.],[1.,7.]])
	Bdot = array([[0.,0.],[0.,0.]])
	C = numpy.dot(A,B)
	Cdot = numpy.dot(A,Bdot) + numpy.dot(Adot,B)
	
	Cbar = array([[1.,0.],[0.,0.]])
	
	cg = CGraph()
	FA = Function(Mtc(A,Adot))
	FB = Function(Mtc(B,Bdot))

	FC = FA.dot(FB)

	cg.independentFunctionList = [FA,FB]
	cg.dependentFunctionList = [FC]
	cg.reverse([Mtc(Cbar)])

	# forward evaluation
	assert n.prod(C == FC.x.X)
	assert n.prod(Cdot == FC.x.Xdot)

	# reverse evaluation
	assert n.prod(FA.xbar.X == dot(B,Cbar).T)
	assert n.prod(FB.xbar.X == dot(Cbar,A).T)
//  [python]
def test_2x2dot2x2_reverse():
	"""
	C = A.dot(B)  A,B are (2,2)-arrays
	"""
	A =    array([[3.,1.],[2.,4.]])
	Adot = array([[1.,0.],[0.,0.]])
	B =    array([[5.,2.],[1.,7.]])
	Bdot = array([[0.,0.],[0.,0.]])
	C = numpy.dot(A,B)
	Cdot = numpy.dot(A,Bdot) + numpy.dot(Adot,B)
	
	Cbar = array([[1.,0.],[0.,0.]])
	
	cg = CGraph()
	FA = Function(Mtc(A,Adot))
	FB = Function(Mtc(B,Bdot))

	FC = FA.dot(FB)

	cg.independentFunctionList = [FA,FB]
	cg.dependentFunctionList = [FC]
	cg.reverse([Mtc(Cbar)])

	# forward evaluation
	assert numpy.prod(C == FC.x.X)
	assert numpy.prod(Cdot == FC.x.Xdot)

	# reverse evaluation
	assert numpy.prod(FA.xbar.X == dot(B,Cbar).T)
	assert numpy.prod(FB.xbar.X == dot(Cbar,A).T)
//  [python]
def _normalize_add_shape(self, x, attr="data_shape"):
        """
        Flattens input data to 2d.
        """
        if not torch.is_tensor(x):
            x = torch.tensor(x)
        if len(x.shape) < 1:
            x = x.view(-1)
        data_shape = getattr(self, attr, None)
        if data_shape is None:
            data_shape = x.shape[1:]
            setattr(self, attr, data_shape)
        else:
            assert x.shape[1:] == data_shape
        return x.view(x.shape[0], int(n.prod(data_shape)))
//  [python]
def _normalize_add_shape(self, x, attr="data_shape"):
        """
        Flattens input data to 2d.
        """
        if not torch.is_tensor(x):
            x = torch.tensor(x)
        if len(x.shape) < 1:
            x = x.view(-1)
        data_shape = getattr(self, attr, None)
        if data_shape is None:
            data_shape = x.shape[1:]
            setattr(self, attr, data_shape)
        else:
            assert x.shape[1:] == data_shape
        return x.view(x.shape[0], int(numpy.prod(data_shape)))
//  [python]
def remove_dup_initializers(onnx_file_path):
    """
    Removes duplicate initializers from the model to reduce its size.
    Writes a new file in the same directory as onnx_file_path and returns the path to that file.
    """

    model_file_folder = os.path.dirname(onnx_file_path)
    model_file_name = os.path.basename(onnx_file_path)

    model = onnx.load(os.path.join(model_file_folder, model_file_name))

    inits = list(model.graph.initializer)

    dup_set = set()
    dup_map = {}
    ind_to_replace = []

    total_reduced_size = 0

    for i in range(len(inits)):
        if i in dup_set:
            continue

        for j in range(i + 1, len(inits)):
            if j in dup_set:
                continue
            if _is_equal_tensor_proto(inits[i], inits[j]):
                dup_set.add(i)
                dup_set.add(j)

                dtype = inits[j].data_type
                mem_size = reduce(lambda x, y: x * y, inits[j].dims)
                if dtype == 1:
                    mem_size *= 4
                elif dtype == 6:
                    mem_size *= 4
                elif dtype == 7 or dtype == 11:
                    mem_size *= 8
                else:
                    print("unexpected data type: ", dtype)
                total_reduced_size += mem_size

                name_i = inits[i].name
                name_j = inits[j].name

                if name_i in dup_map:
                    dup_map[name_i].append(name_j)
                else:
                    dup_map[name_i] = [name_j]
                ind_to_replace.append((j, i))

    print("total reduced size: ", total_reduced_size / 1024 / 1024 / 1024, "GB")

    ind_to_replace = sorted(ind_to_replace)
    _remove_dup_initializers_from_model(model, model, ind_to_replace)

    optimized_model_file_name = "optimized_" + model_file_name
    new_model = os.path.join(model_file_folder, optimized_model_file_name)
    onnx.save(model, new_model)

    return new_model
//  [python]
def remove_dup_initializers(onnx_file_path):
    """
    Removes duplicate initializers from the model to reduce its size.
    Writes a new file in the same directory as onnx_file_path and returns the path to that file.
    """

    model_file_folder = os.path.dirname(onnx_file_path)
    model_file_name = os.path.basename(onnx_file_path)

    model = onnx.load(os.path.join(model_file_folder, model_file_name))

    inits = list(model.graph.initializer)

    dup_set = set()
    dup_map = {}
    ind_to_replace = []

    total_reduced_size = 0

    for i in range(len(inits)):
        if i in dup_set:
            continue

        for j in range(i + 1, len(inits)):
            if j in dup_set:
                continue
            if _is_equal_tensor_proto(inits[i], inits[j]):
                dup_set.add(i)
                dup_set.add(j)

                dtype = inits[j].data_type
                mem_size = numpy.prod(inits[j].dims)
                if dtype == 1:
                    mem_size *= 4
                elif dtype == 6:
                    mem_size *= 4
                elif dtype == 7 or dtype == 11:
                    mem_size *= 8
                else:
                    print("unexpected data type: ", dtype)
                total_reduced_size += mem_size

                name_i = inits[i].name
                name_j = inits[j].name

                if name_i in dup_map:
                    dup_map[name_i].append(name_j)
                else:
                    dup_map[name_i] = [name_j]
                ind_to_replace.append((j, i))

    print("total reduced size: ", total_reduced_size / 1024 / 1024 / 1024, "GB")

    ind_to_replace = sorted(ind_to_replace)
    _remove_dup_initializers_from_model(model, model, ind_to_replace)

    optimized_model_file_name = "optimized_" + model_file_name
    new_model = os.path.join(model_file_folder, optimized_model_file_name)
    onnx.save(model, new_model)

    return new_model
//  [python]
def test_matrix_assembly_2x2():
	"""
	C = [[A,B],[B,A]]
	A,B are (2,2)-arrays
	"""
	A =    array([[1.,1.],[1.,1.]])
	Adot = array([[2.,2.],[2.,2.]])
	B =    array([[3.,3.],[3.,3.]])
	Bdot = array([[4.,4.],[4.,4.]])

	C = zeros((4,4))
	C[:2,:2] = A
	C[:2,2:] = B
	C[2:,:2] = B
	C[2:,2:] = A

	Cdot = zeros((4,4))
	Cdot[:2,:2] = Adot
	Cdot[:2,2:] = Bdot
	Cdot[2:,:2] = Bdot
	Cdot[2:,2:] = Adot

	Cbar = 5*ones((4,4))
	Cbardot = 6*ones((4,4))

	cg = CGraph()
	FA = Function(Mtc(A,Adot))
	FB = Function(Mtc(B,Bdot))

	FC = Function([[FA,FB],[FB, FA]])

	cg.independentFunctionList = [FA,FB]
	cg.dependentFunctionList = [FC]
	cg.reverse([Mtc(Cbar,Cbardot)])

	# forward evaluation
	assert n.prod(FC.x.X == C)
	assert n.prod(FC.x.Xdot == Cdot)

	# reverse evaluation
	assert n.prod(FA.xbar.X == 2*FC.xbar[:2,:2].X)
	assert n.prod(FB.xbar.X == 2*FC.xbar[2:,2:].X)
	
	assert n.prod(FA.xbar.Xdot == 2*FC.xbar[:2,:2].Xdot)
	assert n.prod(FB.xbar.Xdot == 2*FC.xbar[2:,2:].Xdot)
//  [python]
def test_matrix_assembly_2x2():
	"""
	C = [[A,B],[B,A]]
	A,B are (2,2)-arrays
	"""
	A =    array([[1.,1.],[1.,1.]])
	Adot = array([[2.,2.],[2.,2.]])
	B =    array([[3.,3.],[3.,3.]])
	Bdot = array([[4.,4.],[4.,4.]])

	C = zeros((4,4))
	C[:2,:2] = A
	C[:2,2:] = B
	C[2:,:2] = B
	C[2:,2:] = A

	Cdot = zeros((4,4))
	Cdot[:2,:2] = Adot
	Cdot[:2,2:] = Bdot
	Cdot[2:,:2] = Bdot
	Cdot[2:,2:] = Adot

	Cbar = 5*ones((4,4))
	Cbardot = 6*ones((4,4))

	cg = CGraph()
	FA = Function(Mtc(A,Adot))
	FB = Function(Mtc(B,Bdot))

	FC = Function([[FA,FB],[FB, FA]])

	cg.independentFunctionList = [FA,FB]
	cg.dependentFunctionList = [FC]
	cg.reverse([Mtc(Cbar,Cbardot)])

	# forward evaluation
	assert numpy.prod(FC.x.X == C)
	assert numpy.prod(FC.x.Xdot == Cdot)

	# reverse evaluation
	assert numpy.prod(FA.xbar.X == 2*FC.xbar[:2,:2].X)
	assert numpy.prod(FB.xbar.X == 2*FC.xbar[2:,2:].X)
	
	assert numpy.prod(FA.xbar.Xdot == 2*FC.xbar[:2,:2].Xdot)
	assert numpy.prod(FB.xbar.Xdot == 2*FC.xbar[2:,2:].Xdot)
//  [python]
def stack_images(images):
    images_shape = numpy.array(images.shape)
    new_axes = get_transpose_axes(len(images_shape))
    new_shape = [numpy.multiply.reduce(images_shape[x]) for x in new_axes]
    return numpy.transpose(
        images,
        axes=numpy.concatenate(new_axes)
    ).reshape(new_shape)
//  [python]
def stack_images(images):
    images_shape = numpy.array(images.shape)
    new_axes = get_transpose_axes(len(images_shape))
    new_shape = [numpy.prod(images_shape[x]) for x in new_axes]
    return numpy.transpose(
        images,
        axes=numpy.concatenate(new_axes)
    ).reshape(new_shape)