// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#if defined _MSC_VER
// Inline expansion warnings
#pragma warning(disable:4710 4711)
#endif

#include "TestMain.h"
#include "TestCase.h"
/*
* Interesting numbers:
*
*  std::uint64_t
*  0, 1, 2, 0x7fffffff, 0x80000000, 0xffffffff, 0x100000000, 0x200000000, 0x7fffffffffffffff, 0x8000000000000000, 0xffffffffffffffff
*  std::uint32_t
*  0, 1, 2, 0x7fffffff, 0x80000000, 0xffffffff
*  std::int64_t
*  0, 1, 2, 0x7fffffff, 0x80000000, 0xffffffff, 0x100000000, 0x200000000, 0x7fffffffffffffff, 0x8000000000000000, 0xffffffffffffffff
*/

static const TestCase< std::uint64_t, std::uint64_t, OpType::Mult > uint64_uint64[] =
{
	{ 0,                     0, true },
	{ 1,                     0, true },
	{ 2,                     0, true },
	{ 0x7fffffff,            0, true },
	{ 0x80000000,            0, true },
	{ 0xffffffff,            0, true },
	{ 0x100000000,           0, true },
	{ 0x200000000,           0, true },
	{ 0x7fffffffffffffff,    0, true },
	{ 0x8000000000000000,    0, true },
	{ 0xffffffffffffffff,    0, true },
	{ 0,                     1, true },
	{ 1,                     1, true },
	{ 2,                     1, true },
	{ 0x7fffffff,            1, true },
	{ 0x80000000,            1, true },
	{ 0xffffffff,            1, true },
	{ 0x100000000,           1, true },
	{ 0x200000000,           1, true },
	{ 0x7fffffffffffffff,    1, true },
	{ 0x8000000000000000,    1, true },
	{ 0xffffffffffffffff,    1, true },
	{ 0,                     2, true },
	{ 1,                     2, true },
	{ 2,                     2, true },
	{ 0x7fffffff,            2, true },
	{ 0x80000000,            2, true },
	{ 0xffffffff,            2, true },
	{ 0x100000000,           2, true },
	{ 0x200000000,           2, true },
	{ 0x7fffffffffffffff,    2, true },
	{ 0x8000000000000000,    2, false },
	{ 0xffffffffffffffff,    2, false },
	{ 0,                     0x7fffffff, true },
	{ 1,                     0x7fffffff, true },
	{ 2,                     0x7fffffff, true },
	{ 0x7fffffff,            0x7fffffff, true },
	{ 0x80000000,            0x7fffffff, true },
	{ 0xffffffff,            0x7fffffff, true },
	{ 0x100000000,           0x7fffffff, true },
	{ 0x200000000,           0x7fffffff, true },
	{ 0x7fffffffffffffff,    0x7fffffff, false },
	{ 0x8000000000000000,    0x7fffffff, false },
	{ 0xffffffffffffffff,    0x7fffffff, false },
	{ 0,                     0x80000000, true },
	{ 1,                     0x80000000, true },
	{ 2,                     0x80000000, true },
	{ 0x7fffffff,            0x80000000, true },
	{ 0x80000000,            0x80000000, true },
	{ 0xffffffff,            0x80000000, true },
	{ 0x100000000,           0x80000000, true },
	{ 0x200000000,           0x80000000, false },
	{ 0x7fffffffffffffff,    0x80000000, false },
	{ 0x8000000000000000,    0x80000000, false },
	{ 0xffffffffffffffff,    0x80000000, false },
	{ 0,                     0xffffffff, true },
	{ 1,                     0xffffffff, true },
	{ 2,                     0xffffffff, true },
	{ 0x7fffffff,            0xffffffff, true },
	{ 0x80000000,            0xffffffff, true },
	{ 0xffffffff,            0xffffffff, true },
	{ 0x100000000,           0xffffffff, true },
	{ 0x200000000,           0xffffffff, false },
	{ 0x7fffffffffffffff,    0xffffffff, false },
	{ 0x8000000000000000,    0xffffffff, false },
	{ 0xffffffffffffffff,    0xffffffff, false },
	{ 0,                     0x100000000, true },
	{ 1,                     0x100000000, true },
	{ 2,                     0x100000000, true },
	{ 0x7fffffff,            0x100000000, true },
	{ 0x80000000,            0x100000000, true },
	{ 0xffffffff,            0x100000000, true },
	{ 0x100000000,           0x100000000, false },
	{ 0x200000000,           0x100000000, false },
	{ 0x7fffffffffffffff,    0x100000000, false },
	{ 0x8000000000000000,    0x100000000, false },
	{ 0xffffffffffffffff,    0x100000000, false },
	{ 0,                     0x200000000, true },
	{ 1,                     0x200000000, true },
	{ 2,                     0x200000000, true },
	{ 0x7fffffff,            0x200000000, true },
	{ 0x80000000,            0x200000000, false },
	{ 0xffffffff,            0x200000000, false },
	{ 0x100000000,           0x200000000, false },
	{ 0x200000000,           0x200000000, false },
	{ 0x7fffffffffffffff,    0x200000000, false },
	{ 0x8000000000000000,    0x200000000, false },
	{ 0xffffffffffffffff,    0x200000000, false },
	{ 0,                     0x7fffffffffffffff, true },
	{ 1,                     0x7fffffffffffffff, true },
	{ 2,                     0x7fffffffffffffff, true },
	{ 0x7fffffff,            0x7fffffffffffffff, false },
	{ 0x80000000,            0x7fffffffffffffff, false },
	{ 0xffffffff,            0x7fffffffffffffff, false },
	{ 0x100000000,           0x7fffffffffffffff, false },
	{ 0x200000000,           0x7fffffffffffffff, false },
	{ 0x7fffffffffffffff,    0x7fffffffffffffff, false },
	{ 0x8000000000000000,    0x7fffffffffffffff, false },
	{ 0xffffffffffffffff,    0x7fffffffffffffff, false },
	{ 0,                     0x8000000000000000, true },
	{ 1,                     0x8000000000000000, true },
	{ 2,                     0x8000000000000000, false },
	{ 0x7fffffff,            0x8000000000000000, false },
	{ 0x80000000,            0x8000000000000000, false },
	{ 0xffffffff,            0x8000000000000000, false },
	{ 0x100000000,           0x8000000000000000, false },
	{ 0x200000000,           0x8000000000000000, false },
	{ 0x7fffffffffffffff,    0x8000000000000000, false },
	{ 0x8000000000000000,    0x8000000000000000, false },
	{ 0xffffffffffffffff,    0x8000000000000000, false },
	{ 0,                     0xffffffffffffffff, true },
	{ 1,                     0xffffffffffffffff, true },
	{ 2,                     0xffffffffffffffff, false },
	{ 0x7fffffff,            0xffffffffffffffff, false },
	{ 0x80000000,            0xffffffffffffffff, false },
	{ 0xffffffff,            0xffffffffffffffff, false },
	{ 0x100000000,           0xffffffffffffffff, false },
	{ 0x200000000,           0xffffffffffffffff, false },
	{ 0x7fffffffffffffff,    0xffffffffffffffff, false },
	{ 0x8000000000000000,    0xffffffffffffffff, false },
	{ 0xffffffffffffffff,    0xffffffffffffffff, false },
	// Special case - force addition overflow case
	{ 0xffffffff,            0x100000002, false }
};

template<> TestVector< std::uint64_t, std::uint64_t, OpType::Mult>::TestVector() : current(0)
{
	this->test_cases = uint64_uint64;
	this->count = COUNTOF(uint64_uint64);
}

static const TestCase< std::uint64_t, std::uint32_t, OpType::Mult > uint64_uint32[] =
{
	{ 0,                     0, true },
	{ 1,                     0, true },
	{ 2,                     0, true },
	{ 0x7fffffff,            0, true },
	{ 0x80000000,            0, true },
	{ 0xffffffff,            0, true },
	{ 0x100000000,           0, true },
	{ 0x200000000,           0, true },
	{ 0x7fffffffffffffff,    0, true },
	{ 0x8000000000000000,    0, true },
	{ 0xffffffffffffffff,    0, true },
	{ 0,                     1, true },
	{ 1,                     1, true },
	{ 2,                     1, true },
	{ 0x7fffffff,            1, true },
	{ 0x80000000,            1, true },
	{ 0xffffffff,            1, true },
	{ 0x100000000,           1, true },
	{ 0x200000000,           1, true },
	{ 0x7fffffffffffffff,    1, true },
	{ 0x8000000000000000,    1, true },
	{ 0xffffffffffffffff,    1, true },
	{ 0,                     2, true },
	{ 1,                     2, true },
	{ 2,                     2, true },
	{ 0x7fffffff,            2, true },
	{ 0x80000000,            2, true },
	{ 0xffffffff,            2, true },
	{ 0x100000000,           2, true },
	{ 0x200000000,           2, true },
	{ 0x7fffffffffffffff,    2, true },
	{ 0x8000000000000000,    2, false },
	{ 0xffffffffffffffff,    2, false },
	{ 0,                     0x7fffffff, true },
	{ 1,                     0x7fffffff, true },
	{ 2,                     0x7fffffff, true },
	{ 0x7fffffff,            0x7fffffff, true },
	{ 0x80000000,            0x7fffffff, true },
	{ 0xffffffff,            0x7fffffff, true },
	{ 0x100000000,           0x7fffffff, true },
	{ 0x200000000,           0x7fffffff, true },
	{ 0x7fffffffffffffff,    0x7fffffff, false },
	{ 0x8000000000000000,    0x7fffffff, false },
	{ 0xffffffffffffffff,    0x7fffffff, false },
	{ 0,                     0x80000000, true },
	{ 1,                     0x80000000, true },
	{ 2,                     0x80000000, true },
	{ 0x7fffffff,            0x80000000, true },
	{ 0x80000000,            0x80000000, true },
	{ 0xffffffff,            0x80000000, true },
	{ 0x100000000,           0x80000000, true },
	{ 0x200000000,           0x80000000, false },
	{ 0x7fffffffffffffff,    0x80000000, false },
	{ 0x8000000000000000,    0x80000000, false },
	{ 0xffffffffffffffff,    0x80000000, false },
	{ 0,                     0xffffffff, true },
	{ 1,                     0xffffffff, true },
	{ 2,                     0xffffffff, true },
	{ 0x7fffffff,            0xffffffff, true },
	{ 0x80000000,            0xffffffff, true },
	{ 0xffffffff,            0xffffffff, true },
	{ 0x100000000,           0xffffffff, true },
	{ 0x200000000,           0xffffffff, false },
	{ 0x7fffffffffffffff,    0xffffffff, false },
	{ 0x8000000000000000,    0xffffffff, false },
	{ 0xffffffffffffffff,    0xffffffff, false }
};

template<> TestVector< std::uint64_t, std::uint32_t, OpType::Mult>::TestVector() : current(0)
{
	this->test_cases = uint64_uint32;
	this->count = COUNTOF(uint64_uint32);
}

static const TestCase< std::uint64_t, std::int64_t, OpType::Mult > uint64_int64[] =
{
	{ 0,                     0, true },
	{ 1,                     0, true },
	{ 2,                     0, true },
	{ 0x7fffffff,            0, true },
	{ 0x80000000,            0, true },
	{ 0xffffffff,            0, true },
	{ 0x100000000,           0, true },
	{ 0x200000000,           0, true },
	{ 0x7fffffffffffffff,    0, true },
	{ 0x8000000000000000,    0, true },
	{ 0xffffffffffffffff,    0, true },
	{ 0,                     1, true },
	{ 1,                     1, true },
	{ 2,                     1, true },
	{ 0x7fffffff,            1, true },
	{ 0x80000000,            1, true },
	{ 0xffffffff,            1, true },
	{ 0x100000000,           1, true },
	{ 0x200000000,           1, true },
	{ 0x7fffffffffffffff,    1, true },
	{ 0x8000000000000000,    1, true },
	{ 0xffffffffffffffff,    1, true },
	{ 0,                     2, true },
	{ 1,                     2, true },
	{ 2,                     2, true },
	{ 0x7fffffff,            2, true },
	{ 0x80000000,            2, true },
	{ 0xffffffff,            2, true },
	{ 0x100000000,           2, true },
	{ 0x200000000,           2, true },
	{ 0x7fffffffffffffff,    2, true },
	{ 0x8000000000000000,    2, false },
	{ 0xffffffffffffffff,    2, false },
	{ 0,                     0x7fffffff, true },
	{ 1,                     0x7fffffff, true },
	{ 2,                     0x7fffffff, true },
	{ 0x7fffffff,            0x7fffffff, true },
	{ 0x80000000,            0x7fffffff, true },
	{ 0xffffffff,            0x7fffffff, true },
	{ 0x100000000,           0x7fffffff, true },
	{ 0x200000000,           0x7fffffff, true },
	{ 0x7fffffffffffffff,    0x7fffffff, false },
	{ 0x8000000000000000,    0x7fffffff, false },
	{ 0xffffffffffffffff,    0x7fffffff, false },
	{ 0,                     0x80000000, true },
	{ 1,                     0x80000000, true },
	{ 2,                     0x80000000, true },
	{ 0x7fffffff,            0x80000000, true },
	{ 0x80000000,            0x80000000, true },
	{ 0xffffffff,            0x80000000, true },
	{ 0x100000000,           0x80000000, true },
	{ 0x200000000,           0x80000000, false },
	{ 0x7fffffffffffffff,    0x80000000, false },
	{ 0x8000000000000000,    0x80000000, false },
	{ 0xffffffffffffffff,    0x80000000, false },
	{ 0,                     0xffffffff, true },
	{ 1,                     0xffffffff, true },
	{ 2,                     0xffffffff, true },
	{ 0x7fffffff,            0xffffffff, true },
	{ 0x80000000,            0xffffffff, true },
	{ 0xffffffff,            0xffffffff, true },
	{ 0x100000000,           0xffffffff, true },
	{ 0x200000000,           0xffffffff, false },
	{ 0x7fffffffffffffff,    0xffffffff, false },
	{ 0x8000000000000000,    0xffffffff, false },
	{ 0xffffffffffffffff,    0xffffffff, false },
	{ 0,                     0x100000000, true },
	{ 1,                     0x100000000, true },
	{ 2,                     0x100000000, true },
	{ 0x7fffffff,            0x100000000, true },
	{ 0x80000000,            0x100000000, true },
	{ 0xffffffff,            0x100000000, true },
	{ 0x100000000,           0x100000000, false },
	{ 0x200000000,           0x100000000, false },
	{ 0x7fffffffffffffff,    0x100000000, false },
	{ 0x8000000000000000,    0x100000000, false },
	{ 0xffffffffffffffff,    0x100000000, false },
	{ 0,                     0x200000000, true },
	{ 1,                     0x200000000, true },
	{ 2,                     0x200000000, true },
	{ 0x7fffffff,            0x200000000, true },
	{ 0x80000000,            0x200000000, false },
	{ 0xffffffff,            0x200000000, false },
	{ 0x100000000,           0x200000000, false },
	{ 0x200000000,           0x200000000, false },
	{ 0x7fffffffffffffff,    0x200000000, false },
	{ 0x8000000000000000,    0x200000000, false },
	{ 0xffffffffffffffff,    0x200000000, false },
	{ 0,                     0x7fffffffffffffff, true },
	{ 1,                     0x7fffffffffffffff, true },
	{ 2,                     0x7fffffffffffffff, true },
	{ 0x7fffffff,            0x7fffffffffffffff, false },
	{ 0x80000000,            0x7fffffffffffffff, false },
	{ 0xffffffff,            0x7fffffffffffffff, false },
	{ 0x100000000,           0x7fffffffffffffff, false },
	{ 0x200000000,           0x7fffffffffffffff, false },
	{ 0x7fffffffffffffff,    0x7fffffffffffffff, false },
	{ 0x8000000000000000,    0x7fffffffffffffff, false },
	{ 0xffffffffffffffff,    0x7fffffffffffffff, false },
	{ 0,                     (std::int64_t)0x8000000000000000, true },
	{ 1,                     (std::int64_t)0x8000000000000000, false },
	{ 2,                     (std::int64_t)0x8000000000000000, false },
	{ 0x7fffffff,            (std::int64_t)0x8000000000000000, false },
	{ 0x80000000,            (std::int64_t)0x8000000000000000, false },
	{ 0xffffffff,            (std::int64_t)0x8000000000000000, false },
	{ 0x100000000,           (std::int64_t)0x8000000000000000, false },
	{ 0x200000000,           (std::int64_t)0x8000000000000000, false },
	{ 0x7fffffffffffffff,    (std::int64_t)0x8000000000000000, false },
	{ 0x8000000000000000,    (std::int64_t)0x8000000000000000, false },
	{ 0xffffffffffffffff,    (std::int64_t)0x8000000000000000, false },
	{ 0,                     (std::int64_t)0xffffffffffffffff, true },
	{ 1,                     (std::int64_t)0xffffffffffffffff, false },
	{ 2,                     (std::int64_t)0xffffffffffffffff, false },
	{ 0x7fffffff,            (std::int64_t)0xffffffffffffffff, false },
	{ 0x80000000,            (std::int64_t)0xffffffffffffffff, false },
	{ 0xffffffff,            (std::int64_t)0xffffffffffffffff, false },
	{ 0x100000000,           (std::int64_t)0xffffffffffffffff, false },
	{ 0x200000000,           (std::int64_t)0xffffffffffffffff, false },
	{ 0x7fffffffffffffff,    (std::int64_t)0xffffffffffffffff, false },
	{ 0x8000000000000000,    (std::int64_t)0xffffffffffffffff, false },
	{ 0xffffffffffffffff,    (std::int64_t)0xffffffffffffffff, false }
};

template<> TestVector< std::uint64_t, std::int64_t, OpType::Mult>::TestVector() : current(0)
{
	this->test_cases = uint64_int64;
	this->count = COUNTOF(uint64_int64);
}

static const TestCase< std::uint64_t, std::int32_t, OpType::Mult > uint64_int32[] =
{
	{ 0,                     0, true },
	{ 1,                     0, true },
	{ 2,                     0, true },
	{ 0x7fffffff,            0, true },
	{ 0x80000000,            0, true },
	{ 0xffffffff,            0, true },
	{ 0x100000000,           0, true },
	{ 0x200000000,           0, true },
	{ 0x7fffffffffffffff,    0, true },
	{ 0x8000000000000000,    0, true },
	{ 0xffffffffffffffff,    0, true },
	{ 0,                     1, true },
	{ 1,                     1, true },
	{ 2,                     1, true },
	{ 0x7fffffff,            1, true },
	{ 0x80000000,            1, true },
	{ 0xffffffff,            1, true },
	{ 0x100000000,           1, true },
	{ 0x200000000,           1, true },
	{ 0x7fffffffffffffff,    1, true },
	{ 0x8000000000000000,    1, true },
	{ 0xffffffffffffffff,    1, true },
	{ 0,                     2, true },
	{ 1,                     2, true },
	{ 2,                     2, true },
	{ 0x7fffffff,            2, true },
	{ 0x80000000,            2, true },
	{ 0xffffffff,            2, true },
	{ 0x100000000,           2, true },
	{ 0x200000000,           2, true },
	{ 0x7fffffffffffffff,    2, true },
	{ 0x8000000000000000,    2, false },
	{ 0xffffffffffffffff,    2, false },
	{ 0,                     0x7fffffff, true },
	{ 1,                     0x7fffffff, true },
	{ 2,                     0x7fffffff, true },
	{ 0x7fffffff,            0x7fffffff, true },
	{ 0x80000000,            0x7fffffff, true },
	{ 0xffffffff,            0x7fffffff, true },
	{ 0x100000000,           0x7fffffff, true },
	{ 0x200000000,           0x7fffffff, true },
	{ 0x7fffffffffffffff,    0x7fffffff, false },
	{ 0x8000000000000000,    0x7fffffff, false },
	{ 0xffffffffffffffff,    0x7fffffff, false },
	{ 0,                     (std::int32_t)0x80000000, true },
	{ 1,                     (std::int32_t)0x80000000, false },
	{ 2,                     (std::int32_t)0x80000000, false },
	{ 0x7fffffff,            (std::int32_t)0x80000000, false },
	{ 0x80000000,            (std::int32_t)0x80000000, false },
	{ 0xffffffff,            (std::int32_t)0x80000000, false },
	{ 0x100000000,           (std::int32_t)0x80000000, false },
	{ 0x200000000,           (std::int32_t)0x80000000, false },
	{ 0x7fffffffffffffff,    (std::int32_t)0x80000000, false },
	{ 0x8000000000000000,    (std::int32_t)0x80000000, false },
	{ 0xffffffffffffffff,    (std::int32_t)0x80000000, false },
	{ 0,                     (std::int32_t)0xffffffff, true },
	{ 1,                     (std::int32_t)0xffffffff, false },
	{ 2,                     (std::int32_t)0xffffffff, false },
	{ 0x7fffffff,            (std::int32_t)0xffffffff, false },
	{ 0x80000000,            (std::int32_t)0xffffffff, false },
	{ 0xffffffff,            (std::int32_t)0xffffffff, false },
	{ 0x100000000,           (std::int32_t)0xffffffff, false },
	{ 0x200000000,           (std::int32_t)0xffffffff, false },
	{ 0x7fffffffffffffff,    (std::int32_t)0xffffffff, false },
	{ 0x8000000000000000,    (std::int32_t)0xffffffff, false },
	{ 0xffffffffffffffff,    (std::int32_t)0xffffffff, false }
};

template<> TestVector< std::uint64_t, std::int32_t, OpType::Mult>::TestVector() : current(0)
{
	this->test_cases = uint64_int32;
	this->count = COUNTOF(uint64_int32);
}

static const TestCase< std::int64_t, std::uint64_t, OpType::Mult > int64_uint64[] =
{
	{ (std::int64_t)0,                     0, true },
	{ (std::int64_t)1,                     0, true },
	{ (std::int64_t)2,                     0, true },
	{ (std::int64_t)0x7fffffff,            0, true },
	{ (std::int64_t)0x80000000,            0, true },
	{ (std::int64_t)0xffffffff,            0, true },
	{ (std::int64_t)0x100000000,           0, true },
	{ (std::int64_t)0x200000000,           0, true },
	{ (std::int64_t)0x7fffffffffffffff,    0, true },
	{ (std::int64_t)0x8000000000000000,    0, true },
	{ (std::int64_t)0xffffffffffffffff,    0, true },
	{ (std::int64_t)0,                     1, true },
	{ (std::int64_t)1,                     1, true },
	{ (std::int64_t)2,                     1, true },
	{ (std::int64_t)0x7fffffff,            1, true },
	{ (std::int64_t)0x80000000,            1, true },
	{ (std::int64_t)0xffffffff,            1, true },
	{ (std::int64_t)0x100000000,           1, true },
	{ (std::int64_t)0x200000000,           1, true },
	{ (std::int64_t)0x7fffffffffffffff,    1, true },
	{ (std::int64_t)0x8000000000000000,    1, true },
	{ (std::int64_t)0xffffffffffffffff,    1, true },
	{ (std::int64_t)0,                     2, true },
	{ (std::int64_t)1,                     2, true },
	{ (std::int64_t)2,                     2, true },
	{ (std::int64_t)0x7fffffff,            2, true },
	{ (std::int64_t)0x80000000,            2, true },
	{ (std::int64_t)0xffffffff,            2, true },
	{ (std::int64_t)0x100000000,           2, true },
	{ (std::int64_t)0x200000000,           2, true },
	{ (std::int64_t)0x7fffffffffffffff,    2, false },
	{ (std::int64_t)0x8000000000000000,    2, false },
	{ (std::int64_t)0xffffffffffffffff,    2, true },
	{ (std::int64_t)0,                     0x7fffffff, true },
	{ (std::int64_t)1,                     0x7fffffff, true },
	{ (std::int64_t)2,                     0x7fffffff, true },
	{ (std::int64_t)0x7fffffff,            0x7fffffff, true },
	{ (std::int64_t)0x80000000,            0x7fffffff, true },
	{ (std::int64_t)0xffffffff,            0x7fffffff, true },
	{ (std::int64_t)0x100000000,           0x7fffffff, true },
	{ (std::int64_t)0x200000000,           0x7fffffff, false },
	{ (std::int64_t)0x7fffffffffffffff,    0x7fffffff, false },
	{ (std::int64_t)0x8000000000000000,    0x7fffffff, false },
	{ (std::int64_t)0xffffffffffffffff,    0x7fffffff, true },
	{ (std::int64_t)0,                     0x80000000, true },
	{ (std::int64_t)1,                     0x80000000, true },
	{ (std::int64_t)2,                     0x80000000, true },
	{ (std::int64_t)0x7fffffff,            0x80000000, true },
	{ (std::int64_t)0x80000000,            0x80000000, true },
	{ (std::int64_t)0xffffffff,            0x80000000, true },
	{ (std::int64_t)0x100000000,           0x80000000, false },
	{ (std::int64_t)0x200000000,           0x80000000, false },
	{ (std::int64_t)0x7fffffffffffffff,    0x80000000, false },
	{ (std::int64_t)0x8000000000000000,    0x80000000, false },
	{ (std::int64_t)0xffffffffffffffff,    0x80000000, true },
	{ (std::int64_t)0,                     0xffffffff, true },
	{ (std::int64_t)1,                     0xffffffff, true },
	{ (std::int64_t)2,                     0xffffffff, true },
	{ (std::int64_t)0x7fffffff,            0xffffffff, true },
	{ (std::int64_t)0x80000000,            0xffffffff, true },
	{ (std::int64_t)0xffffffff,            0xffffffff, false },
	{ (std::int64_t)0x100000000,           0xffffffff, false },
	{ (std::int64_t)0x200000000,           0xffffffff, false },
	{ (std::int64_t)0x7fffffffffffffff,    0xffffffff, false },
	{ (std::int64_t)0x8000000000000000,    0xffffffff, false },
	{ (std::int64_t)0xffffffffffffffff,    0xffffffff, true },
	{ (std::int64_t)0,                     0x100000000, true },
	{ (std::int64_t)1,                     0x100000000, true },
	{ (std::int64_t)2,                     0x100000000, true },
	{ (std::int64_t)0x7fffffff,            0x100000000, true },
	{ (std::int64_t)0x80000000,            0x100000000, false },
	{ (std::int64_t)0xffffffff,            0x100000000, false },
	{ (std::int64_t)0x100000000,           0x100000000, false },
	{ (std::int64_t)0x200000000,           0x100000000, false },
	{ (std::int64_t)0x7fffffffffffffff,    0x100000000, false },
	{ (std::int64_t)0x8000000000000000,    0x100000000, false },
	{ (std::int64_t)0xffffffffffffffff,    0x100000000, true },
	{ (std::int64_t)0,                     0x200000000, true },
	{ (std::int64_t)1,                     0x200000000, true },
	{ (std::int64_t)2,                     0x200000000, true },
	{ (std::int64_t)0x7fffffff,            0x200000000, false },
	{ (std::int64_t)0x80000000,            0x200000000, false },
	{ (std::int64_t)0xffffffff,            0x200000000, false },
	{ (std::int64_t)0x100000000,           0x200000000, false },
	{ (std::int64_t)0x200000000,           0x200000000, false },
	{ (std::int64_t)0x7fffffffffffffff,    0x200000000, false },
	{ (std::int64_t)0x8000000000000000,    0x200000000, false },
	{ (std::int64_t)0xffffffffffffffff,    0x200000000, true },
	{ (std::int64_t)0,                     0x7fffffffffffffff, true },
	{ (std::int64_t)1,                     0x7fffffffffffffff, true },
	{ (std::int64_t)2,                     0x7fffffffffffffff, false },
	{ (std::int64_t)0x7fffffff,            0x7fffffffffffffff, false },
	{ (std::int64_t)0x80000000,            0x7fffffffffffffff, false },
	{ (std::int64_t)0xffffffff,            0x7fffffffffffffff, false },
	{ (std::int64_t)0x100000000,           0x7fffffffffffffff, false },
	{ (std::int64_t)0x200000000,           0x7fffffffffffffff, false },
	{ (std::int64_t)0x7fffffffffffffff,    0x7fffffffffffffff, false },
	{ (std::int64_t)0x8000000000000000,    0x7fffffffffffffff, false },
	{ (std::int64_t)0xffffffffffffffff,    0x7fffffffffffffff, true },
	{ (std::int64_t)0,                     0x8000000000000000, true },
	{ (std::int64_t)1,                     0x8000000000000000, false },
	{ (std::int64_t)2,                     0x8000000000000000, false },
	{ (std::int64_t)0x7fffffff,            0x8000000000000000, false },
	{ (std::int64_t)0x80000000,            0x8000000000000000, false },
	{ (std::int64_t)0xffffffff,            0x8000000000000000, false },
	{ (std::int64_t)0x100000000,           0x8000000000000000, false },
	{ (std::int64_t)0x200000000,           0x8000000000000000, false },
	{ (std::int64_t)0x7fffffffffffffff,    0x8000000000000000, false },
	{ (std::int64_t)0x8000000000000000,    0x8000000000000000, false },
	{ (std::int64_t)0xffffffffffffffff,    0x8000000000000000, true },
	{ (std::int64_t)0,                     0xffffffffffffffff, true },
	{ (std::int64_t)1,                     0xffffffffffffffff, false },
	{ (std::int64_t)2,                     0xffffffffffffffff, false },
	{ (std::int64_t)0x7fffffff,            0xffffffffffffffff, false },
	{ (std::int64_t)0x80000000,            0xffffffffffffffff, false },
	{ (std::int64_t)0xffffffff,            0xffffffffffffffff, false },
	{ (std::int64_t)0x100000000,           0xffffffffffffffff, false },
	{ (std::int64_t)0x200000000,           0xffffffffffffffff, false },
	{ (std::int64_t)0x7fffffffffffffff,    0xffffffffffffffff, false },
	{ (std::int64_t)0x8000000000000000,    0xffffffffffffffff, false },
	{ (std::int64_t)0xffffffffffffffff,    0xffffffffffffffff, false },
	// Special case - force addition overflow case
	{ (std::int64_t)0xffffffff,            0x100000002, false }
};

template<> TestVector< std::int64_t, std::uint64_t, OpType::Mult>::TestVector() : current(0)
{
	this->test_cases = int64_uint64;
	this->count = COUNTOF(int64_uint64);
}

static const TestCase< std::int64_t, std::uint32_t, OpType::Mult > int64_uint32[] =
{
	{ (std::int64_t)0,                     0, true },
	{ (std::int64_t)1,                     0, true },
	{ (std::int64_t)2,                     0, true },
	{ (std::int64_t)0x7fffffff,            0, true },
	{ (std::int64_t)0x80000000,            0, true },
	{ (std::int64_t)0xffffffff,            0, true },
	{ (std::int64_t)0x100000000,           0, true },
	{ (std::int64_t)0x200000000,           0, true },
	{ (std::int64_t)0x7fffffffffffffff,    0, true },
	{ (std::int64_t)0x8000000000000000,    0, true },
	{ (std::int64_t)0xffffffffffffffff,    0, true },
	{ (std::int64_t)0,                     1, true },
	{ (std::int64_t)1,                     1, true },
	{ (std::int64_t)2,                     1, true },
	{ (std::int64_t)0x7fffffff,            1, true },
	{ (std::int64_t)0x80000000,            1, true },
	{ (std::int64_t)0xffffffff,            1, true },
	{ (std::int64_t)0x100000000,           1, true },
	{ (std::int64_t)0x200000000,           1, true },
	{ (std::int64_t)0x7fffffffffffffff,    1, true },
	{ (std::int64_t)0x8000000000000000,    1, true },
	{ (std::int64_t)0xffffffffffffffff,    1, true },
	{ (std::int64_t)0,                     2, true },
	{ (std::int64_t)1,                     2, true },
	{ (std::int64_t)2,                     2, true },
	{ (std::int64_t)0x7fffffff,            2, true },
	{ (std::int64_t)0x80000000,            2, true },
	{ (std::int64_t)0xffffffff,            2, true },
	{ (std::int64_t)0x100000000,           2, true },
	{ (std::int64_t)0x200000000,           2, true },
	{ (std::int64_t)0x7fffffffffffffff,    2, false },
	{ (std::int64_t)0x8000000000000000,    2, false },
	{ (std::int64_t)0xffffffffffffffff,    2, true },
	{ (std::int64_t)0,                     0x7fffffff, true },
	{ (std::int64_t)1,                     0x7fffffff, true },
	{ (std::int64_t)2,                     0x7fffffff, true },
	{ (std::int64_t)0x7fffffff,            0x7fffffff, true },
	{ (std::int64_t)0x80000000,            0x7fffffff, true },
	{ (std::int64_t)0xffffffff,            0x7fffffff, true },
	{ (std::int64_t)0x100000000,           0x7fffffff, true },
	{ (std::int64_t)0x200000000,           0x7fffffff, false },
	{ (std::int64_t)0x7fffffffffffffff,    0x7fffffff, false },
	{ (std::int64_t)0x8000000000000000,    0x7fffffff, false },
	{ (std::int64_t)0xffffffffffffffff,    0x7fffffff, true },
	{ (std::int64_t)0,                     0x80000000, true },
	{ (std::int64_t)1,                     0x80000000, true },
	{ (std::int64_t)2,                     0x80000000, true },
	{ (std::int64_t)0x7fffffff,            0x80000000, true },
	{ (std::int64_t)0x80000000,            0x80000000, true },
	{ (std::int64_t)0xffffffff,            0x80000000, true },
	{ (std::int64_t)0x100000000,           0x80000000, false },
	{ (std::int64_t)0x200000000,           0x80000000, false },
	{ (std::int64_t)0x7fffffffffffffff,    0x80000000, false },
	{ (std::int64_t)0x8000000000000000,    0x80000000, false },
	{ (std::int64_t)0xffffffffffffffff,    0x80000000, true },
	{ (std::int64_t)0,                     0xffffffff, true },
	{ (std::int64_t)1,                     0xffffffff, true },
	{ (std::int64_t)2,                     0xffffffff, true },
	{ (std::int64_t)0x7fffffff,            0xffffffff, true },
	{ (std::int64_t)0x80000000,            0xffffffff, true },
	{ (std::int64_t)0xffffffff,            0xffffffff, false },
	{ (std::int64_t)0x100000000,           0xffffffff, false },
	{ (std::int64_t)0x200000000,           0xffffffff, false },
	{ (std::int64_t)0x7fffffffffffffff,    0xffffffff, false },
	{ (std::int64_t)0x8000000000000000,    0xffffffff, false },
	{ (std::int64_t)0xffffffffffffffff,    0xffffffff, true }
};

template<> TestVector< std::int64_t, std::uint32_t, OpType::Mult>::TestVector() : current(0)
{
	this->test_cases = int64_uint32;
	this->count = COUNTOF(int64_uint32);
}

static const TestCase< std::int64_t, std::int64_t, OpType::Mult > int64_int64[] =
{
	{ (std::int64_t)0,                     0, true },
	{ (std::int64_t)1,                     0, true },
	{ (std::int64_t)2,                     0, true },
	{ (std::int64_t)0x7fffffff,            0, true },
	{ (std::int64_t)0x80000000,            0, true },
	{ (std::int64_t)0xffffffff,            0, true },
	{ (std::int64_t)0x100000000,           0, true },
	{ (std::int64_t)0x200000000,           0, true },
	{ (std::int64_t)0x7fffffffffffffff,    0, true },
	{ (std::int64_t)0x8000000000000000,    0, true },
	{ (std::int64_t)0xffffffffffffffff,    0, true },
	{ (std::int64_t)0,                     1, true },
	{ (std::int64_t)1,                     1, true },
	{ (std::int64_t)2,                     1, true },
	{ (std::int64_t)0x7fffffff,            1, true },
	{ (std::int64_t)0x80000000,            1, true },
	{ (std::int64_t)0xffffffff,            1, true },
	{ (std::int64_t)0x100000000,           1, true },
	{ (std::int64_t)0x200000000,           1, true },
	{ (std::int64_t)0x7fffffffffffffff,    1, true },
	{ (std::int64_t)0x8000000000000000,    1, true },
	{ (std::int64_t)0xffffffffffffffff,    1, true },
	{ (std::int64_t)0,                     2, true },
	{ (std::int64_t)1,                     2, true },
	{ (std::int64_t)2,                     2, true },
	{ (std::int64_t)0x7fffffff,            2, true },
	{ (std::int64_t)0x80000000,            2, true },
	{ (std::int64_t)0xffffffff,            2, true },
	{ (std::int64_t)0x100000000,           2, true },
	{ (std::int64_t)0x200000000,           2, true },
	{ (std::int64_t)0x7fffffffffffffff,    2, false },
	{ (std::int64_t)0x8000000000000000,    2, false },
	{ (std::int64_t)0xffffffffffffffff,    2, true },
	{ (std::int64_t)0,                     0x7fffffff, true },
	{ (std::int64_t)1,                     0x7fffffff, true },
	{ (std::int64_t)2,                     0x7fffffff, true },
	{ (std::int64_t)0x7fffffff,            0x7fffffff, true },
	{ (std::int64_t)0x80000000,            0x7fffffff, true },
	{ (std::int64_t)0xffffffff,            0x7fffffff, true },
	{ (std::int64_t)0x100000000,           0x7fffffff, true },
	{ (std::int64_t)0x200000000,           0x7fffffff, false },
	{ (std::int64_t)0x7fffffffffffffff,    0x7fffffff, false },
	{ (std::int64_t)0x8000000000000000,    0x7fffffff, false },
	{ (std::int64_t)0xffffffffffffffff,    0x7fffffff, true },
	{ (std::int64_t)0,                     0x80000000, true },
	{ (std::int64_t)1,                     0x80000000, true },
	{ (std::int64_t)2,                     0x80000000, true },
	{ (std::int64_t)0x7fffffff,            0x80000000, true },
	{ (std::int64_t)0x80000000,            0x80000000, true },
	{ (std::int64_t)0xffffffff,            0x80000000, true },
	{ (std::int64_t)0x100000000,           0x80000000, false },
	{ (std::int64_t)0x200000000,           0x80000000, false },
	{ (std::int64_t)0x7fffffffffffffff,    0x80000000, false },
	{ (std::int64_t)0x8000000000000000,    0x80000000, false },
	{ (std::int64_t)0xffffffffffffffff,    0x80000000, true },
	{ (std::int64_t)0,                     0xffffffff, true },
	{ (std::int64_t)1,                     0xffffffff, true },
	{ (std::int64_t)2,                     0xffffffff, true },
	{ (std::int64_t)0x7fffffff,            0xffffffff, true },
	{ (std::int64_t)0x80000000,            0xffffffff, true },
	{ (std::int64_t)0xffffffff,            0xffffffff, false },
	{ (std::int64_t)0x100000000,           0xffffffff, false },
	{ (std::int64_t)0x200000000,           0xffffffff, false },
	{ (std::int64_t)0x7fffffffffffffff,    0xffffffff, false },
	{ (std::int64_t)0x8000000000000000,    0xffffffff, false },
	{ (std::int64_t)0xffffffffffffffff,    0xffffffff, true },
	{ (std::int64_t)0,                     0x100000000, true },
	{ (std::int64_t)1,                     0x100000000, true },
	{ (std::int64_t)2,                     0x100000000, true },
	{ (std::int64_t)0x7fffffff,            0x100000000, true },
	{ (std::int64_t)0x80000000,            0x100000000, false },
	{ (std::int64_t)0xffffffff,            0x100000000, false },
	{ (std::int64_t)0x100000000,           0x100000000, false },
	{ (std::int64_t)0x200000000,           0x100000000, false },
	{ (std::int64_t)0x7fffffffffffffff,    0x100000000, false },
	{ (std::int64_t)0x8000000000000000,    0x100000000, false },
	{ (std::int64_t)0xffffffffffffffff,    0x100000000, true },
	{ (std::int64_t)0,                     0x200000000, true },
	{ (std::int64_t)1,                     0x200000000, true },
	{ (std::int64_t)2,                     0x200000000, true },
	{ (std::int64_t)0x7fffffff,            0x200000000, false },
	{ (std::int64_t)0x80000000,            0x200000000, false },
	{ (std::int64_t)0xffffffff,            0x200000000, false },
	{ (std::int64_t)0x100000000,           0x200000000, false },
	{ (std::int64_t)0x200000000,           0x200000000, false },
	{ (std::int64_t)0x7fffffffffffffff,    0x200000000, false },
	{ (std::int64_t)0x8000000000000000,    0x200000000, false },
	{ (std::int64_t)0xffffffffffffffff,    0x200000000, true },
	{ (std::int64_t)0,                     0x7fffffffffffffff, true },
	{ (std::int64_t)1,                     0x7fffffffffffffff, true },
	{ (std::int64_t)2,                     0x7fffffffffffffff, false },
	{ (std::int64_t)0x7fffffff,            0x7fffffffffffffff, false },
	{ (std::int64_t)0x80000000,            0x7fffffffffffffff, false },
	{ (std::int64_t)0xffffffff,            0x7fffffffffffffff, false },
	{ (std::int64_t)0x100000000,           0x7fffffffffffffff, false },
	{ (std::int64_t)0x200000000,           0x7fffffffffffffff, false },
	{ (std::int64_t)0x7fffffffffffffff,    0x7fffffffffffffff, false },
	{ (std::int64_t)0x8000000000000000,    0x7fffffffffffffff, false },
	{ (std::int64_t)0xffffffffffffffff,    0x7fffffffffffffff, true },
	{ (std::int64_t)0,                     (std::int64_t)0x8000000000000000, true },
	{ (std::int64_t)1,                     (std::int64_t)0x8000000000000000, true },
	{ (std::int64_t)2,                     (std::int64_t)0x8000000000000000, false },
	{ (std::int64_t)0x7fffffff,            (std::int64_t)0x8000000000000000, false },
	{ (std::int64_t)0x80000000,            (std::int64_t)0x8000000000000000, false },
	{ (std::int64_t)0xffffffff,            (std::int64_t)0x8000000000000000, false },
	{ (std::int64_t)0x100000000,           (std::int64_t)0x8000000000000000, false },
	{ (std::int64_t)0x200000000,           (std::int64_t)0x8000000000000000, false },
	{ (std::int64_t)0x7fffffffffffffff,    (std::int64_t)0x8000000000000000, false },
	{ (std::int64_t)0x8000000000000000,    (std::int64_t)0x8000000000000000, false },
	{ (std::int64_t)0xffffffffffffffff,    (std::int64_t)0x8000000000000000, false },
	{ (std::int64_t)0,                     (std::int64_t)0xffffffffffffffff, true },
	{ (std::int64_t)1,                     (std::int64_t)0xffffffffffffffff, true },
	{ (std::int64_t)2,                     (std::int64_t)0xffffffffffffffff, true },
	{ (std::int64_t)0x7fffffff,            (std::int64_t)0xffffffffffffffff, true },
	{ (std::int64_t)0x80000000,            (std::int64_t)0xffffffffffffffff, true },
	{ (std::int64_t)0xffffffff,            (std::int64_t)0xffffffffffffffff, true },
	{ (std::int64_t)0x100000000,           (std::int64_t)0xffffffffffffffff, true },
	{ (std::int64_t)0x200000000,           (std::int64_t)0xffffffffffffffff, true },
	{ (std::int64_t)0x7fffffffffffffff,    (std::int64_t)0xffffffffffffffff, true },
	{ (std::int64_t)0x8000000000000000,    (std::int64_t)0xffffffffffffffff, false },
	{ (std::int64_t)0xffffffffffffffff,    (std::int64_t)0xffffffffffffffff, true },
	// Special case - force addition overflow case
	{ (std::int64_t)0xffffffff,            0x100000002, false }
};

template<> TestVector< std::int64_t, std::int64_t, OpType::Mult>::TestVector() : current(0)
{
	this->test_cases = int64_int64;
	this->count = COUNTOF(int64_int64);
}

static const TestCase< std::int64_t, std::int32_t, OpType::Mult > int64_int32[] =
{
	{ (std::int64_t)0,                     0, true },
	{ (std::int64_t)1,                     0, true },
	{ (std::int64_t)2,                     0, true },
	{ (std::int64_t)0x7fffffff,            0, true },
	{ (std::int64_t)0x80000000,            0, true },
	{ (std::int64_t)0xffffffff,            0, true },
	{ (std::int64_t)0x100000000,           0, true },
	{ (std::int64_t)0x200000000,           0, true },
	{ (std::int64_t)0x7fffffffffffffff,    0, true },
	{ (std::int64_t)0x8000000000000000,    0, true },
	{ (std::int64_t)0xffffffffffffffff,    0, true },
	{ (std::int64_t)0,                     1, true },
	{ (std::int64_t)1,                     1, true },
	{ (std::int64_t)2,                     1, true },
	{ (std::int64_t)0x7fffffff,            1, true },
	{ (std::int64_t)0x80000000,            1, true },
	{ (std::int64_t)0xffffffff,            1, true },
	{ (std::int64_t)0x100000000,           1, true },
	{ (std::int64_t)0x200000000,           1, true },
	{ (std::int64_t)0x7fffffffffffffff,    1, true },
	{ (std::int64_t)0x8000000000000000,    1, true },
	{ (std::int64_t)0xffffffffffffffff,    1, true },
	{ (std::int64_t)0,                     2, true },
	{ (std::int64_t)1,                     2, true },
	{ (std::int64_t)2,                     2, true },
	{ (std::int64_t)0x7fffffff,            2, true },
	{ (std::int64_t)0x80000000,            2, true },
	{ (std::int64_t)0xffffffff,            2, true },
	{ (std::int64_t)0x100000000,           2, true },
	{ (std::int64_t)0x200000000,           2, true },
	{ (std::int64_t)0x7fffffffffffffff,    2, false },
	{ (std::int64_t)0x8000000000000000,    2, false },
	{ (std::int64_t)0xffffffffffffffff,    2, true },
	{ (std::int64_t)0,                     0x7fffffff, true },
	{ (std::int64_t)1,                     0x7fffffff, true },
	{ (std::int64_t)2,                     0x7fffffff, true },
	{ (std::int64_t)0x7fffffff,            0x7fffffff, true },
	{ (std::int64_t)0x80000000,            0x7fffffff, true },
	{ (std::int64_t)0xffffffff,            0x7fffffff, true },
	{ (std::int64_t)0x100000000,           0x7fffffff, true },
	{ (std::int64_t)0x200000000,           0x7fffffff, false },
	{ (std::int64_t)0x7fffffffffffffff,    0x7fffffff, false },
	{ (std::int64_t)0x8000000000000000,    0x7fffffff, false },
	{ (std::int64_t)0xffffffffffffffff,    0x7fffffff, true },
	{ (std::int64_t)0,                     (std::int32_t)0x80000000, true },
	{ (std::int64_t)1,                     (std::int32_t)0x80000000, true },
	{ (std::int64_t)2,                     (std::int32_t)0x80000000, true },
	{ (std::int64_t)0x7fffffff,            (std::int32_t)0x80000000, true },
	{ (std::int64_t)0x80000000,            (std::int32_t)0x80000000, true },
	{ (std::int64_t)0xffffffff,            (std::int32_t)0x80000000, true },
	{ (std::int64_t)0x100000000,           (std::int32_t)0x80000000, true },
	{ (std::int64_t)0x200000000,           (std::int32_t)0x80000000, false },
	{ (std::int64_t)0x7fffffffffffffff,    (std::int32_t)0x80000000, false },
	{ (std::int64_t)0x8000000000000000,    (std::int32_t)0x80000000, false },
	{ (std::int64_t)0xffffffffffffffff,    (std::int32_t)0x80000000, true },
	{ (std::int64_t)0,                     (std::int32_t)0xffffffff, true },
	{ (std::int64_t)1,                     (std::int32_t)0xffffffff, true },
	{ (std::int64_t)2,                     (std::int32_t)0xffffffff, true },
	{ (std::int64_t)0x7fffffff,            (std::int32_t)0xffffffff, true },
	{ (std::int64_t)0x80000000,            (std::int32_t)0xffffffff, true },
	{ (std::int64_t)0xffffffff,            (std::int32_t)0xffffffff, true },
	{ (std::int64_t)0x100000000,           (std::int32_t)0xffffffff, true },
	{ (std::int64_t)0x200000000,           (std::int32_t)0xffffffff, true },
	{ (std::int64_t)0x7fffffffffffffff,    (std::int32_t)0xffffffff, true },
	{ (std::int64_t)0x8000000000000000,    (std::int32_t)0xffffffff, false },
	{ (std::int64_t)0xffffffffffffffff,    (std::int32_t)0xffffffff, true }
};

template<> TestVector< std::int64_t, std::int32_t, OpType::Mult>::TestVector() : current(0)
{
	this->test_cases = int64_int32;
	this->count = COUNTOF(int64_int32);
}

static const TestCase< std::uint32_t, std::uint64_t, OpType::Mult > uint32_uint64[] =
{
	{ 0,                     0, true },
	{ 1,                     0, true },
	{ 2,                     0, true },
	{ 0x7fffffff,            0, true },
	{ 0x80000000,            0, true },
	{ 0xffffffff,            0, true },
	{ 0,                     1, true },
	{ 1,                     1, true },
	{ 2,                     1, true },
	{ 0x7fffffff,            1, true },
	{ 0x80000000,            1, true },
	{ 0xffffffff,            1, true },
	{ 0,                     2, true },
	{ 1,                     2, true },
	{ 2,                     2, true },
	{ 0x7fffffff,            2, true },
	{ 0x80000000,            2, false },
	{ 0xffffffff,            2, false },
	{ 0,                     0x7fffffff, true },
	{ 1,                     0x7fffffff, true },
	{ 2,                     0x7fffffff, true },
	{ 0x7fffffff,            0x7fffffff, false },
	{ 0x80000000,            0x7fffffff, false },
	{ 0xffffffff,            0x7fffffff, false },
	{ 0,                     0x80000000, true },
	{ 1,                     0x80000000, true },
	{ 2,                     0x80000000, false },
	{ 0x7fffffff,            0x80000000, false },
	{ 0x80000000,            0x80000000, false },
	{ 0xffffffff,            0x80000000, false },
	{ 0,                     0xffffffff, true },
	{ 1,                     0xffffffff, true },
	{ 2,                     0xffffffff, false },
	{ 0x7fffffff,            0xffffffff, false },
	{ 0x80000000,            0xffffffff, false },
	{ 0xffffffff,            0xffffffff, false },
	{ 0,                     0x100000000, true },
	{ 1,                     0x100000000, false },
	{ 2,                     0x100000000, false },
	{ 0x7fffffff,            0x100000000, false },
	{ 0x80000000,            0x100000000, false },
	{ 0xffffffff,            0x100000000, false },
	{ 0,                     0x200000000, true },
	{ 1,                     0x200000000, false },
	{ 2,                     0x200000000, false },
	{ 0x7fffffff,            0x200000000, false },
	{ 0x80000000,            0x200000000, false },
	{ 0xffffffff,            0x200000000, false },
	{ 0,                     0x7fffffffffffffff, true },
	{ 1,                     0x7fffffffffffffff, false },
	{ 2,                     0x7fffffffffffffff, false },
	{ 0x7fffffff,            0x7fffffffffffffff, false },
	{ 0x80000000,            0x7fffffffffffffff, false },
	{ 0xffffffff,            0x7fffffffffffffff, false },
	{ 0,                     0x8000000000000000, true },
	{ 1,                     0x8000000000000000, false },
	{ 2,                     0x8000000000000000, false },
	{ 0x7fffffff,            0x8000000000000000, false },
	{ 0x80000000,            0x8000000000000000, false },
	{ 0xffffffff,            0x8000000000000000, false },
	{ 0,                     0xffffffffffffffff, true },
	{ 1,                     0xffffffffffffffff, false },
	{ 2,                     0xffffffffffffffff, false },
	{ 0x7fffffff,            0xffffffffffffffff, false },
	{ 0x80000000,            0xffffffffffffffff, false },
	{ 0xffffffff,            0xffffffffffffffff, false }
};

template<> TestVector< std::uint32_t, std::uint64_t, OpType::Mult>::TestVector() : current(0)
{
	this->test_cases = uint32_uint64;
	this->count = COUNTOF(uint32_uint64);
}

static const TestCase< std::uint32_t, std::uint32_t, OpType::Mult > uint32_uint32[] =
{
	{ 0,                     0, true },
	{ 1,                     0, true },
	{ 2,                     0, true },
	{ 0x7fffffff,            0, true },
	{ 0x80000000,            0, true },
	{ 0xffffffff,            0, true },
	{ 0,                     1, true },
	{ 1,                     1, true },
	{ 2,                     1, true },
	{ 0x7fffffff,            1, true },
	{ 0x80000000,            1, true },
	{ 0xffffffff,            1, true },
	{ 0,                     2, true },
	{ 1,                     2, true },
	{ 2,                     2, true },
	{ 0x7fffffff,            2, true },
	{ 0x80000000,            2, false },
	{ 0xffffffff,            2, false },
	{ 0,                     0x7fffffff, true },
	{ 1,                     0x7fffffff, true },
	{ 2,                     0x7fffffff, true },
	{ 0x7fffffff,            0x7fffffff, false },
	{ 0x80000000,            0x7fffffff, false },
	{ 0xffffffff,            0x7fffffff, false },
	{ 0,                     0x80000000, true },
	{ 1,                     0x80000000, true },
	{ 2,                     0x80000000, false },
	{ 0x7fffffff,            0x80000000, false },
	{ 0x80000000,            0x80000000, false },
	{ 0xffffffff,            0x80000000, false },
	{ 0,                     0xffffffff, true },
	{ 1,                     0xffffffff, true },
	{ 2,                     0xffffffff, false },
	{ 0x7fffffff,            0xffffffff, false },
	{ 0x80000000,            0xffffffff, false },
	{ 0xffffffff,            0xffffffff, false },
};

template<> TestVector< std::uint32_t, std::uint32_t, OpType::Mult>::TestVector() : current(0)
{
	this->test_cases = uint32_uint32;
	this->count = COUNTOF(uint32_uint32);
}

static const TestCase< std::uint32_t, std::int64_t, OpType::Mult > uint32_int64[] =
{
	{ 0,                     0, true },
	{ 1,                     0, true },
	{ 2,                     0, true },
	{ 0x7fffffff,            0, true },
	{ 0x80000000,            0, true },
	{ 0xffffffff,            0, true },
	{ 0,                     1, true },
	{ 1,                     1, true },
	{ 2,                     1, true },
	{ 0x7fffffff,            1, true },
	{ 0x80000000,            1, true },
	{ 0xffffffff,            1, true },
	{ 0,                     2, true },
	{ 1,                     2, true },
	{ 2,                     2, true },
	{ 0x7fffffff,            2, true },
	{ 0x80000000,            2, false },
	{ 0xffffffff,            2, false },
	{ 0,                     0x7fffffff, true },
	{ 1,                     0x7fffffff, true },
	{ 2,                     0x7fffffff, true },
	{ 0x7fffffff,            0x7fffffff, false },
	{ 0x80000000,            0x7fffffff, false },
	{ 0xffffffff,            0x7fffffff, false },
	{ 0,                     0x80000000, true },
	{ 1,                     0x80000000, true },
	{ 2,                     0x80000000, false },
	{ 0x7fffffff,            0x80000000, false },
	{ 0x80000000,            0x80000000, false },
	{ 0xffffffff,            0x80000000, false },
	{ 0,                     0xffffffff, true },
	{ 1,                     0xffffffff, true },
	{ 2,                     0xffffffff, false },
	{ 0x7fffffff,            0xffffffff, false },
	{ 0x80000000,            0xffffffff, false },
	{ 0xffffffff,            0xffffffff, false },
	{ 0,                     0x100000000, true },
	{ 1,                     0x100000000, false },
	{ 2,                     0x100000000, false },
	{ 0x7fffffff,            0x100000000, false },
	{ 0x80000000,            0x100000000, false },
	{ 0xffffffff,            0x100000000, false },
	{ 0,                     0x200000000, true },
	{ 1,                     0x200000000, false },
	{ 2,                     0x200000000, false },
	{ 0x7fffffff,            0x200000000, false },
	{ 0x80000000,            0x200000000, false },
	{ 0xffffffff,            0x200000000, false },
	{ 0,                     0x7fffffffffffffff, true },
	{ 1,                     0x7fffffffffffffff, false },
	{ 2,                     0x7fffffffffffffff, false },
	{ 0x7fffffff,            0x7fffffffffffffff, false },
	{ 0x80000000,            0x7fffffffffffffff, false },
	{ 0xffffffff,            0x7fffffffffffffff, false },
	{ 0,                     (std::int64_t)0x8000000000000000, true },
	{ 1,                     (std::int64_t)0x8000000000000000, false },
	{ 2,                     (std::int64_t)0x8000000000000000, false },
	{ 0x7fffffff,            (std::int64_t)0x8000000000000000, false },
	{ 0x80000000,            (std::int64_t)0x8000000000000000, false },
	{ 0xffffffff,            (std::int64_t)0x8000000000000000, false },
	{ 0,                     (std::int64_t)0xffffffffffffffff, true },
	{ 1,                     (std::int64_t)0xffffffffffffffff, false },
	{ 2,                     (std::int64_t)0xffffffffffffffff, false },
	{ 0x7fffffff,            (std::int64_t)0xffffffffffffffff, false },
	{ 0x80000000,            (std::int64_t)0xffffffffffffffff, false },
	{ 0xffffffff,            (std::int64_t)0xffffffffffffffff, false }
};

template<> TestVector< std::uint32_t, std::int64_t, OpType::Mult>::TestVector() : current(0)
{
	this->test_cases = uint32_int64;
	this->count = COUNTOF(uint32_int64);
}

static const TestCase< std::uint32_t, std::int32_t, OpType::Mult > uint32_int32[] =
{
	{ 0,                     0, true },
	{ 1,                     0, true },
	{ 2,                     0, true },
	{ 0x7fffffff,            0, true },
	{ 0x80000000,            0, true },
	{ 0xffffffff,            0, true },
	{ 0,                     1, true },
	{ 1,                     1, true },
	{ 2,                     1, true },
	{ 0x7fffffff,            1, true },
	{ 0x80000000,            1, true },
	{ 0xffffffff,            1, true },
	{ 0,                     2, true },
	{ 1,                     2, true },
	{ 2,                     2, true },
	{ 0x7fffffff,            2, true },
	{ 0x80000000,            2, false },
	{ 0xffffffff,            2, false },
	{ 0,                     0x7fffffff, true },
	{ 1,                     0x7fffffff, true },
	{ 2,                     0x7fffffff, true },
	{ 0x7fffffff,            0x7fffffff, false },
	{ 0x80000000,            0x7fffffff, false },
	{ 0xffffffff,            0x7fffffff, false },
	{ 0,                     (std::int32_t)0x80000000, true },
	{ 1,                     (std::int32_t)0x80000000, false },
	{ 2,                     (std::int32_t)0x80000000, false },
	{ 0x7fffffff,            (std::int32_t)0x80000000, false },
	{ 0x80000000,            (std::int32_t)0x80000000, false },
	{ 0xffffffff,            (std::int32_t)0x80000000, false },
	{ 0,                     (std::int32_t)0xffffffff, true },
	{ 1,                     (std::int32_t)0xffffffff, false },
	{ 2,                     (std::int32_t)0xffffffff, false },
	{ 0x7fffffff,            (std::int32_t)0xffffffff, false },
	{ 0x80000000,            (std::int32_t)0xffffffff, false },
	{ 0xffffffff,            (std::int32_t)0xffffffff, false },
};

template<> TestVector< std::uint32_t, std::int32_t, OpType::Mult>::TestVector() : current(0)
{
	this->test_cases = uint32_int32;
	this->count = COUNTOF(uint32_int32);
}

static const TestCase< std::int32_t, std::uint64_t, OpType::Mult > int32_uint64[] =
{
	{ (std::int32_t)0,                     0, true },
	{ (std::int32_t)1,                     0, true },
	{ (std::int32_t)2,                     0, true },
	{ (std::int32_t)0x7fffffff,            0, true },
	{ (std::int32_t)0x80000000,            0, true },
	{ (std::int32_t)0xffffffff,            0, true },
	{ (std::int32_t)0,                     1, true },
	{ (std::int32_t)1,                     1, true },
	{ (std::int32_t)2,                     1, true },
	{ (std::int32_t)0x7fffffff,            1, true },
	{ (std::int32_t)0x80000000,            1, true },
	{ (std::int32_t)0xffffffff,            1, true },
	{ (std::int32_t)0,                     2, true },
	{ (std::int32_t)1,                     2, true },
	{ (std::int32_t)2,                     2, true },
	{ (std::int32_t)0x7fffffff,            2, false },
	{ (std::int32_t)0x80000000,            2, false },
	{ (std::int32_t)0xffffffff,            2, true },
	{ (std::int32_t)0,                     0x7fffffff, true },
	{ (std::int32_t)1,                     0x7fffffff, true },
	{ (std::int32_t)2,                     0x7fffffff, false },
	{ (std::int32_t)0x7fffffff,            0x7fffffff, false },
	{ (std::int32_t)0x80000000,            0x7fffffff, false },
	{ (std::int32_t)0xffffffff,            0x7fffffff, true },
	{ (std::int32_t)0,                     0x80000000, true },
	{ (std::int32_t)1,                     0x80000000, false },
	{ (std::int32_t)2,                     0x80000000, false },
	{ (std::int32_t)0x7fffffff,            0x80000000, false },
	{ (std::int32_t)0x80000000,            0x80000000, false },
	{ (std::int32_t)0xffffffff,            0x80000000, true },
	{ (std::int32_t)0,                     0xffffffff, true },
	{ (std::int32_t)1,                     0xffffffff, false },
	{ (std::int32_t)2,                     0xffffffff, false },
	{ (std::int32_t)0x7fffffff,            0xffffffff, false },
	{ (std::int32_t)0x80000000,            0xffffffff, false },
	{ (std::int32_t)0xffffffff,            0xffffffff, false },
	{ (std::int32_t)0,                     0x100000000, true },
	{ (std::int32_t)1,                     0x100000000, false },
	{ (std::int32_t)2,                     0x100000000, false },
	{ (std::int32_t)0x7fffffff,            0x100000000, false },
	{ (std::int32_t)0x80000000,            0x100000000, false },
	{ (std::int32_t)0xffffffff,            0x100000000, false },
	{ (std::int32_t)0,                     0x200000000, true },
	{ (std::int32_t)1,                     0x200000000, false },
	{ (std::int32_t)2,                     0x200000000, false },
	{ (std::int32_t)0x7fffffff,            0x200000000, false },
	{ (std::int32_t)0x80000000,            0x200000000, false },
	{ (std::int32_t)0xffffffff,            0x200000000, false },
	{ (std::int32_t)0,                     0x7fffffffffffffff, true },
	{ (std::int32_t)1,                     0x7fffffffffffffff, false },
	{ (std::int32_t)2,                     0x7fffffffffffffff, false },
	{ (std::int32_t)0x7fffffff,            0x7fffffffffffffff, false },
	{ (std::int32_t)0x80000000,            0x7fffffffffffffff, false },
	{ (std::int32_t)0xffffffff,            0x7fffffffffffffff, false },
	{ (std::int32_t)0,                     0x8000000000000000, true },
	{ (std::int32_t)1,                     0x8000000000000000, false },
	{ (std::int32_t)2,                     0x8000000000000000, false },
	{ (std::int32_t)0x7fffffff,            0x8000000000000000, false },
	{ (std::int32_t)0x80000000,            0x8000000000000000, false },
	{ (std::int32_t)0xffffffff,            0x8000000000000000, false },
	{ (std::int32_t)0,                     0xffffffffffffffff, true },
	{ (std::int32_t)1,                     0xffffffffffffffff, false },
	{ (std::int32_t)2,                     0xffffffffffffffff, false },
	{ (std::int32_t)0x7fffffff,            0xffffffffffffffff, false },
	{ (std::int32_t)0x80000000,            0xffffffffffffffff, false },
	{ (std::int32_t)0xffffffff,            0xffffffffffffffff, false },
	// Special case - force addition overflow case
	{ (std::int32_t)0xffffffff,            0x100000002, false }
};

template<> TestVector< std::int32_t, std::uint64_t, OpType::Mult>::TestVector() : current(0)
{
	this->test_cases = int32_uint64;
	this->count = COUNTOF(int32_uint64);
}

static const TestCase< std::int32_t, std::uint32_t, OpType::Mult > int32_uint32[] =
{
	{ (std::int32_t)0,                     0, true },
	{ (std::int32_t)1,                     0, true },
	{ (std::int32_t)2,                     0, true },
	{ (std::int32_t)0x7fffffff,            0, true },
	{ (std::int32_t)0x80000000,            0, true },
	{ (std::int32_t)0xffffffff,            0, true },
	{ (std::int32_t)0,                     1, true },
	{ (std::int32_t)1,                     1, true },
	{ (std::int32_t)2,                     1, true },
	{ (std::int32_t)0x7fffffff,            1, true },
	{ (std::int32_t)0x80000000,            1, true },
	{ (std::int32_t)0xffffffff,            1, true },
	{ (std::int32_t)0,                     2, true },
	{ (std::int32_t)1,                     2, true },
	{ (std::int32_t)2,                     2, true },
	{ (std::int32_t)0x7fffffff,            2, false },
	{ (std::int32_t)0x80000000,            2, false },
	{ (std::int32_t)0xffffffff,            2, true },
	{ (std::int32_t)0,                     0x7fffffff, true },
	{ (std::int32_t)1,                     0x7fffffff, true },
	{ (std::int32_t)2,                     0x7fffffff, false },
	{ (std::int32_t)0x7fffffff,            0x7fffffff, false },
	{ (std::int32_t)0x80000000,            0x7fffffff, false },
	{ (std::int32_t)0xffffffff,            0x7fffffff, true },
	{ (std::int32_t)0,                     0x80000000, true },
	{ (std::int32_t)1,                     0x80000000, false },
	{ (std::int32_t)2,                     0x80000000, false },
	{ (std::int32_t)0x7fffffff,            0x80000000, false },
	{ (std::int32_t)0x80000000,            0x80000000, false },
	{ (std::int32_t)0xffffffff,            0x80000000, true },
	{ (std::int32_t)0,                     0xffffffff, true },
	{ (std::int32_t)1,                     0xffffffff, false },
	{ (std::int32_t)2,                     0xffffffff, false },
	{ (std::int32_t)0x7fffffff,            0xffffffff, false },
	{ (std::int32_t)0x80000000,            0xffffffff, false },
	{ (std::int32_t)0xffffffff,            0xffffffff, false },
};

template<> TestVector< std::int32_t, std::uint32_t, OpType::Mult>::TestVector() : current(0)
{
	this->test_cases = int32_uint32;
	this->count = COUNTOF(int32_uint32);
}

static const TestCase< std::int32_t, std::int64_t, OpType::Mult > int32_int64[] =
{
	{ (std::int32_t)0,                     0, true },
	{ (std::int32_t)1,                     0, true },
	{ (std::int32_t)2,                     0, true },
	{ (std::int32_t)0x7fffffff,            0, true },
	{ (std::int32_t)0x80000000,            0, true },
	{ (std::int32_t)0xffffffff,            0, true },
	{ (std::int32_t)0,                     1, true },
	{ (std::int32_t)1,                     1, true },
	{ (std::int32_t)2,                     1, true },
	{ (std::int32_t)0x7fffffff,            1, true },
	{ (std::int32_t)0x80000000,            1, true },
	{ (std::int32_t)0xffffffff,            1, true },
	{ (std::int32_t)0,                     2, true },
	{ (std::int32_t)1,                     2, true },
	{ (std::int32_t)2,                     2, true },
	{ (std::int32_t)0x7fffffff,            2, false },
	{ (std::int32_t)0x80000000,            2, false },
	{ (std::int32_t)0xffffffff,            2, true },
	{ (std::int32_t)0,                     0x7fffffff, true },
	{ (std::int32_t)1,                     0x7fffffff, true },
	{ (std::int32_t)2,                     0x7fffffff, false },
	{ (std::int32_t)0x7fffffff,            0x7fffffff, false },
	{ (std::int32_t)0x80000000,            0x7fffffff, false },
	{ (std::int32_t)0xffffffff,            0x7fffffff, true },
	{ (std::int32_t)0,                     0x80000000, true },
	{ (std::int32_t)1,                     0x80000000, false },
	{ (std::int32_t)2,                     0x80000000, false },
	{ (std::int32_t)0x7fffffff,            0x80000000, false },
	{ (std::int32_t)0x80000000,            0x80000000, false },
	{ (std::int32_t)0xffffffff,            0x80000000, true },
	{ (std::int32_t)0,                     0xffffffff, true },
	{ (std::int32_t)1,                     0xffffffff, false },
	{ (std::int32_t)2,                     0xffffffff, false },
	{ (std::int32_t)0x7fffffff,            0xffffffff, false },
	{ (std::int32_t)0x80000000,            0xffffffff, false },
	{ (std::int32_t)0xffffffff,            0xffffffff, false },
	{ (std::int32_t)0,                     0x100000000, true },
	{ (std::int32_t)1,                     0x100000000, false },
	{ (std::int32_t)2,                     0x100000000, false },
	{ (std::int32_t)0x7fffffff,            0x100000000, false },
	{ (std::int32_t)0x80000000,            0x100000000, false },
	{ (std::int32_t)0xffffffff,            0x100000000, false },
	{ (std::int32_t)0,                     0x200000000, true },
	{ (std::int32_t)1,                     0x200000000, false },
	{ (std::int32_t)2,                     0x200000000, false },
	{ (std::int32_t)0x7fffffff,            0x200000000, false },
	{ (std::int32_t)0x80000000,            0x200000000, false },
	{ (std::int32_t)0xffffffff,            0x200000000, false },
	{ (std::int32_t)0,                     0x7fffffffffffffff, true },
	{ (std::int32_t)1,                     0x7fffffffffffffff, false },
	{ (std::int32_t)2,                     0x7fffffffffffffff, false },
	{ (std::int32_t)0x7fffffff,            0x7fffffffffffffff, false },
	{ (std::int32_t)0x80000000,            0x7fffffffffffffff, false },
	{ (std::int32_t)0xffffffff,            0x7fffffffffffffff, false },
	{ (std::int32_t)0,                     (std::int64_t)0x8000000000000000, true },
	{ (std::int32_t)1,                     (std::int64_t)0x8000000000000000, false },
	{ (std::int32_t)2,                     (std::int64_t)0x8000000000000000, false },
	{ (std::int32_t)0x7fffffff,            (std::int64_t)0x8000000000000000, false },
	{ (std::int32_t)0x80000000,            (std::int64_t)0x8000000000000000, false },
	{ (std::int32_t)0xffffffff,            (std::int64_t)0x8000000000000000, false },
	{ (std::int32_t)0,                     (std::int64_t)0xffffffffffffffff, true },
	{ (std::int32_t)1,                     (std::int64_t)0xffffffffffffffff, true },
	{ (std::int32_t)2,                     (std::int64_t)0xffffffffffffffff, true },
	{ (std::int32_t)0x7fffffff,            (std::int64_t)0xffffffffffffffff, true },
	{ (std::int32_t)0x80000000,            (std::int64_t)0xffffffffffffffff, false },
	{ (std::int32_t)0xffffffff,            (std::int64_t)0xffffffffffffffff, true },
	// Special case - force addition overflow case
	{ (std::int32_t)0xffffffff,            0x100000002, false }
};

template<> TestVector< std::int32_t, std::int64_t, OpType::Mult>::TestVector() : current(0)
{
	this->test_cases = int32_int64;
	this->count = COUNTOF(int32_int64);
}

static const TestCase< std::int32_t, std::int32_t, OpType::Mult > int32_int32[] =
{
	{ (std::int32_t)0,                     0, true },
	{ (std::int32_t)1,                     0, true },
	{ (std::int32_t)2,                     0, true },
	{ (std::int32_t)0x7fffffff,            0, true },
	{ (std::int32_t)0x80000000,            0, true },
	{ (std::int32_t)0xffffffff,            0, true },
	{ (std::int32_t)0,                     1, true },
	{ (std::int32_t)1,                     1, true },
	{ (std::int32_t)2,                     1, true },
	{ (std::int32_t)0x7fffffff,            1, true },
	{ (std::int32_t)0x80000000,            1, true },
	{ (std::int32_t)0xffffffff,            1, true },
	{ (std::int32_t)0,                     2, true },
	{ (std::int32_t)1,                     2, true },
	{ (std::int32_t)2,                     2, true },
	{ (std::int32_t)0x7fffffff,            2, false },
	{ (std::int32_t)0x80000000,            2, false },
	{ (std::int32_t)0xffffffff,            2, true },
	{ (std::int32_t)0,                     0x7fffffff, true },
	{ (std::int32_t)1,                     0x7fffffff, true },
	{ (std::int32_t)2,                     0x7fffffff, false },
	{ (std::int32_t)0x7fffffff,            0x7fffffff, false },
	{ (std::int32_t)0x80000000,            0x7fffffff, false },
	{ (std::int32_t)0xffffffff,            0x7fffffff, true },
	{ (std::int32_t)0,                     (std::int32_t)0x80000000, true },
	{ (std::int32_t)1,                     (std::int32_t)0x80000000, true },
	{ (std::int32_t)2,                     (std::int32_t)0x80000000, false },
	{ (std::int32_t)0x7fffffff,            (std::int32_t)0x80000000, false },
	{ (std::int32_t)0x80000000,            (std::int32_t)0x80000000, false },
	{ (std::int32_t)0xffffffff,            (std::int32_t)0x80000000, false },
	{ (std::int32_t)0,                     (std::int32_t)0xffffffff, true },
	{ (std::int32_t)1,                     (std::int32_t)0xffffffff, true },
	{ (std::int32_t)2,                     (std::int32_t)0xffffffff, true },
	{ (std::int32_t)0x7fffffff,            (std::int32_t)0xffffffff, true },
	{ (std::int32_t)0x80000000,            (std::int32_t)0xffffffff, false },
	{ (std::int32_t)0xffffffff,            (std::int32_t)0xffffffff, true },
};

template<> TestVector< std::int32_t, std::int32_t, OpType::Mult>::TestVector() : current(0)
{
	this->test_cases = int32_int32;
	this->count = COUNTOF(int32_int32);
}


