/*------------------------------------------------------------------------
 * Vulkan Conformance Tests
 * ------------------------
 *
 * Copyright (c) 2015 The Khronos Group Inc.
 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
 * Copyright (c) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief Integer built-in function tests.
 *//*--------------------------------------------------------------------*/

#include "vktShaderIntegerFunctionTests.hpp"
#include "vktShaderExecutor.hpp"
#include "tcuTestLog.hpp"
#include "tcuFormatUtil.hpp"
#include "tcuFloat.hpp"
#include "deRandom.hpp"
#include "deMath.h"
#include "deString.h"
#include "deInt32.h"
#include "deSharedPtr.hpp"

#include <iostream>

namespace vkt
{
namespace shaderexecutor
{

using std::vector;
using std::string;
using tcu::TestLog;

using tcu::IVec2;
using tcu::IVec3;
using tcu::IVec4;
using tcu::UVec2;
using tcu::UVec3;
using tcu::UVec4;

// Utilities

namespace
{

struct HexFloat
{
	const float value;
	HexFloat (const float value_) : value(value_) {}
};

std::ostream& operator<< (std::ostream& str, const HexFloat& v)
{
	return str << v.value << " / " << tcu::toHex(tcu::Float32(v.value).bits());
}

struct VarValue
{
	const glu::VarType&	type;
	const void*			value;

	VarValue (const glu::VarType& type_, const void* value_) : type(type_), value(value_) {}
};

std::ostream& operator<< (std::ostream& str, const VarValue& varValue)
{
	DE_ASSERT(varValue.type.isBasicType());

	const glu::DataType		basicType		= varValue.type.getBasicType();
	const glu::DataType		scalarType		= glu::getDataTypeScalarType(basicType);
	const int				numComponents	= glu::getDataTypeScalarSize(basicType);

	if (numComponents > 1)
		str << glu::getDataTypeName(basicType) << "(";

	for (int compNdx = 0; compNdx < numComponents; compNdx++)
	{
		if (compNdx != 0)
			str << ", ";

		switch (scalarType)
		{
			case glu::TYPE_FLOAT:	str << HexFloat(((const float*)varValue.value)[compNdx]);						break;
			case glu::TYPE_INT:		str << ((const deInt32*)varValue.value)[compNdx];								break;
			case glu::TYPE_UINT:	str << tcu::toHex(((const deUint32*)varValue.value)[compNdx]);					break;
			case glu::TYPE_BOOL:	str << (((const deUint32*)varValue.value)[compNdx] != 0 ? "true" : "false");	break;

			default:
				DE_ASSERT(false);
		}
	}

	if (numComponents > 1)
		str << ")";

	return str;
}

inline int getShaderUintBitCount (glu::ShaderType shaderType, glu::Precision precision)
{
	// \todo [2013-10-31 pyry] Query from GL for vertex and fragment shaders.
	DE_UNREF(shaderType);
	const int bitCounts[] = { 9, 16, 32 };
	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(bitCounts) == glu::PRECISION_LAST);
	return bitCounts[precision];
}

static inline deUint32 extendSignTo32 (deUint32 integer, deUint32 integerLength)
{
	DE_ASSERT(integerLength > 0 && integerLength <= 32);

	return deUint32(0 - deInt32((integer & (1 << (integerLength - 1))) << 1)) | integer;
}

static inline deUint32 getLowBitMask (int integerLength)
{
	DE_ASSERT(integerLength >= 0 && integerLength <= 32);

	// \note: shifting more or equal to 32 => undefined behavior. Avoid it by shifting in two parts (1 << (num-1) << 1)
	if (integerLength == 0u)
		return 0u;
	return ((1u << ((deUint32)integerLength - 1u)) << 1u) - 1u;
}

static void generateRandomInputData (de::Random& rnd, glu::ShaderType shaderType, glu::DataType dataType, glu::Precision precision, deUint32* dst, int numValues)
{
	const int				scalarSize		= glu::getDataTypeScalarSize(dataType);
	const deUint32			integerLength	= (deUint32)getShaderUintBitCount(shaderType, precision);
	const deUint32			integerMask		= getLowBitMask(integerLength);
	const bool				isUnsigned		= glu::isDataTypeUintOrUVec(dataType);

	if (isUnsigned)
	{
		for (int valueNdx = 0; valueNdx < numValues; ++valueNdx)
			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
				dst[valueNdx*scalarSize + compNdx] = rnd.getUint32() & integerMask;
	}
	else
	{
		for (int valueNdx = 0; valueNdx < numValues; ++valueNdx)
			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
				dst[valueNdx*scalarSize + compNdx] = extendSignTo32(rnd.getUint32() & integerMask, integerLength);
	}
}

static vector<int> getScalarSizes (const vector<Symbol>& symbols)
{
	vector<int> sizes(symbols.size());
	for (int ndx = 0; ndx < (int)symbols.size(); ++ndx)
		sizes[ndx] = symbols[ndx].varType.getScalarSize();
	return sizes;
}

static int computeTotalScalarSize (const vector<Symbol>& symbols)
{
	int totalSize = 0;
	for (vector<Symbol>::const_iterator sym = symbols.begin(); sym != symbols.end(); ++sym)
		totalSize += sym->varType.getScalarSize();
	return totalSize;
}

static vector<void*> getInputOutputPointers (const vector<Symbol>& symbols, vector<deUint32>& data, const int numValues)
{
	vector<void*>	pointers		(symbols.size());
	int				curScalarOffset	= 0;

	for (int varNdx = 0; varNdx < (int)symbols.size(); ++varNdx)
	{
		const Symbol&	var				= symbols[varNdx];
		const int		scalarSize		= var.varType.getScalarSize();

		// Uses planar layout as input/output specs do not support strides.
		pointers[varNdx] = &data[curScalarOffset];
		curScalarOffset += scalarSize*numValues;
	}

	DE_ASSERT(curScalarOffset == (int)data.size());

	return pointers;
}

static std::string getIntegerFuncCaseName (glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
{
	return string(glu::getDataTypeName(baseType)) + getPrecisionPostfix(precision) + getShaderTypePostfix(shaderType);
}

static inline deUint32 reverseBits (deUint32 v)
{
	v = (((v & 0xaaaaaaaa) >> 1) | ((v & 0x55555555) << 1));
	v = (((v & 0xcccccccc) >> 2) | ((v & 0x33333333) << 2));
	v = (((v & 0xf0f0f0f0) >> 4) | ((v & 0x0f0f0f0f) << 4));
	v = (((v & 0xff00ff00) >> 8) | ((v & 0x00ff00ff) << 8));
	return((v >> 16) | (v << 16));
}

static int findLSB (deUint32 value)
{
	for (int i = 0; i < 32; i++)
	{
		if (value & (1u<<i))
			return i;
	}
	return -1;
}

static int findMSB (deInt32 value)
{
	if (value > 0)
		return 31 - deClz32((deUint32)value);
	else if (value < 0)
		return 31 - deClz32(~(deUint32)value);
	else
		return -1;
}

static int findMSB (deUint32 value)
{
	if (value > 0)
		return 31 - deClz32(value);
	else
		return -1;
}

static deUint32 toPrecision (deUint32 value, int numIntegerBits)
{
	return value & getLowBitMask(numIntegerBits);
}

static deInt32 toPrecision (deInt32 value, int numIntegerBits)
{
	return (deInt32)extendSignTo32((deUint32)value & getLowBitMask(numIntegerBits), numIntegerBits);
}

template<class TestClass>
static void addFunctionCases (tcu::TestCaseGroup* parent, const char* functionName, bool intTypes, bool uintTypes, bool allPrec, deUint32 shaderBits)
{
	tcu::TestCaseGroup* group = new tcu::TestCaseGroup(parent->getTestContext(), functionName, functionName);

	parent->addChild(group);
	const glu::DataType scalarTypes[] =
	{
		glu::TYPE_INT,
		glu::TYPE_UINT
	};

	for (int scalarTypeNdx = 0; scalarTypeNdx < DE_LENGTH_OF_ARRAY(scalarTypes); scalarTypeNdx++)
	{
		const glu::DataType scalarType = scalarTypes[scalarTypeNdx];

		if ((!intTypes && scalarType == glu::TYPE_INT) || (!uintTypes && scalarType == glu::TYPE_UINT))
			continue;

		for (int vecSize = 1; vecSize <= 4; vecSize++)
		{
			for (int prec = glu::PRECISION_MEDIUMP; prec <= glu::PRECISION_HIGHP; prec++)
			{
				if (prec != glu::PRECISION_HIGHP && !allPrec)
					continue;

				for (int shaderTypeNdx = 0; shaderTypeNdx < glu::SHADERTYPE_LAST; shaderTypeNdx++)
				{
					if (shaderBits & (1<<shaderTypeNdx))
						group->addChild(new TestClass(parent->getTestContext(), glu::DataType(scalarType + vecSize - 1), glu::Precision(prec), glu::ShaderType(shaderTypeNdx)));
				}
			}
		}
	}
}

} // anonymous

// IntegerFunctionCase

class IntegerFunctionCase : public TestCase
{
public:
										IntegerFunctionCase		(tcu::TestContext& testCtx, const char* name, const char* description, glu::ShaderType shaderType);
										~IntegerFunctionCase	(void);

	virtual	void						initPrograms			(vk::SourceCollections& programCollection) const
										{
											generateSources(m_shaderType, m_spec, programCollection);
										}

	virtual TestInstance*				createInstance			(Context& context) const = 0;

protected:
										IntegerFunctionCase		(const IntegerFunctionCase& other);
	IntegerFunctionCase&				operator=				(const IntegerFunctionCase& other);

	const glu::ShaderType				m_shaderType;

	ShaderSpec							m_spec;

	const int							m_numValues;
};

IntegerFunctionCase::IntegerFunctionCase (tcu::TestContext& testCtx, const char* name, const char* description, glu::ShaderType shaderType)
	: TestCase		(testCtx, name, description)
	, m_shaderType	(shaderType)
	, m_numValues	(100)
{
}

IntegerFunctionCase::~IntegerFunctionCase (void)
{
}

// IntegerFunctionTestInstance

class IntegerFunctionTestInstance : public TestInstance
{
public:
								IntegerFunctionTestInstance		(Context& context, glu::ShaderType shaderType, const ShaderSpec& spec, int numValues, const char* name)
									: TestInstance	(context)
									, m_shaderType	(shaderType)
									, m_spec		(spec)
									, m_numValues	(numValues)
									, m_name		(name)
									, m_executor	(createExecutor(context, m_shaderType, m_spec))
								{
								}
	virtual tcu::TestStatus		iterate							(void);
protected:
	virtual bool						compare					(const void* const* inputs, const void* const* outputs) = 0;

	virtual void						getInputValues			(int numValues, void* const* values) const = 0;

	const glu::ShaderType				m_shaderType;

	ShaderSpec							m_spec;

	const int							m_numValues;

	const char*							m_name;

	std::ostringstream					m_failMsg;				//!< Comparison failure help message.

	de::UniquePtr<ShaderExecutor>		m_executor;
};

tcu::TestStatus IntegerFunctionTestInstance::iterate (void)
{
	const int				numInputScalars			= computeTotalScalarSize(m_spec.inputs);
	const int				numOutputScalars		= computeTotalScalarSize(m_spec.outputs);
	vector<deUint32>		inputData				(numInputScalars * m_numValues);
	vector<deUint32>		outputData				(numOutputScalars * m_numValues);
	const vector<void*>		inputPointers			= getInputOutputPointers(m_spec.inputs, inputData, m_numValues);
	const vector<void*>		outputPointers			= getInputOutputPointers(m_spec.outputs, outputData, m_numValues);

	// Initialize input data.
	getInputValues(m_numValues, &inputPointers[0]);

	// Execute shader.
	m_executor->execute(m_numValues, &inputPointers[0], &outputPointers[0]);

	// Compare results.
	{
		const vector<int>		inScalarSizes		= getScalarSizes(m_spec.inputs);
		const vector<int>		outScalarSizes		= getScalarSizes(m_spec.outputs);
		vector<void*>			curInputPtr			(inputPointers.size());
		vector<void*>			curOutputPtr		(outputPointers.size());
		int						numFailed			= 0;
		tcu::TestContext&		testCtx				= m_context.getTestContext();
		for (int valNdx = 0; valNdx < m_numValues; valNdx++)
		{
			// Set up pointers for comparison.
			for (int inNdx = 0; inNdx < (int)curInputPtr.size(); ++inNdx)
				curInputPtr[inNdx] = (deUint32*)inputPointers[inNdx] + inScalarSizes[inNdx]*valNdx;

			for (int outNdx = 0; outNdx < (int)curOutputPtr.size(); ++outNdx)
				curOutputPtr[outNdx] = (deUint32*)outputPointers[outNdx] + outScalarSizes[outNdx]*valNdx;

			if (!compare(&curInputPtr[0], &curOutputPtr[0]))
			{
				// \todo [2013-08-08 pyry] We probably want to log reference value as well?

				testCtx.getLog() << TestLog::Message << "ERROR: comparison failed for value " << valNdx << ":\n  " << m_failMsg.str() << TestLog::EndMessage;

				testCtx.getLog() << TestLog::Message << "  inputs:" << TestLog::EndMessage;
				for (int inNdx = 0; inNdx < (int)curInputPtr.size(); inNdx++)
					testCtx.getLog() << TestLog::Message << "    " << m_spec.inputs[inNdx].name << " = "
														   << VarValue(m_spec.inputs[inNdx].varType, curInputPtr[inNdx])
									   << TestLog::EndMessage;

				testCtx.getLog() << TestLog::Message << "  outputs:" << TestLog::EndMessage;
				for (int outNdx = 0; outNdx < (int)curOutputPtr.size(); outNdx++)
					testCtx.getLog() << TestLog::Message << "    " << m_spec.outputs[outNdx].name << " = "
														   << VarValue(m_spec.outputs[outNdx].varType, curOutputPtr[outNdx])
									   << TestLog::EndMessage;

				m_failMsg.str("");
				m_failMsg.clear();
				numFailed += 1;
			}
		}

		testCtx.getLog() << TestLog::Message << (m_numValues - numFailed) << " / " << m_numValues << " values passed" << TestLog::EndMessage;

		if (numFailed == 0)
			return tcu::TestStatus::pass("Pass");
		else
			return tcu::TestStatus::fail("Result comparison failed");
	}
}

// Test cases

class UaddCarryCaseInstance : public IntegerFunctionTestInstance
{
public:
	UaddCarryCaseInstance (Context& context, glu::ShaderType shaderType, const ShaderSpec& spec, int numValues, const char* name)
		: IntegerFunctionTestInstance	(context, shaderType, spec, numValues, name)
	{
	}

	void getInputValues (int numValues, void* const* values) const
	{
		de::Random				rnd				(deStringHash(m_name) ^ 0x235facu);
		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
		const int				scalarSize		= glu::getDataTypeScalarSize(type);
		const int				integerLength	= getShaderUintBitCount(m_shaderType, precision);
		const deUint32			integerMask		= getLowBitMask(integerLength);
		const bool				isSigned		= glu::isDataTypeIntOrIVec(type);
		deUint32*				in0				= (deUint32*)values[0];
		deUint32*				in1				= (deUint32*)values[1];

		const struct
		{
			deUint32	x;
			deUint32	y;
		} easyCases[] =
		{
			{ 0x00000000u,	0x00000000u },
			{ 0xfffffffeu,	0x00000001u },
			{ 0x00000001u,	0xfffffffeu },
			{ 0xffffffffu,	0x00000001u },
			{ 0x00000001u,	0xffffffffu },
			{ 0xfffffffeu,	0x00000002u },
			{ 0x00000002u,	0xfffffffeu },
			{ 0xffffffffu,	0xffffffffu }
		};

		// generate integers with proper bit count
		for (int easyCaseNdx = 0; easyCaseNdx < DE_LENGTH_OF_ARRAY(easyCases); easyCaseNdx++)
		{
			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
			{
				in0[easyCaseNdx*scalarSize + compNdx] = easyCases[easyCaseNdx].x & integerMask;
				in1[easyCaseNdx*scalarSize + compNdx] = easyCases[easyCaseNdx].y & integerMask;
			}
		}

		// convert to signed
		if (isSigned)
		{
			for (int easyCaseNdx = 0; easyCaseNdx < DE_LENGTH_OF_ARRAY(easyCases); easyCaseNdx++)
			{
				for (int compNdx = 0; compNdx < scalarSize; compNdx++)
				{
					in0[easyCaseNdx*scalarSize + compNdx] = extendSignTo32(in0[easyCaseNdx*scalarSize + compNdx], integerLength);
					in1[easyCaseNdx*scalarSize + compNdx] = extendSignTo32(in1[easyCaseNdx*scalarSize + compNdx], integerLength);
				}
			}
		}

		generateRandomInputData(rnd, m_shaderType, type, precision, in0, numValues - DE_LENGTH_OF_ARRAY(easyCases));
		generateRandomInputData(rnd, m_shaderType, type, precision, in1, numValues - DE_LENGTH_OF_ARRAY(easyCases));
	}

	bool compare (const void* const* inputs, const void* const* outputs)
	{
		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
		const int				scalarSize		= glu::getDataTypeScalarSize(type);
		const int				integerLength	= getShaderUintBitCount(m_shaderType, precision);
		const deUint32			mask0			= getLowBitMask(integerLength);

		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
		{
			const deUint32	in0		= ((const deUint32*)inputs[0])[compNdx];
			const deUint32	in1		= ((const deUint32*)inputs[1])[compNdx];
			const deUint32	out0	= ((const deUint32*)outputs[0])[compNdx];
			const deUint32	out1	= ((const deUint32*)outputs[1])[compNdx];
			const deUint32	ref0	= in0+in1;
			const deUint32	ref1	= (deUint64(in0)+deUint64(in1)) > 0xffffffffu ? 1u : 0u;

			if (((out0&mask0) != (ref0&mask0)) || out1 != ref1)
			{
				m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(ref0) << ", " << tcu::toHex(ref1);
				return false;
			}
		}

		return true;
	}
};

class UaddCarryCase : public IntegerFunctionCase
{
public:
	UaddCarryCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
		: IntegerFunctionCase	(testCtx, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "uaddCarry", shaderType)
	{
		m_spec.inputs.push_back(Symbol("x", glu::VarType(baseType, precision)));
		m_spec.inputs.push_back(Symbol("y", glu::VarType(baseType, precision)));
		m_spec.outputs.push_back(Symbol("sum", glu::VarType(baseType, precision)));
		m_spec.outputs.push_back(Symbol("carry", glu::VarType(baseType, glu::PRECISION_LOWP)));
		m_spec.source = "sum = uaddCarry(x, y, carry);";
	}

	TestInstance* createInstance (Context& ctx) const
	{
		return new UaddCarryCaseInstance(ctx, m_shaderType, m_spec, m_numValues, getName());
	}
};

class UsubBorrowCaseInstance : public IntegerFunctionTestInstance
{
public:
	UsubBorrowCaseInstance (Context& context, glu::ShaderType shaderType, const ShaderSpec& spec, int numValues, const char* name)
		: IntegerFunctionTestInstance	(context, shaderType, spec, numValues, name)
	{
	}

	void getInputValues (int numValues, void* const* values) const
	{
		de::Random				rnd				(deStringHash(m_name) ^ 0x235facu);
		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
		const int				scalarSize		= glu::getDataTypeScalarSize(type);
		const int				integerLength	= getShaderUintBitCount(m_shaderType, precision);
		const deUint32			integerMask		= getLowBitMask(integerLength);
		const bool				isSigned		= glu::isDataTypeIntOrIVec(type);
		deUint32*				in0				= (deUint32*)values[0];
		deUint32*				in1				= (deUint32*)values[1];

		const struct
		{
			deUint32	x;
			deUint32	y;
		} easyCases[] =
		{
			{ 0x00000000u,	0x00000000u },
			{ 0x00000001u,	0x00000001u },
			{ 0x00000001u,	0x00000002u },
			{ 0x00000001u,	0xffffffffu },
			{ 0xfffffffeu,	0xffffffffu },
			{ 0xffffffffu,	0xffffffffu },
		};

		// generate integers with proper bit count
		for (int easyCaseNdx = 0; easyCaseNdx < DE_LENGTH_OF_ARRAY(easyCases); easyCaseNdx++)
		{
			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
			{
				in0[easyCaseNdx*scalarSize + compNdx] = easyCases[easyCaseNdx].x & integerMask;
				in1[easyCaseNdx*scalarSize + compNdx] = easyCases[easyCaseNdx].y & integerMask;
			}
		}

		// convert to signed
		if (isSigned)
		{
			for (int easyCaseNdx = 0; easyCaseNdx < DE_LENGTH_OF_ARRAY(easyCases); easyCaseNdx++)
			{
				for (int compNdx = 0; compNdx < scalarSize; compNdx++)
				{
					in0[easyCaseNdx*scalarSize + compNdx] = extendSignTo32(in0[easyCaseNdx*scalarSize + compNdx], integerLength);
					in1[easyCaseNdx*scalarSize + compNdx] = extendSignTo32(in1[easyCaseNdx*scalarSize + compNdx], integerLength);
				}
			}
		}

		generateRandomInputData(rnd, m_shaderType, type, precision, in0, numValues - DE_LENGTH_OF_ARRAY(easyCases));
		generateRandomInputData(rnd, m_shaderType, type, precision, in1, numValues - DE_LENGTH_OF_ARRAY(easyCases));
	}

	bool compare (const void* const* inputs, const void* const* outputs)
	{
		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
		const int				scalarSize		= glu::getDataTypeScalarSize(type);
		const int				integerLength	= getShaderUintBitCount(m_shaderType, precision);
		const deUint32			mask0			= getLowBitMask(integerLength);

		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
		{
			const deUint32	in0		= ((const deUint32*)inputs[0])[compNdx];
			const deUint32	in1		= ((const deUint32*)inputs[1])[compNdx];
			const deUint32	out0	= ((const deUint32*)outputs[0])[compNdx];
			const deUint32	out1	= ((const deUint32*)outputs[1])[compNdx];
			const deUint32	ref0	= in0-in1;
			const deUint32	ref1	= in0 >= in1 ? 0u : 1u;

			if (((out0&mask0) != (ref0&mask0)) || out1 != ref1)
			{
				m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(ref0) << ", " << tcu::toHex(ref1);
				return false;
			}
		}

		return true;
	}
};

class UsubBorrowCase : public IntegerFunctionCase
{
public:
	UsubBorrowCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
		: IntegerFunctionCase	(testCtx, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "usubBorrow", shaderType)
	{
		m_spec.inputs.push_back(Symbol("x", glu::VarType(baseType, precision)));
		m_spec.inputs.push_back(Symbol("y", glu::VarType(baseType, precision)));
		m_spec.outputs.push_back(Symbol("diff", glu::VarType(baseType, precision)));
		m_spec.outputs.push_back(Symbol("carry", glu::VarType(baseType, glu::PRECISION_LOWP)));
		m_spec.source = "diff = usubBorrow(x, y, carry);";
	}

	TestInstance* createInstance (Context& ctx) const
	{
		return new UsubBorrowCaseInstance(ctx, m_shaderType, m_spec, m_numValues, getName());
	}
};

class UmulExtendedCaseInstance : public IntegerFunctionTestInstance
{
public:
	UmulExtendedCaseInstance (Context& context, glu::ShaderType shaderType, const ShaderSpec& spec, int numValues, const char* name)
		: IntegerFunctionTestInstance	(context, shaderType, spec, numValues, name)
	{
	}

	void getInputValues (int numValues, void* const* values) const
	{
		de::Random				rnd			(deStringHash(m_name) ^ 0x235facu);
		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
//		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
		const int				scalarSize	= glu::getDataTypeScalarSize(type);
		deUint32*				in0			= (deUint32*)values[0];
		deUint32*				in1			= (deUint32*)values[1];
		int						valueNdx	= 0;

		const struct
		{
			deUint32	x;
			deUint32	y;
		} easyCases[] =
		{
			{ 0x00000000u,	0x00000000u },
			{ 0xffffffffu,	0x00000001u },
			{ 0xffffffffu,	0x00000002u },
			{ 0x00000001u,	0xffffffffu },
			{ 0x00000002u,	0xffffffffu },
			{ 0xffffffffu,	0xffffffffu },
		};

		for (int easyCaseNdx = 0; easyCaseNdx < DE_LENGTH_OF_ARRAY(easyCases); easyCaseNdx++)
		{
			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
			{
				in0[valueNdx*scalarSize + compNdx] = easyCases[easyCaseNdx].x;
				in1[valueNdx*scalarSize + compNdx] = easyCases[easyCaseNdx].y;
			}

			valueNdx += 1;
		}

		while (valueNdx < numValues)
		{
			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
			{
				const deUint32	base0	= rnd.getUint32();
				const deUint32	base1	= rnd.getUint32();
				const int		adj0	= rnd.getInt(0, 20);
				const int		adj1	= rnd.getInt(0, 20);
				in0[valueNdx*scalarSize + compNdx] = base0 >> adj0;
				in1[valueNdx*scalarSize + compNdx] = base1 >> adj1;
			}

			valueNdx += 1;
		}
	}

	bool compare (const void* const* inputs, const void* const* outputs)
	{
		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
		const int				scalarSize		= glu::getDataTypeScalarSize(type);

		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
		{
			const deUint32	in0		= ((const deUint32*)inputs[0])[compNdx];
			const deUint32	in1		= ((const deUint32*)inputs[1])[compNdx];
			const deUint32	out0	= ((const deUint32*)outputs[0])[compNdx];
			const deUint32	out1	= ((const deUint32*)outputs[1])[compNdx];
			const deUint64	mul64	= deUint64(in0)*deUint64(in1);
			const deUint32	ref0	= deUint32(mul64 >> 32);
			const deUint32	ref1	= deUint32(mul64 & 0xffffffffu);

			if (out0 != ref0 || out1 != ref1)
			{
				m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(ref0) << ", " << tcu::toHex(ref1);
				return false;
			}
		}

		return true;
	}
};

class UmulExtendedCase : public IntegerFunctionCase
{
public:
	UmulExtendedCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
		: IntegerFunctionCase	(testCtx, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "umulExtended", shaderType)
	{
		m_spec.inputs.push_back(Symbol("x", glu::VarType(baseType, precision)));
		m_spec.inputs.push_back(Symbol("y", glu::VarType(baseType, precision)));
		m_spec.outputs.push_back(Symbol("msb", glu::VarType(baseType, precision)));
		m_spec.outputs.push_back(Symbol("lsb", glu::VarType(baseType, precision)));
		m_spec.source = "umulExtended(x, y, msb, lsb);";
	}

	TestInstance* createInstance (Context& ctx) const
	{
		return new UmulExtendedCaseInstance(ctx, m_shaderType, m_spec, m_numValues, getName());
	}
};

class ImulExtendedCaseInstance : public IntegerFunctionTestInstance
{
public:
	ImulExtendedCaseInstance (Context& context, glu::ShaderType shaderType, const ShaderSpec& spec, int numValues, const char* name)
		: IntegerFunctionTestInstance	(context, shaderType, spec, numValues, name)
	{
	}

	void getInputValues (int numValues, void* const* values) const
	{
		de::Random				rnd			(deStringHash(m_name) ^ 0x224fa1u);
		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
//		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
		const int				scalarSize	= glu::getDataTypeScalarSize(type);
		deUint32*				in0			= (deUint32*)values[0];
		deUint32*				in1			= (deUint32*)values[1];
		int						valueNdx	= 0;

		const struct
		{
			deUint32	x;
			deUint32	y;
		} easyCases[] =
		{
			{ 0x00000000u,	0x00000000u },
			{ 0xffffffffu,	0x00000002u },
			{ 0x7fffffffu,	0x00000001u },
			{ 0x7fffffffu,	0x00000002u },
			{ 0x7fffffffu,	0x7fffffffu },
			{ 0xffffffffu,	0xffffffffu },
			{ 0x7fffffffu,	0xfffffffeu },
		};

		for (int easyCaseNdx = 0; easyCaseNdx < DE_LENGTH_OF_ARRAY(easyCases); easyCaseNdx++)
		{
			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
			{
				in0[valueNdx*scalarSize + compNdx] = (deInt32)easyCases[easyCaseNdx].x;
				in1[valueNdx*scalarSize + compNdx] = (deInt32)easyCases[easyCaseNdx].y;
			}

			valueNdx += 1;
		}

		while (valueNdx < numValues)
		{
			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
			{
				const deInt32	base0	= (deInt32)rnd.getUint32();
				const deInt32	base1	= (deInt32)rnd.getUint32();
				const int		adj0	= rnd.getInt(0, 20);
				const int		adj1	= rnd.getInt(0, 20);
				in0[valueNdx*scalarSize + compNdx] = base0 >> adj0;
				in1[valueNdx*scalarSize + compNdx] = base1 >> adj1;
			}

			valueNdx += 1;
		}
	}

	bool compare (const void* const* inputs, const void* const* outputs)
	{
		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
		const int				scalarSize		= glu::getDataTypeScalarSize(type);

		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
		{
			const deInt32	in0		= ((const deInt32*)inputs[0])[compNdx];
			const deInt32	in1		= ((const deInt32*)inputs[1])[compNdx];
			const deInt32	out0	= ((const deInt32*)outputs[0])[compNdx];
			const deInt32	out1	= ((const deInt32*)outputs[1])[compNdx];
			const deInt64	mul64	= deInt64(in0)*deInt64(in1);
			const deInt32	ref0	= deInt32(mul64 >> 32);
			const deInt32	ref1	= deInt32(mul64 & 0xffffffffu);

			if (out0 != ref0 || out1 != ref1)
			{
				m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(ref0) << ", " << tcu::toHex(ref1);
				return false;
			}
		}

		return true;
	}
};

class ImulExtendedCase : public IntegerFunctionCase
{
public:
	ImulExtendedCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
		: IntegerFunctionCase	(testCtx, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "imulExtended", shaderType)
	{
		m_spec.inputs.push_back(Symbol("x", glu::VarType(baseType, precision)));
		m_spec.inputs.push_back(Symbol("y", glu::VarType(baseType, precision)));
		m_spec.outputs.push_back(Symbol("msb", glu::VarType(baseType, precision)));
		m_spec.outputs.push_back(Symbol("lsb", glu::VarType(baseType, precision)));
		m_spec.source = "imulExtended(x, y, msb, lsb);";
	}

	TestInstance* createInstance (Context& ctx) const
	{
		return new ImulExtendedCaseInstance(ctx, m_shaderType, m_spec, m_numValues, getName());
	}
};

class BitfieldExtractCaseInstance : public IntegerFunctionTestInstance
{
public:
	BitfieldExtractCaseInstance (Context& context, glu::ShaderType shaderType, const ShaderSpec& spec, int numValues, const char* name)
		: IntegerFunctionTestInstance	(context, shaderType, spec, numValues, name)
	{
	}

	void getInputValues (int numValues, void* const* values) const
	{
		de::Random				rnd			(deStringHash(m_name) ^ 0xa113fca2u);
		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
		const bool				ignoreSign	= precision != glu::PRECISION_HIGHP && glu::isDataTypeIntOrIVec(type);
		const int				numBits		= getShaderUintBitCount(m_shaderType, precision) - (ignoreSign ? 1 : 0);
		deUint32*				inValue		= (deUint32*)values[0];
		int*					inOffset	= (int*)values[1];
		int*					inBits		= (int*)values[2];

		for (int valueNdx = 0; valueNdx < numValues; ++valueNdx)
		{
			const int		bits	= rnd.getInt(0, numBits);
			const int		offset	= rnd.getInt(0, numBits-bits);

			inOffset[valueNdx]	= offset;
			inBits[valueNdx]	= bits;
		}

		generateRandomInputData(rnd, m_shaderType, type, precision, inValue, numValues);
	}

	bool compare (const void* const* inputs, const void* const* outputs)
	{
		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
		const bool				isSigned		= glu::isDataTypeIntOrIVec(type);
		const int				scalarSize		= glu::getDataTypeScalarSize(type);
		const int				offset			= *((const int*)inputs[1]);
		const int				bits			= *((const int*)inputs[2]);

		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
		{
			const deUint32	value	= ((const deUint32*)inputs[0])[compNdx];
			const deUint32	out		= ((const deUint32*)outputs[0])[compNdx];
			const deUint32	valMask	= (bits == 32 ? ~0u : ((1u<<bits)-1u));
			const deUint32	baseVal	= (offset == 32) ? (0) : ((value >> offset) & valMask);
			const deUint32	ref		= baseVal | ((isSigned && (baseVal & (1<<(bits-1)))) ? ~valMask : 0u);

			if (out != ref)
			{
				m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(ref);
				return false;
			}
		}

		return true;
	}
};

class BitfieldExtractCase : public IntegerFunctionCase
{
public:
	BitfieldExtractCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
		: IntegerFunctionCase	(testCtx, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "bitfieldExtract", shaderType)
	{
		m_spec.inputs.push_back(Symbol("value", glu::VarType(baseType, precision)));
		m_spec.inputs.push_back(Symbol("offset", glu::VarType(glu::TYPE_INT, precision)));
		m_spec.inputs.push_back(Symbol("bits", glu::VarType(glu::TYPE_INT, precision)));
		m_spec.outputs.push_back(Symbol("extracted", glu::VarType(baseType, precision)));
		m_spec.source = "extracted = bitfieldExtract(value, offset, bits);";
	}

	TestInstance* createInstance (Context& ctx) const
	{
		return new BitfieldExtractCaseInstance(ctx, m_shaderType, m_spec, m_numValues, getName());
	}
};

class BitfieldInsertCaseInstance : public IntegerFunctionTestInstance
{
public:
	BitfieldInsertCaseInstance (Context& context, glu::ShaderType shaderType, const ShaderSpec& spec, int numValues, const char* name)
		: IntegerFunctionTestInstance	(context, shaderType, spec, numValues, name)
	{
	}

	void getInputValues (int numValues, void* const* values) const
	{
		de::Random				rnd			(deStringHash(m_name) ^ 0x12c2acff);
		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
		const int				numBits		= getShaderUintBitCount(m_shaderType, precision);
		deUint32*				inBase		= (deUint32*)values[0];
		deUint32*				inInsert	= (deUint32*)values[1];
		int*					inOffset	= (int*)values[2];
		int*					inBits		= (int*)values[3];

		for (int valueNdx = 0; valueNdx < numValues; ++valueNdx)
		{
			const int bits		= rnd.getInt(0, numBits);
			const int offset	= rnd.getInt(0, numBits-bits);

			inOffset[valueNdx]	= offset;
			inBits[valueNdx]	= bits;
		}

		generateRandomInputData(rnd, m_shaderType, type, precision, inBase, numValues);
		generateRandomInputData(rnd, m_shaderType, type, precision, inInsert, numValues);
	}

	bool compare (const void* const* inputs, const void* const* outputs)
	{
		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
		const int				scalarSize		= glu::getDataTypeScalarSize(type);
		const int				integerLength	= getShaderUintBitCount(m_shaderType, precision);
		const deUint32			cmpMask			= getLowBitMask(integerLength);
		const int				offset			= *((const int*)inputs[2]);
		const int				bits			= *((const int*)inputs[3]);

		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
		{
			const deUint32	base	= ((const deUint32*)inputs[0])[compNdx];
			const deUint32	insert	= ((const deUint32*)inputs[1])[compNdx];
			const deInt32	out		= ((const deUint32*)outputs[0])[compNdx];

			const deUint32	mask	= bits == 32 ? ~0u : (1u<<bits)-1;
			const deUint32	ref		= (base & ~(mask<<offset)) | ((insert & mask)<<offset);

			if ((out&cmpMask) != (ref&cmpMask))
			{
				m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(ref);
				return false;
			}
		}

		return true;
	}
};

class BitfieldInsertCase : public IntegerFunctionCase
{
public:
	BitfieldInsertCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
		: IntegerFunctionCase	(testCtx, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "bitfieldInsert", shaderType)
	{
		m_spec.inputs.push_back(Symbol("base", glu::VarType(baseType, precision)));
		m_spec.inputs.push_back(Symbol("insert", glu::VarType(baseType, precision)));
		m_spec.inputs.push_back(Symbol("offset", glu::VarType(glu::TYPE_INT, precision)));
		m_spec.inputs.push_back(Symbol("bits", glu::VarType(glu::TYPE_INT, precision)));
		m_spec.outputs.push_back(Symbol("result", glu::VarType(baseType, precision)));
		m_spec.source = "result = bitfieldInsert(base, insert, offset, bits);";
	}

	TestInstance* createInstance (Context& ctx) const
	{
		return new BitfieldInsertCaseInstance(ctx, m_shaderType, m_spec, m_numValues, getName());
	}
};

class BitfieldReverseCaseInstance : public IntegerFunctionTestInstance
{
public:
	BitfieldReverseCaseInstance (Context& context, glu::ShaderType shaderType, const ShaderSpec& spec, int numValues, const char* name)
		: IntegerFunctionTestInstance	(context, shaderType, spec, numValues, name)
	{
	}

	void getInputValues (int numValues, void* const* values) const
	{
		de::Random				rnd			(deStringHash(m_name) ^ 0xff23a4);
		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
		deUint32*				inValue		= (deUint32*)values[0];

		generateRandomInputData(rnd, m_shaderType, type, precision, inValue, numValues);
	}

	bool compare (const void* const* inputs, const void* const* outputs)
	{
		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
		const int				integerLength	= getShaderUintBitCount(m_shaderType, precision);
		const int				scalarSize		= glu::getDataTypeScalarSize(type);
		const deUint32			cmpMask			= reverseBits(getLowBitMask(integerLength));

		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
		{
			const deUint32	value	= ((const deUint32*)inputs[0])[compNdx];
			const deInt32	out		= ((const deUint32*)outputs[0])[compNdx];
			const deUint32	ref		= reverseBits(value);

			if ((out&cmpMask) != (ref&cmpMask))
			{
				m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(ref);
				return false;
			}
		}

		return true;
	}
};

class BitfieldReverseCase : public IntegerFunctionCase
{
public:
	BitfieldReverseCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
		: IntegerFunctionCase	(testCtx, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "bitfieldReverse", shaderType)
	{
		m_spec.inputs.push_back(Symbol("value", glu::VarType(baseType, precision)));
		m_spec.outputs.push_back(Symbol("result", glu::VarType(baseType, glu::PRECISION_HIGHP)));
		m_spec.source = "result = bitfieldReverse(value);";
	}

	TestInstance* createInstance (Context& ctx) const
	{
		return new BitfieldReverseCaseInstance(ctx, m_shaderType, m_spec, m_numValues, getName());
	}
};

class BitCountCaseInstance : public IntegerFunctionTestInstance
{
public:
	BitCountCaseInstance (Context& context, glu::ShaderType shaderType, const ShaderSpec& spec, int numValues, const char* name)
		: IntegerFunctionTestInstance	(context, shaderType, spec, numValues, name)
	{
	}

	void getInputValues (int numValues, void* const* values) const
	{
		de::Random				rnd			(deStringHash(m_name) ^ 0xab2cca4);
		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
		deUint32*				inValue		= (deUint32*)values[0];

		generateRandomInputData(rnd, m_shaderType, type, precision, inValue, numValues);
	}

	bool compare (const void* const* inputs, const void* const* outputs)
	{
		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
		const int				integerLength	= getShaderUintBitCount(m_shaderType, precision);
		const int				scalarSize		= glu::getDataTypeScalarSize(type);
		const deUint32			countMask		= getLowBitMask(integerLength);

		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
		{
			const deUint32	value	= ((const deUint32*)inputs[0])[compNdx];
			const int		out		= ((const int*)outputs[0])[compNdx];
			const int		minRef	= dePop32(value&countMask);
			const int		maxRef	= dePop32(value);

			if (!de::inRange(out, minRef, maxRef))
			{
				m_failMsg << "Expected [" << compNdx << "] in range [" << minRef << ", " << maxRef << "]";
				return false;
			}
		}

		return true;
	}
};

class BitCountCase : public IntegerFunctionCase
{
public:
	BitCountCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
		: IntegerFunctionCase	(testCtx, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "bitCount", shaderType)
	{
		const int			vecSize		= glu::getDataTypeScalarSize(baseType);
		const glu::DataType	intType		= vecSize == 1 ? glu::TYPE_INT : glu::getDataTypeIntVec(vecSize);

		m_spec.inputs.push_back(Symbol("value", glu::VarType(baseType, precision)));
		m_spec.outputs.push_back(Symbol("count", glu::VarType(intType, glu::PRECISION_MEDIUMP)));
		m_spec.source = "count = bitCount(value);";
	}

	TestInstance* createInstance (Context& ctx) const
	{
		return new BitCountCaseInstance(ctx, m_shaderType, m_spec, m_numValues, getName());
	}
};

class FindLSBCaseInstance : public IntegerFunctionTestInstance
{
public:
	FindLSBCaseInstance (Context& context, glu::ShaderType shaderType, const ShaderSpec& spec, int numValues, const char* name)
		: IntegerFunctionTestInstance	(context, shaderType, spec, numValues, name)
	{
	}

	void getInputValues (int numValues, void* const* values) const
	{
		de::Random				rnd			(deStringHash(m_name) ^ 0x9923c2af);
		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
		deUint32*				inValue		= (deUint32*)values[0];

		generateRandomInputData(rnd, m_shaderType, type, precision, inValue, numValues);
	}

	bool compare (const void* const* inputs, const void* const* outputs)
	{
		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
		const int				scalarSize		= glu::getDataTypeScalarSize(type);
		const int				integerLength	= getShaderUintBitCount(m_shaderType, precision);
		const deUint32			mask			= getLowBitMask(integerLength);

		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
		{
			const deUint32	value	= ((const deUint32*)inputs[0])[compNdx];
			const int		out		= ((const int*)outputs[0])[compNdx];
			const int		minRef	= findLSB(value&mask);
			const int		maxRef	= findLSB(value);

			if (!de::inRange(out, minRef, maxRef))
			{
				m_failMsg << "Expected [" << compNdx << "] in range [" << minRef << ", " << maxRef << "]";
				return false;
			}
		}

		return true;
	}
};

class FindLSBCase : public IntegerFunctionCase
{
public:
	FindLSBCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
		: IntegerFunctionCase	(testCtx, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "findLSB", shaderType)
	{
		const int			vecSize		= glu::getDataTypeScalarSize(baseType);
		const glu::DataType	intType		= vecSize == 1 ? glu::TYPE_INT : glu::getDataTypeIntVec(vecSize);

		m_spec.inputs.push_back(Symbol("value", glu::VarType(baseType, precision)));
		m_spec.outputs.push_back(Symbol("lsb", glu::VarType(intType, glu::PRECISION_LOWP)));
		m_spec.source = "lsb = findLSB(value);";
	}

	TestInstance* createInstance (Context& ctx) const
	{
		return new FindLSBCaseInstance(ctx, m_shaderType, m_spec, m_numValues, getName());
	}
};

class findMSBCaseInstance : public IntegerFunctionTestInstance
{
public:
	findMSBCaseInstance (Context& context, glu::ShaderType shaderType, const ShaderSpec& spec, int numValues, const char* name)
		: IntegerFunctionTestInstance	(context, shaderType, spec, numValues, name)
	{
	}

	void getInputValues (int numValues, void* const* values) const
	{
		de::Random				rnd			(deStringHash(m_name) ^ 0x742ac4e);
		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
		deUint32*				inValue		= (deUint32*)values[0];

		generateRandomInputData(rnd, m_shaderType, type, precision, inValue, numValues);
	}

	bool compare (const void* const* inputs, const void* const* outputs)
	{
		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
		const bool				isSigned		= glu::isDataTypeIntOrIVec(type);
		const int				scalarSize		= glu::getDataTypeScalarSize(type);
		const int				integerLength	= getShaderUintBitCount(m_shaderType, precision);

		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
		{
			const deUint32	value	= ((const deUint32*)inputs[0])[compNdx];
			const int		out		= ((const deInt32*)outputs[0])[compNdx];
			const int		minRef	= isSigned ? findMSB(toPrecision(deInt32(value), integerLength))	: findMSB(toPrecision(value, integerLength));
			const int		maxRef	= isSigned ? findMSB(deInt32(value))								: findMSB(value);

			if (!de::inRange(out, minRef, maxRef))
			{
				m_failMsg << "Expected [" << compNdx << "] in range [" << minRef << ", " << maxRef << "]";
				return false;
			}
		}

		return true;
	}
};

class findMSBCase : public IntegerFunctionCase
{
public:
	findMSBCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
		: IntegerFunctionCase	(testCtx, getIntegerFuncCaseName(baseType, precision, shaderType).c_str(), "findMSB", shaderType)
	{
		const int			vecSize		= glu::getDataTypeScalarSize(baseType);
		const glu::DataType	intType		= vecSize == 1 ? glu::TYPE_INT : glu::getDataTypeIntVec(vecSize);

		m_spec.inputs.push_back(Symbol("value", glu::VarType(baseType, precision)));
		m_spec.outputs.push_back(Symbol("msb", glu::VarType(intType, glu::PRECISION_LOWP)));
		m_spec.source = "msb = findMSB(value);";
	}

	TestInstance* createInstance (Context& ctx) const
	{
		return new findMSBCaseInstance(ctx, m_shaderType, m_spec, m_numValues, getName());
	}
};

ShaderIntegerFunctionTests::ShaderIntegerFunctionTests (tcu::TestContext& testCtx)
	: tcu::TestCaseGroup	(testCtx, "integer", "Integer function tests")
{
}

ShaderIntegerFunctionTests::~ShaderIntegerFunctionTests (void)
{
}

void ShaderIntegerFunctionTests::init (void)
{
	enum
	{
		VS = (1<<glu::SHADERTYPE_VERTEX),
		FS = (1<<glu::SHADERTYPE_FRAGMENT),
		CS = (1<<glu::SHADERTYPE_COMPUTE),
		GS = (1<<glu::SHADERTYPE_GEOMETRY),
		TC = (1<<glu::SHADERTYPE_TESSELLATION_CONTROL),
		TE = (1<<glu::SHADERTYPE_TESSELLATION_EVALUATION),

		ALL_SHADERS = VS|TC|TE|GS|FS|CS
	};

	//																		Int?	Uint?	AllPrec?	Shaders
	addFunctionCases<UaddCarryCase>				(this,	"uaddcarry",		false,	true,	true,		ALL_SHADERS);
	addFunctionCases<UsubBorrowCase>			(this,	"usubborrow",		false,	true,	true,		ALL_SHADERS);
	addFunctionCases<UmulExtendedCase>			(this,	"umulextended",		false,	true,	false,		ALL_SHADERS);
	addFunctionCases<ImulExtendedCase>			(this,	"imulextended",		true,	false,	false,		ALL_SHADERS);
	addFunctionCases<BitfieldExtractCase>		(this,	"bitfieldextract",	true,	true,	true,		ALL_SHADERS);
	addFunctionCases<BitfieldInsertCase>		(this,	"bitfieldinsert",	true,	true,	true,		ALL_SHADERS);
	addFunctionCases<BitfieldReverseCase>		(this,	"bitfieldreverse",	true,	true,	true,		ALL_SHADERS);
	addFunctionCases<BitCountCase>				(this,	"bitcount",			true,	true,	true,		ALL_SHADERS);
	addFunctionCases<FindLSBCase>				(this,	"findlsb",			true,	true,	true,		ALL_SHADERS);
	addFunctionCases<findMSBCase>				(this,	"findMSB",			true,	true,	true,		ALL_SHADERS);
}

} // shaderexecutor
} // vkt
