     Test<2> (g_allocator);
     Test<15> (g_allocator);
 
+    Test<int32_t, 1, 64, 2, 2>(g_allocator);
+
     return 0;
 }


template <
        typename DataType,
        unsigned int ThreadsInBlock,
        template<typename, unsigned int> class TestType>
struct SingleItemTestHelper<DataType, 1, ThreadsInBlock, TestType>
{
    static void run(unsigned int num_items,
                   DataType *d_data,
                   DataType *h_data)
    {
        TestType<DataType, ThreadsInBlock> test;

        Iota(num_items, d_data);
        BlockShuffleTest<DataType, 1 /* ItemsPerThread */, ThreadsInBlock>(d_data, test);
        AssertEquals(0, CheckResult(num_items, d_data, h_data, test));
    }
};


template <
        typename DataType,
        unsigned int ItemsPerThread,
        unsigned int ThreadsInBlock>
void Test(
    CachingDeviceAllocator &g_allocator
)
{
    const unsigned int num_items = ItemsPerThread * ThreadsInBlock;

    DataType *d_data = nullptr;
    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_data, sizeof(DataType) * num_items));

    std::unique_ptr<DataType[]> h_data(new DataType[num_items]);

    Test<DataType, ItemsPerThread, ThreadsInBlock, UpTest>(num_items, d_data, h_data.get());
    Test<DataType, ItemsPerThread, ThreadsInBlock, DownTest>(num_items, d_data, h_data.get());

    SingleItemTestHelper<DataType, ItemsPerThread, ThreadsInBlock, OffsetUpTest>().run(num_items,
                                                                                       d_data,
                                                                                       h_data.get());

    SingleItemTestHelper<DataType, ItemsPerThread, ThreadsInBlock, OffsetDownTest>().run(num_items,
                                                                                         d_data,
                                                                                         h_data.get());

    SingleItemTestHelper<DataType, ItemsPerThread, ThreadsInBlock, RotateUpTest>().run(num_items,
                                                                                       d_data,
                                                                                       h_data.get());

    SingleItemTestHelper<DataType, ItemsPerThread, ThreadsInBlock, RotateTest>().run(num_items,
                                                                                     d_data,
                                                                                     h_data.get());

    if (d_data)
    {
        CubDebugExit(g_allocator.DeviceFree(d_data));
    }
}

template <unsigned int ItemsPerThread>
void Test(CachingDeviceAllocator &g_allocator)
{
    Test<int16_t, ItemsPerThread, 32>(g_allocator);
    Test<int32_t, ItemsPerThread, 32>(g_allocator);
    Test<int32_t, ItemsPerThread, 512>(g_allocator);
    Test<int64_t, ItemsPerThread, 512>(g_allocator);
    Test<int64_t, ItemsPerThread, 1024>(g_allocator);
}

int main(int argc, char** argv)

template <
        typename DataType,
        unsigned int ItemsPerThread,
        unsigned int BlockDimX, 
        unsigned int BlockDimY, 
        unsigned int BlockDimZ, 
        template<typename, unsigned int, unsigned int, unsigned int, unsigned int> class TestType>
void Test(unsigned int num_items,
          DataType *d_data,
          DataType *h_data)
{
    TestType<DataType, ItemsPerThread, BlockDimX, BlockDimY, BlockDimZ> test;

    Iota(num_items, d_data);
    BlockShuffleTest<DataType, ItemsPerThread, BlockDimX, BlockDimY, BlockDimZ>(d_data, test);
    AssertEquals(0, CheckResult(num_items, d_data, h_data, test));
}

