13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program OpenGL ES 3.0 Module
33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * -------------------------------------------------
43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project
63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License");
83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License.
93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at
103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *      http://www.apache.org/licenses/LICENSE-2.0
123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software
143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS,
153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and
173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License.
183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*!
203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file
213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Common built-in function tests.
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "es3fShaderCommonFunctionTests.hpp"
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glsShaderExecUtil.hpp"
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTestLog.hpp"
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuFormatUtil.hpp"
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuFloat.hpp"
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deRandom.hpp"
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deMath.h"
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deString.h"
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace deqp
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace gles3
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace Functional
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::vector;
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::string;
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::TestLog;
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing namespace gls::ShaderExecUtil;
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::Vec2;
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::Vec3;
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::Vec4;
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::IVec2;
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::IVec3;
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::IVec4;
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Utilities
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename T, int Size>
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct VecArrayAccess
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									VecArrayAccess	(const void* ptr) : m_array((tcu::Vector<T, Size>*)ptr) {}
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									~VecArrayAccess	(void) {}
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vector<T, Size>&		operator[]		(size_t offset) const	{ return m_array[offset];	}
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vector<T, Size>&			operator[]		(size_t offset)			{ return m_array[offset];	}
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vector<T, Size>*			m_array;
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename T>	T			randomScalar	(de::Random& rnd, T minValue, T maxValue);
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<> inline		float		randomScalar	(de::Random& rnd, float minValue, float maxValue)		{ return rnd.getFloat(minValue, maxValue);	}
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<> inline		deInt32		randomScalar	(de::Random& rnd, deInt32 minValue, deInt32 maxValue)	{ return rnd.getInt(minValue, maxValue);	}
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<> inline		deUint32	randomScalar	(de::Random& rnd, deUint32 minValue, deUint32 maxValue)	{ return minValue + rnd.getUint32() % (maxValue - minValue + 1); }
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename T, int Size>
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline tcu::Vector<T, Size> randomVector (de::Random& rnd, const tcu::Vector<T, Size>& minValue, const tcu::Vector<T, Size>& maxValue)
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vector<T, Size> res;
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < Size; ndx++)
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		res[ndx] = randomScalar<T>(rnd, minValue[ndx], maxValue[ndx]);
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return res;
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename T, int Size>
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void fillRandomVectors (de::Random& rnd, const tcu::Vector<T, Size>& minValue, const tcu::Vector<T, Size>& maxValue, void* dst, int numValues, int offset = 0)
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VecArrayAccess<T, Size> access(dst);
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < numValues; ndx++)
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		access[offset + ndx] = randomVector<T, Size>(rnd, minValue, maxValue);
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename T>
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void fillRandomScalars (de::Random& rnd, T minValue, T maxValue, void* dst, int numValues, int offset = 0)
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	T* typedPtr = (T*)dst;
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < numValues; ndx++)
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		typedPtr[offset + ndx] = randomScalar<T>(rnd, minValue, maxValue);
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline int numBitsLostInOp (float input, float output)
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	inExp		= tcu::Float32(input).exponent();
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	outExp		= tcu::Float32(output).exponent();
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return de::max(0, inExp-outExp); // Lost due to mantissa shift.
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline deUint32 getUlpDiff (float a, float b)
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32	aBits	= tcu::Float32(a).bits();
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32	bBits	= tcu::Float32(b).bits();
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return aBits > bBits ? aBits - bBits : bBits - aBits;
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline deUint32 getUlpDiffIgnoreZeroSign (float a, float b)
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (tcu::Float32(a).isZero())
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return getUlpDiff(tcu::Float32::construct(tcu::Float32(b).sign(), 0, 0).asFloat(), b);
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (tcu::Float32(b).isZero())
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return getUlpDiff(a, tcu::Float32::construct(tcu::Float32(a).sign(), 0, 0).asFloat());
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return getUlpDiff(a, b);
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline bool supportsSignedZero (glu::Precision precision)
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// \note GLSL ES 3.0 doesn't really require support for -0, but we require it for highp
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	//		 as it is very widely supported.
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return precision == glu::PRECISION_HIGHP;
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline float getEpsFromMaxUlpDiff (float value, deUint32 ulpDiff)
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int exp = tcu::Float32(value).exponent();
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return tcu::Float32::construct(+1, exp, (1u<<23) | ulpDiff).asFloat() - tcu::Float32::construct(+1, exp, 1u<<23).asFloat();
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline deUint32 getMaxUlpDiffFromBits (int numAccurateBits)
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		numGarbageBits	= 23-numAccurateBits;
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32	mask			= (1u<<numGarbageBits)-1u;
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return mask;
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline float getEpsFromBits (float value, int numAccurateBits)
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return getEpsFromMaxUlpDiff(value, getMaxUlpDiffFromBits(numAccurateBits));
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getMinMantissaBits (glu::Precision precision)
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int bits[] =
1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		7,		// lowp
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		10,		// mediump
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		23		// highp
1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(bits) == glu::PRECISION_LAST);
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(de::inBounds<int>(precision, 0, DE_LENGTH_OF_ARRAY(bits)));
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return bits[precision];
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// CommonFunctionCase
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass CommonFunctionCase : public TestCase
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							CommonFunctionCase		(Context& context, const char* name, const char* description, glu::ShaderType shaderType);
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							~CommonFunctionCase		(void);
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					init					(void);
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					deinit					(void);
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult			iterate					(void);
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							CommonFunctionCase		(const CommonFunctionCase& other);
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	CommonFunctionCase&		operator=				(const CommonFunctionCase& other);
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual void			getInputValues			(int numValues, void* const* values) const = 0;
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual bool			compare					(const void* const* inputs, const void* const* outputs) = 0;
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::ShaderType			m_shaderType;
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ShaderSpec				m_spec;
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int						m_numValues;
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream		m_failMsg;				//!< Comparison failure help message.
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ShaderExecutor*			m_executor;
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1913c827367444ee418f129b2c238299f49d3264554Jarkko PoyryCommonFunctionCase::CommonFunctionCase (Context& context, const char* name, const char* description, glu::ShaderType shaderType)
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCase		(context, name, description)
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_shaderType	(shaderType)
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_numValues	(100)
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_executor	(DE_NULL)
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_spec.version = glu::GLSL_VERSION_300_ES;
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2003c827367444ee418f129b2c238299f49d3264554Jarkko PoyryCommonFunctionCase::~CommonFunctionCase (void)
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	CommonFunctionCase::deinit();
2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid CommonFunctionCase::init (void)
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(!m_executor);
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_executor = createExecutor(m_context.getRenderContext(), m_shaderType, m_spec);
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << m_executor;
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_executor->isOk())
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::TestError("Compile failed");
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid CommonFunctionCase::deinit (void)
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	delete m_executor;
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_executor = DE_NULL;
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic vector<int> getScalarSizes (const vector<Symbol>& symbols)
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<int> sizes(symbols.size());
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)symbols.size(); ++ndx)
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		sizes[ndx] = symbols[ndx].varType.getScalarSize();
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return sizes;
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int computeTotalScalarSize (const vector<Symbol>& symbols)
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int totalSize = 0;
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (vector<Symbol>::const_iterator sym = symbols.begin(); sym != symbols.end(); ++sym)
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		totalSize += sym->varType.getScalarSize();
2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return totalSize;
2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic vector<void*> getInputOutputPointers (const vector<Symbol>& symbols, vector<deUint32>& data, const int numValues)
2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<void*>	pointers		(symbols.size());
2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int				curScalarOffset	= 0;
2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int varNdx = 0; varNdx < (int)symbols.size(); ++varNdx)
2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Symbol&	var				= symbols[varNdx];
2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int		scalarSize		= var.varType.getScalarSize();
2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Uses planar layout as input/output specs do not support strides.
2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pointers[varNdx] = &data[curScalarOffset];
2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		curScalarOffset += scalarSize*numValues;
2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(curScalarOffset == (int)data.size());
2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return pointers;
2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// \todo [2013-08-08 pyry] Make generic utility and move to glu?
2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct HexFloat
2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float value;
2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	HexFloat (const float value_) : value(value_) {}
2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::ostream& operator<< (std::ostream& str, const HexFloat& v)
2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return str << v.value << " / " << tcu::toHex(tcu::Float32(v.value).bits());
2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct HexBool
2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32 value;
2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	HexBool (const deUint32 value_) : value(value_) {}
2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::ostream& operator<< (std::ostream& str, const HexBool& v)
2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return str << (v.value ? "true" : "false") << " / " << tcu::toHex(v.value);
2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct VarValue
2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::VarType&	type;
2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const void*			value;
2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VarValue (const glu::VarType& type_, const void* value_) : type(type_), value(value_) {}
2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::ostream& operator<< (std::ostream& str, const VarValue& varValue)
2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(varValue.type.isBasicType());
2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::DataType		basicType		= varValue.type.getBasicType();
2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::DataType		scalarType		= glu::getDataTypeScalarType(basicType);
2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				numComponents	= glu::getDataTypeScalarSize(basicType);
2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numComponents > 1)
2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		str << glu::getDataTypeName(basicType) << "(";
3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int compNdx = 0; compNdx < numComponents; compNdx++)
3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (compNdx != 0)
3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			str << ", ";
3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (scalarType)
3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case glu::TYPE_FLOAT:	str << HexFloat(((const float*)varValue.value)[compNdx]);			break;
3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case glu::TYPE_INT:		str << ((const deInt32*)varValue.value)[compNdx];					break;
3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case glu::TYPE_UINT:	str << tcu::toHex(((const deUint32*)varValue.value)[compNdx]);		break;
3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case glu::TYPE_BOOL:	str << HexBool(((const deUint32*)varValue.value)[compNdx]);			break;
3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:
3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(false);
3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numComponents > 1)
3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		str << ")";
3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return str;
3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3243c827367444ee418f129b2c238299f49d3264554Jarkko PoyryCommonFunctionCase::IterateResult CommonFunctionCase::iterate (void)
3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				numInputScalars			= computeTotalScalarSize(m_spec.inputs);
3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				numOutputScalars		= computeTotalScalarSize(m_spec.outputs);
3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<deUint32>		inputData				(numInputScalars * m_numValues);
3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<deUint32>		outputData				(numOutputScalars * m_numValues);
3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const vector<void*>		inputPointers			= getInputOutputPointers(m_spec.inputs, inputData, m_numValues);
3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const vector<void*>		outputPointers			= getInputOutputPointers(m_spec.outputs, outputData, m_numValues);
3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Initialize input data.
3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	getInputValues(m_numValues, &inputPointers[0]);
3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Execute shader.
3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_executor->useProgram();
3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_executor->execute(m_numValues, &inputPointers[0], &outputPointers[0]);
3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Compare results.
3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const vector<int>		inScalarSizes		= getScalarSizes(m_spec.inputs);
3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const vector<int>		outScalarSizes		= getScalarSizes(m_spec.outputs);
3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vector<void*>			curInputPtr			(inputPointers.size());
3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vector<void*>			curOutputPtr		(outputPointers.size());
3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int						numFailed			= 0;
3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int valNdx = 0; valNdx < m_numValues; valNdx++)
3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Set up pointers for comparison.
3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int inNdx = 0; inNdx < (int)curInputPtr.size(); ++inNdx)
3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				curInputPtr[inNdx] = (deUint32*)inputPointers[inNdx] + inScalarSizes[inNdx]*valNdx;
3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int outNdx = 0; outNdx < (int)curOutputPtr.size(); ++outNdx)
3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				curOutputPtr[outNdx] = (deUint32*)outputPointers[outNdx] + outScalarSizes[outNdx]*valNdx;
3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!compare(&curInputPtr[0], &curOutputPtr[0]))
3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// \todo [2013-08-08 pyry] We probably want to log reference value as well?
3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.getLog() << TestLog::Message << "ERROR: comparison failed for value " << valNdx << ":\n  " << m_failMsg.str() << TestLog::EndMessage;
3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.getLog() << TestLog::Message << "  inputs:" << TestLog::EndMessage;
3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int inNdx = 0; inNdx < (int)curInputPtr.size(); inNdx++)
3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.getLog() << TestLog::Message << "    " << m_spec.inputs[inNdx].name << " = "
3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														   << VarValue(m_spec.inputs[inNdx].varType, curInputPtr[inNdx])
3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									   << TestLog::EndMessage;
3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.getLog() << TestLog::Message << "  outputs:" << TestLog::EndMessage;
3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int outNdx = 0; outNdx < (int)curOutputPtr.size(); outNdx++)
3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.getLog() << TestLog::Message << "    " << m_spec.outputs[outNdx].name << " = "
3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														   << VarValue(m_spec.outputs[outNdx].varType, curOutputPtr[outNdx])
3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									   << TestLog::EndMessage;
3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_failMsg.str("");
3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_failMsg.clear();
3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				numFailed += 1;
3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << TestLog::Message << (m_numValues - numFailed) << " / " << m_numValues << " values passed" << TestLog::EndMessage;
3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.setTestResult(numFailed == 0 ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								numFailed == 0 ? "Pass"					: "Result comparison failed");
3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3903c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const char* getPrecisionPostfix (glu::Precision precision)
3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const char* s_postfix[] =
3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"_lowp",
3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"_mediump",
3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"_highp"
3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_postfix) == glu::PRECISION_LAST);
3993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(de::inBounds<int>(precision, 0, DE_LENGTH_OF_ARRAY(s_postfix)));
4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return s_postfix[precision];
4013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const char* getShaderTypePostfix (glu::ShaderType shaderType)
4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const char* s_postfix[] =
4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"_vertex",
4083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"_fragment"
4093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
4103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(de::inBounds<int>(shaderType, 0, DE_LENGTH_OF_ARRAY(s_postfix)));
4113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return s_postfix[shaderType];
4123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4143c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic std::string getCommonFuncCaseName (glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
4153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return string(glu::getDataTypeName(baseType)) + getPrecisionPostfix(precision) + getShaderTypePostfix(shaderType);
4173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4193c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass AbsCase : public CommonFunctionCase
4203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4213c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
4223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	AbsCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
4233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "abs", shaderType)
4243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
4263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
4273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.source = "out0 = abs(in0);";
4283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void getInputValues (int numValues, void* const* values) const
4313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Vec2 floatRanges[] =
4333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-2.0f,		2.0f),	// lowp
4353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e3f,		1e3f),	// mediump
4363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e7f,		1e7f)	// highp
4373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
4383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const IVec2 intRanges[] =
4393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			IVec2(-(1<<7)+1,	(1<<7)-1),
4413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			IVec2(-(1<<15)+1,	(1<<15)-1),
4423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			IVec2(0x80000001,	0x7fffffff)
4433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
4443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random				rnd			(deStringHash(getName()) ^ 0x235facu);
4463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
4473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
4483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize	= glu::getDataTypeScalarSize(type);
4493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (glu::isDataTypeFloatOrVec(type))
4513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			fillRandomScalars(rnd, floatRanges[precision].x(), floatRanges[precision].y(), values[0], numValues*scalarSize);
4523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
4533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			fillRandomScalars(rnd, intRanges[precision].x(), intRanges[precision].y(), values[0], numValues*scalarSize);
4543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool compare (const void* const* inputs, const void* const* outputs)
4573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
4593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
4603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
4613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (glu::isDataTypeFloatOrVec(type))
4633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		mantissaBits	= getMinMantissaBits(precision);
4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	maxUlpDiff		= (1u<<(23-mantissaBits))-1u;
4663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
4683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
4693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		in0			= ((const float*)inputs[0])[compNdx];
4703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		out0		= ((const float*)outputs[0])[compNdx];
4713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		ref0		= de::abs(in0);
4723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const deUint32	ulpDiff0	= getUlpDiff(out0, ref0);
4733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (ulpDiff0 > maxUlpDiff)
4753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
4763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref0) << " with ULP threshold " << maxUlpDiff << ", got ULP diff " << ulpDiff0;
4773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
4783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
4793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
4803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
4823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
4853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int	in0		= ((const int*)inputs[0])[compNdx];
4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int	out0	= ((const int*)outputs[0])[compNdx];
4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int	ref0	= de::abs(in0);
4883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (out0 != ref0)
4903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
4913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_failMsg << "Expected [" << compNdx << "] = " << ref0;
4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
4943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
4953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
4983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
5003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5013c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass SignCase : public CommonFunctionCase
5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5033c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
5043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	SignCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
5053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "sign", shaderType)
5063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
5083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
5093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.source = "out0 = sign(in0);";
5103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void getInputValues (int numValues, void* const* values) const
5133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Vec2 floatRanges[] =
5153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-2.0f,		2.0f),	// lowp
5173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e4f,		1e4f),	// mediump	- note: may end up as inf
5183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e8f,		1e8f)	// highp	- note: may end up as inf
5193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
5203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const IVec2 intRanges[] =
5213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			IVec2(-(1<<7),		(1<<7)-1),
5233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			IVec2(-(1<<15),		(1<<15)-1),
5243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			IVec2(0x80000000,	0x7fffffff)
5253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
5263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random				rnd			(deStringHash(getName()) ^ 0x324u);
5283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
5293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
5303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize	= glu::getDataTypeScalarSize(type);
5313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (glu::isDataTypeFloatOrVec(type))
5333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Special cases.
535b55a172c47932197abc5e18950a70c938ef302c0Pyry Haulos			std::fill((float*)values[0],				(float*)values[0] + scalarSize,		+1.0f);
536b55a172c47932197abc5e18950a70c938ef302c0Pyry Haulos			std::fill((float*)values[0] + scalarSize*1,	(float*)values[0] + scalarSize*2,	-1.0f);
537b55a172c47932197abc5e18950a70c938ef302c0Pyry Haulos			std::fill((float*)values[0] + scalarSize*2,	(float*)values[0] + scalarSize*3,	0.0f);
5383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			fillRandomScalars(rnd, floatRanges[precision].x(), floatRanges[precision].y(), (float*)values[0] + scalarSize*3, (numValues-3)*scalarSize);
5393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
5413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
542b55a172c47932197abc5e18950a70c938ef302c0Pyry Haulos			std::fill((int*)values[0],					(int*)values[0] + scalarSize,		+1);
543b55a172c47932197abc5e18950a70c938ef302c0Pyry Haulos			std::fill((int*)values[0] + scalarSize*1,	(int*)values[0] + scalarSize*2,		-1);
544b55a172c47932197abc5e18950a70c938ef302c0Pyry Haulos			std::fill((int*)values[0] + scalarSize*2,	(int*)values[0] + scalarSize*3,		0);
5453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			fillRandomScalars(rnd, intRanges[precision].x(), intRanges[precision].y(), (int*)values[0] + scalarSize*3, (numValues-3)*scalarSize);
5463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool compare (const void* const* inputs, const void* const* outputs)
5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
5523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
5533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
5543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (glu::isDataTypeFloatOrVec(type))
5563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Both highp and mediump should be able to represent -1, 0, and +1 exactly
5583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32 maxUlpDiff = precision == glu::PRECISION_LOWP ? getMaxUlpDiffFromBits(getMinMantissaBits(precision)) : 0;
5593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
5613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		in0			= ((const float*)inputs[0])[compNdx];
5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		out0		= ((const float*)outputs[0])[compNdx];
5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		ref0		= in0 < 0.0f ? -1.0f :
5653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											  in0 > 0.0f ? +1.0f : 0.0f;
5663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const deUint32	ulpDiff0	= getUlpDiff(out0, ref0);
5673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (ulpDiff0 > maxUlpDiff)
5693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
5703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref0) << " with ULP threshold " << maxUlpDiff << ", got ULP diff " << ulpDiff0;
5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
5733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
5743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
5763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
5783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
5793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int	in0		= ((const int*)inputs[0])[compNdx];
5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int	out0	= ((const int*)outputs[0])[compNdx];
5813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int	ref0	= in0 < 0 ? -1 :
5823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									  in0 > 0 ? +1 : 0;
5833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (out0 != ref0)
5853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
5863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_failMsg << "Expected [" << compNdx << "] = " << ref0;
5873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
5883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
5893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
5903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
5933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
5953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5963c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic float roundEven (float v)
5973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float		q			= deFloatFrac(v);
5993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		truncated	= int(v-q);
6003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		rounded		= (q > 0.5f)							? (truncated + 1) :	// Rounded up
6013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									(q == 0.5f && (truncated % 2 != 0))	? (truncated + 1) :	// Round to nearest even at 0.5
6023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									truncated;												// Rounded down
6033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return float(rounded);
6053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6073c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass RoundEvenCase : public CommonFunctionCase
6083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6093c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
6103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	RoundEvenCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
6113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "roundEven", shaderType)
6123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
6143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
6153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.source = "out0 = roundEven(in0);";
6163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void getInputValues (int numValues, void* const* values) const
6193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Vec2 ranges[] =
6213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-2.0f,		2.0f),	// lowp
6233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e3f,		1e3f),	// mediump
6243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e7f,		1e7f)	// highp
6253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
6263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random				rnd				(deStringHash(getName()) ^ 0xac23fu);
6283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
6293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
6303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
6313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int						numSpecialCases	= 0;
6323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Special cases.
6343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (precision != glu::PRECISION_LOWP)
6353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(numValues >= 20);
6373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int ndx = 0; ndx < 20; ndx++)
6383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
6393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float v = de::clamp(float(ndx) - 10.5f, ranges[precision].x(), ranges[precision].y());
6403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				std::fill((float*)values[0], (float*)values[0] + scalarSize, v);
6413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				numSpecialCases += 1;
6423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
6433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Random cases.
6463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[0] + numSpecialCases*scalarSize, (numValues-numSpecialCases)*scalarSize);
6473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// If precision is mediump, make sure values can be represented in fp16 exactly
6493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (precision == glu::PRECISION_MEDIUMP)
6503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int ndx = 0; ndx < numValues*scalarSize; ndx++)
6523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				((float*)values[0])[ndx] = tcu::Float16(((float*)values[0])[ndx]).asFloat();
6533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool compare (const void* const* inputs, const void* const* outputs)
6573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
6593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
6603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool				hasSignedZero	= supportsSignedZero(precision);
6613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
6623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP)
6643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Require exact rounding result.
6663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
6673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
6683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		in0			= ((const float*)inputs[0])[compNdx];
6693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		out0		= ((const float*)outputs[0])[compNdx];
6703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		ref			= roundEven(in0);
6713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const deUint32	ulpDiff		= hasSignedZero ? getUlpDiff(out0, ref) : getUlpDiffIgnoreZeroSign(out0, ref);
6733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (ulpDiff > 0)
6753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
6763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff " << tcu::toHex(ulpDiff);
6773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
6783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
6793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
6803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
6823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		mantissaBits	= getMinMantissaBits(precision);
6843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	maxUlpDiff		= getMaxUlpDiffFromBits(mantissaBits);	// ULP diff for rounded integer value.
6853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		eps				= getEpsFromBits(1.0f, mantissaBits);	// epsilon for rounding bounds
6863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
6883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
6893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		in0			= ((const float*)inputs[0])[compNdx];
6903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		out0		= ((const float*)outputs[0])[compNdx];
6913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		minRes		= int(roundEven(in0-eps));
6923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		maxRes		= int(roundEven(in0+eps));
6933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				bool			anyOk		= false;
6943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int roundedVal = minRes; roundedVal <= maxRes; roundedVal++)
6963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
6973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const deUint32 ulpDiff = getUlpDiffIgnoreZeroSign(out0, float(roundedVal));
6983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (ulpDiff <= maxUlpDiff)
7003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
7013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						anyOk = true;
7023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						break;
7033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
7043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
7053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!anyOk)
7073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
7083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_failMsg << "Expected [" << compNdx << "] = [" << minRes << ", " << maxRes << "] with ULP threshold " << tcu::toHex(maxUlpDiff);
7093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
7103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
7113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
7123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
7153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
7173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7183c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ModfCase : public CommonFunctionCase
7193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7203c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
7213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ModfCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
7223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "modf", shaderType)
7233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
7253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
7263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("out1", glu::VarType(baseType, precision)));
7273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.source = "out0 = modf(in0, out1);";
7283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void getInputValues (int numValues, void* const* values) const
7313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Vec2 ranges[] =
7333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-2.0f,		2.0f),	// lowp
7353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e3f,		1e3f),	// mediump
7363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e7f,		1e7f)	// highp
7373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
7383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random				rnd			(deStringHash(getName()) ^ 0xac23fu);
7403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
7413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
7423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize	= glu::getDataTypeScalarSize(type);
7433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), values[0], numValues*scalarSize);
7453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool compare (const void* const* inputs, const void* const* outputs)
7483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
7503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
7513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool				hasZeroSign		= supportsSignedZero(precision);
7523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
7533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				mantissaBits	= getMinMantissaBits(precision);
7553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
7573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		in0			= ((const float*)inputs[0])[compNdx];
7593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		out0		= ((const float*)outputs[0])[compNdx];
7603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		out1		= ((const float*)outputs[1])[compNdx];
7613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		refOut1		= float(int(in0));
7633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		refOut0		= in0 - refOut1;
7643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		bitsLost	= precision != glu::PRECISION_HIGHP ? numBitsLostInOp(in0, refOut0) : 0;
7663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	maxUlpDiff	= getMaxUlpDiffFromBits(de::max(mantissaBits - bitsLost, 0));
7673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		resSum		= out0 + out1;
7693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	ulpDiff		= hasZeroSign ? getUlpDiff(resSum, in0) : getUlpDiffIgnoreZeroSign(resSum, in0);
7713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (ulpDiff > maxUlpDiff)
7733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
7743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_failMsg << "Expected [" << compNdx << "] = (" << HexFloat(refOut0) << ") + (" << HexFloat(refOut1) << ") = " << HexFloat(in0) << " with ULP threshold "
7753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							<< tcu::toHex(maxUlpDiff) << ", got ULP diff " << tcu::toHex(ulpDiff);
7763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return false;
7773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
7783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
7813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
7833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7843c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass IsnanCase : public CommonFunctionCase
7853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7863c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
7873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IsnanCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
7883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "isnan", shaderType)
7893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(glu::isDataTypeFloatOrVec(baseType));
7913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int			vecSize		= glu::getDataTypeScalarSize(baseType);
7933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType	boolType	= vecSize > 1 ? glu::getDataTypeBoolVec(vecSize) : glu::TYPE_BOOL;
7943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
7963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("out0", glu::VarType(boolType, glu::PRECISION_LAST)));
7973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.source = "out0 = isnan(in0);";
7983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void getInputValues (int numValues, void* const* values) const
8013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random				rnd				(deStringHash(getName()) ^ 0xc2a39fu);
8033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
8043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
8053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
8063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				mantissaBits	= getMinMantissaBits(precision);
8073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint32			mantissaMask	= ~getMaxUlpDiffFromBits(mantissaBits) & ((1u<<23)-1u);
8083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int valNdx = 0; valNdx < numValues*scalarSize; valNdx++)
8103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const bool		isNan		= rnd.getFloat() > 0.3f;
8123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const bool		isInf		= !isNan && rnd.getFloat() > 0.4f;
8133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	mantissa	= !isInf ? ((1u<<22) | (rnd.getUint32() & mantissaMask)) : 0;
8143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	exp			= !isNan && !isInf ? (rnd.getUint32() & 0x7fu) : 0xffu;
8153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	sign		= rnd.getUint32() & 0x1u;
8163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	value		= (sign << 31) | (exp << 23) | mantissa;
8173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(tcu::Float32(value).isInf() == isInf && tcu::Float32(value).isNaN() == isNan);
8193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			((deUint32*)values[0])[valNdx] = value;
8213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
8223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool compare (const void* const* inputs, const void* const* outputs)
8253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
8273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
8283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
8293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (precision == glu::PRECISION_HIGHP)
8313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Only highp is required to support inf/nan
8333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
8343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
8353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		in0		= ((const float*)inputs[0])[compNdx];
8363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const deUint32	out0	= ((const deUint32*)outputs[0])[compNdx];
8373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const deUint32	ref		= tcu::Float32(in0).isNaN() ? 1u : 0u;
8383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (out0 != ref)
8403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
8413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_failMsg << "Expected [" << compNdx << "] = " << HexBool(ref);
8423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
8433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
8443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
8453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
8463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
8473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Value can be either 0 or 1
8493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
8503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
8513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int out0 = ((const int*)outputs[0])[compNdx];
8523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (out0 != 0 && out0 != 1)
8543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
8553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_failMsg << "Expected [" << compNdx << "] = 0 / 1";
8563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
8573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
8583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
8593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
8603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
8623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
8643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8653c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass IsinfCase : public CommonFunctionCase
8663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8673c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
8683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IsinfCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
8693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "isinf", shaderType)
8703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(glu::isDataTypeFloatOrVec(baseType));
8723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int			vecSize		= glu::getDataTypeScalarSize(baseType);
8743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType	boolType	= vecSize > 1 ? glu::getDataTypeBoolVec(vecSize) : glu::TYPE_BOOL;
8753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
8773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("out0", glu::VarType(boolType, glu::PRECISION_LAST)));
8783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.source = "out0 = isinf(in0);";
8793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void getInputValues (int numValues, void* const* values) const
8823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random				rnd				(deStringHash(getName()) ^ 0xc2a39fu);
8843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
8853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
8863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
8873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				mantissaBits	= getMinMantissaBits(precision);
8883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint32			mantissaMask	= ~getMaxUlpDiffFromBits(mantissaBits) & ((1u<<23)-1u);
8893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int valNdx = 0; valNdx < numValues*scalarSize; valNdx++)
8913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const bool		isInf		= rnd.getFloat() > 0.3f;
8933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const bool		isNan		= !isInf && rnd.getFloat() > 0.4f;
8943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	mantissa	= !isInf ? ((1u<<22) | (rnd.getUint32() & mantissaMask)) : 0;
8953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	exp			= !isNan && !isInf ? (rnd.getUint32() & 0x7fu) : 0xffu;
8963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	sign		= rnd.getUint32() & 0x1u;
8973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	value		= (sign << 31) | (exp << 23) | mantissa;
8983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(tcu::Float32(value).isInf() == isInf && tcu::Float32(value).isNaN() == isNan);
9003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			((deUint32*)values[0])[valNdx] = value;
9023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
9033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool compare (const void* const* inputs, const void* const* outputs)
9063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
9083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
9093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
9103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (precision == glu::PRECISION_HIGHP)
9123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
9133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Only highp is required to support inf/nan
9143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
9153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
9163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		in0		= ((const float*)inputs[0])[compNdx];
9173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const deUint32	out0	= ((const deUint32*)outputs[0])[compNdx];
9183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const deUint32	ref		= tcu::Float32(in0).isInf() ? 1u : 0u;
9193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (out0 != ref)
9213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
9223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_failMsg << "Expected [" << compNdx << "] = " << HexBool(ref);
9233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
9243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
9253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
9263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
9273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
9283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
9293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Value can be either 0 or 1
9303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
9313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
9323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int out0 = ((const int*)outputs[0])[compNdx];
9333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (out0 != 0 && out0 != 1)
9353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
9363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_failMsg << "Expected [" << compNdx << "] = 0 / 1";
9373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
9383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
9393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
9403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
9413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
9433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
9453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9463c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FloatBitsToUintIntCase : public CommonFunctionCase
9473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9483c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
9493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FloatBitsToUintIntCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType, bool outIsSigned)
9503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), outIsSigned ? "floatBitsToInt" : "floatBitsToUint", shaderType)
9513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int			vecSize		= glu::getDataTypeScalarSize(baseType);
9533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType	intType		= outIsSigned ? (vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT)
9543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  : (vecSize > 1 ? glu::getDataTypeUintVec(vecSize) : glu::TYPE_UINT);
9553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
9573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("out0", glu::VarType(intType, glu::PRECISION_HIGHP)));
9583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.source = outIsSigned ? "out0 = floatBitsToInt(in0);" : "out0 = floatBitsToUint(in0);";
9593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void getInputValues (int numValues, void* const* values) const
9623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Vec2 ranges[] =
9643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
9653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-2.0f,		2.0f),	// lowp
9663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e3f,		1e3f),	// mediump
9673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e7f,		1e7f)	// highp
9683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
9693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random				rnd			(deStringHash(getName()) ^ 0x2790au);
9713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
9723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
9733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize	= glu::getDataTypeScalarSize(type);
9743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), values[0], numValues*scalarSize);
9763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool compare (const void* const* inputs, const void* const* outputs)
9793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
9813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
9823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
9833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				mantissaBits	= getMinMantissaBits(precision);
9853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				maxUlpDiff		= getMaxUlpDiffFromBits(mantissaBits);
9863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
9883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
9893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		in0			= ((const float*)inputs[0])[compNdx];
9903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	out0		= ((const deUint32*)outputs[0])[compNdx];
9913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	refOut0		= tcu::Float32(in0).bits();
9923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		ulpDiff		= de::abs((int)out0 - (int)refOut0);
9933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (ulpDiff > maxUlpDiff)
9953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
9963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(refOut0) << " with threshold "
9973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							<< tcu::toHex(maxUlpDiff) << ", got diff " << tcu::toHex(ulpDiff);
9983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return false;
9993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
10003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
10013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
10033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
10053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10063c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FloatBitsToIntCase : public FloatBitsToUintIntCase
10073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10083c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
10093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FloatBitsToIntCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
10103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: FloatBitsToUintIntCase(context, baseType, precision, shaderType, true)
10113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
10143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10153c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FloatBitsToUintCase : public FloatBitsToUintIntCase
10163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10173c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
10183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FloatBitsToUintCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
10193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: FloatBitsToUintIntCase(context, baseType, precision, shaderType, false)
10203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
10233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10243c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass BitsToFloatCase : public CommonFunctionCase
10253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10263c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
10273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	BitsToFloatCase (Context& context, glu::DataType baseType, glu::ShaderType shaderType)
10283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, glu::PRECISION_HIGHP, shaderType).c_str(), glu::isDataTypeIntOrIVec(baseType) ? "intBitsToFloat" : "uintBitsToFloat", shaderType)
10293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool			inIsSigned	= glu::isDataTypeIntOrIVec(baseType);
10313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int			vecSize		= glu::getDataTypeScalarSize(baseType);
10323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType	floatType	= vecSize > 1 ? glu::getDataTypeFloatVec(vecSize) : glu::TYPE_FLOAT;
10333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, glu::PRECISION_HIGHP)));
10353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("out0", glu::VarType(floatType, glu::PRECISION_HIGHP)));
10363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.source = inIsSigned ? "out0 = intBitsToFloat(in0);" : "out0 = uintBitsToFloat(in0);";
10373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void getInputValues (int numValues, void* const* values) const
10403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random				rnd			(deStringHash(getName()) ^ 0xbbb225u);
10423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
10433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize	= glu::getDataTypeScalarSize(type);
10443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Vec2				range		(-1e8f, +1e8f);
10453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// \note Filled as floats.
10473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		fillRandomScalars(rnd, range.x(), range.y(), values[0], numValues*scalarSize);
10483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool compare (const void* const* inputs, const void* const* outputs)
10513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
10533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
10548a14bbb74876a4a318d6277a3afeb8d35d682aafPyry Haulos		const deUint32			maxUlpDiff		= 0;
10553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
10573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
10583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		in0			= ((const float*)inputs[0])[compNdx];
10593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		out0		= ((const float*)outputs[0])[compNdx];
10608a14bbb74876a4a318d6277a3afeb8d35d682aafPyry Haulos			const deUint32	ulpDiff		= getUlpDiff(in0, out0);
10613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (ulpDiff > maxUlpDiff)
10633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
10648a14bbb74876a4a318d6277a3afeb8d35d682aafPyry Haulos				m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(tcu::Float32(in0).bits()) << " with ULP threshold "
10653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							<< tcu::toHex(maxUlpDiff) << ", got ULP diff " << tcu::toHex(ulpDiff);
10663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return false;
10673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
10683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
10693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
10713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
10733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10743c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FloorCase : public CommonFunctionCase
10753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10763c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
10773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FloorCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
10783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "floor", shaderType)
10793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
10813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
10823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.source = "out0 = floor(in0);";
10833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void getInputValues (int numValues, void* const* values) const
10863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Vec2 ranges[] =
10883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
10893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-2.0f,		2.0f),	// lowp
10903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e3f,		1e3f),	// mediump
10913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e7f,		1e7f)	// highp
10923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
10933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random				rnd			(deStringHash(getName()) ^ 0xac23fu);
10953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
10963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
10973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize	= glu::getDataTypeScalarSize(type);
10983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Random cases.
10993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[0], numValues*scalarSize);
11003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// If precision is mediump, make sure values can be represented in fp16 exactly
11023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (precision == glu::PRECISION_MEDIUMP)
11033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int ndx = 0; ndx < numValues*scalarSize; ndx++)
11053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				((float*)values[0])[ndx] = tcu::Float16(((float*)values[0])[ndx]).asFloat();
11063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
11073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool compare (const void* const* inputs, const void* const* outputs)
11103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
11123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
11133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
11143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP)
11163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Require exact result.
11183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
11193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
11203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		in0			= ((const float*)inputs[0])[compNdx];
11213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		out0		= ((const float*)outputs[0])[compNdx];
11223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		ref			= deFloatFloor(in0);
11233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const deUint32	ulpDiff		= getUlpDiff(out0, ref);
11253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (ulpDiff > 0)
11273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
11283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff " << tcu::toHex(ulpDiff);
11293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
11303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
11313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
11323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
11333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
11343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		mantissaBits	= getMinMantissaBits(precision);
11363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	maxUlpDiff		= getMaxUlpDiffFromBits(mantissaBits);	// ULP diff for rounded integer value.
11373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		eps				= getEpsFromBits(1.0f, mantissaBits);	// epsilon for rounding bounds
11383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
11403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
11413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		in0			= ((const float*)inputs[0])[compNdx];
11423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		out0		= ((const float*)outputs[0])[compNdx];
11433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		minRes		= int(deFloatFloor(in0-eps));
11443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		maxRes		= int(deFloatFloor(in0+eps));
11453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				bool			anyOk		= false;
11463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int roundedVal = minRes; roundedVal <= maxRes; roundedVal++)
11483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
11493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const deUint32 ulpDiff = getUlpDiff(out0, float(roundedVal));
11503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (ulpDiff <= maxUlpDiff)
11523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
11533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						anyOk = true;
11543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						break;
11553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
11563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
11573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!anyOk)
11593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
11603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_failMsg << "Expected [" << compNdx << "] = [" << minRes << ", " << maxRes << "] with ULP threshold " << tcu::toHex(maxUlpDiff);
11613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
11623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
11633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
11643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
11653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
11673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
11693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11703c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass TruncCase : public CommonFunctionCase
11713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11723c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
11733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TruncCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
11743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "trunc", shaderType)
11753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
11773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
11783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.source = "out0 = trunc(in0);";
11793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void getInputValues (int numValues, void* const* values) const
11823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Vec2 ranges[] =
11843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-2.0f,		2.0f),	// lowp
11863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e3f,		1e3f),	// mediump
11873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e7f,		1e7f)	// highp
11883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
11893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random				rnd				(deStringHash(getName()) ^ 0xac23fu);
11913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
11923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
11933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
11943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float				specialCases[]	= { 0.0f, -0.0f, -0.9f, 0.9f, 1.0f, -1.0f };
11953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				numSpecialCases	= DE_LENGTH_OF_ARRAY(specialCases);
11963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Special cases
11983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int caseNdx = 0; caseNdx < numSpecialCases; caseNdx++)
11993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++)
12013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				((float*)values[0])[caseNdx*scalarSize + scalarNdx] = specialCases[caseNdx];
12023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Random cases.
12053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[0] + scalarSize*numSpecialCases, (numValues-numSpecialCases)*scalarSize);
12063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// If precision is mediump, make sure values can be represented in fp16 exactly
12083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (precision == glu::PRECISION_MEDIUMP)
12093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int ndx = 0; ndx < numValues*scalarSize; ndx++)
12113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				((float*)values[0])[ndx] = tcu::Float16(((float*)values[0])[ndx]).asFloat();
12123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool compare (const void* const* inputs, const void* const* outputs)
12163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
12183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
12193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
12203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP)
12223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Require exact result.
12243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
12253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
12263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		in0			= ((const float*)inputs[0])[compNdx];
12273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		out0		= ((const float*)outputs[0])[compNdx];
12283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const bool		isNeg		= tcu::Float32(in0).sign() < 0;
12293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		ref			= isNeg ? (-float(int(-in0))) : float(int(in0));
12303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1231ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry				// \note: trunc() function definition is a bit broad on negative zeros. Ignore result sign if zero.
1232ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry				const deUint32	ulpDiff		= getUlpDiffIgnoreZeroSign(out0, ref);
12333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (ulpDiff > 0)
12353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
12363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff " << tcu::toHex(ulpDiff);
12373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
12383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
12393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
12403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
12423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		mantissaBits	= getMinMantissaBits(precision);
12443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	maxUlpDiff		= getMaxUlpDiffFromBits(mantissaBits);	// ULP diff for rounded integer value.
12453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		eps				= getEpsFromBits(1.0f, mantissaBits);	// epsilon for rounding bounds
12463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
12483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
12493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		in0			= ((const float*)inputs[0])[compNdx];
12503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		out0		= ((const float*)outputs[0])[compNdx];
12513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		minRes		= int(in0-eps);
12523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		maxRes		= int(in0+eps);
12533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				bool			anyOk		= false;
12543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int roundedVal = minRes; roundedVal <= maxRes; roundedVal++)
12563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
12573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const deUint32 ulpDiff = getUlpDiffIgnoreZeroSign(out0, float(roundedVal));
12583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (ulpDiff <= maxUlpDiff)
12603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
12613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						anyOk = true;
12623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						break;
12633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
12643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
12653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!anyOk)
12673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
12683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_failMsg << "Expected [" << compNdx << "] = [" << minRes << ", " << maxRes << "] with ULP threshold " << tcu::toHex(maxUlpDiff);
12693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
12703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
12713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
12723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
12753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
12773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12783c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass RoundCase : public CommonFunctionCase
12793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
12803c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
12813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	RoundCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
12823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "round", shaderType)
12833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
12853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
12863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.source = "out0 = round(in0);";
12873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void getInputValues (int numValues, void* const* values) const
12903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Vec2 ranges[] =
12923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-2.0f,		2.0f),	// lowp
12943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e3f,		1e3f),	// mediump
12953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e7f,		1e7f)	// highp
12963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
12973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random				rnd				(deStringHash(getName()) ^ 0xac23fu);
12993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
13003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
13013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
13023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int						numSpecialCases	= 0;
13033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Special cases.
13053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (precision != glu::PRECISION_LOWP)
13063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
13073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(numValues >= 10);
13083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int ndx = 0; ndx < 10; ndx++)
13093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
13103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float v = de::clamp(float(ndx) - 5.5f, ranges[precision].x(), ranges[precision].y());
13113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				std::fill((float*)values[0], (float*)values[0] + scalarSize, v);
13123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				numSpecialCases += 1;
13133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
13143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
13153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Random cases.
13173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[0] + numSpecialCases*scalarSize, (numValues-numSpecialCases)*scalarSize);
13183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// If precision is mediump, make sure values can be represented in fp16 exactly
13203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (precision == glu::PRECISION_MEDIUMP)
13213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
13223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int ndx = 0; ndx < numValues*scalarSize; ndx++)
13233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				((float*)values[0])[ndx] = tcu::Float16(((float*)values[0])[ndx]).asFloat();
13243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
13253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool compare (const void* const* inputs, const void* const* outputs)
13283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
13303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
13313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool				hasZeroSign		= supportsSignedZero(precision);
13323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
13333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP)
13353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
13363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
13373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
13383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		in0			= ((const float*)inputs[0])[compNdx];
13393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		out0		= ((const float*)outputs[0])[compNdx];
13403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (deFloatFrac(in0) == 0.5f)
13423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
13433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					// Allow both ceil(in) and floor(in)
13443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		ref0		= deFloatFloor(in0);
13453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		ref1		= deFloatCeil(in0);
13463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const deUint32	ulpDiff0	= hasZeroSign ? getUlpDiff(out0, ref0) : getUlpDiffIgnoreZeroSign(out0, ref0);
13473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const deUint32	ulpDiff1	= hasZeroSign ? getUlpDiff(out0, ref1) : getUlpDiffIgnoreZeroSign(out0, ref1);
13483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (ulpDiff0 > 0 && ulpDiff1 > 0)
13503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
13513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref0) << " or " << HexFloat(ref1) << ", got ULP diff " << tcu::toHex(de::min(ulpDiff0, ulpDiff1));
13523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						return false;
13533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
13543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
13553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else
13563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
13573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					// Require exact result
13583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		ref		= roundEven(in0);
13593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const deUint32	ulpDiff	= hasZeroSign ? getUlpDiff(out0, ref) : getUlpDiffIgnoreZeroSign(out0, ref);
13603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (ulpDiff > 0)
13623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
13633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff " << tcu::toHex(ulpDiff);
13643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						return false;
13653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
13663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
13673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
13683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
13693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
13703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
13713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		mantissaBits	= getMinMantissaBits(precision);
13723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	maxUlpDiff		= getMaxUlpDiffFromBits(mantissaBits);	// ULP diff for rounded integer value.
13733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		eps				= getEpsFromBits(1.0f, mantissaBits);	// epsilon for rounding bounds
13743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
13763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
13773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		in0			= ((const float*)inputs[0])[compNdx];
13783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		out0		= ((const float*)outputs[0])[compNdx];
13793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		minRes		= int(roundEven(in0-eps));
13803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		maxRes		= int(roundEven(in0+eps));
13813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				bool			anyOk		= false;
13823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int roundedVal = minRes; roundedVal <= maxRes; roundedVal++)
13843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
13853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const deUint32 ulpDiff = getUlpDiffIgnoreZeroSign(out0, float(roundedVal));
13863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (ulpDiff <= maxUlpDiff)
13883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
13893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						anyOk = true;
13903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						break;
13913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
13923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
13933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!anyOk)
13953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
13963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_failMsg << "Expected [" << compNdx << "] = [" << minRes << ", " << maxRes << "] with ULP threshold " << tcu::toHex(maxUlpDiff);
13973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
13983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
13993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
14003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
14013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
14033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
14053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14063c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass CeilCase : public CommonFunctionCase
14073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
14083c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
14093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	CeilCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
14103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "ceil", shaderType)
14113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
14133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
14143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.source = "out0 = ceil(in0);";
14153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void getInputValues (int numValues, void* const* values) const
14183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Vec2 ranges[] =
14203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
14213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-2.0f,		2.0f),	// lowp
14223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e3f,		1e3f),	// mediump
14233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e7f,		1e7f)	// highp
14243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
14253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random				rnd			(deStringHash(getName()) ^ 0xac23fu);
14273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
14283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
14293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize	= glu::getDataTypeScalarSize(type);
14303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Random cases.
14323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[0], numValues*scalarSize);
14333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// If precision is mediump, make sure values can be represented in fp16 exactly
14353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (precision == glu::PRECISION_MEDIUMP)
14363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
14373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int ndx = 0; ndx < numValues*scalarSize; ndx++)
14383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				((float*)values[0])[ndx] = tcu::Float16(((float*)values[0])[ndx]).asFloat();
14393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
14403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool compare (const void* const* inputs, const void* const* outputs)
14433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
14453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
14463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool				hasZeroSign		= supportsSignedZero(precision);
14473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
14483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP)
14503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
14513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Require exact result.
14523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
14533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
14543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		in0			= ((const float*)inputs[0])[compNdx];
14553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		out0		= ((const float*)outputs[0])[compNdx];
14563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		ref			= deFloatCeil(in0);
14573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const deUint32	ulpDiff		= hasZeroSign ? getUlpDiff(out0, ref) : getUlpDiffIgnoreZeroSign(out0, ref);
14593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (ulpDiff > 0)
14613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
14623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff " << tcu::toHex(ulpDiff);
14633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
14643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
14653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
14663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
14673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
14683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
14693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		mantissaBits	= getMinMantissaBits(precision);
14703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	maxUlpDiff		= getMaxUlpDiffFromBits(mantissaBits);	// ULP diff for rounded integer value.
14713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		eps				= getEpsFromBits(1.0f, mantissaBits);	// epsilon for rounding bounds
14723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
14743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
14753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		in0			= ((const float*)inputs[0])[compNdx];
14763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		out0		= ((const float*)outputs[0])[compNdx];
14773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		minRes		= int(deFloatCeil(in0-eps));
14783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		maxRes		= int(deFloatCeil(in0+eps));
14793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				bool			anyOk		= false;
14803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int roundedVal = minRes; roundedVal <= maxRes; roundedVal++)
14823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
14833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const deUint32 ulpDiff = getUlpDiffIgnoreZeroSign(out0, float(roundedVal));
14843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (ulpDiff <= maxUlpDiff)
14863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
14873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						anyOk = true;
14883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						break;
14893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
14903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
14913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!anyOk && de::inRange(0, minRes, maxRes))
14933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
14943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					// Allow -0 as well.
14953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const int ulpDiff = de::abs((int)tcu::Float32(out0).bits() - (int)0x80000000u);
14963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					anyOk = ((deUint32)ulpDiff <= maxUlpDiff);
14973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
14983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!anyOk)
15003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
15013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_failMsg << "Expected [" << compNdx << "] = [" << minRes << ", " << maxRes << "] with ULP threshold " << tcu::toHex(maxUlpDiff);
15023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
15033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
15043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
15053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
15063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
15083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
15103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15113c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FractCase : public CommonFunctionCase
15123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15133c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
15143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FractCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
15153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "fract", shaderType)
15163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
15183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
15193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.source = "out0 = fract(in0);";
15203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void getInputValues (int numValues, void* const* values) const
15233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Vec2 ranges[] =
15253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
15263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-2.0f,		2.0f),	// lowp
15273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e3f,		1e3f),	// mediump
15283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e7f,		1e7f)	// highp
15293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
15303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random				rnd				(deStringHash(getName()) ^ 0xac23fu);
15323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
15333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
15343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
15353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int						numSpecialCases	= 0;
15363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Special cases.
15383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (precision != glu::PRECISION_LOWP)
15393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
15403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(numValues >= 10);
15413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int ndx = 0; ndx < 10; ndx++)
15423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
15433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float v = de::clamp(float(ndx) - 5.5f, ranges[precision].x(), ranges[precision].y());
15443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				std::fill((float*)values[0], (float*)values[0] + scalarSize, v);
15453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				numSpecialCases += 1;
15463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
15473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
15483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Random cases.
15503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[0] + numSpecialCases*scalarSize, (numValues-numSpecialCases)*scalarSize);
15513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// If precision is mediump, make sure values can be represented in fp16 exactly
15533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (precision == glu::PRECISION_MEDIUMP)
15543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
15553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int ndx = 0; ndx < numValues*scalarSize; ndx++)
15563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				((float*)values[0])[ndx] = tcu::Float16(((float*)values[0])[ndx]).asFloat();
15573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
15583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool compare (const void* const* inputs, const void* const* outputs)
15613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
15633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
15643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool				hasZeroSign		= supportsSignedZero(precision);
15653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
15663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP)
15683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
15693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Require exact result.
15703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
15713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
15723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		in0			= ((const float*)inputs[0])[compNdx];
15733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		out0		= ((const float*)outputs[0])[compNdx];
15743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		ref			= deFloatFrac(in0);
15753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const deUint32	ulpDiff		= hasZeroSign ? getUlpDiff(out0, ref) : getUlpDiffIgnoreZeroSign(out0, ref);
15773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (ulpDiff > 0)
15793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
15803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff " << tcu::toHex(ulpDiff);
15813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
15823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
15833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
15843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
15853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
15863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
15873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		mantissaBits	= getMinMantissaBits(precision);
15883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		eps				= getEpsFromBits(1.0f, mantissaBits);	// epsilon for rounding bounds
15893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
15913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
15923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		in0			= ((const float*)inputs[0])[compNdx];
15933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		out0		= ((const float*)outputs[0])[compNdx];
15943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (int(deFloatFloor(in0-eps)) == int(deFloatFloor(in0+eps)))
15963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
15973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		ref			= deFloatFrac(in0);
15983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const int		bitsLost	= numBitsLostInOp(in0, ref);
15993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const deUint32	maxUlpDiff	= getMaxUlpDiffFromBits(de::max(0, mantissaBits-bitsLost));	// ULP diff for rounded integer value.
16003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const deUint32	ulpDiff		= getUlpDiffIgnoreZeroSign(out0, ref);
16013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (ulpDiff > maxUlpDiff)
16033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
16043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << " with ULP threshold " << tcu::toHex(maxUlpDiff) << ", got diff " << tcu::toHex(ulpDiff);
16053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						return false;
16063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
16073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
16083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else
16093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
16103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (out0 >= 1.0f)
16113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
16123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						m_failMsg << "Expected [" << compNdx << "] < 1.0";
16133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						return false;
16143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
16153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
16163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
16173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
16183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
16203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
16223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16233c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderCommonFunctionTests::ShaderCommonFunctionTests (Context& context)
16243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCaseGroup(context, "common", "Common function tests")
16253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
16263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
16273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16283c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderCommonFunctionTests::~ShaderCommonFunctionTests (void)
16293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
16303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
16313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16323c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<class TestClass>
16333c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void addFunctionCases (TestCaseGroup* parent, const char* functionName, bool floatTypes, bool intTypes, bool uintTypes)
16343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
16353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::TestCaseGroup* group = new tcu::TestCaseGroup(parent->getTestContext(), functionName, functionName);
16363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	parent->addChild(group);
16373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::DataType scalarTypes[] =
16393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::TYPE_FLOAT,
16413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::TYPE_INT,
16423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::TYPE_UINT
16433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
16443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int scalarTypeNdx = 0; scalarTypeNdx < DE_LENGTH_OF_ARRAY(scalarTypes); scalarTypeNdx++)
16463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType scalarType = scalarTypes[scalarTypeNdx];
16483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if ((!floatTypes && scalarType == glu::TYPE_FLOAT)	||
16503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			(!intTypes && scalarType == glu::TYPE_INT)		||
16513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			(!uintTypes && scalarType == glu::TYPE_UINT))
16523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			continue;
16533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int vecSize = 1; vecSize <= 4; vecSize++)
16553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
16563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int prec = glu::PRECISION_LOWP; prec <= glu::PRECISION_HIGHP; prec++)
16573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
16583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int shaderType = glu::SHADERTYPE_VERTEX; shaderType <= glu::SHADERTYPE_FRAGMENT; shaderType++)
16593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					group->addChild(new TestClass(parent->getContext(), glu::DataType(scalarType + vecSize - 1), glu::Precision(prec), glu::ShaderType(shaderType)));
16603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
16613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
16623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
16643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16653c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ShaderCommonFunctionTests::init (void)
16663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
16673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	//																	Float?	Int?	Uint?
16683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addFunctionCases<AbsCase>				(this,	"abs",				true,	true,	false);
16693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addFunctionCases<SignCase>				(this,	"sign",				true,	true,	false);
16703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addFunctionCases<FloorCase>				(this,	"floor",			true,	false,	false);
16713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addFunctionCases<TruncCase>				(this,	"trunc",			true,	false,	false);
16723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addFunctionCases<RoundCase>				(this,	"round",			true,	false,	false);
16733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addFunctionCases<RoundEvenCase>			(this,	"roundeven",		true,	false,	false);
16743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addFunctionCases<CeilCase>				(this,	"ceil",				true,	false,	false);
16753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addFunctionCases<FractCase>				(this,	"fract",			true,	false,	false);
16763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// mod
16773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addFunctionCases<ModfCase>				(this,	"modf",				true,	false,	false);
16783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// min
16793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// max
16803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// clamp
16813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// mix
16823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// step
16833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// smoothstep
16843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addFunctionCases<IsnanCase>				(this,	"isnan",			true,	false,	false);
16853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addFunctionCases<IsinfCase>				(this,	"isinf",			true,	false,	false);
16863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addFunctionCases<FloatBitsToIntCase>	(this,	"floatbitstoint",	true,	false,	false);
16873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addFunctionCases<FloatBitsToUintCase>	(this,	"floatbitstouint",	true,	false,	false);
16883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// (u)intBitsToFloat()
16903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::TestCaseGroup* intGroup	= new tcu::TestCaseGroup(m_testCtx, "intbitstofloat",	"intBitsToFloat() Tests");
16923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::TestCaseGroup* uintGroup	= new tcu::TestCaseGroup(m_testCtx, "uintbitstofloat",	"uintBitsToFloat() Tests");
16933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addChild(intGroup);
16953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addChild(uintGroup);
16963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int vecSize = 1; vecSize < 4; vecSize++)
16983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
16993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glu::DataType		intType		= vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
17003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glu::DataType		uintType	= vecSize > 1 ? glu::getDataTypeUintVec(vecSize) : glu::TYPE_UINT;
17013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int shaderType = glu::SHADERTYPE_VERTEX; shaderType <= glu::SHADERTYPE_FRAGMENT; shaderType++)
17033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
17043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				intGroup->addChild(new BitsToFloatCase(m_context, intType, glu::ShaderType(shaderType)));
17053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				uintGroup->addChild(new BitsToFloatCase(m_context, uintType, glu::ShaderType(shaderType)));
17063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
17073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
17083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
17093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
17103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // Functional
17123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // gles3
17133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // deqp
1714