/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL ES 3.0 Module
 * -------------------------------------------------
 *
 * Copyright 2014 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 Common built-in function tests.
 *//*--------------------------------------------------------------------*/

#include "es3fShaderCommonFunctionTests.hpp"
#include "glsShaderExecUtil.hpp"
#include "tcuTestLog.hpp"
#include "tcuFormatUtil.hpp"
#include "tcuFloat.hpp"
#include "deRandom.hpp"
#include "deMath.h"
#include "deString.h"

namespace deqp
{
namespace gles3
{
namespace Functional
{

using std::vector;
using std::string;
using tcu::TestLog;
using namespace gls::ShaderExecUtil;

using tcu::Vec2;
using tcu::Vec3;
using tcu::Vec4;
using tcu::IVec2;
using tcu::IVec3;
using tcu::IVec4;

// Utilities

template<typename T, int Size>
struct VecArrayAccess
{
public:
									VecArrayAccess	(const void* ptr) : m_array((tcu::Vector<T, Size>*)ptr) {}
									~VecArrayAccess	(void) {}

	const tcu::Vector<T, Size>&		operator[]		(size_t offset) const	{ return m_array[offset];	}
	tcu::Vector<T, Size>&			operator[]		(size_t offset)			{ return m_array[offset];	}

private:
	tcu::Vector<T, Size>*			m_array;
};

template<typename T>	T			randomScalar	(de::Random& rnd, T minValue, T maxValue);
template<> inline		float		randomScalar	(de::Random& rnd, float minValue, float maxValue)		{ return rnd.getFloat(minValue, maxValue);	}
template<> inline		deInt32		randomScalar	(de::Random& rnd, deInt32 minValue, deInt32 maxValue)	{ return rnd.getInt(minValue, maxValue);	}
template<> inline		deUint32	randomScalar	(de::Random& rnd, deUint32 minValue, deUint32 maxValue)	{ return minValue + rnd.getUint32() % (maxValue - minValue + 1); }

template<typename T, int Size>
inline tcu::Vector<T, Size> randomVector (de::Random& rnd, const tcu::Vector<T, Size>& minValue, const tcu::Vector<T, Size>& maxValue)
{
	tcu::Vector<T, Size> res;
	for (int ndx = 0; ndx < Size; ndx++)
		res[ndx] = randomScalar<T>(rnd, minValue[ndx], maxValue[ndx]);
	return res;
}

template<typename T, int Size>
static void fillRandomVectors (de::Random& rnd, const tcu::Vector<T, Size>& minValue, const tcu::Vector<T, Size>& maxValue, void* dst, int numValues, int offset = 0)
{
	VecArrayAccess<T, Size> access(dst);
	for (int ndx = 0; ndx < numValues; ndx++)
		access[offset + ndx] = randomVector<T, Size>(rnd, minValue, maxValue);
}

template<typename T>
static void fillRandomScalars (de::Random& rnd, T minValue, T maxValue, void* dst, int numValues, int offset = 0)
{
	T* typedPtr = (T*)dst;
	for (int ndx = 0; ndx < numValues; ndx++)
		typedPtr[offset + ndx] = randomScalar<T>(rnd, minValue, maxValue);
}

inline int numBitsLostInOp (float input, float output)
{
	const int	inExp		= tcu::Float32(input).exponent();
	const int	outExp		= tcu::Float32(output).exponent();

	return de::max(0, inExp-outExp); // Lost due to mantissa shift.
}

inline deUint32 getUlpDiff (float a, float b)
{
	const deUint32	aBits	= tcu::Float32(a).bits();
	const deUint32	bBits	= tcu::Float32(b).bits();
	return aBits > bBits ? aBits - bBits : bBits - aBits;
}

inline deUint32 getUlpDiffIgnoreZeroSign (float a, float b)
{
	if (tcu::Float32(a).isZero())
		return getUlpDiff(tcu::Float32::construct(tcu::Float32(b).sign(), 0, 0).asFloat(), b);
	else if (tcu::Float32(b).isZero())
		return getUlpDiff(a, tcu::Float32::construct(tcu::Float32(a).sign(), 0, 0).asFloat());
	else
		return getUlpDiff(a, b);
}

inline bool supportsSignedZero (glu::Precision precision)
{
	// \note GLSL ES 3.0 doesn't really require support for -0, but we require it for highp
	//		 as it is very widely supported.
	return precision == glu::PRECISION_HIGHP;
}

inline float getEpsFromMaxUlpDiff (float value, deUint32 ulpDiff)
{
	const int exp = tcu::Float32(value).exponent();
	return tcu::Float32::construct(+1, exp, (1u<<23) | ulpDiff).asFloat() - tcu::Float32::construct(+1, exp, 1u<<23).asFloat();
}

inline deUint32 getMaxUlpDiffFromBits (int numAccurateBits)
{
	const int		numGarbageBits	= 23-numAccurateBits;
	const deUint32	mask			= (1u<<numGarbageBits)-1u;

	return mask;
}

inline float getEpsFromBits (float value, int numAccurateBits)
{
	return getEpsFromMaxUlpDiff(value, getMaxUlpDiffFromBits(numAccurateBits));
}

static int getMinMantissaBits (glu::Precision precision)
{
	const int bits[] =
	{
		7,		// lowp
		10,		// mediump
		23		// highp
	};
	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(bits) == glu::PRECISION_LAST);
	DE_ASSERT(de::inBounds<int>(precision, 0, DE_LENGTH_OF_ARRAY(bits)));
	return bits[precision];
}

// CommonFunctionCase

class CommonFunctionCase : public TestCase
{
public:
							CommonFunctionCase		(Context& context, const char* name, const char* description, glu::ShaderType shaderType);
							~CommonFunctionCase		(void);

	void					init					(void);
	void					deinit					(void);
	IterateResult			iterate					(void);

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

	virtual void			getInputValues			(int numValues, void* const* values) const = 0;
	virtual bool			compare					(const void* const* inputs, const void* const* outputs) = 0;

	glu::ShaderType			m_shaderType;
	ShaderSpec				m_spec;
	int						m_numValues;

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

private:
	ShaderExecutor*			m_executor;
};

CommonFunctionCase::CommonFunctionCase (Context& context, const char* name, const char* description, glu::ShaderType shaderType)
	: TestCase		(context, name, description)
	, m_shaderType	(shaderType)
	, m_numValues	(100)
	, m_executor	(DE_NULL)
{
	m_spec.version = glu::GLSL_VERSION_300_ES;
}

CommonFunctionCase::~CommonFunctionCase (void)
{
	CommonFunctionCase::deinit();
}

void CommonFunctionCase::init (void)
{
	DE_ASSERT(!m_executor);

	m_executor = createExecutor(m_context.getRenderContext(), m_shaderType, m_spec);
	m_testCtx.getLog() << m_executor;

	if (!m_executor->isOk())
		throw tcu::TestError("Compile failed");
}

void CommonFunctionCase::deinit (void)
{
	delete m_executor;
	m_executor = DE_NULL;
}

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;
}

// \todo [2013-08-08 pyry] Make generic utility and move to glu?

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 HexBool
{
	const deUint32 value;
	HexBool (const deUint32 value_) : value(value_) {}
};

std::ostream& operator<< (std::ostream& str, const HexBool& v)
{
	return str << (v.value ? "true" : "false") << " / " << tcu::toHex(v.value);
}

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 << HexBool(((const deUint32*)varValue.value)[compNdx]);			break;

			default:
				DE_ASSERT(false);
		}
	}

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

	return str;
}

CommonFunctionCase::IterateResult CommonFunctionCase::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->useProgram();
	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;

		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?

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

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

				m_testCtx.getLog() << TestLog::Message << "  outputs:" << TestLog::EndMessage;
				for (int outNdx = 0; outNdx < (int)curOutputPtr.size(); outNdx++)
					m_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;
			}
		}

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

		m_testCtx.setTestResult(numFailed == 0 ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
								numFailed == 0 ? "Pass"					: "Result comparison failed");
	}

	return STOP;
}

static const char* getPrecisionPostfix (glu::Precision precision)
{
	static const char* s_postfix[] =
	{
		"_lowp",
		"_mediump",
		"_highp"
	};
	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_postfix) == glu::PRECISION_LAST);
	DE_ASSERT(de::inBounds<int>(precision, 0, DE_LENGTH_OF_ARRAY(s_postfix)));
	return s_postfix[precision];
}

static const char* getShaderTypePostfix (glu::ShaderType shaderType)
{
	static const char* s_postfix[] =
	{
		"_vertex",
		"_fragment"
	};
	DE_ASSERT(de::inBounds<int>(shaderType, 0, DE_LENGTH_OF_ARRAY(s_postfix)));
	return s_postfix[shaderType];
}

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

class AbsCase : public CommonFunctionCase
{
public:
	AbsCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "abs", shaderType)
	{
		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
		m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
		m_spec.source = "out0 = abs(in0);";
	}

	void getInputValues (int numValues, void* const* values) const
	{
		const Vec2 floatRanges[] =
		{
			Vec2(-2.0f,		2.0f),	// lowp
			Vec2(-1e3f,		1e3f),	// mediump
			Vec2(-1e7f,		1e7f)	// highp
		};
		const IVec2 intRanges[] =
		{
			IVec2(-(1<<7)+1,	(1<<7)-1),
			IVec2(-(1<<15)+1,	(1<<15)-1),
			IVec2(0x80000001,	0x7fffffff)
		};

		de::Random				rnd			(deStringHash(getName()) ^ 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);

		if (glu::isDataTypeFloatOrVec(type))
			fillRandomScalars(rnd, floatRanges[precision].x(), floatRanges[precision].y(), values[0], numValues*scalarSize);
		else
			fillRandomScalars(rnd, intRanges[precision].x(), intRanges[precision].y(), values[0], numValues*scalarSize);
	}

	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);

		if (glu::isDataTypeFloatOrVec(type))
		{
			const int		mantissaBits	= getMinMantissaBits(precision);
			const deUint32	maxUlpDiff		= (1u<<(23-mantissaBits))-1u;

			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
			{
				const float		in0			= ((const float*)inputs[0])[compNdx];
				const float		out0		= ((const float*)outputs[0])[compNdx];
				const float		ref0		= de::abs(in0);
				const deUint32	ulpDiff0	= getUlpDiff(out0, ref0);

				if (ulpDiff0 > maxUlpDiff)
				{
					m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref0) << " with ULP threshold " << maxUlpDiff << ", got ULP diff " << ulpDiff0;
					return false;
				}
			}
		}
		else
		{
			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
			{
				const int	in0		= ((const int*)inputs[0])[compNdx];
				const int	out0	= ((const int*)outputs[0])[compNdx];
				const int	ref0	= de::abs(in0);

				if (out0 != ref0)
				{
					m_failMsg << "Expected [" << compNdx << "] = " << ref0;
					return false;
				}
			}
		}

		return true;
	}
};

class SignCase : public CommonFunctionCase
{
public:
	SignCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "sign", shaderType)
	{
		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
		m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
		m_spec.source = "out0 = sign(in0);";
	}

	void getInputValues (int numValues, void* const* values) const
	{
		const Vec2 floatRanges[] =
		{
			Vec2(-2.0f,		2.0f),	// lowp
			Vec2(-1e4f,		1e4f),	// mediump	- note: may end up as inf
			Vec2(-1e8f,		1e8f)	// highp	- note: may end up as inf
		};
		const IVec2 intRanges[] =
		{
			IVec2(-(1<<7),		(1<<7)-1),
			IVec2(-(1<<15),		(1<<15)-1),
			IVec2(0x80000000,	0x7fffffff)
		};

		de::Random				rnd			(deStringHash(getName()) ^ 0x324u);
		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);

		if (glu::isDataTypeFloatOrVec(type))
		{
			// Special cases.
			std::fill((float*)values[0],				(float*)values[0] + scalarSize,		+1.0f);
			std::fill((float*)values[0] + scalarSize*1,	(float*)values[0] + scalarSize*2,	-1.0f);
			std::fill((float*)values[0] + scalarSize*2,	(float*)values[0] + scalarSize*3,	0.0f);
			fillRandomScalars(rnd, floatRanges[precision].x(), floatRanges[precision].y(), (float*)values[0] + scalarSize*3, (numValues-3)*scalarSize);
		}
		else
		{
			std::fill((int*)values[0],					(int*)values[0] + scalarSize,		+1);
			std::fill((int*)values[0] + scalarSize*1,	(int*)values[0] + scalarSize*2,		-1);
			std::fill((int*)values[0] + scalarSize*2,	(int*)values[0] + scalarSize*3,		0);
			fillRandomScalars(rnd, intRanges[precision].x(), intRanges[precision].y(), (int*)values[0] + scalarSize*3, (numValues-3)*scalarSize);
		}
	}

	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);

		if (glu::isDataTypeFloatOrVec(type))
		{
			// Both highp and mediump should be able to represent -1, 0, and +1 exactly
			const deUint32 maxUlpDiff = precision == glu::PRECISION_LOWP ? getMaxUlpDiffFromBits(getMinMantissaBits(precision)) : 0;

			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
			{
				const float		in0			= ((const float*)inputs[0])[compNdx];
				const float		out0		= ((const float*)outputs[0])[compNdx];
				const float		ref0		= in0 < 0.0f ? -1.0f :
											  in0 > 0.0f ? +1.0f : 0.0f;
				const deUint32	ulpDiff0	= getUlpDiff(out0, ref0);

				if (ulpDiff0 > maxUlpDiff)
				{
					m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref0) << " with ULP threshold " << maxUlpDiff << ", got ULP diff " << ulpDiff0;
					return false;
				}
			}
		}
		else
		{
			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
			{
				const int	in0		= ((const int*)inputs[0])[compNdx];
				const int	out0	= ((const int*)outputs[0])[compNdx];
				const int	ref0	= in0 < 0 ? -1 :
									  in0 > 0 ? +1 : 0;

				if (out0 != ref0)
				{
					m_failMsg << "Expected [" << compNdx << "] = " << ref0;
					return false;
				}
			}
		}

		return true;
	}
};

static float roundEven (float v)
{
	const float		q			= deFloatFrac(v);
	const int		truncated	= int(v-q);
	const int		rounded		= (q > 0.5f)							? (truncated + 1) :	// Rounded up
									(q == 0.5f && (truncated % 2 != 0))	? (truncated + 1) :	// Round to nearest even at 0.5
									truncated;												// Rounded down

	return float(rounded);
}

class RoundEvenCase : public CommonFunctionCase
{
public:
	RoundEvenCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "roundEven", shaderType)
	{
		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
		m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
		m_spec.source = "out0 = roundEven(in0);";
	}

	void getInputValues (int numValues, void* const* values) const
	{
		const Vec2 ranges[] =
		{
			Vec2(-2.0f,		2.0f),	// lowp
			Vec2(-1e3f,		1e3f),	// mediump
			Vec2(-1e7f,		1e7f)	// highp
		};

		de::Random				rnd				(deStringHash(getName()) ^ 0xac23fu);
		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);
		int						numSpecialCases	= 0;

		// Special cases.
		if (precision != glu::PRECISION_LOWP)
		{
			DE_ASSERT(numValues >= 20);
			for (int ndx = 0; ndx < 20; ndx++)
			{
				const float v = de::clamp(float(ndx) - 10.5f, ranges[precision].x(), ranges[precision].y());
				std::fill((float*)values[0], (float*)values[0] + scalarSize, v);
				numSpecialCases += 1;
			}
		}

		// Random cases.
		fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[0] + numSpecialCases*scalarSize, (numValues-numSpecialCases)*scalarSize);

		// If precision is mediump, make sure values can be represented in fp16 exactly
		if (precision == glu::PRECISION_MEDIUMP)
		{
			for (int ndx = 0; ndx < numValues*scalarSize; ndx++)
				((float*)values[0])[ndx] = tcu::Float16(((float*)values[0])[ndx]).asFloat();
		}
	}

	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				hasSignedZero	= supportsSignedZero(precision);
		const int				scalarSize		= glu::getDataTypeScalarSize(type);

		if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP)
		{
			// Require exact rounding result.
			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
			{
				const float		in0			= ((const float*)inputs[0])[compNdx];
				const float		out0		= ((const float*)outputs[0])[compNdx];
				const float		ref			= roundEven(in0);

				const deUint32	ulpDiff		= hasSignedZero ? getUlpDiff(out0, ref) : getUlpDiffIgnoreZeroSign(out0, ref);

				if (ulpDiff > 0)
				{
					m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff " << tcu::toHex(ulpDiff);
					return false;
				}
			}
		}
		else
		{
			const int		mantissaBits	= getMinMantissaBits(precision);
			const deUint32	maxUlpDiff		= getMaxUlpDiffFromBits(mantissaBits);	// ULP diff for rounded integer value.
			const float		eps				= getEpsFromBits(1.0f, mantissaBits);	// epsilon for rounding bounds

			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
			{
				const float		in0			= ((const float*)inputs[0])[compNdx];
				const float		out0		= ((const float*)outputs[0])[compNdx];
				const int		minRes		= int(roundEven(in0-eps));
				const int		maxRes		= int(roundEven(in0+eps));
				bool			anyOk		= false;

				for (int roundedVal = minRes; roundedVal <= maxRes; roundedVal++)
				{
					const deUint32 ulpDiff = getUlpDiffIgnoreZeroSign(out0, float(roundedVal));

					if (ulpDiff <= maxUlpDiff)
					{
						anyOk = true;
						break;
					}
				}

				if (!anyOk)
				{
					m_failMsg << "Expected [" << compNdx << "] = [" << minRes << ", " << maxRes << "] with ULP threshold " << tcu::toHex(maxUlpDiff);
					return false;
				}
			}
		}

		return true;
	}
};

class ModfCase : public CommonFunctionCase
{
public:
	ModfCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "modf", shaderType)
	{
		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
		m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
		m_spec.outputs.push_back(Symbol("out1", glu::VarType(baseType, precision)));
		m_spec.source = "out0 = modf(in0, out1);";
	}

	void getInputValues (int numValues, void* const* values) const
	{
		const Vec2 ranges[] =
		{
			Vec2(-2.0f,		2.0f),	// lowp
			Vec2(-1e3f,		1e3f),	// mediump
			Vec2(-1e7f,		1e7f)	// highp
		};

		de::Random				rnd			(deStringHash(getName()) ^ 0xac23fu);
		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);

		fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), values[0], numValues*scalarSize);
	}

	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				hasZeroSign		= supportsSignedZero(precision);
		const int				scalarSize		= glu::getDataTypeScalarSize(type);

		const int				mantissaBits	= getMinMantissaBits(precision);

		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
		{
			const float		in0			= ((const float*)inputs[0])[compNdx];
			const float		out0		= ((const float*)outputs[0])[compNdx];
			const float		out1		= ((const float*)outputs[1])[compNdx];

			const float		refOut1		= float(int(in0));
			const float		refOut0		= in0 - refOut1;

			const int		bitsLost	= precision != glu::PRECISION_HIGHP ? numBitsLostInOp(in0, refOut0) : 0;
			const deUint32	maxUlpDiff	= getMaxUlpDiffFromBits(de::max(mantissaBits - bitsLost, 0));

			const float		resSum		= out0 + out1;

			const deUint32	ulpDiff		= hasZeroSign ? getUlpDiff(resSum, in0) : getUlpDiffIgnoreZeroSign(resSum, in0);

			if (ulpDiff > maxUlpDiff)
			{
				m_failMsg << "Expected [" << compNdx << "] = (" << HexFloat(refOut0) << ") + (" << HexFloat(refOut1) << ") = " << HexFloat(in0) << " with ULP threshold "
							<< tcu::toHex(maxUlpDiff) << ", got ULP diff " << tcu::toHex(ulpDiff);
				return false;
			}
		}

		return true;
	}
};

class IsnanCase : public CommonFunctionCase
{
public:
	IsnanCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "isnan", shaderType)
	{
		DE_ASSERT(glu::isDataTypeFloatOrVec(baseType));

		const int			vecSize		= glu::getDataTypeScalarSize(baseType);
		const glu::DataType	boolType	= vecSize > 1 ? glu::getDataTypeBoolVec(vecSize) : glu::TYPE_BOOL;

		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
		m_spec.outputs.push_back(Symbol("out0", glu::VarType(boolType, glu::PRECISION_LAST)));
		m_spec.source = "out0 = isnan(in0);";
	}

	void getInputValues (int numValues, void* const* values) const
	{
		de::Random				rnd				(deStringHash(getName()) ^ 0xc2a39fu);
		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				mantissaBits	= getMinMantissaBits(precision);
		const deUint32			mantissaMask	= ~getMaxUlpDiffFromBits(mantissaBits) & ((1u<<23)-1u);

		for (int valNdx = 0; valNdx < numValues*scalarSize; valNdx++)
		{
			const bool		isNan		= rnd.getFloat() > 0.3f;
			const bool		isInf		= !isNan && rnd.getFloat() > 0.4f;
			const deUint32	mantissa	= !isInf ? ((1u<<22) | (rnd.getUint32() & mantissaMask)) : 0;
			const deUint32	exp			= !isNan && !isInf ? (rnd.getUint32() & 0x7fu) : 0xffu;
			const deUint32	sign		= rnd.getUint32() & 0x1u;
			const deUint32	value		= (sign << 31) | (exp << 23) | mantissa;

			DE_ASSERT(tcu::Float32(value).isInf() == isInf && tcu::Float32(value).isNaN() == isNan);

			((deUint32*)values[0])[valNdx] = value;
		}
	}

	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);

		if (precision == glu::PRECISION_HIGHP)
		{
			// Only highp is required to support inf/nan
			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
			{
				const float		in0		= ((const float*)inputs[0])[compNdx];
				const deUint32	out0	= ((const deUint32*)outputs[0])[compNdx];
				const deUint32	ref		= tcu::Float32(in0).isNaN() ? 1u : 0u;

				if (out0 != ref)
				{
					m_failMsg << "Expected [" << compNdx << "] = " << HexBool(ref);
					return false;
				}
			}
		}
		else
		{
			// Value can be either 0 or 1
			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
			{
				const int out0 = ((const int*)outputs[0])[compNdx];

				if (out0 != 0 && out0 != 1)
				{
					m_failMsg << "Expected [" << compNdx << "] = 0 / 1";
					return false;
				}
			}
		}

		return true;
	}
};

class IsinfCase : public CommonFunctionCase
{
public:
	IsinfCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "isinf", shaderType)
	{
		DE_ASSERT(glu::isDataTypeFloatOrVec(baseType));

		const int			vecSize		= glu::getDataTypeScalarSize(baseType);
		const glu::DataType	boolType	= vecSize > 1 ? glu::getDataTypeBoolVec(vecSize) : glu::TYPE_BOOL;

		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
		m_spec.outputs.push_back(Symbol("out0", glu::VarType(boolType, glu::PRECISION_LAST)));
		m_spec.source = "out0 = isinf(in0);";
	}

	void getInputValues (int numValues, void* const* values) const
	{
		de::Random				rnd				(deStringHash(getName()) ^ 0xc2a39fu);
		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				mantissaBits	= getMinMantissaBits(precision);
		const deUint32			mantissaMask	= ~getMaxUlpDiffFromBits(mantissaBits) & ((1u<<23)-1u);

		for (int valNdx = 0; valNdx < numValues*scalarSize; valNdx++)
		{
			const bool		isInf		= rnd.getFloat() > 0.3f;
			const bool		isNan		= !isInf && rnd.getFloat() > 0.4f;
			const deUint32	mantissa	= !isInf ? ((1u<<22) | (rnd.getUint32() & mantissaMask)) : 0;
			const deUint32	exp			= !isNan && !isInf ? (rnd.getUint32() & 0x7fu) : 0xffu;
			const deUint32	sign		= rnd.getUint32() & 0x1u;
			const deUint32	value		= (sign << 31) | (exp << 23) | mantissa;

			DE_ASSERT(tcu::Float32(value).isInf() == isInf && tcu::Float32(value).isNaN() == isNan);

			((deUint32*)values[0])[valNdx] = value;
		}
	}

	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);

		if (precision == glu::PRECISION_HIGHP)
		{
			// Only highp is required to support inf/nan
			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
			{
				const float		in0		= ((const float*)inputs[0])[compNdx];
				const deUint32	out0	= ((const deUint32*)outputs[0])[compNdx];
				const deUint32	ref		= tcu::Float32(in0).isInf() ? 1u : 0u;

				if (out0 != ref)
				{
					m_failMsg << "Expected [" << compNdx << "] = " << HexBool(ref);
					return false;
				}
			}
		}
		else
		{
			// Value can be either 0 or 1
			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
			{
				const int out0 = ((const int*)outputs[0])[compNdx];

				if (out0 != 0 && out0 != 1)
				{
					m_failMsg << "Expected [" << compNdx << "] = 0 / 1";
					return false;
				}
			}
		}

		return true;
	}
};

class FloatBitsToUintIntCase : public CommonFunctionCase
{
public:
	FloatBitsToUintIntCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType, bool outIsSigned)
		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), outIsSigned ? "floatBitsToInt" : "floatBitsToUint", shaderType)
	{
		const int			vecSize		= glu::getDataTypeScalarSize(baseType);
		const glu::DataType	intType		= outIsSigned ? (vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT)
													  : (vecSize > 1 ? glu::getDataTypeUintVec(vecSize) : glu::TYPE_UINT);

		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
		m_spec.outputs.push_back(Symbol("out0", glu::VarType(intType, glu::PRECISION_HIGHP)));
		m_spec.source = outIsSigned ? "out0 = floatBitsToInt(in0);" : "out0 = floatBitsToUint(in0);";
	}

	void getInputValues (int numValues, void* const* values) const
	{
		const Vec2 ranges[] =
		{
			Vec2(-2.0f,		2.0f),	// lowp
			Vec2(-1e3f,		1e3f),	// mediump
			Vec2(-1e7f,		1e7f)	// highp
		};

		de::Random				rnd			(deStringHash(getName()) ^ 0x2790au);
		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);

		fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), values[0], numValues*scalarSize);
	}

	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				mantissaBits	= getMinMantissaBits(precision);
		const int				maxUlpDiff		= getMaxUlpDiffFromBits(mantissaBits);

		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
		{
			const float		in0			= ((const float*)inputs[0])[compNdx];
			const deUint32	out0		= ((const deUint32*)outputs[0])[compNdx];
			const deUint32	refOut0		= tcu::Float32(in0).bits();
			const int		ulpDiff		= de::abs((int)out0 - (int)refOut0);

			if (ulpDiff > maxUlpDiff)
			{
				m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(refOut0) << " with threshold "
							<< tcu::toHex(maxUlpDiff) << ", got diff " << tcu::toHex(ulpDiff);
				return false;
			}
		}

		return true;
	}
};

class FloatBitsToIntCase : public FloatBitsToUintIntCase
{
public:
	FloatBitsToIntCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
		: FloatBitsToUintIntCase(context, baseType, precision, shaderType, true)
	{
	}
};

class FloatBitsToUintCase : public FloatBitsToUintIntCase
{
public:
	FloatBitsToUintCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
		: FloatBitsToUintIntCase(context, baseType, precision, shaderType, false)
	{
	}
};

class BitsToFloatCase : public CommonFunctionCase
{
public:
	BitsToFloatCase (Context& context, glu::DataType baseType, glu::ShaderType shaderType)
		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, glu::PRECISION_HIGHP, shaderType).c_str(), glu::isDataTypeIntOrIVec(baseType) ? "intBitsToFloat" : "uintBitsToFloat", shaderType)
	{
		const bool			inIsSigned	= glu::isDataTypeIntOrIVec(baseType);
		const int			vecSize		= glu::getDataTypeScalarSize(baseType);
		const glu::DataType	floatType	= vecSize > 1 ? glu::getDataTypeFloatVec(vecSize) : glu::TYPE_FLOAT;

		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, glu::PRECISION_HIGHP)));
		m_spec.outputs.push_back(Symbol("out0", glu::VarType(floatType, glu::PRECISION_HIGHP)));
		m_spec.source = inIsSigned ? "out0 = intBitsToFloat(in0);" : "out0 = uintBitsToFloat(in0);";
	}

	void getInputValues (int numValues, void* const* values) const
	{
		de::Random				rnd			(deStringHash(getName()) ^ 0xbbb225u);
		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
		const int				scalarSize	= glu::getDataTypeScalarSize(type);
		const Vec2				range		(-1e8f, +1e8f);

		// \note Filled as floats.
		fillRandomScalars(rnd, range.x(), range.y(), values[0], numValues*scalarSize);
	}

	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);
		const deUint32			maxUlpDiff		= 0;

		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
		{
			const float		in0			= ((const float*)inputs[0])[compNdx];
			const float		out0		= ((const float*)outputs[0])[compNdx];
			const deUint32	ulpDiff		= getUlpDiff(in0, out0);

			if (ulpDiff > maxUlpDiff)
			{
				m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(tcu::Float32(in0).bits()) << " with ULP threshold "
							<< tcu::toHex(maxUlpDiff) << ", got ULP diff " << tcu::toHex(ulpDiff);
				return false;
			}
		}

		return true;
	}
};

class FloorCase : public CommonFunctionCase
{
public:
	FloorCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "floor", shaderType)
	{
		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
		m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
		m_spec.source = "out0 = floor(in0);";
	}

	void getInputValues (int numValues, void* const* values) const
	{
		const Vec2 ranges[] =
		{
			Vec2(-2.0f,		2.0f),	// lowp
			Vec2(-1e3f,		1e3f),	// mediump
			Vec2(-1e7f,		1e7f)	// highp
		};

		de::Random				rnd			(deStringHash(getName()) ^ 0xac23fu);
		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);
		// Random cases.
		fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[0], numValues*scalarSize);

		// If precision is mediump, make sure values can be represented in fp16 exactly
		if (precision == glu::PRECISION_MEDIUMP)
		{
			for (int ndx = 0; ndx < numValues*scalarSize; ndx++)
				((float*)values[0])[ndx] = tcu::Float16(((float*)values[0])[ndx]).asFloat();
		}
	}

	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);

		if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP)
		{
			// Require exact result.
			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
			{
				const float		in0			= ((const float*)inputs[0])[compNdx];
				const float		out0		= ((const float*)outputs[0])[compNdx];
				const float		ref			= deFloatFloor(in0);

				const deUint32	ulpDiff		= getUlpDiff(out0, ref);

				if (ulpDiff > 0)
				{
					m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff " << tcu::toHex(ulpDiff);
					return false;
				}
			}
		}
		else
		{
			const int		mantissaBits	= getMinMantissaBits(precision);
			const deUint32	maxUlpDiff		= getMaxUlpDiffFromBits(mantissaBits);	// ULP diff for rounded integer value.
			const float		eps				= getEpsFromBits(1.0f, mantissaBits);	// epsilon for rounding bounds

			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
			{
				const float		in0			= ((const float*)inputs[0])[compNdx];
				const float		out0		= ((const float*)outputs[0])[compNdx];
				const int		minRes		= int(deFloatFloor(in0-eps));
				const int		maxRes		= int(deFloatFloor(in0+eps));
				bool			anyOk		= false;

				for (int roundedVal = minRes; roundedVal <= maxRes; roundedVal++)
				{
					const deUint32 ulpDiff = getUlpDiff(out0, float(roundedVal));

					if (ulpDiff <= maxUlpDiff)
					{
						anyOk = true;
						break;
					}
				}

				if (!anyOk)
				{
					m_failMsg << "Expected [" << compNdx << "] = [" << minRes << ", " << maxRes << "] with ULP threshold " << tcu::toHex(maxUlpDiff);
					return false;
				}
			}
		}

		return true;
	}
};

class TruncCase : public CommonFunctionCase
{
public:
	TruncCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "trunc", shaderType)
	{
		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
		m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
		m_spec.source = "out0 = trunc(in0);";
	}

	void getInputValues (int numValues, void* const* values) const
	{
		const Vec2 ranges[] =
		{
			Vec2(-2.0f,		2.0f),	// lowp
			Vec2(-1e3f,		1e3f),	// mediump
			Vec2(-1e7f,		1e7f)	// highp
		};

		de::Random				rnd				(deStringHash(getName()) ^ 0xac23fu);
		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 float				specialCases[]	= { 0.0f, -0.0f, -0.9f, 0.9f, 1.0f, -1.0f };
		const int				numSpecialCases	= DE_LENGTH_OF_ARRAY(specialCases);

		// Special cases
		for (int caseNdx = 0; caseNdx < numSpecialCases; caseNdx++)
		{
			for (int scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++)
				((float*)values[0])[caseNdx*scalarSize + scalarNdx] = specialCases[caseNdx];
		}

		// Random cases.
		fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[0] + scalarSize*numSpecialCases, (numValues-numSpecialCases)*scalarSize);

		// If precision is mediump, make sure values can be represented in fp16 exactly
		if (precision == glu::PRECISION_MEDIUMP)
		{
			for (int ndx = 0; ndx < numValues*scalarSize; ndx++)
				((float*)values[0])[ndx] = tcu::Float16(((float*)values[0])[ndx]).asFloat();
		}
	}

	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);

		if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP)
		{
			// Require exact result.
			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
			{
				const float		in0			= ((const float*)inputs[0])[compNdx];
				const float		out0		= ((const float*)outputs[0])[compNdx];
				const bool		isNeg		= tcu::Float32(in0).sign() < 0;
				const float		ref			= isNeg ? (-float(int(-in0))) : float(int(in0));

				// \note: trunc() function definition is a bit broad on negative zeros. Ignore result sign if zero.
				const deUint32	ulpDiff		= getUlpDiffIgnoreZeroSign(out0, ref);

				if (ulpDiff > 0)
				{
					m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff " << tcu::toHex(ulpDiff);
					return false;
				}
			}
		}
		else
		{
			const int		mantissaBits	= getMinMantissaBits(precision);
			const deUint32	maxUlpDiff		= getMaxUlpDiffFromBits(mantissaBits);	// ULP diff for rounded integer value.
			const float		eps				= getEpsFromBits(1.0f, mantissaBits);	// epsilon for rounding bounds

			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
			{
				const float		in0			= ((const float*)inputs[0])[compNdx];
				const float		out0		= ((const float*)outputs[0])[compNdx];
				const int		minRes		= int(in0-eps);
				const int		maxRes		= int(in0+eps);
				bool			anyOk		= false;

				for (int roundedVal = minRes; roundedVal <= maxRes; roundedVal++)
				{
					const deUint32 ulpDiff = getUlpDiffIgnoreZeroSign(out0, float(roundedVal));

					if (ulpDiff <= maxUlpDiff)
					{
						anyOk = true;
						break;
					}
				}

				if (!anyOk)
				{
					m_failMsg << "Expected [" << compNdx << "] = [" << minRes << ", " << maxRes << "] with ULP threshold " << tcu::toHex(maxUlpDiff);
					return false;
				}
			}
		}

		return true;
	}
};

class RoundCase : public CommonFunctionCase
{
public:
	RoundCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "round", shaderType)
	{
		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
		m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
		m_spec.source = "out0 = round(in0);";
	}

	void getInputValues (int numValues, void* const* values) const
	{
		const Vec2 ranges[] =
		{
			Vec2(-2.0f,		2.0f),	// lowp
			Vec2(-1e3f,		1e3f),	// mediump
			Vec2(-1e7f,		1e7f)	// highp
		};

		de::Random				rnd				(deStringHash(getName()) ^ 0xac23fu);
		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);
		int						numSpecialCases	= 0;

		// Special cases.
		if (precision != glu::PRECISION_LOWP)
		{
			DE_ASSERT(numValues >= 10);
			for (int ndx = 0; ndx < 10; ndx++)
			{
				const float v = de::clamp(float(ndx) - 5.5f, ranges[precision].x(), ranges[precision].y());
				std::fill((float*)values[0], (float*)values[0] + scalarSize, v);
				numSpecialCases += 1;
			}
		}

		// Random cases.
		fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[0] + numSpecialCases*scalarSize, (numValues-numSpecialCases)*scalarSize);

		// If precision is mediump, make sure values can be represented in fp16 exactly
		if (precision == glu::PRECISION_MEDIUMP)
		{
			for (int ndx = 0; ndx < numValues*scalarSize; ndx++)
				((float*)values[0])[ndx] = tcu::Float16(((float*)values[0])[ndx]).asFloat();
		}
	}

	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				hasZeroSign		= supportsSignedZero(precision);
		const int				scalarSize		= glu::getDataTypeScalarSize(type);

		if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP)
		{
			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
			{
				const float		in0			= ((const float*)inputs[0])[compNdx];
				const float		out0		= ((const float*)outputs[0])[compNdx];

				if (deFloatFrac(in0) == 0.5f)
				{
					// Allow both ceil(in) and floor(in)
					const float		ref0		= deFloatFloor(in0);
					const float		ref1		= deFloatCeil(in0);
					const deUint32	ulpDiff0	= hasZeroSign ? getUlpDiff(out0, ref0) : getUlpDiffIgnoreZeroSign(out0, ref0);
					const deUint32	ulpDiff1	= hasZeroSign ? getUlpDiff(out0, ref1) : getUlpDiffIgnoreZeroSign(out0, ref1);

					if (ulpDiff0 > 0 && ulpDiff1 > 0)
					{
						m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref0) << " or " << HexFloat(ref1) << ", got ULP diff " << tcu::toHex(de::min(ulpDiff0, ulpDiff1));
						return false;
					}
				}
				else
				{
					// Require exact result
					const float		ref		= roundEven(in0);
					const deUint32	ulpDiff	= hasZeroSign ? getUlpDiff(out0, ref) : getUlpDiffIgnoreZeroSign(out0, ref);

					if (ulpDiff > 0)
					{
						m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff " << tcu::toHex(ulpDiff);
						return false;
					}
				}
			}
		}
		else
		{
			const int		mantissaBits	= getMinMantissaBits(precision);
			const deUint32	maxUlpDiff		= getMaxUlpDiffFromBits(mantissaBits);	// ULP diff for rounded integer value.
			const float		eps				= getEpsFromBits(1.0f, mantissaBits);	// epsilon for rounding bounds

			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
			{
				const float		in0			= ((const float*)inputs[0])[compNdx];
				const float		out0		= ((const float*)outputs[0])[compNdx];
				const int		minRes		= int(roundEven(in0-eps));
				const int		maxRes		= int(roundEven(in0+eps));
				bool			anyOk		= false;

				for (int roundedVal = minRes; roundedVal <= maxRes; roundedVal++)
				{
					const deUint32 ulpDiff = getUlpDiffIgnoreZeroSign(out0, float(roundedVal));

					if (ulpDiff <= maxUlpDiff)
					{
						anyOk = true;
						break;
					}
				}

				if (!anyOk)
				{
					m_failMsg << "Expected [" << compNdx << "] = [" << minRes << ", " << maxRes << "] with ULP threshold " << tcu::toHex(maxUlpDiff);
					return false;
				}
			}
		}

		return true;
	}
};

class CeilCase : public CommonFunctionCase
{
public:
	CeilCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "ceil", shaderType)
	{
		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
		m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
		m_spec.source = "out0 = ceil(in0);";
	}

	void getInputValues (int numValues, void* const* values) const
	{
		const Vec2 ranges[] =
		{
			Vec2(-2.0f,		2.0f),	// lowp
			Vec2(-1e3f,		1e3f),	// mediump
			Vec2(-1e7f,		1e7f)	// highp
		};

		de::Random				rnd			(deStringHash(getName()) ^ 0xac23fu);
		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);

		// Random cases.
		fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[0], numValues*scalarSize);

		// If precision is mediump, make sure values can be represented in fp16 exactly
		if (precision == glu::PRECISION_MEDIUMP)
		{
			for (int ndx = 0; ndx < numValues*scalarSize; ndx++)
				((float*)values[0])[ndx] = tcu::Float16(((float*)values[0])[ndx]).asFloat();
		}
	}

	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				hasZeroSign		= supportsSignedZero(precision);
		const int				scalarSize		= glu::getDataTypeScalarSize(type);

		if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP)
		{
			// Require exact result.
			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
			{
				const float		in0			= ((const float*)inputs[0])[compNdx];
				const float		out0		= ((const float*)outputs[0])[compNdx];
				const float		ref			= deFloatCeil(in0);

				const deUint32	ulpDiff		= hasZeroSign ? getUlpDiff(out0, ref) : getUlpDiffIgnoreZeroSign(out0, ref);

				if (ulpDiff > 0)
				{
					m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff " << tcu::toHex(ulpDiff);
					return false;
				}
			}
		}
		else
		{
			const int		mantissaBits	= getMinMantissaBits(precision);
			const deUint32	maxUlpDiff		= getMaxUlpDiffFromBits(mantissaBits);	// ULP diff for rounded integer value.
			const float		eps				= getEpsFromBits(1.0f, mantissaBits);	// epsilon for rounding bounds

			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
			{
				const float		in0			= ((const float*)inputs[0])[compNdx];
				const float		out0		= ((const float*)outputs[0])[compNdx];
				const int		minRes		= int(deFloatCeil(in0-eps));
				const int		maxRes		= int(deFloatCeil(in0+eps));
				bool			anyOk		= false;

				for (int roundedVal = minRes; roundedVal <= maxRes; roundedVal++)
				{
					const deUint32 ulpDiff = getUlpDiffIgnoreZeroSign(out0, float(roundedVal));

					if (ulpDiff <= maxUlpDiff)
					{
						anyOk = true;
						break;
					}
				}

				if (!anyOk && de::inRange(0, minRes, maxRes))
				{
					// Allow -0 as well.
					const int ulpDiff = de::abs((int)tcu::Float32(out0).bits() - (int)0x80000000u);
					anyOk = ((deUint32)ulpDiff <= maxUlpDiff);
				}

				if (!anyOk)
				{
					m_failMsg << "Expected [" << compNdx << "] = [" << minRes << ", " << maxRes << "] with ULP threshold " << tcu::toHex(maxUlpDiff);
					return false;
				}
			}
		}

		return true;
	}
};

class FractCase : public CommonFunctionCase
{
public:
	FractCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "fract", shaderType)
	{
		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
		m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
		m_spec.source = "out0 = fract(in0);";
	}

	void getInputValues (int numValues, void* const* values) const
	{
		const Vec2 ranges[] =
		{
			Vec2(-2.0f,		2.0f),	// lowp
			Vec2(-1e3f,		1e3f),	// mediump
			Vec2(-1e7f,		1e7f)	// highp
		};

		de::Random				rnd				(deStringHash(getName()) ^ 0xac23fu);
		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);
		int						numSpecialCases	= 0;

		// Special cases.
		if (precision != glu::PRECISION_LOWP)
		{
			DE_ASSERT(numValues >= 10);
			for (int ndx = 0; ndx < 10; ndx++)
			{
				const float v = de::clamp(float(ndx) - 5.5f, ranges[precision].x(), ranges[precision].y());
				std::fill((float*)values[0], (float*)values[0] + scalarSize, v);
				numSpecialCases += 1;
			}
		}

		// Random cases.
		fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[0] + numSpecialCases*scalarSize, (numValues-numSpecialCases)*scalarSize);

		// If precision is mediump, make sure values can be represented in fp16 exactly
		if (precision == glu::PRECISION_MEDIUMP)
		{
			for (int ndx = 0; ndx < numValues*scalarSize; ndx++)
				((float*)values[0])[ndx] = tcu::Float16(((float*)values[0])[ndx]).asFloat();
		}
	}

	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				hasZeroSign		= supportsSignedZero(precision);
		const int				scalarSize		= glu::getDataTypeScalarSize(type);

		if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP)
		{
			// Require exact result.
			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
			{
				const float		in0			= ((const float*)inputs[0])[compNdx];
				const float		out0		= ((const float*)outputs[0])[compNdx];
				const float		ref			= deFloatFrac(in0);

				const deUint32	ulpDiff		= hasZeroSign ? getUlpDiff(out0, ref) : getUlpDiffIgnoreZeroSign(out0, ref);

				if (ulpDiff > 0)
				{
					m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff " << tcu::toHex(ulpDiff);
					return false;
				}
			}
		}
		else
		{
			const int		mantissaBits	= getMinMantissaBits(precision);
			const float		eps				= getEpsFromBits(1.0f, mantissaBits);	// epsilon for rounding bounds

			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
			{
				const float		in0			= ((const float*)inputs[0])[compNdx];
				const float		out0		= ((const float*)outputs[0])[compNdx];

				if (int(deFloatFloor(in0-eps)) == int(deFloatFloor(in0+eps)))
				{
					const float		ref			= deFloatFrac(in0);
					const int		bitsLost	= numBitsLostInOp(in0, ref);
					const deUint32	maxUlpDiff	= getMaxUlpDiffFromBits(de::max(0, mantissaBits-bitsLost));	// ULP diff for rounded integer value.
					const deUint32	ulpDiff		= getUlpDiffIgnoreZeroSign(out0, ref);

					if (ulpDiff > maxUlpDiff)
					{
						m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << " with ULP threshold " << tcu::toHex(maxUlpDiff) << ", got diff " << tcu::toHex(ulpDiff);
						return false;
					}
				}
				else
				{
					if (out0 >= 1.0f)
					{
						m_failMsg << "Expected [" << compNdx << "] < 1.0";
						return false;
					}
				}
			}
		}

		return true;
	}
};

ShaderCommonFunctionTests::ShaderCommonFunctionTests (Context& context)
	: TestCaseGroup(context, "common", "Common function tests")
{
}

ShaderCommonFunctionTests::~ShaderCommonFunctionTests (void)
{
}

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

	const glu::DataType scalarTypes[] =
	{
		glu::TYPE_FLOAT,
		glu::TYPE_INT,
		glu::TYPE_UINT
	};

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

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

		for (int vecSize = 1; vecSize <= 4; vecSize++)
		{
			for (int prec = glu::PRECISION_LOWP; prec <= glu::PRECISION_HIGHP; prec++)
			{
				for (int shaderType = glu::SHADERTYPE_VERTEX; shaderType <= glu::SHADERTYPE_FRAGMENT; shaderType++)
					group->addChild(new TestClass(parent->getContext(), glu::DataType(scalarType + vecSize - 1), glu::Precision(prec), glu::ShaderType(shaderType)));
			}
		}
	}
}

void ShaderCommonFunctionTests::init (void)
{
	//																	Float?	Int?	Uint?
	addFunctionCases<AbsCase>				(this,	"abs",				true,	true,	false);
	addFunctionCases<SignCase>				(this,	"sign",				true,	true,	false);
	addFunctionCases<FloorCase>				(this,	"floor",			true,	false,	false);
	addFunctionCases<TruncCase>				(this,	"trunc",			true,	false,	false);
	addFunctionCases<RoundCase>				(this,	"round",			true,	false,	false);
	addFunctionCases<RoundEvenCase>			(this,	"roundeven",		true,	false,	false);
	addFunctionCases<CeilCase>				(this,	"ceil",				true,	false,	false);
	addFunctionCases<FractCase>				(this,	"fract",			true,	false,	false);
	// mod
	addFunctionCases<ModfCase>				(this,	"modf",				true,	false,	false);
	// min
	// max
	// clamp
	// mix
	// step
	// smoothstep
	addFunctionCases<IsnanCase>				(this,	"isnan",			true,	false,	false);
	addFunctionCases<IsinfCase>				(this,	"isinf",			true,	false,	false);
	addFunctionCases<FloatBitsToIntCase>	(this,	"floatbitstoint",	true,	false,	false);
	addFunctionCases<FloatBitsToUintCase>	(this,	"floatbitstouint",	true,	false,	false);

	// (u)intBitsToFloat()
	{
		tcu::TestCaseGroup* intGroup	= new tcu::TestCaseGroup(m_testCtx, "intbitstofloat",	"intBitsToFloat() Tests");
		tcu::TestCaseGroup* uintGroup	= new tcu::TestCaseGroup(m_testCtx, "uintbitstofloat",	"uintBitsToFloat() Tests");

		addChild(intGroup);
		addChild(uintGroup);

		for (int vecSize = 1; vecSize < 4; vecSize++)
		{
			const glu::DataType		intType		= vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
			const glu::DataType		uintType	= vecSize > 1 ? glu::getDataTypeUintVec(vecSize) : glu::TYPE_UINT;

			for (int shaderType = glu::SHADERTYPE_VERTEX; shaderType <= glu::SHADERTYPE_FRAGMENT; shaderType++)
			{
				intGroup->addChild(new BitsToFloatCase(m_context, intType, glu::ShaderType(shaderType)));
				uintGroup->addChild(new BitsToFloatCase(m_context, uintType, glu::ShaderType(shaderType)));
			}
		}
	}
}

} // Functional
} // gles3
} // deqp
