es31fShaderCommonFunctionTests.cpp revision 3c827367444ee418f129b2c238299f49d3264554
13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program OpenGL ES 3.1 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 "es31fShaderCommonFunctionTests.hpp"
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluContextInfo.hpp"
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glsShaderExecUtil.hpp"
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTestLog.hpp"
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuFormatUtil.hpp"
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuFloat.hpp"
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deRandom.hpp"
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deMath.h"
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deString.h"
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace deqp
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace gles31
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace Functional
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::vector;
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::string;
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::TestLog;
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing namespace gls::ShaderExecUtil;
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::Vec2;
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::Vec3;
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::Vec4;
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::IVec2;
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::IVec3;
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::IVec4;
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Utilities
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename T, int Size>
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct VecArrayAccess
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									VecArrayAccess	(const void* ptr) : m_array((tcu::Vector<T, Size>*)ptr) {}
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									~VecArrayAccess	(void) {}
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vector<T, Size>&		operator[]		(size_t offset) const	{ return m_array[offset];	}
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vector<T, Size>&			operator[]		(size_t offset)			{ return m_array[offset];	}
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vector<T, Size>*			m_array;
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename T>	T			randomScalar	(de::Random& rnd, T minValue, T maxValue);
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<> inline		float		randomScalar	(de::Random& rnd, float minValue, float maxValue)		{ return rnd.getFloat(minValue, maxValue);	}
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<> inline		deInt32		randomScalar	(de::Random& rnd, deInt32 minValue, deInt32 maxValue)	{ return rnd.getInt(minValue, maxValue);	}
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<> inline		deUint32	randomScalar	(de::Random& rnd, deUint32 minValue, deUint32 maxValue)	{ return minValue + rnd.getUint32() % (maxValue - minValue + 1); }
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename T, int Size>
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline tcu::Vector<T, Size> randomVector (de::Random& rnd, const tcu::Vector<T, Size>& minValue, const tcu::Vector<T, Size>& maxValue)
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vector<T, Size> res;
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < Size; ndx++)
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		res[ndx] = randomScalar<T>(rnd, minValue[ndx], maxValue[ndx]);
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return res;
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename T, int Size>
843c827367444ee418f129b2c238299f49d3264554Jarkko 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)
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VecArrayAccess<T, Size> access(dst);
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < numValues; ndx++)
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		access[offset + ndx] = randomVector<T, Size>(rnd, minValue, maxValue);
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename T>
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void fillRandomScalars (de::Random& rnd, T minValue, T maxValue, void* dst, int numValues, int offset = 0)
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	T* typedPtr = (T*)dst;
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < numValues; ndx++)
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		typedPtr[offset + ndx] = randomScalar<T>(rnd, minValue, maxValue);
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline int numBitsLostInOp (float input, float output)
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	inExp		= tcu::Float32(input).exponent();
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	outExp		= tcu::Float32(output).exponent();
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return de::max(0, inExp-outExp); // Lost due to mantissa shift.
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline deUint32 getUlpDiff (float a, float b)
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32	aBits	= tcu::Float32(a).bits();
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32	bBits	= tcu::Float32(b).bits();
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return aBits > bBits ? aBits - bBits : bBits - aBits;
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline deUint32 getUlpDiffIgnoreZeroSign (float a, float b)
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (tcu::Float32(a).isZero())
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return getUlpDiff(tcu::Float32::construct(tcu::Float32(b).sign(), 0, 0).asFloat(), b);
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (tcu::Float32(b).isZero())
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return getUlpDiff(a, tcu::Float32::construct(tcu::Float32(a).sign(), 0, 0).asFloat());
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return getUlpDiff(a, b);
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline bool supportsSignedZero (glu::Precision precision)
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// \note GLSL ES 3.1 doesn't really require support for -0, but we require it for highp
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	//		 as it is very widely supported.
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return precision == glu::PRECISION_HIGHP;
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline float getEpsFromMaxUlpDiff (float value, deUint32 ulpDiff)
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int exp = tcu::Float32(value).exponent();
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return tcu::Float32::construct(+1, exp, (1u<<23) | ulpDiff).asFloat() - tcu::Float32::construct(+1, exp, 1u<<23).asFloat();
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline deUint32 getMaxUlpDiffFromBits (int numAccurateBits)
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		numGarbageBits	= 23-numAccurateBits;
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32	mask			= (1u<<numGarbageBits)-1u;
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return mask;
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline float getEpsFromBits (float value, int numAccurateBits)
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return getEpsFromMaxUlpDiff(value, getMaxUlpDiffFromBits(numAccurateBits));
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getMinMantissaBits (glu::Precision precision)
1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int bits[] =
1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		7,		// lowp
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		10,		// mediump
1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		23		// highp
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(bits) == glu::PRECISION_LAST);
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(de::inBounds<int>(precision, 0, DE_LENGTH_OF_ARRAY(bits)));
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return bits[precision];
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// CommonFunctionCase
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass CommonFunctionCase : public TestCase
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							CommonFunctionCase		(Context& context, const char* name, const char* description, glu::ShaderType shaderType);
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							~CommonFunctionCase		(void);
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					init					(void);
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					deinit					(void);
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult			iterate					(void);
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							CommonFunctionCase		(const CommonFunctionCase& other);
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	CommonFunctionCase&		operator=				(const CommonFunctionCase& other);
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual void			getInputValues			(int numValues, void* const* values) const = 0;
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual bool			compare					(const void* const* inputs, const void* const* outputs) = 0;
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::ShaderType			m_shaderType;
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ShaderSpec				m_spec;
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int						m_numValues;
1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream		m_failMsg;				//!< Comparison failure help message.
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ShaderExecutor*			m_executor;
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1923c827367444ee418f129b2c238299f49d3264554Jarkko PoyryCommonFunctionCase::CommonFunctionCase (Context& context, const char* name, const char* description, glu::ShaderType shaderType)
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCase		(context, name, description)
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_shaderType	(shaderType)
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_numValues	(100)
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_executor	(DE_NULL)
1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_spec.version = glu::GLSL_VERSION_310_ES;
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2013c827367444ee418f129b2c238299f49d3264554Jarkko PoyryCommonFunctionCase::~CommonFunctionCase (void)
2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	CommonFunctionCase::deinit();
2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid CommonFunctionCase::init (void)
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(!m_executor);
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_executor = createExecutor(m_context.getRenderContext(), m_shaderType, m_spec);
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << m_executor;
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_executor->isOk())
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::TestError("Compile failed");
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid CommonFunctionCase::deinit (void)
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	delete m_executor;
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_executor = DE_NULL;
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic vector<int> getScalarSizes (const vector<Symbol>& symbols)
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<int> sizes(symbols.size());
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)symbols.size(); ++ndx)
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		sizes[ndx] = symbols[ndx].varType.getScalarSize();
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return sizes;
2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int computeTotalScalarSize (const vector<Symbol>& symbols)
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int totalSize = 0;
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (vector<Symbol>::const_iterator sym = symbols.begin(); sym != symbols.end(); ++sym)
2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		totalSize += sym->varType.getScalarSize();
2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return totalSize;
2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic vector<void*> getInputOutputPointers (const vector<Symbol>& symbols, vector<deUint32>& data, const int numValues)
2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<void*>	pointers		(symbols.size());
2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int				curScalarOffset	= 0;
2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int varNdx = 0; varNdx < (int)symbols.size(); ++varNdx)
2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Symbol&	var				= symbols[varNdx];
2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int		scalarSize		= var.varType.getScalarSize();
2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Uses planar layout as input/output specs do not support strides.
2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pointers[varNdx] = &data[curScalarOffset];
2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		curScalarOffset += scalarSize*numValues;
2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(curScalarOffset == (int)data.size());
2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return pointers;
2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// \todo [2013-08-08 pyry] Make generic utility and move to glu?
2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct HexFloat
2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float value;
2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	HexFloat (const float value_) : value(value_) {}
2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::ostream& operator<< (std::ostream& str, const HexFloat& v)
2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return str << v.value << " / " << tcu::toHex(tcu::Float32(v.value).bits());
2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct HexBool
2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32 value;
2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	HexBool (const deUint32 value_) : value(value_) {}
2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::ostream& operator<< (std::ostream& str, const HexBool& v)
2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return str << (v.value ? "true" : "false") << " / " << tcu::toHex(v.value);
2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct VarValue
2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::VarType&	type;
2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const void*			value;
2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VarValue (const glu::VarType& type_, const void* value_) : type(type_), value(value_) {}
2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::ostream& operator<< (std::ostream& str, const VarValue& varValue)
2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(varValue.type.isBasicType());
2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::DataType		basicType		= varValue.type.getBasicType();
2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::DataType		scalarType		= glu::getDataTypeScalarType(basicType);
2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				numComponents	= glu::getDataTypeScalarSize(basicType);
2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numComponents > 1)
3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		str << glu::getDataTypeName(basicType) << "(";
3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int compNdx = 0; compNdx < numComponents; compNdx++)
3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (compNdx != 0)
3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			str << ", ";
3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (scalarType)
3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case glu::TYPE_FLOAT:	str << HexFloat(((const float*)varValue.value)[compNdx]);			break;
3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case glu::TYPE_INT:		str << ((const deInt32*)varValue.value)[compNdx];					break;
3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case glu::TYPE_UINT:	str << tcu::toHex(((const deUint32*)varValue.value)[compNdx]);		break;
3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case glu::TYPE_BOOL:	str << HexBool(((const deUint32*)varValue.value)[compNdx]);			break;
3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:
3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(false);
3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numComponents > 1)
3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		str << ")";
3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return str;
3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3253c827367444ee418f129b2c238299f49d3264554Jarkko PoyryCommonFunctionCase::IterateResult CommonFunctionCase::iterate (void)
3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				numInputScalars			= computeTotalScalarSize(m_spec.inputs);
3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				numOutputScalars		= computeTotalScalarSize(m_spec.outputs);
3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<deUint32>		inputData				(numInputScalars * m_numValues);
3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<deUint32>		outputData				(numOutputScalars * m_numValues);
3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const vector<void*>		inputPointers			= getInputOutputPointers(m_spec.inputs, inputData, m_numValues);
3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const vector<void*>		outputPointers			= getInputOutputPointers(m_spec.outputs, outputData, m_numValues);
3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Initialize input data.
3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	getInputValues(m_numValues, &inputPointers[0]);
3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Execute shader.
3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_executor->useProgram();
3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_executor->execute(m_numValues, &inputPointers[0], &outputPointers[0]);
3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Compare results.
3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const vector<int>		inScalarSizes		= getScalarSizes(m_spec.inputs);
3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const vector<int>		outScalarSizes		= getScalarSizes(m_spec.outputs);
3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vector<void*>			curInputPtr			(inputPointers.size());
3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vector<void*>			curOutputPtr		(outputPointers.size());
3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int						numFailed			= 0;
3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int valNdx = 0; valNdx < m_numValues; valNdx++)
3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Set up pointers for comparison.
3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int inNdx = 0; inNdx < (int)curInputPtr.size(); ++inNdx)
3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				curInputPtr[inNdx] = (deUint32*)inputPointers[inNdx] + inScalarSizes[inNdx]*valNdx;
3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int outNdx = 0; outNdx < (int)curOutputPtr.size(); ++outNdx)
3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				curOutputPtr[outNdx] = (deUint32*)outputPointers[outNdx] + outScalarSizes[outNdx]*valNdx;
3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!compare(&curInputPtr[0], &curOutputPtr[0]))
3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// \todo [2013-08-08 pyry] We probably want to log reference value as well?
3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.getLog() << TestLog::Message << "ERROR: comparison failed for value " << valNdx << ":\n  " << m_failMsg.str() << TestLog::EndMessage;
3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.getLog() << TestLog::Message << "  inputs:" << TestLog::EndMessage;
3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int inNdx = 0; inNdx < (int)curInputPtr.size(); inNdx++)
3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.getLog() << TestLog::Message << "    " << m_spec.inputs[inNdx].name << " = "
3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														   << VarValue(m_spec.inputs[inNdx].varType, curInputPtr[inNdx])
3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									   << TestLog::EndMessage;
3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.getLog() << TestLog::Message << "  outputs:" << TestLog::EndMessage;
3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int outNdx = 0; outNdx < (int)curOutputPtr.size(); outNdx++)
3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.getLog() << TestLog::Message << "    " << m_spec.outputs[outNdx].name << " = "
3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														   << VarValue(m_spec.outputs[outNdx].varType, curOutputPtr[outNdx])
3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									   << TestLog::EndMessage;
3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_failMsg.str("");
3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_failMsg.clear();
3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				numFailed += 1;
3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << TestLog::Message << (m_numValues - numFailed) << " / " << m_numValues << " values passed" << TestLog::EndMessage;
3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.setTestResult(numFailed == 0 ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								numFailed == 0 ? "Pass"					: "Result comparison failed");
3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
3893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const char* getPrecisionPostfix (glu::Precision precision)
3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const char* s_postfix[] =
3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"_lowp",
3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"_mediump",
3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"_highp"
3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
3993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_postfix) == glu::PRECISION_LAST);
4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(de::inBounds<int>(precision, 0, DE_LENGTH_OF_ARRAY(s_postfix)));
4013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return s_postfix[precision];
4023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const char* getShaderTypePostfix (glu::ShaderType shaderType)
4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const char* s_postfix[] =
4073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"_vertex",
4093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"_fragment",
4103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"_geometry",
4113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"_tess_control",
4123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"_tess_eval",
4133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"_compute"
4143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
4153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(de::inBounds<int>(shaderType, 0, DE_LENGTH_OF_ARRAY(s_postfix)));
4163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return s_postfix[shaderType];
4173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4193c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic std::string getCommonFuncCaseName (glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
4203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return string(glu::getDataTypeName(baseType)) + getPrecisionPostfix(precision) + getShaderTypePostfix(shaderType);
4223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4243c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass AbsCase : public CommonFunctionCase
4253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4263c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
4273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	AbsCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
4283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "abs", shaderType)
4293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
4313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
4323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.source = "out0 = abs(in0);";
4333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void getInputValues (int numValues, void* const* values) const
4363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Vec2 floatRanges[] =
4383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-2.0f,		2.0f),	// lowp
4403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e3f,		1e3f),	// mediump
4413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e7f,		1e7f)	// highp
4423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
4433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const IVec2 intRanges[] =
4443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			IVec2(-(1<<7)+1,	(1<<7)-1),
4463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			IVec2(-(1<<15)+1,	(1<<15)-1),
4473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			IVec2(0x80000001,	0x7fffffff)
4483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
4493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random				rnd			(deStringHash(getName()) ^ 0x235facu);
4513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
4523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
4533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize	= glu::getDataTypeScalarSize(type);
4543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (glu::isDataTypeFloatOrVec(type))
4563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			fillRandomScalars(rnd, floatRanges[precision].x(), floatRanges[precision].y(), values[0], numValues*scalarSize);
4573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
4583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			fillRandomScalars(rnd, intRanges[precision].x(), intRanges[precision].y(), values[0], numValues*scalarSize);
4593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool compare (const void* const* inputs, const void* const* outputs)
4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
4643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
4663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (glu::isDataTypeFloatOrVec(type))
4683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		mantissaBits	= getMinMantissaBits(precision);
4703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	maxUlpDiff		= (1u<<(23-mantissaBits))-1u;
4713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
4733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
4743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		in0			= ((const float*)inputs[0])[compNdx];
4753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		out0		= ((const float*)outputs[0])[compNdx];
4763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		ref0		= de::abs(in0);
4773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const deUint32	ulpDiff0	= getUlpDiff(out0, ref0);
4783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (ulpDiff0 > maxUlpDiff)
4803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
4813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref0) << " with ULP threshold " << maxUlpDiff << ", got ULP diff " << ulpDiff0;
4823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
4833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
4853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
4903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int	in0		= ((const int*)inputs[0])[compNdx];
4913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int	out0	= ((const int*)outputs[0])[compNdx];
4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int	ref0	= de::abs(in0);
4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (out0 != ref0)
4953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
4963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_failMsg << "Expected [" << compNdx << "] = " << ref0;
4973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
4983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
4993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
5003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
5033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
5053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5063c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass SignCase : public CommonFunctionCase
5073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5083c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
5093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	SignCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
5103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "sign", shaderType)
5113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
5133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
5143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.source = "out0 = sign(in0);";
5153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void getInputValues (int numValues, void* const* values) const
5183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Vec2 floatRanges[] =
5203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-2.0f,		2.0f),	// lowp
5223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e4f,		1e4f),	// mediump	- note: may end up as inf
5233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e8f,		1e8f)	// highp	- note: may end up as inf
5243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
5253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const IVec2 intRanges[] =
5263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			IVec2(-(1<<7),		(1<<7)-1),
5283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			IVec2(-(1<<15),		(1<<15)-1),
5293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			IVec2(0x80000000,	0x7fffffff)
5303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
5313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random				rnd			(deStringHash(getName()) ^ 0x324u);
5333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
5343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
5353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize	= glu::getDataTypeScalarSize(type);
5363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (glu::isDataTypeFloatOrVec(type))
5383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Special cases.
5403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			std::fill((float*)values[0], (float*)values[0] + scalarSize, +1.0f);
5413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			std::fill((float*)values[0], (float*)values[0] + scalarSize, -1.0f);
5423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			std::fill((float*)values[0], (float*)values[0] + scalarSize,  0.0f);
5433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			fillRandomScalars(rnd, floatRanges[precision].x(), floatRanges[precision].y(), (float*)values[0] + scalarSize*3, (numValues-3)*scalarSize);
5443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
5463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			std::fill((int*)values[0], (int*)values[0] + scalarSize, +1);
5483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			std::fill((int*)values[0], (int*)values[0] + scalarSize, -1);
5493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			std::fill((int*)values[0], (int*)values[0] + scalarSize,  0);
5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			fillRandomScalars(rnd, intRanges[precision].x(), intRanges[precision].y(), (int*)values[0] + scalarSize*3, (numValues-3)*scalarSize);
5513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool compare (const void* const* inputs, const void* const* outputs)
5553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
5573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
5583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
5593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (glu::isDataTypeFloatOrVec(type))
5613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Both highp and mediump should be able to represent -1, 0, and +1 exactly
5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32 maxUlpDiff = precision == glu::PRECISION_LOWP ? getMaxUlpDiffFromBits(getMinMantissaBits(precision)) : 0;
5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
5663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
5673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		in0			= ((const float*)inputs[0])[compNdx];
5683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		out0		= ((const float*)outputs[0])[compNdx];
5693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		ref0		= in0 < 0.0f ? -1.0f :
5703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											  in0 > 0.0f ? +1.0f : 0.0f;
5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const deUint32	ulpDiff0	= getUlpDiff(out0, ref0);
5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (ulpDiff0 > maxUlpDiff)
5743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
5753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref0) << " with ULP threshold " << maxUlpDiff << ", got ULP diff " << ulpDiff0;
5763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
5783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
5793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
5813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
5833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
5843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int	in0		= ((const int*)inputs[0])[compNdx];
5853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int	out0	= ((const int*)outputs[0])[compNdx];
5863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int	ref0	= in0 < 0 ? -1 :
5873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									  in0 > 0 ? +1 : 0;
5883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (out0 != ref0)
5903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
5913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_failMsg << "Expected [" << compNdx << "] = " << ref0;
5923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
5933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
5943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
5953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
5983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
6003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6013c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic float roundEven (float v)
6023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float		q			= deFloatFrac(v);
6043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		truncated	= int(v-q);
6053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		rounded		= (q > 0.5f)							? (truncated + 1) :	// Rounded up
6063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									(q == 0.5f && (truncated % 2 != 0))	? (truncated + 1) :	// Round to nearest even at 0.5
6073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									truncated;												// Rounded down
6083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return float(rounded);
6103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6123c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass RoundEvenCase : public CommonFunctionCase
6133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6143c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
6153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	RoundEvenCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
6163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "roundEven", shaderType)
6173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
6193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
6203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.source = "out0 = roundEven(in0);";
6213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void getInputValues (int numValues, void* const* values) const
6243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Vec2 ranges[] =
6263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-2.0f,		2.0f),	// lowp
6283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e3f,		1e3f),	// mediump
6293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e7f,		1e7f)	// highp
6303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
6313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random				rnd				(deStringHash(getName()) ^ 0xac23fu);
6333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
6343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
6353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
6363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int						numSpecialCases	= 0;
6373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Special cases.
6393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (precision != glu::PRECISION_LOWP)
6403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(numValues >= 20);
6423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int ndx = 0; ndx < 20; ndx++)
6433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
6443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float v = de::clamp(float(ndx) - 10.5f, ranges[precision].x(), ranges[precision].y());
6453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				std::fill((float*)values[0], (float*)values[0] + scalarSize, v);
6463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				numSpecialCases += 1;
6473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
6483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Random cases.
6513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[0] + numSpecialCases*scalarSize, (numValues-numSpecialCases)*scalarSize);
6523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// If precision is mediump, make sure values can be represented in fp16 exactly
6543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (precision == glu::PRECISION_MEDIUMP)
6553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int ndx = 0; ndx < numValues*scalarSize; ndx++)
6573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				((float*)values[0])[ndx] = tcu::Float16(((float*)values[0])[ndx]).asFloat();
6583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool compare (const void* const* inputs, const void* const* outputs)
6623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
6643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
6653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool				hasSignedZero	= supportsSignedZero(precision);
6663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
6673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP)
6693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Require exact rounding result.
6713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
6723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
6733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		in0			= ((const float*)inputs[0])[compNdx];
6743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		out0		= ((const float*)outputs[0])[compNdx];
6753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		ref			= roundEven(in0);
6763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const deUint32	ulpDiff		= hasSignedZero ? getUlpDiff(out0, ref) : getUlpDiffIgnoreZeroSign(out0, ref);
6783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (ulpDiff > 0)
6803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
6813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff " << tcu::toHex(ulpDiff);
6823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
6833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
6843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
6853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
6873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		mantissaBits	= getMinMantissaBits(precision);
6893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	maxUlpDiff		= getMaxUlpDiffFromBits(mantissaBits);	// ULP diff for rounded integer value.
6903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		eps				= getEpsFromBits(1.0f, mantissaBits);	// epsilon for rounding bounds
6913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
6933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
6943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		in0			= ((const float*)inputs[0])[compNdx];
6953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		out0		= ((const float*)outputs[0])[compNdx];
6963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		minRes		= int(roundEven(in0-eps));
6973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		maxRes		= int(roundEven(in0+eps));
6983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				bool			anyOk		= false;
6993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int roundedVal = minRes; roundedVal <= maxRes; roundedVal++)
7013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
7023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const deUint32 ulpDiff = getUlpDiffIgnoreZeroSign(out0, float(roundedVal));
7033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (ulpDiff <= maxUlpDiff)
7053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
7063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						anyOk = true;
7073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						break;
7083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
7093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
7103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!anyOk)
7123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
7133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_failMsg << "Expected [" << compNdx << "] = [" << minRes << ", " << maxRes << "] with ULP threshold " << tcu::toHex(maxUlpDiff);
7143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
7153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
7163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
7173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
7203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
7223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7233c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ModfCase : public CommonFunctionCase
7243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7253c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
7263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ModfCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
7273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "modf", shaderType)
7283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
7303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
7313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("out1", glu::VarType(baseType, precision)));
7323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.source = "out0 = modf(in0, out1);";
7333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void getInputValues (int numValues, void* const* values) const
7363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Vec2 ranges[] =
7383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-2.0f,		2.0f),	// lowp
7403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e3f,		1e3f),	// mediump
7413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e7f,		1e7f)	// highp
7423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
7433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random				rnd			(deStringHash(getName()) ^ 0xac23fu);
7453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
7463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
7473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize	= glu::getDataTypeScalarSize(type);
7483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), values[0], numValues*scalarSize);
7503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool compare (const void* const* inputs, const void* const* outputs)
7533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
7553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
7563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool				hasZeroSign		= supportsSignedZero(precision);
7573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
7583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				mantissaBits	= getMinMantissaBits(precision);
7603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
7623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		in0			= ((const float*)inputs[0])[compNdx];
7643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		out0		= ((const float*)outputs[0])[compNdx];
7653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		out1		= ((const float*)outputs[1])[compNdx];
7663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		refOut1		= float(int(in0));
7683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		refOut0		= in0 - refOut1;
7693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		bitsLost	= precision != glu::PRECISION_HIGHP ? numBitsLostInOp(in0, refOut0) : 0;
7713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	maxUlpDiff	= getMaxUlpDiffFromBits(de::max(mantissaBits - bitsLost, 0));
7723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		resSum		= out0 + out1;
7743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	ulpDiff		= hasZeroSign ? getUlpDiff(resSum, in0) : getUlpDiffIgnoreZeroSign(resSum, in0);
7763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (ulpDiff > maxUlpDiff)
7783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
7793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_failMsg << "Expected [" << compNdx << "] = (" << HexFloat(refOut0) << ") + (" << HexFloat(refOut1) << ") = " << HexFloat(in0) << " with ULP threshold "
7803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							<< tcu::toHex(maxUlpDiff) << ", got ULP diff " << tcu::toHex(ulpDiff);
7813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return false;
7823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
7833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
7863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
7883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7893c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass IsnanCase : public CommonFunctionCase
7903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7913c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
7923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IsnanCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
7933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "isnan", shaderType)
7943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(glu::isDataTypeFloatOrVec(baseType));
7963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int			vecSize		= glu::getDataTypeScalarSize(baseType);
7983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType	boolType	= vecSize > 1 ? glu::getDataTypeBoolVec(vecSize) : glu::TYPE_BOOL;
7993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
8013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("out0", glu::VarType(boolType, glu::PRECISION_LAST)));
8023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.source = "out0 = isnan(in0);";
8033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void getInputValues (int numValues, void* const* values) const
8063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random				rnd				(deStringHash(getName()) ^ 0xc2a39fu);
8083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
8093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
8103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
8113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				mantissaBits	= getMinMantissaBits(precision);
8123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint32			mantissaMask	= ~getMaxUlpDiffFromBits(mantissaBits) & ((1u<<23)-1u);
8133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int valNdx = 0; valNdx < numValues*scalarSize; valNdx++)
8153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const bool		isNan		= rnd.getFloat() > 0.3f;
8173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const bool		isInf		= !isNan && rnd.getFloat() > 0.4f;
8183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	mantissa	= !isInf ? ((1u<<22) | (rnd.getUint32() & mantissaMask)) : 0;
8193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	exp			= !isNan && !isInf ? (rnd.getUint32() & 0x7fu) : 0xffu;
8203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	sign		= rnd.getUint32() & 0x1u;
8213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	value		= (sign << 31) | (exp << 23) | mantissa;
8223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(tcu::Float32(value).isInf() == isInf && tcu::Float32(value).isNaN() == isNan);
8243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			((deUint32*)values[0])[valNdx] = value;
8263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
8273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool compare (const void* const* inputs, const void* const* outputs)
8303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
8323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
8333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
8343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (precision == glu::PRECISION_HIGHP)
8363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Only highp is required to support inf/nan
8383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
8393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
8403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		in0		= ((const float*)inputs[0])[compNdx];
8413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const deUint32	out0	= ((const deUint32*)outputs[0])[compNdx];
8423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const deUint32	ref		= tcu::Float32(in0).isNaN() ? 1u : 0u;
8433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (out0 != ref)
8453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
8463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_failMsg << "Expected [" << compNdx << "] = " << HexBool(ref);
8473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
8483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
8493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
8503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
8513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
8523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Value can be either 0 or 1
8543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
8553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
8563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int out0 = ((const int*)outputs[0])[compNdx];
8573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (out0 != 0 && out0 != 1)
8593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
8603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_failMsg << "Expected [" << compNdx << "] = 0 / 1";
8613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
8623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
8633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
8643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
8653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
8673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
8693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8703c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass IsinfCase : public CommonFunctionCase
8713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8723c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
8733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IsinfCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
8743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "isinf", shaderType)
8753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(glu::isDataTypeFloatOrVec(baseType));
8773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int			vecSize		= glu::getDataTypeScalarSize(baseType);
8793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType	boolType	= vecSize > 1 ? glu::getDataTypeBoolVec(vecSize) : glu::TYPE_BOOL;
8803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
8823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("out0", glu::VarType(boolType, glu::PRECISION_LAST)));
8833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.source = "out0 = isinf(in0);";
8843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void getInputValues (int numValues, void* const* values) const
8873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random				rnd				(deStringHash(getName()) ^ 0xc2a39fu);
8893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
8903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
8913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
8923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				mantissaBits	= getMinMantissaBits(precision);
8933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint32			mantissaMask	= ~getMaxUlpDiffFromBits(mantissaBits) & ((1u<<23)-1u);
8943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int valNdx = 0; valNdx < numValues*scalarSize; valNdx++)
8963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const bool		isInf		= rnd.getFloat() > 0.3f;
8983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const bool		isNan		= !isInf && rnd.getFloat() > 0.4f;
8993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	mantissa	= !isInf ? ((1u<<22) | (rnd.getUint32() & mantissaMask)) : 0;
9003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	exp			= !isNan && !isInf ? (rnd.getUint32() & 0x7fu) : 0xffu;
9013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	sign		= rnd.getUint32() & 0x1u;
9023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	value		= (sign << 31) | (exp << 23) | mantissa;
9033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(tcu::Float32(value).isInf() == isInf && tcu::Float32(value).isNaN() == isNan);
9053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			((deUint32*)values[0])[valNdx] = value;
9073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
9083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool compare (const void* const* inputs, const void* const* outputs)
9113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
9133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
9143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
9153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (precision == glu::PRECISION_HIGHP)
9173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
9183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Only highp is required to support inf/nan
9193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
9203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
9213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		in0		= ((const float*)inputs[0])[compNdx];
9223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const deUint32	out0	= ((const deUint32*)outputs[0])[compNdx];
9233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const deUint32	ref		= tcu::Float32(in0).isInf() ? 1u : 0u;
9243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (out0 != ref)
9263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
9273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_failMsg << "Expected [" << compNdx << "] = " << HexBool(ref);
9283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
9293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
9303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
9313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
9323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
9333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
9343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Value can be either 0 or 1
9353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
9363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
9373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int out0 = ((const int*)outputs[0])[compNdx];
9383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (out0 != 0 && out0 != 1)
9403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
9413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_failMsg << "Expected [" << compNdx << "] = 0 / 1";
9423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
9433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
9443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
9453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
9463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
9483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
9503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9513c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FloatBitsToUintIntCase : public CommonFunctionCase
9523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9533c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
9543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FloatBitsToUintIntCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType, bool outIsSigned)
9553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), outIsSigned ? "floatBitsToInt" : "floatBitsToUint", shaderType)
9563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int			vecSize		= glu::getDataTypeScalarSize(baseType);
9583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType	intType		= outIsSigned ? (vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT)
9593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  : (vecSize > 1 ? glu::getDataTypeUintVec(vecSize) : glu::TYPE_UINT);
9603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
9623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("out0", glu::VarType(intType, glu::PRECISION_HIGHP)));
9633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.source = outIsSigned ? "out0 = floatBitsToInt(in0);" : "out0 = floatBitsToUint(in0);";
9643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void getInputValues (int numValues, void* const* values) const
9673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Vec2 ranges[] =
9693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
9703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-2.0f,		2.0f),	// lowp
9713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e3f,		1e3f),	// mediump
9723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e7f,		1e7f)	// highp
9733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
9743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random				rnd			(deStringHash(getName()) ^ 0x2790au);
9763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
9773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
9783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize	= glu::getDataTypeScalarSize(type);
9793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), values[0], numValues*scalarSize);
9813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool compare (const void* const* inputs, const void* const* outputs)
9843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
9863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
9873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
9883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				mantissaBits	= getMinMantissaBits(precision);
9903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				maxUlpDiff		= getMaxUlpDiffFromBits(mantissaBits);
9913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
9933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
9943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		in0			= ((const float*)inputs[0])[compNdx];
9953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	out0		= ((const deUint32*)outputs[0])[compNdx];
9963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	refOut0		= tcu::Float32(in0).bits();
9973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		ulpDiff		= de::abs((int)out0 - (int)refOut0);
9983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (ulpDiff > maxUlpDiff)
10003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
10013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(refOut0) << " with threshold "
10023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							<< tcu::toHex(maxUlpDiff) << ", got diff " << tcu::toHex(ulpDiff);
10033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return false;
10043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
10053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
10063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
10083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
10103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10113c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FloatBitsToIntCase : public FloatBitsToUintIntCase
10123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10133c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
10143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FloatBitsToIntCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
10153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: FloatBitsToUintIntCase(context, baseType, precision, shaderType, true)
10163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
10193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10203c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FloatBitsToUintCase : public FloatBitsToUintIntCase
10213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10223c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
10233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FloatBitsToUintCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
10243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: FloatBitsToUintIntCase(context, baseType, precision, shaderType, false)
10253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
10283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10293c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass BitsToFloatCase : public CommonFunctionCase
10303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10313c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
10323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	BitsToFloatCase (Context& context, glu::DataType baseType, glu::ShaderType shaderType)
10333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, glu::PRECISION_HIGHP, shaderType).c_str(), glu::isDataTypeIntOrIVec(baseType) ? "intBitsToFloat" : "uintBitsToFloat", shaderType)
10343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool			inIsSigned	= glu::isDataTypeIntOrIVec(baseType);
10363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int			vecSize		= glu::getDataTypeScalarSize(baseType);
10373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType	floatType	= vecSize > 1 ? glu::getDataTypeFloatVec(vecSize) : glu::TYPE_FLOAT;
10383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, glu::PRECISION_HIGHP)));
10403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("out0", glu::VarType(floatType, glu::PRECISION_HIGHP)));
10413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.source = inIsSigned ? "out0 = intBitsToFloat(in0);" : "out0 = uintBitsToFloat(in0);";
10423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void getInputValues (int numValues, void* const* values) const
10453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random				rnd			(deStringHash(getName()) ^ 0xbbb225u);
10473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
10483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize	= glu::getDataTypeScalarSize(type);
10493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Vec2				range		(-1e8f, +1e8f);
10503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// \note Filled as floats.
10523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		fillRandomScalars(rnd, range.x(), range.y(), values[0], numValues*scalarSize);
10533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool compare (const void* const* inputs, const void* const* outputs)
10563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
10583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
10593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				maxUlpDiff		= 0;
10603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
10623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
10633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		in0			= ((const float*)inputs[0])[compNdx];
10643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		out0		= ((const float*)outputs[0])[compNdx];
10653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		ulpDiff		= de::abs((int)in0 - (int)out0);
10663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (ulpDiff > maxUlpDiff)
10683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
10693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(in0) << " with ULP threshold "
10703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							<< tcu::toHex(maxUlpDiff) << ", got ULP diff " << tcu::toHex(ulpDiff);
10713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return false;
10723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
10733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
10743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
10763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
10783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10793c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FloorCase : public CommonFunctionCase
10803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10813c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
10823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FloorCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
10833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "floor", shaderType)
10843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
10863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
10873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.source = "out0 = floor(in0);";
10883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void getInputValues (int numValues, void* const* values) const
10913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Vec2 ranges[] =
10933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
10943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-2.0f,		2.0f),	// lowp
10953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e3f,		1e3f),	// mediump
10963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e7f,		1e7f)	// highp
10973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
10983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random				rnd			(deStringHash(getName()) ^ 0xac23fu);
11003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
11013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
11023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize	= glu::getDataTypeScalarSize(type);
11033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Random cases.
11043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[0], numValues*scalarSize);
11053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// If precision is mediump, make sure values can be represented in fp16 exactly
11073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (precision == glu::PRECISION_MEDIUMP)
11083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int ndx = 0; ndx < numValues*scalarSize; ndx++)
11103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				((float*)values[0])[ndx] = tcu::Float16(((float*)values[0])[ndx]).asFloat();
11113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
11123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool compare (const void* const* inputs, const void* const* outputs)
11153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
11173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
11183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
11193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP)
11213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Require exact result.
11233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
11243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
11253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		in0			= ((const float*)inputs[0])[compNdx];
11263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		out0		= ((const float*)outputs[0])[compNdx];
11273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		ref			= deFloatFloor(in0);
11283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const deUint32	ulpDiff		= getUlpDiff(out0, ref);
11303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (ulpDiff > 0)
11323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
11333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff " << tcu::toHex(ulpDiff);
11343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
11353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
11363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
11373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
11383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
11393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		mantissaBits	= getMinMantissaBits(precision);
11413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	maxUlpDiff		= getMaxUlpDiffFromBits(mantissaBits);	// ULP diff for rounded integer value.
11423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		eps				= getEpsFromBits(1.0f, mantissaBits);	// epsilon for rounding bounds
11433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
11453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
11463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		in0			= ((const float*)inputs[0])[compNdx];
11473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		out0		= ((const float*)outputs[0])[compNdx];
11483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		minRes		= int(deFloatFloor(in0-eps));
11493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		maxRes		= int(deFloatFloor(in0+eps));
11503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				bool			anyOk		= false;
11513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int roundedVal = minRes; roundedVal <= maxRes; roundedVal++)
11533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
11543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const deUint32 ulpDiff = getUlpDiff(out0, float(roundedVal));
11553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (ulpDiff <= maxUlpDiff)
11573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
11583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						anyOk = true;
11593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						break;
11603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
11613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
11623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!anyOk)
11643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
11653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_failMsg << "Expected [" << compNdx << "] = [" << minRes << ", " << maxRes << "] with ULP threshold " << tcu::toHex(maxUlpDiff);
11663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
11673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
11683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
11693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
11703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
11723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
11743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11753c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass TruncCase : public CommonFunctionCase
11763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11773c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
11783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TruncCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
11793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "trunc", shaderType)
11803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
11823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
11833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.source = "out0 = trunc(in0);";
11843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void getInputValues (int numValues, void* const* values) const
11873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Vec2 ranges[] =
11893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-2.0f,		2.0f),	// lowp
11913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e3f,		1e3f),	// mediump
11923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e7f,		1e7f)	// highp
11933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
11943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random				rnd				(deStringHash(getName()) ^ 0xac23fu);
11963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
11973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
11983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
11993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float				specialCases[]	= { 0.0f, -0.0f, -0.9f, 0.9f, 1.0f, -1.0f };
12003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				numSpecialCases	= DE_LENGTH_OF_ARRAY(specialCases);
12013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Special cases
12033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int caseNdx = 0; caseNdx < numSpecialCases; caseNdx++)
12043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++)
12063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				((float*)values[0])[caseNdx*scalarSize + scalarNdx] = specialCases[caseNdx];
12073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Random cases.
12103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[0] + scalarSize*numSpecialCases, (numValues-numSpecialCases)*scalarSize);
12113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// If precision is mediump, make sure values can be represented in fp16 exactly
12133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (precision == glu::PRECISION_MEDIUMP)
12143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int ndx = 0; ndx < numValues*scalarSize; ndx++)
12163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				((float*)values[0])[ndx] = tcu::Float16(((float*)values[0])[ndx]).asFloat();
12173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool compare (const void* const* inputs, const void* const* outputs)
12213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
12233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
12243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool				hasSignedZero	= supportsSignedZero(precision);
12253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
12263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP)
12283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Require exact result.
12303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
12313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
12323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		in0			= ((const float*)inputs[0])[compNdx];
12333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		out0		= ((const float*)outputs[0])[compNdx];
12343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const bool		isNeg		= tcu::Float32(in0).sign() < 0;
12353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		ref			= isNeg ? (-float(int(-in0))) : float(int(in0));
12363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const deUint32	ulpDiff		= hasSignedZero ? getUlpDiff(out0, ref) : getUlpDiffIgnoreZeroSign(out0, ref);
12383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (ulpDiff > 0)
12403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
12413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff " << tcu::toHex(ulpDiff);
12423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
12433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
12443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
12453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
12473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		mantissaBits	= getMinMantissaBits(precision);
12493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	maxUlpDiff		= getMaxUlpDiffFromBits(mantissaBits);	// ULP diff for rounded integer value.
12503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		eps				= getEpsFromBits(1.0f, mantissaBits);	// epsilon for rounding bounds
12513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
12533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
12543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		in0			= ((const float*)inputs[0])[compNdx];
12553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		out0		= ((const float*)outputs[0])[compNdx];
12563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		minRes		= int(in0-eps);
12573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		maxRes		= int(in0+eps);
12583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				bool			anyOk		= false;
12593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int roundedVal = minRes; roundedVal <= maxRes; roundedVal++)
12613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
12623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const deUint32 ulpDiff = getUlpDiffIgnoreZeroSign(out0, float(roundedVal));
12633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (ulpDiff <= maxUlpDiff)
12653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
12663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						anyOk = true;
12673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						break;
12683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
12693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
12703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!anyOk)
12723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
12733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_failMsg << "Expected [" << compNdx << "] = [" << minRes << ", " << maxRes << "] with ULP threshold " << tcu::toHex(maxUlpDiff);
12743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
12753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
12763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
12773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
12803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
12823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12833c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass RoundCase : public CommonFunctionCase
12843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
12853c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
12863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	RoundCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
12873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "round", shaderType)
12883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
12903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
12913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.source = "out0 = round(in0);";
12923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void getInputValues (int numValues, void* const* values) const
12953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Vec2 ranges[] =
12973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-2.0f,		2.0f),	// lowp
12993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e3f,		1e3f),	// mediump
13003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e7f,		1e7f)	// highp
13013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
13023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random				rnd				(deStringHash(getName()) ^ 0xac23fu);
13043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
13053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
13063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
13073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int						numSpecialCases	= 0;
13083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Special cases.
13103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (precision != glu::PRECISION_LOWP)
13113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
13123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(numValues >= 10);
13133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int ndx = 0; ndx < 10; ndx++)
13143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
13153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float v = de::clamp(float(ndx) - 5.5f, ranges[precision].x(), ranges[precision].y());
13163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				std::fill((float*)values[0], (float*)values[0] + scalarSize, v);
13173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				numSpecialCases += 1;
13183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
13193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
13203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Random cases.
13223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[0] + numSpecialCases*scalarSize, (numValues-numSpecialCases)*scalarSize);
13233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// If precision is mediump, make sure values can be represented in fp16 exactly
13253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (precision == glu::PRECISION_MEDIUMP)
13263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
13273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int ndx = 0; ndx < numValues*scalarSize; ndx++)
13283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				((float*)values[0])[ndx] = tcu::Float16(((float*)values[0])[ndx]).asFloat();
13293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
13303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool compare (const void* const* inputs, const void* const* outputs)
13333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
13353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
13363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool				hasZeroSign		= supportsSignedZero(precision);
13373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
13383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP)
13403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
13413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
13423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
13433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		in0			= ((const float*)inputs[0])[compNdx];
13443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		out0		= ((const float*)outputs[0])[compNdx];
13453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (deFloatFrac(in0) == 0.5f)
13473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
13483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					// Allow both ceil(in) and floor(in)
13493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		ref0		= deFloatFloor(in0);
13503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		ref1		= deFloatCeil(in0);
13513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const deUint32	ulpDiff0	= hasZeroSign ? getUlpDiff(out0, ref0) : getUlpDiffIgnoreZeroSign(out0, ref0);
13523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const deUint32	ulpDiff1	= hasZeroSign ? getUlpDiff(out0, ref1) : getUlpDiffIgnoreZeroSign(out0, ref1);
13533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (ulpDiff0 > 0 && ulpDiff1 > 0)
13553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
13563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref0) << " or " << HexFloat(ref1) << ", got ULP diff " << tcu::toHex(de::min(ulpDiff0, ulpDiff1));
13573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						return false;
13583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
13593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
13603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else
13613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
13623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					// Require exact result
13633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		ref		= roundEven(in0);
13643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const deUint32	ulpDiff	= hasZeroSign ? getUlpDiff(out0, ref) : getUlpDiffIgnoreZeroSign(out0, ref);
13653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (ulpDiff > 0)
13673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
13683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff " << tcu::toHex(ulpDiff);
13693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						return false;
13703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
13713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
13723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
13733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
13743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
13753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
13763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		mantissaBits	= getMinMantissaBits(precision);
13773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	maxUlpDiff		= getMaxUlpDiffFromBits(mantissaBits);	// ULP diff for rounded integer value.
13783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		eps				= getEpsFromBits(1.0f, mantissaBits);	// epsilon for rounding bounds
13793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
13813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
13823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		in0			= ((const float*)inputs[0])[compNdx];
13833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		out0		= ((const float*)outputs[0])[compNdx];
13843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		minRes		= int(roundEven(in0-eps));
13853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		maxRes		= int(roundEven(in0+eps));
13863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				bool			anyOk		= false;
13873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int roundedVal = minRes; roundedVal <= maxRes; roundedVal++)
13893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
13903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const deUint32 ulpDiff = getUlpDiffIgnoreZeroSign(out0, float(roundedVal));
13913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (ulpDiff <= maxUlpDiff)
13933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
13943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						anyOk = true;
13953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						break;
13963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
13973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
13983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!anyOk)
14003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
14013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_failMsg << "Expected [" << compNdx << "] = [" << minRes << ", " << maxRes << "] with ULP threshold " << tcu::toHex(maxUlpDiff);
14023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
14033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
14043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
14053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
14063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
14083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
14103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14113c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass CeilCase : public CommonFunctionCase
14123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
14133c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
14143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	CeilCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
14153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "ceil", shaderType)
14163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
14183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
14193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.source = "out0 = ceil(in0);";
14203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void getInputValues (int numValues, void* const* values) const
14233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Vec2 ranges[] =
14253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
14263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-2.0f,		2.0f),	// lowp
14273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e3f,		1e3f),	// mediump
14283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e7f,		1e7f)	// highp
14293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
14303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random				rnd			(deStringHash(getName()) ^ 0xac23fu);
14323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
14333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
14343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize	= glu::getDataTypeScalarSize(type);
14353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Random cases.
14373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[0], numValues*scalarSize);
14383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// If precision is mediump, make sure values can be represented in fp16 exactly
14403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (precision == glu::PRECISION_MEDIUMP)
14413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
14423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int ndx = 0; ndx < numValues*scalarSize; ndx++)
14433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				((float*)values[0])[ndx] = tcu::Float16(((float*)values[0])[ndx]).asFloat();
14443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
14453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool compare (const void* const* inputs, const void* const* outputs)
14483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
14503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
14513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool				hasZeroSign		= supportsSignedZero(precision);
14523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
14533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP)
14553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
14563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Require exact result.
14573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
14583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
14593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		in0			= ((const float*)inputs[0])[compNdx];
14603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		out0		= ((const float*)outputs[0])[compNdx];
14613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		ref			= deFloatCeil(in0);
14623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const deUint32	ulpDiff		= hasZeroSign ? getUlpDiff(out0, ref) : getUlpDiffIgnoreZeroSign(out0, ref);
14643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (ulpDiff > 0)
14663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
14673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff " << tcu::toHex(ulpDiff);
14683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
14693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
14703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
14713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
14723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
14733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
14743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		mantissaBits	= getMinMantissaBits(precision);
14753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	maxUlpDiff		= getMaxUlpDiffFromBits(mantissaBits);	// ULP diff for rounded integer value.
14763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		eps				= getEpsFromBits(1.0f, mantissaBits);	// epsilon for rounding bounds
14773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
14793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
14803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		in0			= ((const float*)inputs[0])[compNdx];
14813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		out0		= ((const float*)outputs[0])[compNdx];
14823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		minRes		= int(deFloatCeil(in0-eps));
14833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		maxRes		= int(deFloatCeil(in0+eps));
14843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				bool			anyOk		= false;
14853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int roundedVal = minRes; roundedVal <= maxRes; roundedVal++)
14873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
14883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const deUint32 ulpDiff = getUlpDiffIgnoreZeroSign(out0, float(roundedVal));
14893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (ulpDiff <= maxUlpDiff)
14913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
14923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						anyOk = true;
14933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						break;
14943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
14953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
14963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!anyOk && de::inRange(0, minRes, maxRes))
14983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
14993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					// Allow -0 as well.
15003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const int ulpDiff = de::abs((int)tcu::Float32(out0).bits() - (int)0x80000000u);
15013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					anyOk = ((deUint32)ulpDiff <= maxUlpDiff);
15023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
15033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!anyOk)
15053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
15063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_failMsg << "Expected [" << compNdx << "] = [" << minRes << ", " << maxRes << "] with ULP threshold " << tcu::toHex(maxUlpDiff);
15073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
15083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
15093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
15103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
15113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
15133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
15153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15163c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FractCase : public CommonFunctionCase
15173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15183c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
15193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FractCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
15203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "fract", shaderType)
15213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
15233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
15243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.source = "out0 = fract(in0);";
15253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void getInputValues (int numValues, void* const* values) const
15283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Vec2 ranges[] =
15303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
15313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-2.0f,		2.0f),	// lowp
15323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e3f,		1e3f),	// mediump
15333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e7f,		1e7f)	// highp
15343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
15353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random				rnd				(deStringHash(getName()) ^ 0xac23fu);
15373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
15383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
15393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
15403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int						numSpecialCases	= 0;
15413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Special cases.
15433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (precision != glu::PRECISION_LOWP)
15443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
15453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(numValues >= 10);
15463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int ndx = 0; ndx < 10; ndx++)
15473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
15483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float v = de::clamp(float(ndx) - 5.5f, ranges[precision].x(), ranges[precision].y());
15493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				std::fill((float*)values[0], (float*)values[0] + scalarSize, v);
15503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				numSpecialCases += 1;
15513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
15523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
15533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Random cases.
15553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[0] + numSpecialCases*scalarSize, (numValues-numSpecialCases)*scalarSize);
15563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// If precision is mediump, make sure values can be represented in fp16 exactly
15583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (precision == glu::PRECISION_MEDIUMP)
15593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
15603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int ndx = 0; ndx < numValues*scalarSize; ndx++)
15613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				((float*)values[0])[ndx] = tcu::Float16(((float*)values[0])[ndx]).asFloat();
15623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
15633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool compare (const void* const* inputs, const void* const* outputs)
15663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
15683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
15693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool				hasZeroSign		= supportsSignedZero(precision);
15703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
15713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP)
15733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
15743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Require exact result.
15753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
15763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
15773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		in0			= ((const float*)inputs[0])[compNdx];
15783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		out0		= ((const float*)outputs[0])[compNdx];
15793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		ref			= deFloatFrac(in0);
15803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const deUint32	ulpDiff		= hasZeroSign ? getUlpDiff(out0, ref) : getUlpDiffIgnoreZeroSign(out0, ref);
15823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (ulpDiff > 0)
15843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
15853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff " << tcu::toHex(ulpDiff);
15863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return false;
15873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
15883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
15893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
15903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
15913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
15923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		mantissaBits	= getMinMantissaBits(precision);
15933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		eps				= getEpsFromBits(1.0f, mantissaBits);	// epsilon for rounding bounds
15943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
15963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
15973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		in0			= ((const float*)inputs[0])[compNdx];
15983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		out0		= ((const float*)outputs[0])[compNdx];
15993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (int(deFloatFloor(in0-eps)) == int(deFloatFloor(in0+eps)))
16013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
16023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		ref			= deFloatFrac(in0);
16033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const int		bitsLost	= numBitsLostInOp(in0, ref);
16043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const deUint32	maxUlpDiff	= getMaxUlpDiffFromBits(de::max(0, mantissaBits-bitsLost));	// ULP diff for rounded integer value.
16053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const deUint32	ulpDiff		= getUlpDiffIgnoreZeroSign(out0, ref);
16063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (ulpDiff > maxUlpDiff)
16083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
16093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << " with ULP threshold " << tcu::toHex(maxUlpDiff) << ", got diff " << tcu::toHex(ulpDiff);
16103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						return false;
16113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
16123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
16133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else
16143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
16153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (out0 >= 1.0f)
16163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
16173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						m_failMsg << "Expected [" << compNdx << "] < 1.0";
16183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						return false;
16193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
16203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
16213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
16223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
16233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
16253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
16273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16283c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline void frexp (float in, float* significand, int* exponent)
16293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
16303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Float32 fpValue(in);
16313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!fpValue.isZero())
16333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Construct float that has exactly the mantissa, and exponent of -1.
16353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		*significand	= tcu::Float32::construct(fpValue.sign(), -1, fpValue.mantissa()).asFloat();
16363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		*exponent		= fpValue.exponent()+1;
16373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
16393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		*significand	= fpValue.sign() < 0 ? -0.0f : 0.0f;
16413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		*exponent		= 0;
16423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
16443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16453c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline float ldexp (float significand, int exponent)
16463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
16473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Float32 mant(significand);
16483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (exponent == 0 && mant.isZero())
16503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return mant.sign() < 0 ? -0.0f : 0.0f;
16523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
16543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return tcu::Float32::construct(mant.sign(), exponent+mant.exponent(), mant.mantissa()).asFloat();
16563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
16583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16593c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FrexpCase : public CommonFunctionCase
16603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
16613c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
16623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FrexpCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
16633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "frexp", shaderType)
16643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int			vecSize		= glu::getDataTypeScalarSize(baseType);
16663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType	intType		= vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
16673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
16693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, glu::PRECISION_HIGHP)));
16703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("out1", glu::VarType(intType, glu::PRECISION_HIGHP)));
16713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.source = "out0 = frexp(in0, out1);";
16723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void getInputValues (int numValues, void* const* values) const
16753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Vec2 ranges[] =
16773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
16783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-2.0f,		2.0f),	// lowp
16793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e3f,		1e3f),	// mediump
16803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e7f,		1e7f)	// highp
16813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
16823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random				rnd			(deStringHash(getName()) ^ 0x2790au);
16843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
16853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
16863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize	= glu::getDataTypeScalarSize(type);
16873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Special cases
16893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
16903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
16913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			((float*)values[0])[scalarSize*0 + compNdx] = 0.0f;
16923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			((float*)values[0])[scalarSize*1 + compNdx] = -0.0f;
16933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			((float*)values[0])[scalarSize*2 + compNdx] = 0.5f;
16943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			((float*)values[0])[scalarSize*3 + compNdx] = -0.5f;
16953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			((float*)values[0])[scalarSize*4 + compNdx] = 1.0f;
16963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			((float*)values[0])[scalarSize*5 + compNdx] = -1.0f;
16973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			((float*)values[0])[scalarSize*6 + compNdx] = 2.0f;
16983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			((float*)values[0])[scalarSize*7 + compNdx] = -2.0f;
16993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
17003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[0] + 8*scalarSize, (numValues-8)*scalarSize);
17023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
17033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool compare (const void* const* inputs, const void* const* outputs)
17053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
17063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
17073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
17083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
17093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool				signedZero		= supportsSignedZero(precision);
17103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				mantissaBits	= getMinMantissaBits(precision);
17123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint32			maxUlpDiff		= getMaxUlpDiffFromBits(mantissaBits);
17133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
17153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
17163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		in0			= ((const float*)inputs[0])[compNdx];
17173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		out0		= ((const float*)outputs[0])[compNdx];
17183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		out1		= ((const int*)outputs[1])[compNdx];
17193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float			refOut0;
17213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int				refOut1;
17223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			frexp(in0, &refOut0, &refOut1);
17243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	ulpDiff0	= signedZero ? getUlpDiff(out0, refOut0) : getUlpDiffIgnoreZeroSign(out0, refOut0);
17263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (ulpDiff0 > maxUlpDiff || out1 != refOut1)
17283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
17293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(refOut0) << ", " << refOut1 << " with ULP threshold "
17303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  << tcu::toHex(maxUlpDiff) << ", got ULP diff " << tcu::toHex(ulpDiff0);
17313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return false;
17323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
17333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
17343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
17363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
17373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
17383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17393c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass LdexpCase : public CommonFunctionCase
17403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
17413c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
17423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	LdexpCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
17433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "ldexp", shaderType)
17443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
17453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int			vecSize		= glu::getDataTypeScalarSize(baseType);
17463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType	intType		= vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
17473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
17493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("in1", glu::VarType(intType, glu::PRECISION_HIGHP)));
17503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, glu::PRECISION_HIGHP)));
17513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.source = "out0 = ldexp(in0, in1);";
17523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
17533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void getInputValues (int numValues, void* const* values) const
17553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
17563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Vec2 ranges[] =
17573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
17583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-2.0f,		2.0f),	// lowp
17593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e3f,		1e3f),	// mediump
17603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e7f,		1e7f)	// highp
17613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
17623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random				rnd					(deStringHash(getName()) ^ 0x2790au);
17643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type				= m_spec.inputs[0].varType.getBasicType();
17653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision			= m_spec.inputs[0].varType.getPrecision();
17663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize			= glu::getDataTypeScalarSize(type);
17673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int						valueNdx			= 0;
17683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
17703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float easySpecialCases[] = { 0.0f, -0.0f, 0.5f, -0.5f, 1.0f, -1.0f, 2.0f, -2.0f };
17713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(valueNdx + DE_LENGTH_OF_ARRAY(easySpecialCases) <= numValues);
17733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(easySpecialCases); caseNdx++)
17743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
17753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				float	in0;
17763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				int		in1;
17773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				frexp(easySpecialCases[caseNdx], &in0, &in1);
17793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int compNdx = 0; compNdx < scalarSize; compNdx++)
17813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
17823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					((float*)values[0])[valueNdx*scalarSize + compNdx] = in0;
17833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					((int*)values[1])[valueNdx*scalarSize + compNdx] = in1;
17843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
17853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				valueNdx += 1;
17873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
17883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
17893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
17913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// \note lowp and mediump can not necessarily fit the values in hard cases, so we'll use only easy ones.
17923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int numEasyRandomCases = precision == glu::PRECISION_HIGHP ? 50 : (numValues-valueNdx);
17933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(valueNdx + numEasyRandomCases <= numValues);
17953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int caseNdx = 0; caseNdx < numEasyRandomCases; caseNdx++)
17963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
17973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int compNdx = 0; compNdx < scalarSize; compNdx++)
17983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
17993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float	in	= rnd.getFloat(ranges[precision].x(), ranges[precision].y());
18003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					float		in0;
18013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					int			in1;
18023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					frexp(in, &in0, &in1);
18043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					((float*)values[0])[valueNdx*scalarSize + compNdx] = in0;
18063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					((int*)values[1])[valueNdx*scalarSize + compNdx] = in1;
18073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
18083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				valueNdx += 1;
18103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
18113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
18123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
18143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int numHardRandomCases = numValues-valueNdx;
18153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(numHardRandomCases >= 0 && valueNdx + numHardRandomCases <= numValues);
18163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int caseNdx = 0; caseNdx < numHardRandomCases; caseNdx++)
18183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
18193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int compNdx = 0; compNdx < scalarSize; compNdx++)
18203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
18213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const int		fpExp		= rnd.getInt(-126, 127);
18223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const int		sign		= rnd.getBool() ? -1 : +1;
18233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const deUint32	mantissa	= (1u<<23) | (rnd.getUint32() & ((1u<<23)-1));
18243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const int		in1			= rnd.getInt(de::max(-126, -126-fpExp), de::min(127, 127-fpExp));
18253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		in0			= tcu::Float32::construct(sign, fpExp, mantissa).asFloat();
18263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					DE_ASSERT(de::inRange(in1, -126, 127)); // See Khronos bug 11180
18283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					DE_ASSERT(de::inRange(in1+fpExp, -126, 127));
18293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		out			= ldexp(in0, in1);
18313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					DE_ASSERT(!tcu::Float32(out).isInf() && !tcu::Float32(out).isDenorm());
18333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					DE_UNREF(out);
18343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					((float*)values[0])[valueNdx*scalarSize + compNdx] = in0;
18363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					((int*)values[1])[valueNdx*scalarSize + compNdx] = in1;
18373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
18383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				valueNdx += 1;
18403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
18413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
18423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
18433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool compare (const void* const* inputs, const void* const* outputs)
18453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
18463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
18473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
18483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
18493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool				signedZero		= supportsSignedZero(precision);
18503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				mantissaBits	= getMinMantissaBits(precision);
18523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint32			maxUlpDiff		= getMaxUlpDiffFromBits(mantissaBits);
18533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
18553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
18563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		in0			= ((const float*)inputs[0])[compNdx];
18573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		in1			= ((const int*)inputs[1])[compNdx];
18583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		out0		= ((const float*)outputs[0])[compNdx];
18593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		refOut0		= ldexp(in0, in1);
18603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	ulpDiff		= signedZero ? getUlpDiff(out0, refOut0) : getUlpDiffIgnoreZeroSign(out0, refOut0);
18613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		inExp		= tcu::Float32(in0).exponent();
18633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (ulpDiff > maxUlpDiff)
18653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
18663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(refOut0) << ", (exp = " << inExp << ") with ULP threshold "
18673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  << tcu::toHex(maxUlpDiff) << ", got ULP diff " << tcu::toHex(ulpDiff);
18683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return false;
18693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
18703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
18713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
18733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
18743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
18753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18763c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FmaCase : public CommonFunctionCase
18773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
18783c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
18793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FmaCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
18803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "fma", shaderType)
18813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
18823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("a", glu::VarType(baseType, precision)));
18833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("b", glu::VarType(baseType, precision)));
18843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.inputs.push_back(Symbol("c", glu::VarType(baseType, precision)));
18853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.outputs.push_back(Symbol("res", glu::VarType(baseType, precision)));
18863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.source = "res = fma(a, b, c);";
18873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_spec.globalDeclarations = "#extension GL_EXT_gpu_shader5 : require\n";
18883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
18893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void init (void)
18913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
18923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_gpu_shader5"))
18933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw tcu::NotSupportedError("GL_EXT_gpu_shader5 not supported");
18943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CommonFunctionCase::init();
18963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
18973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void getInputValues (int numValues, void* const* values) const
18993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
19003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Vec2 ranges[] =
19013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
19023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-2.0f,		2.0f),	// lowp
19033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e3f,		1e3f),	// mediump
19043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec2(-1e7f,		1e7f)	// highp
19053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
19063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random				rnd				(deStringHash(getName()) ^ 0xac23fu);
19083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
19093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
19103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
19113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float				specialCases[][3] =
19123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
19133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// a		b		c
19143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ 0.0f,		0.0f,	0.0f },
19153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ 0.0f,		1.0f,	0.0f },
19163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ 0.0f,		0.0f,	-1.0f },
19173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ 1.0f,		1.0f,	0.0f },
19183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ 1.0f,		1.0f,	1.0f },
19193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ -1.0f,	1.0f,	0.0f },
19203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ 1.0f,		-1.0f,	0.0f },
19213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ -1.0f,	-1.0f,	0.0f },
19223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ -0.0f,	1.0f,	0.0f },
19233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ 1.0f,		-0.0f,	0.0f }
19243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
19253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				numSpecialCases	= DE_LENGTH_OF_ARRAY(specialCases);
19263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Special cases
19283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int caseNdx = 0; caseNdx < numSpecialCases; caseNdx++)
19293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
19303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int inputNdx = 0; inputNdx < 3; inputNdx++)
19313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
19323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++)
19333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					((float*)values[inputNdx])[caseNdx*scalarSize + scalarNdx] = specialCases[caseNdx][inputNdx];
19343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
19353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
19363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Random cases.
19383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
19393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int	numScalars	= (numValues-numSpecialCases)*scalarSize;
19403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int	offs		= scalarSize*numSpecialCases;
19413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int inputNdx = 0; inputNdx < 3; inputNdx++)
19433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[inputNdx] + offs, numScalars);
19443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
19453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
19463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool compare (const void* const* inputs, const void* const* outputs)
19483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
19493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
19503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
19513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				scalarSize		= glu::getDataTypeScalarSize(type);
19523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool				signedZero		= supportsSignedZero(precision);
19533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				mantissaBits	= getMinMantissaBits(precision);
19553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
19573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
19583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		a			= ((const float*)inputs[0])[compNdx];
19593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		b			= ((const float*)inputs[1])[compNdx];
19603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		c			= ((const float*)inputs[2])[compNdx];
19613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		res			= ((const float*)outputs[0])[compNdx];
19623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		ref			= a*b + c;
19633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		numBitsLost	= precision != glu::PRECISION_HIGHP
19653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										? de::max(de::max(numBitsLostInOp(a, res), numBitsLostInOp(b, res)), numBitsLostInOp(c, res))+1
19663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										: 1;
19673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	maxUlpDiff	= getMaxUlpDiffFromBits(de::max(0, mantissaBits-numBitsLost));
19683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	ulpDiff		= signedZero ? getUlpDiff(res, ref) : getUlpDiffIgnoreZeroSign(res, ref);
19703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (ulpDiff > maxUlpDiff)
19723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
19733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << " with ULP threshold "
19743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  << tcu::toHex(maxUlpDiff) << ", got ULP diff " << tcu::toHex(ulpDiff);
19753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return false;
19763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
19773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
19783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
19803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
19813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
19823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19833c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderCommonFunctionTests::ShaderCommonFunctionTests (Context& context)
19843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCaseGroup(context, "common", "Common function tests")
19853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
19863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
19873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19883c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderCommonFunctionTests::~ShaderCommonFunctionTests (void)
19893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
19903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
19913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19923c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<class TestClass>
19933c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void addFunctionCases (TestCaseGroup* parent, const char* functionName, bool floatTypes, bool intTypes, bool uintTypes, deUint32 shaderBits)
19943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
19953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::TestCaseGroup* group = new tcu::TestCaseGroup(parent->getTestContext(), functionName, functionName);
19963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	parent->addChild(group);
19973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::DataType scalarTypes[] =
19993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
20003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::TYPE_FLOAT,
20013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::TYPE_INT,
20023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::TYPE_UINT
20033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
20043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int scalarTypeNdx = 0; scalarTypeNdx < DE_LENGTH_OF_ARRAY(scalarTypes); scalarTypeNdx++)
20063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
20073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::DataType scalarType = scalarTypes[scalarTypeNdx];
20083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if ((!floatTypes && scalarType == glu::TYPE_FLOAT)	||
20103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			(!intTypes && scalarType == glu::TYPE_INT)		||
20113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			(!uintTypes && scalarType == glu::TYPE_UINT))
20123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			continue;
20133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int vecSize = 1; vecSize <= 4; vecSize++)
20153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
20163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int prec = glu::PRECISION_LOWP; prec <= glu::PRECISION_HIGHP; prec++)
20173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
20183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int shaderTypeNdx = 0; shaderTypeNdx < glu::SHADERTYPE_LAST; shaderTypeNdx++)
20193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
20203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (shaderBits & (1<<shaderTypeNdx))
20213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						group->addChild(new TestClass(parent->getContext(), glu::DataType(scalarType + vecSize - 1), glu::Precision(prec), glu::ShaderType(shaderTypeNdx)));
20223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
20233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
20243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
20253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
20263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
20273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20283c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ShaderCommonFunctionTests::init (void)
20293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
20303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enum
20313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
20323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		VS = (1<<glu::SHADERTYPE_VERTEX),
20333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TC = (1<<glu::SHADERTYPE_TESSELLATION_CONTROL),
20343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TE = (1<<glu::SHADERTYPE_TESSELLATION_EVALUATION),
20353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GS = (1<<glu::SHADERTYPE_GEOMETRY),
20363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		FS = (1<<glu::SHADERTYPE_FRAGMENT),
20373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CS = (1<<glu::SHADERTYPE_COMPUTE),
20383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ALL_SHADERS = VS|TC|TE|GS|FS|CS,
20403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		NEW_SHADERS = TC|TE|GS|CS,
20413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
20423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	//																	Float?	Int?	Uint?	Shaders
20443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addFunctionCases<AbsCase>				(this,	"abs",				true,	true,	false,	NEW_SHADERS);
20453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addFunctionCases<SignCase>				(this,	"sign",				true,	true,	false,	NEW_SHADERS);
20463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addFunctionCases<FloorCase>				(this,	"floor",			true,	false,	false,	NEW_SHADERS);
20473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addFunctionCases<TruncCase>				(this,	"trunc",			true,	false,	false,	NEW_SHADERS);
20483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addFunctionCases<RoundCase>				(this,	"round",			true,	false,	false,	NEW_SHADERS);
20493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addFunctionCases<RoundEvenCase>			(this,	"roundeven",		true,	false,	false,	NEW_SHADERS);
20503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addFunctionCases<CeilCase>				(this,	"ceil",				true,	false,	false,	NEW_SHADERS);
20513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addFunctionCases<FractCase>				(this,	"fract",			true,	false,	false,	NEW_SHADERS);
20523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// mod
20533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addFunctionCases<ModfCase>				(this,	"modf",				true,	false,	false,	NEW_SHADERS);
20543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// min
20553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// max
20563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// clamp
20573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// mix
20583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// step
20593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// smoothstep
20603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addFunctionCases<IsnanCase>				(this,	"isnan",			true,	false,	false,	NEW_SHADERS);
20613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addFunctionCases<IsinfCase>				(this,	"isinf",			true,	false,	false,	NEW_SHADERS);
20623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addFunctionCases<FloatBitsToIntCase>	(this,	"floatbitstoint",	true,	false,	false,	NEW_SHADERS);
20633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addFunctionCases<FloatBitsToUintCase>	(this,	"floatbitstouint",	true,	false,	false,	NEW_SHADERS);
20643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addFunctionCases<FrexpCase>				(this,	"frexp",			true,	false,	false,	ALL_SHADERS);
20663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addFunctionCases<LdexpCase>				(this,	"ldexp",			true,	false,	false,	ALL_SHADERS);
20673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addFunctionCases<FmaCase>				(this,	"fma",				true,	false,	false,	ALL_SHADERS);
20683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// (u)intBitsToFloat()
20703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
20713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint32		shaderBits	= NEW_SHADERS;
20723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::TestCaseGroup* intGroup	= new tcu::TestCaseGroup(m_testCtx, "intbitstofloat",	"intBitsToFloat() Tests");
20733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::TestCaseGroup* uintGroup	= new tcu::TestCaseGroup(m_testCtx, "uintbitstofloat",	"uintBitsToFloat() Tests");
20743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addChild(intGroup);
20763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addChild(uintGroup);
20773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int vecSize = 1; vecSize < 4; vecSize++)
20793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
20803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glu::DataType		intType		= vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
20813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glu::DataType		uintType	= vecSize > 1 ? glu::getDataTypeUintVec(vecSize) : glu::TYPE_UINT;
20823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++)
20843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
20853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (shaderBits & (1<<shaderType))
20863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
20873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					intGroup->addChild(new BitsToFloatCase(m_context, intType, glu::ShaderType(shaderType)));
20883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					uintGroup->addChild(new BitsToFloatCase(m_context, uintType, glu::ShaderType(shaderType)));
20893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
20903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
20913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
20923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
20933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
20943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // Functional
20963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // gles31
20973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // deqp
2098