12f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka/*------------------------------------------------------------------------
22f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka * Vulkan Conformance Tests
32f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka * ------------------------
42f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka *
52f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka * Copyright (c) 2015 The Khronos Group Inc.
62f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka * Copyright (c) 2015 Samsung Electronics Co., Ltd.
7c05b7f1437e619205c96eaa31c0b79ec97a0d47dPyry Haulos * Copyright (c) 2016 The Android Open Source Project
82f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka *
9978d3d585aa549eb1e729b51e9d85fc6477240f9Pyry Haulos * Licensed under the Apache License, Version 2.0 (the "License");
10978d3d585aa549eb1e729b51e9d85fc6477240f9Pyry Haulos * you may not use this file except in compliance with the License.
11978d3d585aa549eb1e729b51e9d85fc6477240f9Pyry Haulos * You may obtain a copy of the License at
122f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka *
13978d3d585aa549eb1e729b51e9d85fc6477240f9Pyry Haulos *      http://www.apache.org/licenses/LICENSE-2.0
142f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka *
15978d3d585aa549eb1e729b51e9d85fc6477240f9Pyry Haulos * Unless required by applicable law or agreed to in writing, software
16978d3d585aa549eb1e729b51e9d85fc6477240f9Pyry Haulos * distributed under the License is distributed on an "AS IS" BASIS,
17978d3d585aa549eb1e729b51e9d85fc6477240f9Pyry Haulos * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18978d3d585aa549eb1e729b51e9d85fc6477240f9Pyry Haulos * See the License for the specific language governing permissions and
19978d3d585aa549eb1e729b51e9d85fc6477240f9Pyry Haulos * limitations under the License.
202f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka *
212f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka *//*!
222f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka * \file
232f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka * \brief Common built-in function tests.
242f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka *//*--------------------------------------------------------------------*/
252f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
262f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka#include "vktShaderCommonFunctionTests.hpp"
272f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka#include "vktShaderExecutor.hpp"
282f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka#include "gluContextInfo.hpp"
292f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka#include "tcuTestLog.hpp"
302f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka#include "tcuFormatUtil.hpp"
312f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka#include "tcuFloat.hpp"
322f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka#include "tcuInterval.hpp"
332f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka#include "tcuFloatFormat.hpp"
342f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka#include "deRandom.hpp"
352f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka#include "deMath.h"
362f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka#include "deString.h"
372f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka#include "deArrayUtil.hpp"
382f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka#include "deSharedPtr.hpp"
392f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
402f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkanamespace vkt
412f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
422f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
432f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkanamespace shaderexecutor
442f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
452f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
462f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
472f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkausing std::vector;
482f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkausing std::string;
492f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkausing tcu::TestLog;
502f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
512f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkausing tcu::Vec2;
522f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkausing tcu::Vec3;
532f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkausing tcu::Vec4;
542f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkausing tcu::IVec2;
552f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkausing tcu::IVec3;
562f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkausing tcu::IVec4;
572f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
582f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkanamespace
592f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
602f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
612f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka// Utilities
622f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
632f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkatemplate<typename T, int Size>
642f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkastruct VecArrayAccess
652f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
662f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkapublic:
672f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka									VecArrayAccess	(const void* ptr) : m_array((tcu::Vector<T, Size>*)ptr) {}
682f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka									~VecArrayAccess	(void) {}
692f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
702f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	const tcu::Vector<T, Size>&		operator[]		(size_t offset) const	{ return m_array[offset];	}
712f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	tcu::Vector<T, Size>&			operator[]		(size_t offset)			{ return m_array[offset];	}
722f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
732f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkaprivate:
742f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	tcu::Vector<T, Size>*			m_array;
752f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
762f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
772f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkatemplate<typename T>	T			randomScalar	(de::Random& rnd, T minValue, T maxValue);
782f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkatemplate<> inline		float		randomScalar	(de::Random& rnd, float minValue, float maxValue)		{ return rnd.getFloat(minValue, maxValue);	}
792f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkatemplate<> inline		deInt32		randomScalar	(de::Random& rnd, deInt32 minValue, deInt32 maxValue)	{ return rnd.getInt(minValue, maxValue);	}
802f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
812f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkatemplate<typename T, int Size>
822f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkainline tcu::Vector<T, Size> randomVector (de::Random& rnd, const tcu::Vector<T, Size>& minValue, const tcu::Vector<T, Size>& maxValue)
832f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
842f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	tcu::Vector<T, Size> res;
852f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	for (int ndx = 0; ndx < Size; ndx++)
862f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		res[ndx] = randomScalar<T>(rnd, minValue[ndx], maxValue[ndx]);
872f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	return res;
882f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka}
892f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
902f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkatemplate<typename T, int Size>
912f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkastatic void fillRandomVectors (de::Random& rnd, const tcu::Vector<T, Size>& minValue, const tcu::Vector<T, Size>& maxValue, void* dst, int numValues, int offset = 0)
922f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
932f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	VecArrayAccess<T, Size> access(dst);
942f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	for (int ndx = 0; ndx < numValues; ndx++)
952f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		access[offset + ndx] = randomVector<T, Size>(rnd, minValue, maxValue);
962f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka}
972f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
982f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkatemplate<typename T>
992f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkastatic void fillRandomScalars (de::Random& rnd, T minValue, T maxValue, void* dst, int numValues, int offset = 0)
1002f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
1012f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	T* typedPtr = (T*)dst;
1022f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	for (int ndx = 0; ndx < numValues; ndx++)
1032f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		typedPtr[offset + ndx] = randomScalar<T>(rnd, minValue, maxValue);
1042f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka}
1052f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
1062f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkainline int numBitsLostInOp (float input, float output)
1072f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
1082f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	const int	inExp		= tcu::Float32(input).exponent();
1092f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	const int	outExp		= tcu::Float32(output).exponent();
1102f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
1112f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	return de::max(0, inExp-outExp); // Lost due to mantissa shift.
1122f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka}
1132f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
1142f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkainline deUint32 getUlpDiff (float a, float b)
1152f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
1162f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	const deUint32	aBits	= tcu::Float32(a).bits();
1172f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	const deUint32	bBits	= tcu::Float32(b).bits();
1182f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	return aBits > bBits ? aBits - bBits : bBits - aBits;
1192f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka}
1202f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
1212f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkainline deUint32 getUlpDiffIgnoreZeroSign (float a, float b)
1222f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
1232f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	if (tcu::Float32(a).isZero())
1242f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		return getUlpDiff(tcu::Float32::construct(tcu::Float32(b).sign(), 0, 0).asFloat(), b);
1252f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	else if (tcu::Float32(b).isZero())
1262f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		return getUlpDiff(a, tcu::Float32::construct(tcu::Float32(a).sign(), 0, 0).asFloat());
1272f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	else
1282f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		return getUlpDiff(a, b);
1292f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka}
1302f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
1312f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkainline bool supportsSignedZero (glu::Precision precision)
1322f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
1332f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	// \note GLSL ES 3.1 doesn't really require support for -0, but we require it for highp
1342f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	//		 as it is very widely supported.
1352f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	return precision == glu::PRECISION_HIGHP;
1362f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka}
1372f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
1382f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkainline float getEpsFromMaxUlpDiff (float value, deUint32 ulpDiff)
1392f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
1402f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	const int exp = tcu::Float32(value).exponent();
1412f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	return tcu::Float32::construct(+1, exp, (1u<<23) | ulpDiff).asFloat() - tcu::Float32::construct(+1, exp, 1u<<23).asFloat();
1422f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka}
1432f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
1442f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkainline deUint32 getMaxUlpDiffFromBits (int numAccurateBits)
1452f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
1462f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	const int		numGarbageBits	= 23-numAccurateBits;
1472f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	const deUint32	mask			= (1u<<numGarbageBits)-1u;
1482f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
1492f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	return mask;
1502f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka}
1512f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
1522f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkainline float getEpsFromBits (float value, int numAccurateBits)
1532f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
1542f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	return getEpsFromMaxUlpDiff(value, getMaxUlpDiffFromBits(numAccurateBits));
1552f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka}
1562f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
1572f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkastatic int getMinMantissaBits (glu::Precision precision)
1582f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
1592f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	const int bits[] =
1602f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
1612f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		7,		// lowp
1622f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		10,		// mediump
1632f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		23		// highp
1642f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	};
1652f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(bits) == glu::PRECISION_LAST);
1662f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	DE_ASSERT(de::inBounds<int>(precision, 0, DE_LENGTH_OF_ARRAY(bits)));
1672f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	return bits[precision];
1682f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka}
1692f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
1702f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkastatic int getMaxNormalizedValueExponent (glu::Precision precision)
1712f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
1722f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	const int exponent[] =
1732f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
1742f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		0,		// lowp
1752f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		13,		// mediump
1762f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		127		// highp
1772f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	};
1782f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(exponent) == glu::PRECISION_LAST);
1792f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	DE_ASSERT(de::inBounds<int>(precision, 0, DE_LENGTH_OF_ARRAY(exponent)));
1802f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	return exponent[precision];
1812f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka}
1822f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
1832f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkastatic int getMinNormalizedValueExponent (glu::Precision precision)
1842f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
1852f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	const int exponent[] =
1862f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
1872f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		-7,		// lowp
1882f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		-13,	// mediump
1892f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		-126	// highp
1902f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	};
1912f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(exponent) == glu::PRECISION_LAST);
1922f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	DE_ASSERT(de::inBounds<int>(precision, 0, DE_LENGTH_OF_ARRAY(exponent)));
1932f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	return exponent[precision];
1942f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka}
1952f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
1962f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkastatic float makeFloatRepresentable (float f, glu::Precision precision)
1972f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
1982f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	if (precision == glu::PRECISION_HIGHP)
1992f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
2002f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		// \note: assuming f is not extended-precision
2012f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		return f;
2022f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
2032f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	else
2042f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
2052f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int			numMantissaBits				= getMinMantissaBits(precision);
2062f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int			maxNormalizedValueExponent	= getMaxNormalizedValueExponent(precision);
2072f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int			minNormalizedValueExponent	= getMinNormalizedValueExponent(precision);
2082f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const deUint32		representableMantissaMask	= ((deUint32(1) << numMantissaBits) - 1) << (23 - (deUint32)numMantissaBits);
2092f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const float			largestRepresentableValue	= tcu::Float32::constructBits(+1, maxNormalizedValueExponent, ((1u << numMantissaBits) - 1u) << (23u - (deUint32)numMantissaBits)).asFloat();
2102f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const bool			zeroNotRepresentable		= (precision == glu::PRECISION_LOWP);
2112f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
2122f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		// if zero is not required to be representable, use smallest positive non-subnormal value
2132f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const float			zeroValue					= (zeroNotRepresentable) ? (tcu::Float32::constructBits(+1, minNormalizedValueExponent, 1).asFloat()) : (0.0f);
2142f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
2152f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const tcu::Float32	float32Representation		(f);
2162f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
2172f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		if (float32Representation.exponent() < minNormalizedValueExponent)
2182f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
2192f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			// flush too small values to zero
2202f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			return zeroValue;
2212f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
2222f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		else if (float32Representation.exponent() > maxNormalizedValueExponent)
2232f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
2242f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			// clamp too large values
2252f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			return (float32Representation.sign() == +1) ? (largestRepresentableValue) : (-largestRepresentableValue);
2262f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
2272f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		else
2282f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
2292f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			// remove unrepresentable mantissa bits
2302f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const tcu::Float32 targetRepresentation(tcu::Float32::constructBits(float32Representation.sign(),
2312f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka													float32Representation.exponent(),
2322f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka													float32Representation.mantissaBits() & representableMantissaMask));
2332f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
2342f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			return targetRepresentation.asFloat();
2352f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
2362f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
2372f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka}
2382f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
2392f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkastatic vector<int> getScalarSizes (const vector<Symbol>& symbols)
2402f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
2412f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	vector<int> sizes(symbols.size());
2422f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	for (int ndx = 0; ndx < (int)symbols.size(); ++ndx)
2432f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		sizes[ndx] = symbols[ndx].varType.getScalarSize();
2442f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	return sizes;
2452f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka}
2462f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
2472f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkastatic int computeTotalScalarSize (const vector<Symbol>& symbols)
2482f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
2492f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	int totalSize = 0;
2502f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	for (vector<Symbol>::const_iterator sym = symbols.begin(); sym != symbols.end(); ++sym)
2512f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		totalSize += sym->varType.getScalarSize();
2522f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	return totalSize;
2532f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka}
2542f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
2552f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkastatic vector<void*> getInputOutputPointers (const vector<Symbol>& symbols, vector<deUint32>& data, const int numValues)
2562f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
2572f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	vector<void*>	pointers		(symbols.size());
2582f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	int				curScalarOffset	= 0;
2592f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
2602f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	for (int varNdx = 0; varNdx < (int)symbols.size(); ++varNdx)
2612f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
2622f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const Symbol&	var				= symbols[varNdx];
2632f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int		scalarSize		= var.varType.getScalarSize();
2642f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
2652f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		// Uses planar layout as input/output specs do not support strides.
2662f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		pointers[varNdx] = &data[curScalarOffset];
2672f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		curScalarOffset += scalarSize*numValues;
2682f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
2692f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
2702f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	DE_ASSERT(curScalarOffset == (int)data.size());
2712f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
2722f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	return pointers;
2732f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka}
2742f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
2752f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka// \todo [2013-08-08 pyry] Make generic utility and move to glu?
2762f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
2772f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkastruct HexFloat
2782f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
2792f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	const float value;
2802f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	HexFloat (const float value_) : value(value_) {}
2812f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
2822f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
2832f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkastd::ostream& operator<< (std::ostream& str, const HexFloat& v)
2842f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
2852f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	return str << v.value << " / " << tcu::toHex(tcu::Float32(v.value).bits());
2862f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka}
2872f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
2882f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkastruct HexBool
2892f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
2902f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	const deUint32 value;
2912f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	HexBool (const deUint32 value_) : value(value_) {}
2922f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
2932f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
2942f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkastd::ostream& operator<< (std::ostream& str, const HexBool& v)
2952f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
2962f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	return str << (v.value ? "true" : "false") << " / " << tcu::toHex(v.value);
2972f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka}
2982f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
2992f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkastruct VarValue
3002f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
3012f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	const glu::VarType&	type;
3022f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	const void*			value;
3032f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
3042f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	VarValue (const glu::VarType& type_, const void* value_) : type(type_), value(value_) {}
3052f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
3062f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
3072f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkastd::ostream& operator<< (std::ostream& str, const VarValue& varValue)
3082f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
3092f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	DE_ASSERT(varValue.type.isBasicType());
3102f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
3112f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	const glu::DataType		basicType		= varValue.type.getBasicType();
3122f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	const glu::DataType		scalarType		= glu::getDataTypeScalarType(basicType);
3132f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	const int				numComponents	= glu::getDataTypeScalarSize(basicType);
3142f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
3152f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	if (numComponents > 1)
3162f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		str << glu::getDataTypeName(basicType) << "(";
3172f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
3182f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	for (int compNdx = 0; compNdx < numComponents; compNdx++)
3192f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
3202f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		if (compNdx != 0)
3212f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			str << ", ";
3222f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
3232f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		switch (scalarType)
3242f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
3252f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			case glu::TYPE_FLOAT:	str << HexFloat(((const float*)varValue.value)[compNdx]);			break;
3262f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			case glu::TYPE_INT:		str << ((const deInt32*)varValue.value)[compNdx];					break;
3272f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			case glu::TYPE_UINT:	str << tcu::toHex(((const deUint32*)varValue.value)[compNdx]);		break;
3282f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			case glu::TYPE_BOOL:	str << HexBool(((const deUint32*)varValue.value)[compNdx]);			break;
3292f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
3302f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			default:
3312f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				DE_ASSERT(false);
3322f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
3332f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
3342f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
3352f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	if (numComponents > 1)
3362f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		str << ")";
3372f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
3382f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	return str;
3392f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka}
3402f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
3412f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkastatic const char* getPrecisionPostfix (glu::Precision precision)
3422f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
3432f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	static const char* s_postfix[] =
3442f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
3452f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		"_lowp",
3462f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		"_mediump",
3472f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		"_highp"
3482f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	};
3492f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_postfix) == glu::PRECISION_LAST);
3502f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	DE_ASSERT(de::inBounds<int>(precision, 0, DE_LENGTH_OF_ARRAY(s_postfix)));
3512f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	return s_postfix[precision];
3522f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka}
3532f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
3542f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkastatic const char* getShaderTypePostfix (glu::ShaderType shaderType)
3552f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
3562f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	static const char* s_postfix[] =
3572f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
3582f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		"_vertex",
3592f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		"_fragment",
3602f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		"_geometry",
3612f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		"_tess_control",
3622f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		"_tess_eval",
3632f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		"_compute"
3642f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	};
3652f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	DE_ASSERT(de::inBounds<int>(shaderType, 0, DE_LENGTH_OF_ARRAY(s_postfix)));
3662f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	return s_postfix[shaderType];
3672f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka}
3682f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
3692f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkastatic std::string getCommonFuncCaseName (glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
3702f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
3712f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	return string(glu::getDataTypeName(baseType)) + getPrecisionPostfix(precision) + getShaderTypePostfix(shaderType);
3722f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka}
3732f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
3742f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkastatic inline void frexp (float in, float* significand, int* exponent)
3752f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
3762f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	const tcu::Float32 fpValue(in);
3772f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
3782f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	if (!fpValue.isZero())
3792f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
3802f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		// Construct float that has exactly the mantissa, and exponent of -1.
3812f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		*significand	= tcu::Float32::construct(fpValue.sign(), -1, fpValue.mantissa()).asFloat();
3822f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		*exponent		= fpValue.exponent()+1;
3832f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
3842f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	else
3852f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
3862f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		*significand	= fpValue.sign() < 0 ? -0.0f : 0.0f;
3872f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		*exponent		= 0;
3882f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
3892f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka}
3902f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
3912f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkastatic inline float ldexp (float significand, int exponent)
3922f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
3932f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	const tcu::Float32 mant(significand);
3942f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
3952f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	if (exponent == 0 && mant.isZero())
3962f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
3972f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		return mant.sign() < 0 ? -0.0f : 0.0f;
3982f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
3992f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	else
4002f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
4012f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		return tcu::Float32::construct(mant.sign(), exponent+mant.exponent(), mant.mantissa()).asFloat();
4022f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
4032f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka}
4042f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
4052f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkatemplate<class TestClass>
4062f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkastatic void addFunctionCases (tcu::TestCaseGroup* parent, const char* functionName, bool floatTypes, bool intTypes, bool uintTypes, deUint32 shaderBits)
4072f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
4082f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	tcu::TestCaseGroup* group = new tcu::TestCaseGroup(parent->getTestContext(), functionName, functionName);
4092f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	parent->addChild(group);
4102f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
4112f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	const glu::DataType scalarTypes[] =
4122f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
4132f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		glu::TYPE_FLOAT,
4142f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		glu::TYPE_INT,
4152f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		glu::TYPE_UINT
4162f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	};
4172f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
4182f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	for (int scalarTypeNdx = 0; scalarTypeNdx < DE_LENGTH_OF_ARRAY(scalarTypes); scalarTypeNdx++)
4192f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
4202f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::DataType scalarType = scalarTypes[scalarTypeNdx];
4212f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
4222f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		if ((!floatTypes && scalarType == glu::TYPE_FLOAT)	||
4232f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			(!intTypes && scalarType == glu::TYPE_INT)		||
4242f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			(!uintTypes && scalarType == glu::TYPE_UINT))
4252f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			continue;
4262f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
4272f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		for (int vecSize = 1; vecSize <= 4; vecSize++)
4282f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
42932c0175b73b2d428516a6db91e809ebd13c49999Csaba Osztrogonác			for (int prec = glu::PRECISION_MEDIUMP; prec <= glu::PRECISION_HIGHP; prec++)
4302f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{
4312f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				for (int shaderTypeNdx = 0; shaderTypeNdx < glu::SHADERTYPE_LAST; shaderTypeNdx++)
4322f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				{
4332f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					if (shaderBits & (1<<shaderTypeNdx))
4342f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka						group->addChild(new TestClass(parent->getTestContext(), glu::DataType(scalarType + vecSize - 1), glu::Precision(prec), glu::ShaderType(shaderTypeNdx)));
4352f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				}
4362f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			}
4372f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
4382f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
4392f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka}
4402f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
4412f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka// CommonFunctionCase
4422f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
4432f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkaclass CommonFunctionCase : public TestCase
4442f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
4452f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkapublic:
4462f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka										CommonFunctionCase			(tcu::TestContext& testCtx, const char* name, const char* description, glu::ShaderType shaderType);
4472f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka										~CommonFunctionCase			(void);
4482f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	virtual	void						initPrograms				(vk::SourceCollections& programCollection) const
4492f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka										{
450b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos											generateSources(m_shaderType, m_spec, programCollection);
4512f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka										}
4522f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
4532f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	virtual TestInstance*				createInstance				(Context& context) const = 0;
4542f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
4552f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkaprotected:
456b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos										CommonFunctionCase			(const CommonFunctionCase&);
457b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos	CommonFunctionCase&					operator=					(const CommonFunctionCase&);
4582f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
4592f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	const glu::ShaderType				m_shaderType;
4602f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	ShaderSpec							m_spec;
4612f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	const int							m_numValues;
4622f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
4632f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
4642f7ef42cc1930880dc119fd9659d673a2f15474eRobert SipkaCommonFunctionCase::CommonFunctionCase (tcu::TestContext& testCtx, const char* name, const char* description, glu::ShaderType shaderType)
4652f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	: TestCase		(testCtx, name, description)
4662f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	, m_shaderType	(shaderType)
4672f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	, m_numValues	(100)
4682f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
4692f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka}
4702f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
4712f7ef42cc1930880dc119fd9659d673a2f15474eRobert SipkaCommonFunctionCase::~CommonFunctionCase (void)
4722f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
4732f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka}
4742f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
4752f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka// CommonFunctionTestInstance
4762f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
4772f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkaclass CommonFunctionTestInstance : public TestInstance
4782f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
4792f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkapublic:
480b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos										CommonFunctionTestInstance	(Context& context, glu::ShaderType shaderType, const ShaderSpec& spec, int numValues, const char* name)
4812f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka											: TestInstance	(context)
4822f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka											, m_shaderType	(shaderType)
4832f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka											, m_spec		(spec)
4842f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka											, m_numValues	(numValues)
4852f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka											, m_name		(name)
486b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos											, m_executor	(createExecutor(context, shaderType, spec))
4872f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka										{
4882f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka										}
4892f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	virtual tcu::TestStatus				iterate						(void);
4902f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
4912f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkaprotected:
4922f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	virtual void						getInputValues				(int numValues, void* const* values) const = 0;
4932f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	virtual bool						compare						(const void* const* inputs, const void* const* outputs) = 0;
4942f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
4952f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	const glu::ShaderType				m_shaderType;
496b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos	const ShaderSpec					m_spec;
4972f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	const int							m_numValues;
4982f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
499b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos	// \todo [2017-03-07 pyry] Hack used to generate seeds for test cases - get rid of this.
500e148980e7f95d8a113a7dc84b13ca9906f33869fPyry Haulos	const char*							m_name;
5012f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
5022f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	std::ostringstream					m_failMsg;					//!< Comparison failure help message.
5032f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
504b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos	de::UniquePtr<ShaderExecutor>		m_executor;
5052f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
5062f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
5072f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkatcu::TestStatus CommonFunctionTestInstance::iterate (void)
5082f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
5092f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	const int				numInputScalars			= computeTotalScalarSize(m_spec.inputs);
5102f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	const int				numOutputScalars		= computeTotalScalarSize(m_spec.outputs);
5112f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	vector<deUint32>		inputData				(numInputScalars * m_numValues);
5122f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	vector<deUint32>		outputData				(numOutputScalars * m_numValues);
5132f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	const vector<void*>		inputPointers			= getInputOutputPointers(m_spec.inputs, inputData, m_numValues);
5142f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	const vector<void*>		outputPointers			= getInputOutputPointers(m_spec.outputs, outputData, m_numValues);
5152f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
5162f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	// Initialize input data.
5172f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	getInputValues(m_numValues, &inputPointers[0]);
5182f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
5192f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	// Execute shader.
520b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos	m_executor->execute(m_numValues, &inputPointers[0], &outputPointers[0]);
5212f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
5222f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	// Compare results.
5232f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
5242f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const vector<int>		inScalarSizes		= getScalarSizes(m_spec.inputs);
5252f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const vector<int>		outScalarSizes		= getScalarSizes(m_spec.outputs);
5262f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		vector<void*>			curInputPtr			(inputPointers.size());
5272f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		vector<void*>			curOutputPtr		(outputPointers.size());
5282f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		int						numFailed			= 0;
5292f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		tcu::TestContext&		testCtx				= m_context.getTestContext();
5302f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
5312f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		for (int valNdx = 0; valNdx < m_numValues; valNdx++)
5322f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
5332f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			// Set up pointers for comparison.
5342f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			for (int inNdx = 0; inNdx < (int)curInputPtr.size(); ++inNdx)
5352f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				curInputPtr[inNdx] = (deUint32*)inputPointers[inNdx] + inScalarSizes[inNdx]*valNdx;
5362f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
5372f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			for (int outNdx = 0; outNdx < (int)curOutputPtr.size(); ++outNdx)
5382f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				curOutputPtr[outNdx] = (deUint32*)outputPointers[outNdx] + outScalarSizes[outNdx]*valNdx;
5392f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
5402f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			if (!compare(&curInputPtr[0], &curOutputPtr[0]))
5412f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{
5422f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				// \todo [2013-08-08 pyry] We probably want to log reference value as well?
5432f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
5442f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				testCtx.getLog() << TestLog::Message << "ERROR: comparison failed for value " << valNdx << ":\n  " << m_failMsg.str() << TestLog::EndMessage;
5452f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
5462f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				testCtx.getLog() << TestLog::Message << "  inputs:" << TestLog::EndMessage;
5472f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				for (int inNdx = 0; inNdx < (int)curInputPtr.size(); inNdx++)
5482f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					testCtx.getLog() << TestLog::Message << "    " << m_spec.inputs[inNdx].name << " = "
5492f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka														   << VarValue(m_spec.inputs[inNdx].varType, curInputPtr[inNdx])
5502f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka									   << TestLog::EndMessage;
5512f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
5522f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				testCtx.getLog() << TestLog::Message << "  outputs:" << TestLog::EndMessage;
5532f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				for (int outNdx = 0; outNdx < (int)curOutputPtr.size(); outNdx++)
5542f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					testCtx.getLog() << TestLog::Message << "    " << m_spec.outputs[outNdx].name << " = "
5552f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka														   << VarValue(m_spec.outputs[outNdx].varType, curOutputPtr[outNdx])
5562f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka									   << TestLog::EndMessage;
5572f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
5582f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				m_failMsg.str("");
5592f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				m_failMsg.clear();
5602f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				numFailed += 1;
5612f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			}
5622f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
5632f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
5642f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		testCtx.getLog() << TestLog::Message << (m_numValues - numFailed) << " / " << m_numValues << " values passed" << TestLog::EndMessage;
5652f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
5662f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		if (numFailed == 0)
5672f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			return tcu::TestStatus::pass("Pass");
5682f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		else
5692f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			return tcu::TestStatus::fail("Result comparison failed");
5702f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
5712f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka}
5722f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
5732f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka// Test cases
5742f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
5752f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkaclass AbsCaseInstance : public CommonFunctionTestInstance
5762f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
5772f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkapublic:
578b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos	AbsCaseInstance (Context& context, glu::ShaderType shaderType, const ShaderSpec& spec, int numValues, const char* name)
579b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos		: CommonFunctionTestInstance	(context, shaderType, spec, numValues, name)
5802f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
5812f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
5822f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
5832f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	void getInputValues (int numValues, void* const* values) const
5842f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
5852f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const Vec2 floatRanges[] =
5862f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
5872f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			Vec2(-2.0f,		2.0f),	// lowp
5882f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			Vec2(-1e3f,		1e3f),	// mediump
5892f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			Vec2(-1e7f,		1e7f)	// highp
5902f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		};
5912f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const IVec2 intRanges[] =
5922f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
5932f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			IVec2(-(1<<7)+1,	(1<<7)-1),
5942f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			IVec2(-(1<<15)+1,	(1<<15)-1),
5952f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			IVec2(0x80000001,	0x7fffffff)
5962f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		};
5972f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
5982f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		de::Random				rnd			(deStringHash(m_name) ^ 0x235facu);
5992f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
6002f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
6012f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int				scalarSize	= glu::getDataTypeScalarSize(type);
6022f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
6032f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		if (glu::isDataTypeFloatOrVec(type))
6042f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			fillRandomScalars(rnd, floatRanges[precision].x(), floatRanges[precision].y(), values[0], numValues*scalarSize);
6052f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		else
6062f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			fillRandomScalars(rnd, intRanges[precision].x(), intRanges[precision].y(), values[0], numValues*scalarSize);
6072f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
6082f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
6092f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	bool compare (const void* const* inputs, const void* const* outputs)
6102f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
6112f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
6122f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
6132f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int				scalarSize		= glu::getDataTypeScalarSize(type);
6142f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
6152f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		if (glu::isDataTypeFloatOrVec(type))
6162f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
6172f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const int		mantissaBits	= getMinMantissaBits(precision);
6182f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const deUint32	maxUlpDiff		= (1u<<(23-mantissaBits))-1u;
6192f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
6202f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
6212f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{
6222f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float		in0			= ((const float*)inputs[0])[compNdx];
6232f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float		out0		= ((const float*)outputs[0])[compNdx];
6242f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float		ref0		= de::abs(in0);
6252f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const deUint32	ulpDiff0	= getUlpDiff(out0, ref0);
6262f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
6272f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				if (ulpDiff0 > maxUlpDiff)
6282f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				{
6292f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref0) << " with ULP threshold " << maxUlpDiff << ", got ULP diff " << ulpDiff0;
6302f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					return false;
6312f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				}
6322f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			}
6332f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
6342f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		else
6352f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
6362f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
6372f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{
6382f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const int	in0		= ((const int*)inputs[0])[compNdx];
6392f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const int	out0	= ((const int*)outputs[0])[compNdx];
6402f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const int	ref0	= de::abs(in0);
6412f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
6422f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				if (out0 != ref0)
6432f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				{
6442f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					m_failMsg << "Expected [" << compNdx << "] = " << ref0;
6452f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					return false;
6462f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				}
6472f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			}
6482f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
6492f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
6502f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		return true;
6512f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
6522f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
6532f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
6542f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkaclass AbsCase : public CommonFunctionCase
6552f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
6562f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkapublic:
6572f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	AbsCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
6582f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		: CommonFunctionCase	(testCtx, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "abs", shaderType)
6592f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
6602f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
6612f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
6622f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.source = "out0 = abs(in0);";
6632f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
6642f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
6652f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	TestInstance* createInstance (Context& ctx) const
6662f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
667b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos		return new AbsCaseInstance(ctx, m_shaderType, m_spec, m_numValues, getName());
6682f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
6692f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
6702f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
6712f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkaclass SignCaseInstance : public CommonFunctionTestInstance
6722f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
6732f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkapublic:
674b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos	SignCaseInstance (Context& context, glu::ShaderType shaderType, const ShaderSpec& spec, int numValues, const char* name)
675b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos		: CommonFunctionTestInstance	(context, shaderType, spec, numValues, name)
6762f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
6772f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
6782f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
6792f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	void getInputValues (int numValues, void* const* values) const
6802f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
6812f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const Vec2 floatRanges[] =
6822f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
6832f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			Vec2(-2.0f,		2.0f),	// lowp
6842f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			Vec2(-1e4f,		1e4f),	// mediump	- note: may end up as inf
6852f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			Vec2(-1e8f,		1e8f)	// highp	- note: may end up as inf
6862f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		};
6872f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const IVec2 intRanges[] =
6882f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
6892f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			IVec2(-(1<<7),		(1<<7)-1),
6902f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			IVec2(-(1<<15),		(1<<15)-1),
6912f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			IVec2(0x80000000,	0x7fffffff)
6922f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		};
6932f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
6942f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		de::Random				rnd			(deStringHash(m_name) ^ 0x324u);
6952f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
6962f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
6972f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int				scalarSize	= glu::getDataTypeScalarSize(type);
6982f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
6992f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		if (glu::isDataTypeFloatOrVec(type))
7002f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
7012f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			// Special cases.
7022f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			std::fill((float*)values[0], (float*)values[0] + scalarSize, +1.0f);
7032f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			std::fill((float*)values[0], (float*)values[0] + scalarSize, -1.0f);
7042f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			std::fill((float*)values[0], (float*)values[0] + scalarSize,  0.0f);
7052f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			fillRandomScalars(rnd, floatRanges[precision].x(), floatRanges[precision].y(), (float*)values[0] + scalarSize*3, (numValues-3)*scalarSize);
7062f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
7072f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		else
7082f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
7092f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			std::fill((int*)values[0], (int*)values[0] + scalarSize, +1);
7102f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			std::fill((int*)values[0], (int*)values[0] + scalarSize, -1);
7112f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			std::fill((int*)values[0], (int*)values[0] + scalarSize,  0);
7122f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			fillRandomScalars(rnd, intRanges[precision].x(), intRanges[precision].y(), (int*)values[0] + scalarSize*3, (numValues-3)*scalarSize);
7132f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
7142f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
7152f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
7162f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	bool compare (const void* const* inputs, const void* const* outputs)
7172f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
7182f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
7192f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
7202f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int				scalarSize		= glu::getDataTypeScalarSize(type);
7212f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
7222f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		if (glu::isDataTypeFloatOrVec(type))
7232f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
7242f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			// Both highp and mediump should be able to represent -1, 0, and +1 exactly
7252f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const deUint32 maxUlpDiff = precision == glu::PRECISION_LOWP ? getMaxUlpDiffFromBits(getMinMantissaBits(precision)) : 0;
7262f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
7272f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
7282f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{
7292f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float		in0			= ((const float*)inputs[0])[compNdx];
7302f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float		out0		= ((const float*)outputs[0])[compNdx];
7312f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float		ref0		= in0 < 0.0f ? -1.0f :
7322f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka											  in0 > 0.0f ? +1.0f : 0.0f;
7332f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const deUint32	ulpDiff0	= getUlpDiff(out0, ref0);
7342f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
7352f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				if (ulpDiff0 > maxUlpDiff)
7362f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				{
7372f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref0) << " with ULP threshold " << maxUlpDiff << ", got ULP diff " << ulpDiff0;
7382f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					return false;
7392f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				}
7402f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			}
7412f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
7422f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		else
7432f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
7442f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
7452f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{
7462f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const int	in0		= ((const int*)inputs[0])[compNdx];
7472f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const int	out0	= ((const int*)outputs[0])[compNdx];
7482f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const int	ref0	= in0 < 0 ? -1 :
7492f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka									  in0 > 0 ? +1 : 0;
7502f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
7512f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				if (out0 != ref0)
7522f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				{
7532f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					m_failMsg << "Expected [" << compNdx << "] = " << ref0;
7542f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					return false;
7552f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				}
7562f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			}
7572f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
7582f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
7592f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		return true;
7602f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
7612f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
7622f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
7632f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkaclass SignCase : public CommonFunctionCase
7642f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
7652f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkapublic:
7662f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	SignCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
7672f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		: CommonFunctionCase	(testCtx, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "sign", shaderType)
7682f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
7692f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
7702f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
7712f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.source = "out0 = sign(in0);";
7722f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
7732f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
7742f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	TestInstance* createInstance (Context& ctx) const
7752f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
776b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos		return new SignCaseInstance(ctx, m_shaderType, m_spec, m_numValues, getName());
7772f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
7782f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
7792f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
7802f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkastatic float roundEven (float v)
7812f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
7822f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	const float		q			= deFloatFrac(v);
7832f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	const int		truncated	= int(v-q);
7842f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	const int		rounded		= (q > 0.5f)							? (truncated + 1) :	// Rounded up
7852f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka									(q == 0.5f && (truncated % 2 != 0))	? (truncated + 1) :	// Round to nearest even at 0.5
7862f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka									truncated;												// Rounded down
7872f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
7882f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	return float(rounded);
7892f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka}
7902f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
7912f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkaclass RoundEvenCaseInstance : public CommonFunctionTestInstance
7922f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
7932f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkapublic:
794b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos	RoundEvenCaseInstance (Context& context, glu::ShaderType shaderType, const ShaderSpec& spec, int numValues, const char* name)
795b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos		: CommonFunctionTestInstance(context, shaderType, spec, numValues, name)
7962f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
7972f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
7982f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
7992f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	void getInputValues (int numValues, void* const* values) const
8002f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
8012f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const Vec2 ranges[] =
8022f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
8032f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			Vec2(-2.0f,		2.0f),	// lowp
8042f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			Vec2(-1e3f,		1e3f),	// mediump
8052f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			Vec2(-1e7f,		1e7f)	// highp
8062f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		};
8072f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
8082f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		de::Random				rnd				(deStringHash(m_name) ^ 0xac23fu);
8092f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
8102f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
8112f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int				scalarSize		= glu::getDataTypeScalarSize(type);
8122f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		int						numSpecialCases	= 0;
8132f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
8142f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		// Special cases.
8152f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		if (precision != glu::PRECISION_LOWP)
8162f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
8172f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			DE_ASSERT(numValues >= 20);
8182f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			for (int ndx = 0; ndx < 20; ndx++)
8192f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{
8202f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float v = de::clamp(float(ndx) - 10.5f, ranges[precision].x(), ranges[precision].y());
8212f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				std::fill((float*)values[0], (float*)values[0] + scalarSize, v);
8222f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				numSpecialCases += 1;
8232f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			}
8242f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
8252f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
8262f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		// Random cases.
8272f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[0] + numSpecialCases*scalarSize, (numValues-numSpecialCases)*scalarSize);
8282f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
8292f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		// If precision is mediump, make sure values can be represented in fp16 exactly
8302f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		if (precision == glu::PRECISION_MEDIUMP)
8312f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
8322f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			for (int ndx = 0; ndx < numValues*scalarSize; ndx++)
8332f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				((float*)values[0])[ndx] = tcu::Float16(((float*)values[0])[ndx]).asFloat();
8342f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
8352f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
8362f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
8372f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	bool compare (const void* const* inputs, const void* const* outputs)
8382f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
8392f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
8402f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
8412f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const bool				hasSignedZero	= supportsSignedZero(precision);
8422f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int				scalarSize		= glu::getDataTypeScalarSize(type);
8432f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
8442f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP)
8452f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
8462f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			// Require exact rounding result.
8472f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
8482f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{
8492f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float		in0			= ((const float*)inputs[0])[compNdx];
8502f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float		out0		= ((const float*)outputs[0])[compNdx];
8512f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float		ref			= roundEven(in0);
8522f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
8532f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const deUint32	ulpDiff		= hasSignedZero ? getUlpDiff(out0, ref) : getUlpDiffIgnoreZeroSign(out0, ref);
8542f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
8552f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				if (ulpDiff > 0)
8562f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				{
8572f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff " << tcu::toHex(ulpDiff);
8582f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					return false;
8592f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				}
8602f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			}
8612f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
8622f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		else
8632f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
8642f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const int		mantissaBits	= getMinMantissaBits(precision);
8652f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const deUint32	maxUlpDiff		= getMaxUlpDiffFromBits(mantissaBits);	// ULP diff for rounded integer value.
8662f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const float		eps				= getEpsFromBits(1.0f, mantissaBits);	// epsilon for rounding bounds
8672f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
8682f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
8692f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{
8702f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float		in0			= ((const float*)inputs[0])[compNdx];
8712f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float		out0		= ((const float*)outputs[0])[compNdx];
8722f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const int		minRes		= int(roundEven(in0-eps));
8732f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const int		maxRes		= int(roundEven(in0+eps));
8742f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				bool			anyOk		= false;
8752f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
8762f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				for (int roundedVal = minRes; roundedVal <= maxRes; roundedVal++)
8772f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				{
8782f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					const deUint32 ulpDiff = getUlpDiffIgnoreZeroSign(out0, float(roundedVal));
8792f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
8802f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					if (ulpDiff <= maxUlpDiff)
8812f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					{
8822f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka						anyOk = true;
8832f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka						break;
8842f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					}
8852f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				}
8862f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
8872f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				if (!anyOk)
8882f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				{
8892f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					m_failMsg << "Expected [" << compNdx << "] = [" << minRes << ", " << maxRes << "] with ULP threshold " << tcu::toHex(maxUlpDiff);
8902f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					return false;
8912f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				}
8922f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			}
8932f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
8942f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
8952f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		return true;
8962f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
8972f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
8982f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
8992f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkaclass RoundEvenCase : public CommonFunctionCase
9002f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
9012f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkapublic:
9022f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	RoundEvenCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
9032f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		: CommonFunctionCase	(testCtx, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "roundEven", shaderType)
9042f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
9052f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
9062f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
9072f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.source = "out0 = roundEven(in0);";
9082f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
9092f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
9102f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	TestInstance* createInstance (Context& ctx) const
9112f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
912b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos		return new RoundEvenCaseInstance(ctx, m_shaderType, m_spec, m_numValues, getName());
9132f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
9142f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
9152f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
9162f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkaclass ModfCaseInstance : public CommonFunctionTestInstance
9172f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
9182f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkapublic:
919b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos	ModfCaseInstance (Context& context, glu::ShaderType shaderType, const ShaderSpec& spec, int numValues, const char* name)
920b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos		: CommonFunctionTestInstance(context, shaderType, spec, numValues, name)
9212f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
9222f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
9232f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
9242f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	void getInputValues (int numValues, void* const* values) const
9252f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
9262f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const Vec2 ranges[] =
9272f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
9282f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			Vec2(-2.0f,		2.0f),	// lowp
9292f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			Vec2(-1e3f,		1e3f),	// mediump
9302f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			Vec2(-1e7f,		1e7f)	// highp
9312f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		};
9322f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
9332f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		de::Random				rnd			(deStringHash(m_name) ^ 0xac23fu);
9342f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
9352f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
9362f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int				scalarSize	= glu::getDataTypeScalarSize(type);
9372f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
9382f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), values[0], numValues*scalarSize);
9392f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
9402f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
9412f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	bool compare (const void* const* inputs, const void* const* outputs)
9422f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
9432f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
9442f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
9452f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const bool				hasZeroSign		= supportsSignedZero(precision);
9462f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int				scalarSize		= glu::getDataTypeScalarSize(type);
9472f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
9482f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int				mantissaBits	= getMinMantissaBits(precision);
9492f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
9502f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
9512f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
9522f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const float		in0			= ((const float*)inputs[0])[compNdx];
9532f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const float		out0		= ((const float*)outputs[0])[compNdx];
9542f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const float		out1		= ((const float*)outputs[1])[compNdx];
9552f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
9562f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const float		refOut1		= float(int(in0));
9572f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const float		refOut0		= in0 - refOut1;
9582f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
9592f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const int		bitsLost	= precision != glu::PRECISION_HIGHP ? numBitsLostInOp(in0, refOut0) : 0;
9602f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const deUint32	maxUlpDiff	= getMaxUlpDiffFromBits(de::max(mantissaBits - bitsLost, 0));
9612f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
9622f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const float		resSum		= out0 + out1;
9632f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
9642f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const deUint32	ulpDiff		= hasZeroSign ? getUlpDiff(resSum, in0) : getUlpDiffIgnoreZeroSign(resSum, in0);
9652f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
9662f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			if (ulpDiff > maxUlpDiff)
9672f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{
9682f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				m_failMsg << "Expected [" << compNdx << "] = (" << HexFloat(refOut0) << ") + (" << HexFloat(refOut1) << ") = " << HexFloat(in0) << " with ULP threshold "
9692f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka							<< tcu::toHex(maxUlpDiff) << ", got ULP diff " << tcu::toHex(ulpDiff);
9702f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				return false;
9712f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			}
9722f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
9732f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
9742f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		return true;
9752f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
9762f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
9772f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
9782f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkaclass ModfCase : public CommonFunctionCase
9792f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
9802f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkapublic:
9812f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	ModfCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
9822f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		: CommonFunctionCase	(testCtx, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "modf", shaderType)
9832f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
9842f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
9852f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
9862f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.outputs.push_back(Symbol("out1", glu::VarType(baseType, precision)));
9872f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.source = "out0 = modf(in0, out1);";
9882f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
9892f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
9902f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	TestInstance* createInstance (Context& ctx) const
9912f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
992b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos		return new ModfCaseInstance(ctx, m_shaderType, m_spec, m_numValues, getName());
9932f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
9942f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
9952f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
9962f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkaclass IsnanCaseInstance : public CommonFunctionTestInstance
9972f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
9982f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkapublic:
999b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos	IsnanCaseInstance (Context& context, glu::ShaderType shaderType, const ShaderSpec& spec, int numValues, const char* name)
1000b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos		: CommonFunctionTestInstance	(context, shaderType, spec, numValues, name)
10012f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
10022f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
10032f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
10042f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	void getInputValues (int numValues, void* const* values) const
10052f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
10062f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		de::Random				rnd				(deStringHash(m_name) ^ 0xc2a39fu);
10072f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
10082f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
10092f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int				scalarSize		= glu::getDataTypeScalarSize(type);
10102f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int				mantissaBits	= getMinMantissaBits(precision);
10112f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const deUint32			mantissaMask	= ~getMaxUlpDiffFromBits(mantissaBits) & ((1u<<23)-1u);
10122f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
10132f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		for (int valNdx = 0; valNdx < numValues*scalarSize; valNdx++)
10142f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
10152f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const bool		isNan		= rnd.getFloat() > 0.3f;
10162f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const bool		isInf		= !isNan && rnd.getFloat() > 0.4f;
10172f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const deUint32	mantissa	= !isInf ? ((1u<<22) | (rnd.getUint32() & mantissaMask)) : 0;
10182f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const deUint32	exp			= !isNan && !isInf ? (rnd.getUint32() & 0x7fu) : 0xffu;
10192f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const deUint32	sign		= rnd.getUint32() & 0x1u;
10202f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const deUint32	value		= (sign << 31) | (exp << 23) | mantissa;
10212f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
10222f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			DE_ASSERT(tcu::Float32(value).isInf() == isInf && tcu::Float32(value).isNaN() == isNan);
10232f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
10242f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			((deUint32*)values[0])[valNdx] = value;
10252f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
10262f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
10272f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
10282f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	bool compare (const void* const* inputs, const void* const* outputs)
10292f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
10302f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
10312f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
10322f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int				scalarSize		= glu::getDataTypeScalarSize(type);
10332f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
10342f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		if (precision == glu::PRECISION_HIGHP)
10352f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
10362f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			// Only highp is required to support inf/nan
10372f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
10382f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{
10392f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float		in0		= ((const float*)inputs[0])[compNdx];
10402f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const bool		out0	= ((const deUint32*)outputs[0])[compNdx] != 0;
10412f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const bool		ref		= tcu::Float32(in0).isNaN();
10422f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
10432f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				if (out0 != ref)
10442f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				{
10452f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					m_failMsg << "Expected [" << compNdx << "] = " << (ref ? "true" : "false");
10462f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					return false;
10472f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				}
10482f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			}
10492f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
10502f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		else if (precision == glu::PRECISION_MEDIUMP || precision == glu::PRECISION_LOWP)
10512f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
10522f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			// NaN support is optional, check that inputs that are not NaN don't result in true.
10532f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
10542f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{
10552f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float		in0		= ((const float*)inputs[0])[compNdx];
10562f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const bool		out0	= ((const deUint32*)outputs[0])[compNdx] != 0;
10572f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const bool		ref		= tcu::Float32(in0).isNaN();
10582f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
10592f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				if (!ref && out0)
10602f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				{
10612f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					m_failMsg << "Expected [" << compNdx << "] = " << (ref ? "true" : "false");
10622f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					return false;
10632f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				}
10642f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			}
10652f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
10662f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
10672f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		return true;
10682f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
10692f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
10702f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
10712f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkaclass IsnanCase : public CommonFunctionCase
10722f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
10732f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkapublic:
10742f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	IsnanCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
10752f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		: CommonFunctionCase	(testCtx, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "isnan", shaderType)
10762f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
10772f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		DE_ASSERT(glu::isDataTypeFloatOrVec(baseType));
10782f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
10792f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int			vecSize		= glu::getDataTypeScalarSize(baseType);
10802f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::DataType	boolType	= vecSize > 1 ? glu::getDataTypeBoolVec(vecSize) : glu::TYPE_BOOL;
10812f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
10822f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
10832f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.outputs.push_back(Symbol("out0", glu::VarType(boolType, glu::PRECISION_LAST)));
10842f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.source = "out0 = isnan(in0);";
10852f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
10862f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
10872f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	TestInstance* createInstance (Context& ctx) const
10882f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
1089b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos		return new IsnanCaseInstance(ctx, m_shaderType, m_spec, m_numValues, getName());
10902f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
10912f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
10922f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
10932f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkaclass IsinfCaseInstance : public CommonFunctionTestInstance
10942f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
10952f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkapublic:
1096b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos	IsinfCaseInstance (Context& context, glu::ShaderType shaderType, const ShaderSpec& spec, int numValues, const char* name)
1097b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos		: CommonFunctionTestInstance(context, shaderType, spec, numValues, name)
10982f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
10992f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
11002f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
11012f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	void getInputValues (int numValues, void* const* values) const
11022f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
11032f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		de::Random				rnd				(deStringHash(m_name) ^ 0xc2a39fu);
11042f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
11052f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
11062f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int				scalarSize		= glu::getDataTypeScalarSize(type);
11072f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int				mantissaBits	= getMinMantissaBits(precision);
11082f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const deUint32			mantissaMask	= ~getMaxUlpDiffFromBits(mantissaBits) & ((1u<<23)-1u);
11092f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
11102f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		for (int valNdx = 0; valNdx < numValues*scalarSize; valNdx++)
11112f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
11122f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const bool		isInf		= rnd.getFloat() > 0.3f;
11132f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const bool		isNan		= !isInf && rnd.getFloat() > 0.4f;
11142f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const deUint32	mantissa	= !isInf ? ((1u<<22) | (rnd.getUint32() & mantissaMask)) : 0;
11152f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const deUint32	exp			= !isNan && !isInf ? (rnd.getUint32() & 0x7fu) : 0xffu;
11162f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const deUint32	sign		= rnd.getUint32() & 0x1u;
11172f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const deUint32	value		= (sign << 31) | (exp << 23) | mantissa;
11182f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
11192f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			DE_ASSERT(tcu::Float32(value).isInf() == isInf && tcu::Float32(value).isNaN() == isNan);
11202f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
11212f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			((deUint32*)values[0])[valNdx] = value;
11222f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
11232f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
11242f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
11252f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	bool compare (const void* const* inputs, const void* const* outputs)
11262f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
11272f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
11282f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
11292f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int				scalarSize		= glu::getDataTypeScalarSize(type);
11302f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
11312f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		if (precision == glu::PRECISION_HIGHP)
11322f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
11332f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			// Only highp is required to support inf/nan
11342f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
11352f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{
11362f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float		in0		= ((const float*)inputs[0])[compNdx];
11372f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const bool		out0	= ((const deUint32*)outputs[0])[compNdx] != 0;
11382f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const bool		ref		= tcu::Float32(in0).isInf();
11392f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
11402f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				if (out0 != ref)
11412f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				{
11422f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					m_failMsg << "Expected [" << compNdx << "] = " << HexBool(ref);
11432f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					return false;
11442f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				}
11452f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			}
11462f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
11472f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		else if (precision == glu::PRECISION_MEDIUMP)
11482f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
11492f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			// Inf support is optional, check that inputs that are not Inf in mediump don't result in true.
11502f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
11512f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{
11522f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float		in0		= ((const float*)inputs[0])[compNdx];
11532f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const bool		out0	= ((const deUint32*)outputs[0])[compNdx] != 0;
11542f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const bool		ref		= tcu::Float16(in0).isInf();
11552f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
11562f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				if (!ref && out0)
11572f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				{
11582f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					m_failMsg << "Expected [" << compNdx << "] = " << (ref ? "true" : "false");
11592f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					return false;
11602f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				}
11612f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			}
11622f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
11632f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		// else: no verification can be performed
11642f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
11652f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		return true;
11662f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
11672f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
11682f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
11692f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkaclass IsinfCase : public CommonFunctionCase
11702f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
11712f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkapublic:
11722f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	IsinfCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
11732f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		: CommonFunctionCase	(testCtx, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "isinf", shaderType)
11742f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
11752f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		DE_ASSERT(glu::isDataTypeFloatOrVec(baseType));
11762f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
11772f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int			vecSize		= glu::getDataTypeScalarSize(baseType);
11782f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::DataType	boolType	= vecSize > 1 ? glu::getDataTypeBoolVec(vecSize) : glu::TYPE_BOOL;
11792f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
11802f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
11812f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.outputs.push_back(Symbol("out0", glu::VarType(boolType, glu::PRECISION_LAST)));
11822f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.source = "out0 = isinf(in0);";
11832f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
11842f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
11852f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	TestInstance* createInstance (Context& ctx) const
11862f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
1187b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos		return new IsinfCaseInstance(ctx, m_shaderType, m_spec, m_numValues, getName());
11882f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
11892f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
11902f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
11912f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkaclass FloatBitsToUintIntCaseInstance : public CommonFunctionTestInstance
11922f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
11932f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkapublic:
1194b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos	FloatBitsToUintIntCaseInstance (Context& context, glu::ShaderType shaderType, const ShaderSpec& spec, int numValues, const char* name)
1195b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos		: CommonFunctionTestInstance	(context, shaderType, spec, numValues, name)
11962f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
11972f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
11982f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
11992f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	void getInputValues (int numValues, void* const* values) const
12002f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
12012f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const Vec2 ranges[] =
12022f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
12032f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			Vec2(-2.0f,		2.0f),	// lowp
12042f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			Vec2(-1e3f,		1e3f),	// mediump
12052f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			Vec2(-1e7f,		1e7f)	// highp
12062f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		};
12072f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
12082f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		de::Random				rnd			(deStringHash(m_name) ^ 0x2790au);
12092f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
12102f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
12112f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int				scalarSize	= glu::getDataTypeScalarSize(type);
12122f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
12132f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), values[0], numValues*scalarSize);
12142f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
12152f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
12162f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	bool compare (const void* const* inputs, const void* const* outputs)
12172f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
12182f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
12192f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
12202f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int				scalarSize		= glu::getDataTypeScalarSize(type);
12212f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
12222f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int				mantissaBits	= getMinMantissaBits(precision);
12232f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int				maxUlpDiff		= getMaxUlpDiffFromBits(mantissaBits);
12242f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
12252f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
12262f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
12272f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const float		in0			= ((const float*)inputs[0])[compNdx];
12282f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const deUint32	out0		= ((const deUint32*)outputs[0])[compNdx];
12292f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const deUint32	refOut0		= tcu::Float32(in0).bits();
12302f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const int		ulpDiff		= de::abs((int)out0 - (int)refOut0);
12312f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
12322f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			if (ulpDiff > maxUlpDiff)
12332f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{
12342f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(refOut0) << " with threshold "
12352f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka							<< tcu::toHex(maxUlpDiff) << ", got diff " << tcu::toHex(ulpDiff);
12362f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				return false;
12372f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			}
12382f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
12392f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
12402f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		return true;
12412f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
12422f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
12432f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
12442f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkaclass FloatBitsToUintIntCase : public CommonFunctionCase
12452f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
12462f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkapublic:
12472f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	FloatBitsToUintIntCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType, bool outIsSigned)
12482f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		: CommonFunctionCase	(testCtx, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), outIsSigned ? "floatBitsToInt" : "floatBitsToUint", shaderType)
12492f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
12502f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int			vecSize		= glu::getDataTypeScalarSize(baseType);
12512f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::DataType	intType		= outIsSigned ? (vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT)
12522f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka													  : (vecSize > 1 ? glu::getDataTypeUintVec(vecSize) : glu::TYPE_UINT);
12532f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
12542f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
12552f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.outputs.push_back(Symbol("out0", glu::VarType(intType, glu::PRECISION_HIGHP)));
12562f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.source = outIsSigned ? "out0 = floatBitsToInt(in0);" : "out0 = floatBitsToUint(in0);";
12572f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
12582f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
12592f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	TestInstance* createInstance (Context& ctx) const
12602f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
1261b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos		return new FloatBitsToUintIntCaseInstance(ctx, m_shaderType, m_spec, m_numValues, getName());
12622f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
12632f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
12642f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
12652f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkaclass FloatBitsToIntCaseInstance : public FloatBitsToUintIntCaseInstance
12662f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
12672f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkapublic:
1268b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos	FloatBitsToIntCaseInstance (Context& context, glu::ShaderType shaderType, const ShaderSpec& spec, int numValues, const char* name)
1269b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos		: FloatBitsToUintIntCaseInstance	(context, shaderType, spec, numValues, name)
12702f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
12712f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
12722f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
12732f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
12742f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkaclass FloatBitsToIntCase : public FloatBitsToUintIntCase
12752f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
12762f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkapublic:
12772f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	FloatBitsToIntCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
12782f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		: FloatBitsToUintIntCase	(testCtx, baseType, precision, shaderType, true)
12792f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
12802f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
12812f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
12822f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
12832f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
12842f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkaclass FloatBitsToUintCaseInstance : public FloatBitsToUintIntCaseInstance
12852f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
12862f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkapublic:
1287b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos	FloatBitsToUintCaseInstance (Context& context, glu::ShaderType shaderType, const ShaderSpec& spec, int numValues, const char* name)
1288b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos		: FloatBitsToUintIntCaseInstance	(context, shaderType, spec, numValues, name)
12892f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
12902f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
12912f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
12922f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
12932f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkaclass FloatBitsToUintCase : public FloatBitsToUintIntCase
12942f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
12952f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkapublic:
12962f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	FloatBitsToUintCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
12972f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		: FloatBitsToUintIntCase	(testCtx, baseType, precision, shaderType, false)
12982f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
12992f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
13002f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
13012f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
13022f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkaclass BitsToFloatCaseInstance : public CommonFunctionTestInstance
13032f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
13042f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkapublic:
1305b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos	BitsToFloatCaseInstance (Context& context, glu::ShaderType shaderType, const ShaderSpec& spec, int numValues, const char* name)
1306b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos		: CommonFunctionTestInstance	(context, shaderType, spec, numValues, name)
13072f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
13082f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
13092f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
13102f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	void getInputValues (int numValues, void* const* values) const
13112f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
13122f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		de::Random				rnd			(deStringHash(m_name) ^ 0xbbb225u);
13132f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
13142f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int				scalarSize	= glu::getDataTypeScalarSize(type);
13152f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const Vec2				range		(-1e8f, +1e8f);
13162f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
13172f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		// \note Filled as floats.
13182f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		fillRandomScalars(rnd, range.x(), range.y(), values[0], numValues*scalarSize);
13192f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
13202f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
13212f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	bool compare (const void* const* inputs, const void* const* outputs)
13222f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
13232f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
13242f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int				scalarSize		= glu::getDataTypeScalarSize(type);
13252f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const deUint32			maxUlpDiff		= 0;
13262f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
13272f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
13282f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
13292f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const float		in0			= ((const float*)inputs[0])[compNdx];
13302f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const float		out0		= ((const float*)outputs[0])[compNdx];
13312f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const deUint32	ulpDiff		= getUlpDiff(in0, out0);
13322f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
13332f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			if (ulpDiff > maxUlpDiff)
13342f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{
13352f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(tcu::Float32(in0).bits()) << " with ULP threshold "
13362f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka							<< tcu::toHex(maxUlpDiff) << ", got ULP diff " << tcu::toHex(ulpDiff);
13372f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				return false;
13382f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			}
13392f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
13402f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
13412f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		return true;
13422f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
13432f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
13442f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
13452f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkaclass BitsToFloatCase : public CommonFunctionCase
13462f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
13472f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkapublic:
13482f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	BitsToFloatCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::ShaderType shaderType)
13492f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		: CommonFunctionCase	(testCtx, getCommonFuncCaseName(baseType, glu::PRECISION_HIGHP, shaderType).c_str(), glu::isDataTypeIntOrIVec(baseType) ? "intBitsToFloat" : "uintBitsToFloat", shaderType)
13502f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
13512f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const bool			inIsSigned	= glu::isDataTypeIntOrIVec(baseType);
13522f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int			vecSize		= glu::getDataTypeScalarSize(baseType);
13532f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::DataType	floatType	= vecSize > 1 ? glu::getDataTypeFloatVec(vecSize) : glu::TYPE_FLOAT;
13542f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
13552f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, glu::PRECISION_HIGHP)));
13562f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.outputs.push_back(Symbol("out0", glu::VarType(floatType, glu::PRECISION_HIGHP)));
13572f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.source = inIsSigned ? "out0 = intBitsToFloat(in0);" : "out0 = uintBitsToFloat(in0);";
13582f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
13592f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
13602f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	TestInstance* createInstance (Context& ctx) const
13612f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
1362b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos		return new BitsToFloatCaseInstance(ctx, m_shaderType, m_spec, m_numValues, getName());
13632f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
13642f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
13652f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
13662f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkaclass FloorCaseInstance : public CommonFunctionTestInstance
13672f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
13682f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkapublic:
1369b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos	FloorCaseInstance (Context& context, glu::ShaderType shaderType, const ShaderSpec& spec, int numValues, const char* name)
1370b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos		: CommonFunctionTestInstance	(context, shaderType, spec, numValues, name)
13712f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
13722f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
13732f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
13742f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	void getInputValues (int numValues, void* const* values) const
13752f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
13762f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const Vec2 ranges[] =
13772f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
13782f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			Vec2(-2.0f,		2.0f),	// lowp
13792f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			Vec2(-1e3f,		1e3f),	// mediump
13802f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			Vec2(-1e7f,		1e7f)	// highp
13812f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		};
13822f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
13832f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		de::Random				rnd			(deStringHash(m_name) ^ 0xac23fu);
13842f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
13852f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
13862f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int				scalarSize	= glu::getDataTypeScalarSize(type);
13872f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		// Random cases.
13882f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[0], numValues*scalarSize);
13892f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
13902f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		// If precision is mediump, make sure values can be represented in fp16 exactly
13912f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		if (precision == glu::PRECISION_MEDIUMP)
13922f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
13932f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			for (int ndx = 0; ndx < numValues*scalarSize; ndx++)
13942f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				((float*)values[0])[ndx] = tcu::Float16(((float*)values[0])[ndx]).asFloat();
13952f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
13962f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
13972f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
13982f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	bool compare (const void* const* inputs, const void* const* outputs)
13992f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
14002f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
14012f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
14022f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int				scalarSize		= glu::getDataTypeScalarSize(type);
14032f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
14042f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP)
14052f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
14062f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			// Require exact result.
14072f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
14082f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{
14092f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float		in0			= ((const float*)inputs[0])[compNdx];
14102f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float		out0		= ((const float*)outputs[0])[compNdx];
14112f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float		ref			= deFloatFloor(in0);
14122f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
14132f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const deUint32	ulpDiff		= getUlpDiff(out0, ref);
14142f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
14152f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				if (ulpDiff > 0)
14162f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				{
14172f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff " << tcu::toHex(ulpDiff);
14182f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					return false;
14192f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				}
14202f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			}
14212f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
14222f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		else
14232f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
14242f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const int		mantissaBits	= getMinMantissaBits(precision);
14252f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const deUint32	maxUlpDiff		= getMaxUlpDiffFromBits(mantissaBits);	// ULP diff for rounded integer value.
14262f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const float		eps				= getEpsFromBits(1.0f, mantissaBits);	// epsilon for rounding bounds
14272f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
14282f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
14292f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{
14302f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float		in0			= ((const float*)inputs[0])[compNdx];
14312f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float		out0		= ((const float*)outputs[0])[compNdx];
14322f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const int		minRes		= int(deFloatFloor(in0-eps));
14332f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const int		maxRes		= int(deFloatFloor(in0+eps));
14342f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				bool			anyOk		= false;
14352f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
14362f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				for (int roundedVal = minRes; roundedVal <= maxRes; roundedVal++)
14372f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				{
14382f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					const deUint32 ulpDiff = getUlpDiff(out0, float(roundedVal));
14392f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
14402f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					if (ulpDiff <= maxUlpDiff)
14412f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					{
14422f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka						anyOk = true;
14432f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka						break;
14442f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					}
14452f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				}
14462f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
14472f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				if (!anyOk)
14482f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				{
14492f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					m_failMsg << "Expected [" << compNdx << "] = [" << minRes << ", " << maxRes << "] with ULP threshold " << tcu::toHex(maxUlpDiff);
14502f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					return false;
14512f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				}
14522f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			}
14532f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
14542f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
14552f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		return true;
14562f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
14572f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
14582f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
14592f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkaclass FloorCase : public CommonFunctionCase
14602f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
14612f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkapublic:
14622f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	FloorCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
14632f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		: CommonFunctionCase	(testCtx, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "floor", shaderType)
14642f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
14652f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
14662f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
14672f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.source = "out0 = floor(in0);";
14682f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
14692f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
14702f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	TestInstance* createInstance (Context& ctx) const
14712f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
1472b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos		return new FloorCaseInstance(ctx, m_shaderType, m_spec, m_numValues, getName());
14732f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
14742f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
14752f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
14762f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkaclass TruncCaseInstance : public CommonFunctionTestInstance
14772f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
14782f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkapublic:
1479b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos	TruncCaseInstance (Context& context, glu::ShaderType shaderType, const ShaderSpec& spec, int numValues, const char* name)
1480b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos		: CommonFunctionTestInstance	(context, shaderType, spec, numValues, name)
14812f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
14822f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
14832f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
14842f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	void getInputValues (int numValues, void* const* values) const
14852f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
14862f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const Vec2 ranges[] =
14872f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
14882f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			Vec2(-2.0f,		2.0f),	// lowp
14892f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			Vec2(-1e3f,		1e3f),	// mediump
14902f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			Vec2(-1e7f,		1e7f)	// highp
14912f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		};
14922f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
14932f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		de::Random				rnd				(deStringHash(m_name) ^ 0xac23fu);
14942f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
14952f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
14962f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int				scalarSize		= glu::getDataTypeScalarSize(type);
14972f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const float				specialCases[]	= { 0.0f, -0.0f, -0.9f, 0.9f, 1.0f, -1.0f };
14982f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int				numSpecialCases	= DE_LENGTH_OF_ARRAY(specialCases);
14992f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
15002f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		// Special cases
15012f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		for (int caseNdx = 0; caseNdx < numSpecialCases; caseNdx++)
15022f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
15032f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			for (int scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++)
15042f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				((float*)values[0])[caseNdx*scalarSize + scalarNdx] = specialCases[caseNdx];
15052f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
15062f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
15072f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		// Random cases.
15082f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[0] + scalarSize*numSpecialCases, (numValues-numSpecialCases)*scalarSize);
15092f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
15102f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		// If precision is mediump, make sure values can be represented in fp16 exactly
15112f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		if (precision == glu::PRECISION_MEDIUMP)
15122f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
15132f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			for (int ndx = 0; ndx < numValues*scalarSize; ndx++)
15142f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				((float*)values[0])[ndx] = tcu::Float16(((float*)values[0])[ndx]).asFloat();
15152f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
15162f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
15172f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
15182f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	bool compare (const void* const* inputs, const void* const* outputs)
15192f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
15202f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
15212f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
15222f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int				scalarSize		= glu::getDataTypeScalarSize(type);
15232f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
15242f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP)
15252f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
15262f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			// Require exact result.
15272f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
15282f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{
15292f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float		in0			= ((const float*)inputs[0])[compNdx];
15302f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float		out0		= ((const float*)outputs[0])[compNdx];
15312f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const bool		isNeg		= tcu::Float32(in0).sign() < 0;
15322f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float		ref			= isNeg ? (-float(int(-in0))) : float(int(in0));
15332f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
15342f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				// \note: trunc() function definition is a bit broad on negative zeros. Ignore result sign if zero.
15352f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const deUint32	ulpDiff		= getUlpDiffIgnoreZeroSign(out0, ref);
15362f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
15372f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				if (ulpDiff > 0)
15382f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				{
15392f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff " << tcu::toHex(ulpDiff);
15402f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					return false;
15412f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				}
15422f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			}
15432f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
15442f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		else
15452f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
15462f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const int		mantissaBits	= getMinMantissaBits(precision);
15472f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const deUint32	maxUlpDiff		= getMaxUlpDiffFromBits(mantissaBits);	// ULP diff for rounded integer value.
15482f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const float		eps				= getEpsFromBits(1.0f, mantissaBits);	// epsilon for rounding bounds
15492f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
15502f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
15512f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{
15522f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float		in0			= ((const float*)inputs[0])[compNdx];
15532f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float		out0		= ((const float*)outputs[0])[compNdx];
15542f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const int		minRes		= int(in0-eps);
15552f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const int		maxRes		= int(in0+eps);
15562f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				bool			anyOk		= false;
15572f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
15582f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				for (int roundedVal = minRes; roundedVal <= maxRes; roundedVal++)
15592f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				{
15602f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					const deUint32 ulpDiff = getUlpDiffIgnoreZeroSign(out0, float(roundedVal));
15612f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
15622f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					if (ulpDiff <= maxUlpDiff)
15632f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					{
15642f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka						anyOk = true;
15652f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka						break;
15662f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					}
15672f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				}
15682f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
15692f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				if (!anyOk)
15702f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				{
15712f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					m_failMsg << "Expected [" << compNdx << "] = [" << minRes << ", " << maxRes << "] with ULP threshold " << tcu::toHex(maxUlpDiff);
15722f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					return false;
15732f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				}
15742f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			}
15752f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
15762f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
15772f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		return true;
15782f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
15792f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
15802f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
15812f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkaclass TruncCase : public CommonFunctionCase
15822f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
15832f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkapublic:
15842f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	TruncCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
15852f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		: CommonFunctionCase	(testCtx, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "trunc", shaderType)
15862f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
15872f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
15882f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
15892f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.source = "out0 = trunc(in0);";
15902f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
15912f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
15922f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	TestInstance* createInstance (Context& ctx) const
15932f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
1594b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos		return new TruncCaseInstance(ctx, m_shaderType, m_spec, m_numValues, getName());
15952f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
15962f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
15972f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
15982f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkaclass RoundCaseInstance : public CommonFunctionTestInstance
15992f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
16002f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkapublic:
1601b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos	RoundCaseInstance (Context& context, glu::ShaderType shaderType, const ShaderSpec& spec, int numValues, const char* name)
1602b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos		: CommonFunctionTestInstance	(context, shaderType, spec, numValues, name)
16032f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
16042f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
16052f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
16062f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	void getInputValues (int numValues, void* const* values) const
16072f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
16082f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const Vec2 ranges[] =
16092f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
16102f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			Vec2(-2.0f,		2.0f),	// lowp
16112f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			Vec2(-1e3f,		1e3f),	// mediump
16122f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			Vec2(-1e7f,		1e7f)	// highp
16132f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		};
16142f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
16152f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		de::Random				rnd				(deStringHash(m_name) ^ 0xac23fu);
16162f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
16172f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
16182f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int				scalarSize		= glu::getDataTypeScalarSize(type);
16192f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		int						numSpecialCases	= 0;
16202f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
16212f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		// Special cases.
16222f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		if (precision != glu::PRECISION_LOWP)
16232f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
16242f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			DE_ASSERT(numValues >= 10);
16252f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			for (int ndx = 0; ndx < 10; ndx++)
16262f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{
16272f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float v = de::clamp(float(ndx) - 5.5f, ranges[precision].x(), ranges[precision].y());
16282f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				std::fill((float*)values[0], (float*)values[0] + scalarSize, v);
16292f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				numSpecialCases += 1;
16302f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			}
16312f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
16322f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
16332f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		// Random cases.
16342f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[0] + numSpecialCases*scalarSize, (numValues-numSpecialCases)*scalarSize);
16352f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
16362f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		// If precision is mediump, make sure values can be represented in fp16 exactly
16372f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		if (precision == glu::PRECISION_MEDIUMP)
16382f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
16392f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			for (int ndx = 0; ndx < numValues*scalarSize; ndx++)
16402f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				((float*)values[0])[ndx] = tcu::Float16(((float*)values[0])[ndx]).asFloat();
16412f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
16422f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
16432f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
16442f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	bool compare (const void* const* inputs, const void* const* outputs)
16452f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
16462f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
16472f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
16482f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const bool				hasZeroSign		= supportsSignedZero(precision);
16492f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int				scalarSize		= glu::getDataTypeScalarSize(type);
16502f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
16512f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP)
16522f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
16532f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
16542f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{
16552f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float		in0			= ((const float*)inputs[0])[compNdx];
16562f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float		out0		= ((const float*)outputs[0])[compNdx];
16572f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
16582f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				if (deFloatFrac(in0) == 0.5f)
16592f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				{
16602f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					// Allow both ceil(in) and floor(in)
16612f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					const float		ref0		= deFloatFloor(in0);
16622f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					const float		ref1		= deFloatCeil(in0);
16632f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					const deUint32	ulpDiff0	= hasZeroSign ? getUlpDiff(out0, ref0) : getUlpDiffIgnoreZeroSign(out0, ref0);
16642f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					const deUint32	ulpDiff1	= hasZeroSign ? getUlpDiff(out0, ref1) : getUlpDiffIgnoreZeroSign(out0, ref1);
16652f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
16662f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					if (ulpDiff0 > 0 && ulpDiff1 > 0)
16672f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					{
16682f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka						m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref0) << " or " << HexFloat(ref1) << ", got ULP diff " << tcu::toHex(de::min(ulpDiff0, ulpDiff1));
16692f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka						return false;
16702f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					}
16712f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				}
16722f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				else
16732f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				{
16742f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					// Require exact result
16752f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					const float		ref		= roundEven(in0);
16762f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					const deUint32	ulpDiff	= hasZeroSign ? getUlpDiff(out0, ref) : getUlpDiffIgnoreZeroSign(out0, ref);
16772f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
16782f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					if (ulpDiff > 0)
16792f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					{
16802f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka						m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff " << tcu::toHex(ulpDiff);
16812f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka						return false;
16822f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					}
16832f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				}
16842f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			}
16852f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
16862f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		else
16872f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
16882f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const int		mantissaBits	= getMinMantissaBits(precision);
16892f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const deUint32	maxUlpDiff		= getMaxUlpDiffFromBits(mantissaBits);	// ULP diff for rounded integer value.
16902f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const float		eps				= getEpsFromBits(1.0f, mantissaBits);	// epsilon for rounding bounds
16912f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
16922f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
16932f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{
16942f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float		in0			= ((const float*)inputs[0])[compNdx];
16952f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float		out0		= ((const float*)outputs[0])[compNdx];
16962f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const int		minRes		= int(roundEven(in0-eps));
16972f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const int		maxRes		= int(roundEven(in0+eps));
16982f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				bool			anyOk		= false;
16992f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
17002f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				for (int roundedVal = minRes; roundedVal <= maxRes; roundedVal++)
17012f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				{
17022f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					const deUint32 ulpDiff = getUlpDiffIgnoreZeroSign(out0, float(roundedVal));
17032f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
17042f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					if (ulpDiff <= maxUlpDiff)
17052f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					{
17062f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka						anyOk = true;
17072f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka						break;
17082f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					}
17092f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				}
17102f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
17112f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				if (!anyOk)
17122f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				{
17132f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					m_failMsg << "Expected [" << compNdx << "] = [" << minRes << ", " << maxRes << "] with ULP threshold " << tcu::toHex(maxUlpDiff);
17142f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					return false;
17152f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				}
17162f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			}
17172f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
17182f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
17192f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		return true;
17202f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
17212f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
17222f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
17232f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkaclass RoundCase : public CommonFunctionCase
17242f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
17252f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkapublic:
17262f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	RoundCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
17272f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		: CommonFunctionCase	(testCtx, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "round", shaderType)
17282f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
17292f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
17302f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
17312f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.source = "out0 = round(in0);";
17322f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
17332f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
17342f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	TestInstance* createInstance (Context& ctx) const
17352f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
1736b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos		return new RoundCaseInstance(ctx, m_shaderType, m_spec, m_numValues, getName());
17372f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
17382f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
17392f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
17402f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkaclass CeilCaseInstance : public CommonFunctionTestInstance
17412f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
17422f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkapublic:
1743b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos	CeilCaseInstance (Context& context, glu::ShaderType shaderType, const ShaderSpec& spec, int numValues, const char* name)
1744b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos		: CommonFunctionTestInstance	(context, shaderType, spec, numValues, name)
17452f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
17462f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
17472f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
17482f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	void getInputValues (int numValues, void* const* values) const
17492f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
17502f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const Vec2 ranges[] =
17512f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
17522f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			Vec2(-2.0f,		2.0f),	// lowp
17532f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			Vec2(-1e3f,		1e3f),	// mediump
17542f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			Vec2(-1e7f,		1e7f)	// highp
17552f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		};
17562f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
17572f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		de::Random				rnd			(deStringHash(m_name) ^ 0xac23fu);
17582f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
17592f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
17602f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int				scalarSize	= glu::getDataTypeScalarSize(type);
17612f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
17622f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		// Random cases.
17632f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[0], numValues*scalarSize);
17642f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
17652f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		// If precision is mediump, make sure values can be represented in fp16 exactly
17662f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		if (precision == glu::PRECISION_MEDIUMP)
17672f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
17682f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			for (int ndx = 0; ndx < numValues*scalarSize; ndx++)
17692f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				((float*)values[0])[ndx] = tcu::Float16(((float*)values[0])[ndx]).asFloat();
17702f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
17712f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
17722f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
17732f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	bool compare (const void* const* inputs, const void* const* outputs)
17742f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
17752f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
17762f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
17772f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const bool				hasZeroSign		= supportsSignedZero(precision);
17782f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int				scalarSize		= glu::getDataTypeScalarSize(type);
17792f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
17802f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP)
17812f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
17822f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			// Require exact result.
17832f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
17842f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{
17852f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float		in0			= ((const float*)inputs[0])[compNdx];
17862f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float		out0		= ((const float*)outputs[0])[compNdx];
17872f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float		ref			= deFloatCeil(in0);
17882f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
17892f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const deUint32	ulpDiff		= hasZeroSign ? getUlpDiff(out0, ref) : getUlpDiffIgnoreZeroSign(out0, ref);
17902f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
17912f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				if (ulpDiff > 0)
17922f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				{
17932f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff " << tcu::toHex(ulpDiff);
17942f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					return false;
17952f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				}
17962f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			}
17972f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
17982f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		else
17992f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
18002f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const int		mantissaBits	= getMinMantissaBits(precision);
18012f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const deUint32	maxUlpDiff		= getMaxUlpDiffFromBits(mantissaBits);	// ULP diff for rounded integer value.
18022f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const float		eps				= getEpsFromBits(1.0f, mantissaBits);	// epsilon for rounding bounds
18032f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
18042f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
18052f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{
18062f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float		in0			= ((const float*)inputs[0])[compNdx];
18072f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float		out0		= ((const float*)outputs[0])[compNdx];
18082f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const int		minRes		= int(deFloatCeil(in0-eps));
18092f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const int		maxRes		= int(deFloatCeil(in0+eps));
18102f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				bool			anyOk		= false;
18112f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
18122f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				for (int roundedVal = minRes; roundedVal <= maxRes; roundedVal++)
18132f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				{
18142f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					const deUint32 ulpDiff = getUlpDiffIgnoreZeroSign(out0, float(roundedVal));
18152f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
18162f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					if (ulpDiff <= maxUlpDiff)
18172f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					{
18182f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka						anyOk = true;
18192f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka						break;
18202f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					}
18212f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				}
18222f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
18232f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				if (!anyOk && de::inRange(0, minRes, maxRes))
18242f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				{
18252f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					// Allow -0 as well.
18262f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					const int ulpDiff = de::abs((int)tcu::Float32(out0).bits() - (int)0x80000000u);
18272f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					anyOk = ((deUint32)ulpDiff <= maxUlpDiff);
18282f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				}
18292f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
18302f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				if (!anyOk)
18312f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				{
18322f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					m_failMsg << "Expected [" << compNdx << "] = [" << minRes << ", " << maxRes << "] with ULP threshold " << tcu::toHex(maxUlpDiff);
18332f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					return false;
18342f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				}
18352f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			}
18362f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
18372f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
18382f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		return true;
18392f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
18402f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
18412f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
18422f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkaclass CeilCase : public CommonFunctionCase
18432f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
18442f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkapublic:
18452f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	CeilCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
18462f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		: CommonFunctionCase	(testCtx, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "ceil", shaderType)
18472f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
18482f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
18492f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
18502f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.source = "out0 = ceil(in0);";
18512f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
18522f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
18532f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	TestInstance* createInstance (Context& ctx) const
18542f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
1855b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos		return new CeilCaseInstance(ctx, m_shaderType, m_spec, m_numValues, getName());
18562f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
18572f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
18582f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
18592f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkaclass FractCaseInstance : public CommonFunctionTestInstance
18602f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
18612f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkapublic:
1862b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos	FractCaseInstance (Context& context, glu::ShaderType shaderType, const ShaderSpec& spec, int numValues, const char* name)
1863b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos		: CommonFunctionTestInstance	(context, shaderType, spec, numValues, name)
18642f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
18652f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
18662f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
18672f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	void getInputValues (int numValues, void* const* values) const
18682f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
18692f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const Vec2 ranges[] =
18702f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
18712f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			Vec2(-2.0f,		2.0f),	// lowp
18722f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			Vec2(-1e3f,		1e3f),	// mediump
18732f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			Vec2(-1e7f,		1e7f)	// highp
18742f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		};
18752f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
18762f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		de::Random				rnd				(deStringHash(m_name) ^ 0xac23fu);
18772f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
18782f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
18792f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int				scalarSize		= glu::getDataTypeScalarSize(type);
18802f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		int						numSpecialCases	= 0;
18812f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
18822f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		// Special cases.
18832f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		if (precision != glu::PRECISION_LOWP)
18842f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
18852f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			DE_ASSERT(numValues >= 10);
18862f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			for (int ndx = 0; ndx < 10; ndx++)
18872f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{
18882f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float v = de::clamp(float(ndx) - 5.5f, ranges[precision].x(), ranges[precision].y());
18892f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				std::fill((float*)values[0], (float*)values[0] + scalarSize, v);
18902f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				numSpecialCases += 1;
18912f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			}
18922f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
18932f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
18942f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		// Random cases.
18952f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[0] + numSpecialCases*scalarSize, (numValues-numSpecialCases)*scalarSize);
18962f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
18972f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		// If precision is mediump, make sure values can be represented in fp16 exactly
18982f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		if (precision == glu::PRECISION_MEDIUMP)
18992f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
19002f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			for (int ndx = 0; ndx < numValues*scalarSize; ndx++)
19012f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				((float*)values[0])[ndx] = tcu::Float16(((float*)values[0])[ndx]).asFloat();
19022f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
19032f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
19042f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
19052f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	bool compare (const void* const* inputs, const void* const* outputs)
19062f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
19072f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
19082f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
19092f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const bool				hasZeroSign		= supportsSignedZero(precision);
19102f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int				scalarSize		= glu::getDataTypeScalarSize(type);
19112f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
19122f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP)
19132f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
19142f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			// Require exact result.
19152f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
19162f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{
19172f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float		in0			= ((const float*)inputs[0])[compNdx];
19182f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float		out0		= ((const float*)outputs[0])[compNdx];
19192f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float		ref			= deFloatFrac(in0);
19202f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
19212f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const deUint32	ulpDiff		= hasZeroSign ? getUlpDiff(out0, ref) : getUlpDiffIgnoreZeroSign(out0, ref);
19222f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
19232f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				if (ulpDiff > 0)
19242f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				{
19252f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff " << tcu::toHex(ulpDiff);
19262f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					return false;
19272f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				}
19282f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			}
19292f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
19302f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		else
19312f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
19322f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const int		mantissaBits	= getMinMantissaBits(precision);
19332f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const float		eps				= getEpsFromBits(1.0f, mantissaBits);	// epsilon for rounding bounds
19342f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
19352f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			for (int compNdx = 0; compNdx < scalarSize; compNdx++)
19362f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{
19372f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float		in0			= ((const float*)inputs[0])[compNdx];
19382f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				const float		out0		= ((const float*)outputs[0])[compNdx];
19392f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
19402f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				if (int(deFloatFloor(in0-eps)) == int(deFloatFloor(in0+eps)))
19412f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				{
19422f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					const float		ref			= deFloatFrac(in0);
19432f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					const int		bitsLost	= numBitsLostInOp(in0, ref);
19442f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					const deUint32	maxUlpDiff	= getMaxUlpDiffFromBits(de::max(0, mantissaBits-bitsLost));	// ULP diff for rounded integer value.
19452f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					const deUint32	ulpDiff		= getUlpDiffIgnoreZeroSign(out0, ref);
19462f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
19472f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					if (ulpDiff > maxUlpDiff)
19482f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					{
19492f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka						m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << " with ULP threshold " << tcu::toHex(maxUlpDiff) << ", got diff " << tcu::toHex(ulpDiff);
19502f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka						return false;
19512f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					}
19522f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				}
19532f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				else
19542f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				{
19552f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					if (out0 >= 1.0f)
19562f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					{
19572f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka						m_failMsg << "Expected [" << compNdx << "] < 1.0";
19582f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka						return false;
19592f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					}
19602f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				}
19612f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			}
19622f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
19632f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
19642f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		return true;
19652f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
19662f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
19672f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
19682f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkaclass FractCase : public CommonFunctionCase
19692f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
19702f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkapublic:
19712f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	FractCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
19722f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		: CommonFunctionCase	(testCtx, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "fract", shaderType)
19732f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
19742f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
19752f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
19762f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.source = "out0 = fract(in0);";
19772f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
19782f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
19792f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	TestInstance* createInstance (Context& ctx) const
19802f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
1981b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos		return new FractCaseInstance(ctx, m_shaderType, m_spec, m_numValues, getName());
19822f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
19832f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
19842f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
19852f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkaclass FrexpCaseInstance : public CommonFunctionTestInstance
19862f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
19872f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkapublic:
1988b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos	FrexpCaseInstance (Context& context, glu::ShaderType shaderType, const ShaderSpec& spec, int numValues, const char* name)
1989b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos		: CommonFunctionTestInstance	(context, shaderType, spec, numValues, name)
19902f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
19912f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
19922f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
19932f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	void getInputValues (int numValues, void* const* values) const
19942f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
19952f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const Vec2 ranges[] =
19962f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
19972f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			Vec2(-2.0f,		2.0f),	// lowp
19982f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			Vec2(-1e3f,		1e3f),	// mediump
19992f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			Vec2(-1e7f,		1e7f)	// highp
20002f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		};
20012f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
20022f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		de::Random				rnd			(deStringHash(m_name) ^ 0x2790au);
20032f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::DataType		type		= m_spec.inputs[0].varType.getBasicType();
20042f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::Precision	precision	= m_spec.inputs[0].varType.getPrecision();
20052f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int				scalarSize	= glu::getDataTypeScalarSize(type);
20062f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
20072f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		// Special cases
20082f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
20092f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
20102f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			((float*)values[0])[scalarSize*0 + compNdx] = 0.0f;
20112f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			((float*)values[0])[scalarSize*1 + compNdx] = -0.0f;
20122f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			((float*)values[0])[scalarSize*2 + compNdx] = 0.5f;
20132f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			((float*)values[0])[scalarSize*3 + compNdx] = -0.5f;
20142f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			((float*)values[0])[scalarSize*4 + compNdx] = 1.0f;
20152f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			((float*)values[0])[scalarSize*5 + compNdx] = -1.0f;
20162f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			((float*)values[0])[scalarSize*6 + compNdx] = 2.0f;
20172f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			((float*)values[0])[scalarSize*7 + compNdx] = -2.0f;
20182f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
20192f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
20202f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[0] + 8*scalarSize, (numValues-8)*scalarSize);
20212f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
20222f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		// Make sure the values are representable in the target format
20232f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		for (int caseNdx = 0; caseNdx < numValues; ++caseNdx)
20242f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
20252f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			for (int scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++)
20262f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{
20272f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				float* const valuePtr = &((float*)values[0])[caseNdx * scalarSize + scalarNdx];
20282f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
20292f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				*valuePtr = makeFloatRepresentable(*valuePtr, precision);
20302f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			}
20312f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
20322f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
20332f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
20342f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	bool compare (const void* const* inputs, const void* const* outputs)
20352f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
20362f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::DataType		type						= m_spec.inputs[0].varType.getBasicType();
20372f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::Precision	precision					= m_spec.inputs[0].varType.getPrecision();
20382f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int				scalarSize					= glu::getDataTypeScalarSize(type);
20392f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const bool				transitSupportsSignedZero	= (m_shaderType != glu::SHADERTYPE_FRAGMENT); // executor cannot reliably transit negative zero to fragment stage
20402f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const bool				signedZero					= supportsSignedZero(precision) && transitSupportsSignedZero;
20412f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
20422f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int				mantissaBits				= getMinMantissaBits(precision);
20432f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const deUint32			maxUlpDiff					= getMaxUlpDiffFromBits(mantissaBits);
20442f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
20452f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
20462f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
20472f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const float		in0			= ((const float*)inputs[0])[compNdx];
20482f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const float		out0		= ((const float*)outputs[0])[compNdx];
20492f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const int		out1		= ((const int*)outputs[1])[compNdx];
20502f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
20512f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			float			refOut0;
20522f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			int				refOut1;
20532f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
20542f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			frexp(in0, &refOut0, &refOut1);
20552f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
20562f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const deUint32	ulpDiff0	= signedZero ? getUlpDiff(out0, refOut0) : getUlpDiffIgnoreZeroSign(out0, refOut0);
20572f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
20582f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			if (ulpDiff0 > maxUlpDiff || out1 != refOut1)
20592f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{
20602f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(refOut0) << ", " << refOut1 << " with ULP threshold "
20612f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka						  << tcu::toHex(maxUlpDiff) << ", got ULP diff " << tcu::toHex(ulpDiff0);
20622f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				return false;
20632f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			}
20642f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
20652f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
20662f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		return true;
20672f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
20682f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
20692f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
20702f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkaclass FrexpCase : public CommonFunctionCase
20712f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
20722f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkapublic:
20732f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	FrexpCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
20742f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		: CommonFunctionCase	(testCtx, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "frexp", shaderType)
20752f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
20762f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int			vecSize		= glu::getDataTypeScalarSize(baseType);
20772f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::DataType	intType		= vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
20782f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
20792f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
20802f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, glu::PRECISION_HIGHP)));
20812f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.outputs.push_back(Symbol("out1", glu::VarType(intType, glu::PRECISION_HIGHP)));
20822f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.source = "out0 = frexp(in0, out1);";
20832f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
20842f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
20852f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	TestInstance* createInstance (Context& ctx) const
20862f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
2087b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos		return new FrexpCaseInstance(ctx, m_shaderType, m_spec, m_numValues, getName());
20882f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
20892f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
20902f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
20912f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkaclass LdexpCaseInstance : public CommonFunctionTestInstance
20922f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
20932f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkapublic:
2094b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos	LdexpCaseInstance (Context& context, glu::ShaderType shaderType, const ShaderSpec& spec, int numValues, const char* name)
2095b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos		: CommonFunctionTestInstance	(context, shaderType, spec, numValues, name)
20962f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
20972f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
20982f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
20992f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	void getInputValues (int numValues, void* const* values) const
21002f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
21012f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const Vec2 ranges[] =
21022f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
21032f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			Vec2(-2.0f,		2.0f),	// lowp
21042f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			Vec2(-1e3f,		1e3f),	// mediump
21052f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			Vec2(-1e7f,		1e7f)	// highp
21062f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		};
21072f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
21082f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		de::Random				rnd					(deStringHash(m_name) ^ 0x2790au);
21092f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::DataType		type				= m_spec.inputs[0].varType.getBasicType();
21102f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::Precision	precision			= m_spec.inputs[0].varType.getPrecision();
21112f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int				scalarSize			= glu::getDataTypeScalarSize(type);
21122f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		int						valueNdx			= 0;
21132f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
21142f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
21152f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const float easySpecialCases[] = { 0.0f, -0.0f, 0.5f, -0.5f, 1.0f, -1.0f, 2.0f, -2.0f };
21162f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
21172f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			DE_ASSERT(valueNdx + DE_LENGTH_OF_ARRAY(easySpecialCases) <= numValues);
21182f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(easySpecialCases); caseNdx++)
21192f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{
21202f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				float	in0;
21212f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				int		in1;
21222f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
21232f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				frexp(easySpecialCases[caseNdx], &in0, &in1);
21242f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
21252f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				for (int compNdx = 0; compNdx < scalarSize; compNdx++)
21262f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				{
21272f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					((float*)values[0])[valueNdx*scalarSize + compNdx] = in0;
21282f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					((int*)values[1])[valueNdx*scalarSize + compNdx] = in1;
21292f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				}
21302f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
21312f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				valueNdx += 1;
21322f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			}
21332f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
21342f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
21352f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
21362f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			// \note lowp and mediump can not necessarily fit the values in hard cases, so we'll use only easy ones.
21372f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const int numEasyRandomCases = precision == glu::PRECISION_HIGHP ? 50 : (numValues-valueNdx);
21382f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
21392f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			DE_ASSERT(valueNdx + numEasyRandomCases <= numValues);
21402f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			for (int caseNdx = 0; caseNdx < numEasyRandomCases; caseNdx++)
21412f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{
21422f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				for (int compNdx = 0; compNdx < scalarSize; compNdx++)
21432f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				{
21442f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					const float	in	= rnd.getFloat(ranges[precision].x(), ranges[precision].y());
21452f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					float		in0;
21462f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					int			in1;
21472f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
21482f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					frexp(in, &in0, &in1);
21492f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
21502f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					((float*)values[0])[valueNdx*scalarSize + compNdx] = in0;
21512f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					((int*)values[1])[valueNdx*scalarSize + compNdx] = in1;
21522f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				}
21532f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
21542f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				valueNdx += 1;
21552f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			}
21562f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
21572f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
21582f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
21592f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const int numHardRandomCases = numValues-valueNdx;
21602f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			DE_ASSERT(numHardRandomCases >= 0 && valueNdx + numHardRandomCases <= numValues);
21612f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
21622f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			for (int caseNdx = 0; caseNdx < numHardRandomCases; caseNdx++)
21632f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{
21642f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				for (int compNdx = 0; compNdx < scalarSize; compNdx++)
21652f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				{
21662f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					const int		fpExp		= rnd.getInt(-126, 127);
21672f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					const int		sign		= rnd.getBool() ? -1 : +1;
21682f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					const deUint32	mantissa	= (1u<<23) | (rnd.getUint32() & ((1u<<23)-1));
21692f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					const int		in1			= rnd.getInt(de::max(-126, -126-fpExp), de::min(127, 127-fpExp));
21702f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					const float		in0			= tcu::Float32::construct(sign, fpExp, mantissa).asFloat();
21712f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
21722f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					DE_ASSERT(de::inRange(in1, -126, 127)); // See Khronos bug 11180
21732f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					DE_ASSERT(de::inRange(in1+fpExp, -126, 127));
21742f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
21752f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					const float		out			= ldexp(in0, in1);
21762f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
21772f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					DE_ASSERT(!tcu::Float32(out).isInf() && !tcu::Float32(out).isDenorm());
21782f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					DE_UNREF(out);
21792f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
21802f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					((float*)values[0])[valueNdx*scalarSize + compNdx] = in0;
21812f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					((int*)values[1])[valueNdx*scalarSize + compNdx] = in1;
21822f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				}
21832f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
21842f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				valueNdx += 1;
21852f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			}
21862f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
21872f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
21882f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
21892f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	bool compare (const void* const* inputs, const void* const* outputs)
21902f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
21912f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
21922f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
21932f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int				scalarSize		= glu::getDataTypeScalarSize(type);
21942f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
21952f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int				mantissaBits	= getMinMantissaBits(precision);
21962f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const deUint32			maxUlpDiff		= getMaxUlpDiffFromBits(mantissaBits);
21972f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
21982f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
21992f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
22002f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const float		in0			= ((const float*)inputs[0])[compNdx];
22012f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const int		in1			= ((const int*)inputs[1])[compNdx];
22022f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const float		out0		= ((const float*)outputs[0])[compNdx];
22032f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const float		refOut0		= ldexp(in0, in1);
22042f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const deUint32	ulpDiff		= getUlpDiffIgnoreZeroSign(out0, refOut0);
22052f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
22062f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const int		inExp		= tcu::Float32(in0).exponent();
22072f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
22082f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			if (ulpDiff > maxUlpDiff)
22092f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{
22102f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(refOut0) << ", (exp = " << inExp << ") with ULP threshold "
22112f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka						  << tcu::toHex(maxUlpDiff) << ", got ULP diff " << tcu::toHex(ulpDiff);
22122f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				return false;
22132f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			}
22142f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
22152f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
22162f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		return true;
22172f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
22182f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
22192f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
22202f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkaclass LdexpCase : public CommonFunctionCase
22212f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
22222f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkapublic:
22232f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	LdexpCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
22242f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		: CommonFunctionCase	(testCtx, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "ldexp", shaderType)
22252f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
22262f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int			vecSize		= glu::getDataTypeScalarSize(baseType);
22272f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::DataType	intType		= vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
22282f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
22292f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
22302f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.inputs.push_back(Symbol("in1", glu::VarType(intType, glu::PRECISION_HIGHP)));
22312f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, glu::PRECISION_HIGHP)));
22322f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.source = "out0 = ldexp(in0, in1);";
22332f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
22342f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
22352f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	TestInstance* createInstance (Context& ctx) const
22362f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
2237b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos		return new LdexpCaseInstance(ctx, m_shaderType, m_spec, m_numValues, getName());
22382f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
22392f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
22402f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
22412f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkaclass FmaCaseInstance : public CommonFunctionTestInstance
22422f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
22432f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkapublic:
2244b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos	FmaCaseInstance (Context& context, glu::ShaderType shaderType, const ShaderSpec& spec, int numValues, const char* name)
2245b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos		: CommonFunctionTestInstance	(context, shaderType, spec, numValues, name)
22462f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
22472f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
22482f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
22492f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	void getInputValues (int numValues, void* const* values) const
22502f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
22512f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const Vec2 ranges[] =
22522f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
22532f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			Vec2(-2.0f,		2.0f),	// lowp
22542f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			Vec2(-127.f,	127.f),	// mediump
22552f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			Vec2(-1e7f,		1e7f)	// highp
22562f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		};
22572f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
22582f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		de::Random				rnd							(deStringHash(m_name) ^ 0xac23fu);
22592f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::DataType		type						= m_spec.inputs[0].varType.getBasicType();
22602f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::Precision	precision					= m_spec.inputs[0].varType.getPrecision();
22612f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int				scalarSize					= glu::getDataTypeScalarSize(type);
22622f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const float				specialCases[][3]			=
22632f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
22642f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			// a		b		c
22652f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{ 0.0f,		0.0f,	0.0f },
22662f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{ 0.0f,		1.0f,	0.0f },
22672f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{ 0.0f,		0.0f,	-1.0f },
22682f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{ 1.0f,		1.0f,	0.0f },
22692f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{ 1.0f,		1.0f,	1.0f },
22702f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{ -1.0f,	1.0f,	0.0f },
22712f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{ 1.0f,		-1.0f,	0.0f },
22722f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{ -1.0f,	-1.0f,	0.0f },
22732f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{ -0.0f,	1.0f,	0.0f },
22742f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{ 1.0f,		-0.0f,	0.0f }
22752f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		};
22762f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int				numSpecialCases				= DE_LENGTH_OF_ARRAY(specialCases);
22772f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
22782f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		// Special cases
22792f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		for (int caseNdx = 0; caseNdx < numSpecialCases; caseNdx++)
22802f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
22812f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			for (int inputNdx = 0; inputNdx < 3; inputNdx++)
22822f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{
22832f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				for (int scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++)
22842f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					((float*)values[inputNdx])[caseNdx*scalarSize + scalarNdx] = specialCases[caseNdx][inputNdx];
22852f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			}
22862f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
22872f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
22882f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		// Random cases.
22892f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
22902f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const int	numScalars	= (numValues-numSpecialCases)*scalarSize;
22912f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const int	offs		= scalarSize*numSpecialCases;
22922f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
22932f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			for (int inputNdx = 0; inputNdx < 3; inputNdx++)
22942f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[inputNdx] + offs, numScalars);
22952f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
22962f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
22972f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		// Make sure the values are representable in the target format
22982f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		for (int inputNdx = 0; inputNdx < 3; inputNdx++)
22992f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
23002f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			for (int caseNdx = 0; caseNdx < numValues; ++caseNdx)
23012f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{
23022f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				for (int scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++)
23032f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				{
23042f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					float* const valuePtr = &((float*)values[inputNdx])[caseNdx * scalarSize + scalarNdx];
23052f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
23062f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					*valuePtr = makeFloatRepresentable(*valuePtr, precision);
23072f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				}
23082f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			}
23092f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
23102f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
23112f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
23122f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	static tcu::Interval fma (glu::Precision precision, float a, float b, float c)
23132f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
23142f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const tcu::FloatFormat formats[] =
23152f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
23162f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			//				 minExp		maxExp		mantissa	exact,		subnormals	infinities	NaN
23172f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			tcu::FloatFormat(0,			0,			7,			false,		tcu::YES,	tcu::MAYBE,	tcu::MAYBE),
23182f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			tcu::FloatFormat(-13,		13,			9,			false,		tcu::MAYBE,	tcu::MAYBE,	tcu::MAYBE),
23192f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			tcu::FloatFormat(-126,		127,		23,			true,		tcu::MAYBE, tcu::YES,	tcu::MAYBE)
23202f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		};
23212f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const tcu::FloatFormat&	format	= de::getSizedArrayElement<glu::PRECISION_LAST>(formats, precision);
23222f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const tcu::Interval		ia		= format.convert(a);
23232f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const tcu::Interval		ib		= format.convert(b);
23242f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const tcu::Interval		ic		= format.convert(c);
23252f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		tcu::Interval			prod0;
23262f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		tcu::Interval			prod1;
23272f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		tcu::Interval			prod2;
23282f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		tcu::Interval			prod3;
23292f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		tcu::Interval			prod;
23302f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		tcu::Interval			res;
23312f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
23322f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		TCU_SET_INTERVAL(prod0, tmp, tmp = ia.lo() * ib.lo());
23332f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		TCU_SET_INTERVAL(prod1, tmp, tmp = ia.lo() * ib.hi());
23342f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		TCU_SET_INTERVAL(prod2, tmp, tmp = ia.hi() * ib.lo());
23352f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		TCU_SET_INTERVAL(prod3, tmp, tmp = ia.hi() * ib.hi());
23362f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
23372f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		prod = format.convert(format.roundOut(prod0 | prod1 | prod2 | prod3, ia.isFinite() && ib.isFinite()));
23382f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
23392f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		TCU_SET_INTERVAL_BOUNDS(res, tmp,
23402f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka								tmp = prod.lo() + ic.lo(),
23412f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka								tmp = prod.hi() + ic.hi());
23422f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
23432f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		return format.convert(format.roundOut(res, prod.isFinite() && ic.isFinite()));
23442f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
23452f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
23462f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	bool compare (const void* const* inputs, const void* const* outputs)
23472f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
23482f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::DataType		type			= m_spec.inputs[0].varType.getBasicType();
23492f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const glu::Precision	precision		= m_spec.inputs[0].varType.getPrecision();
23502f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const int				scalarSize		= glu::getDataTypeScalarSize(type);
23512f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
23522f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		for (int compNdx = 0; compNdx < scalarSize; compNdx++)
23532f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
23542f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const float			a			= ((const float*)inputs[0])[compNdx];
23552f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const float			b			= ((const float*)inputs[1])[compNdx];
23562f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const float			c			= ((const float*)inputs[2])[compNdx];
23572f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const float			res			= ((const float*)outputs[0])[compNdx];
23582f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const tcu::Interval	ref			= fma(precision, a, b, c);
23592f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
23602f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			if (!ref.contains(res))
23612f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{
23622f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				m_failMsg << "Expected [" << compNdx << "] = " << ref;
23632f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				return false;
23642f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			}
23652f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
23662f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
23672f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		return true;
23682f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
23692f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
23702f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
23712f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkaclass FmaCase : public CommonFunctionCase
23722f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
23732f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkapublic:
23742f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	FmaCase (tcu::TestContext& testCtx, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
23752f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		: CommonFunctionCase	(testCtx, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "fma", shaderType)
23762f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
23772f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.inputs.push_back(Symbol("a", glu::VarType(baseType, precision)));
23782f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.inputs.push_back(Symbol("b", glu::VarType(baseType, precision)));
23792f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.inputs.push_back(Symbol("c", glu::VarType(baseType, precision)));
23802f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.outputs.push_back(Symbol("res", glu::VarType(baseType, precision)));
23812f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.source = "res = fma(a, b, c);";
23822f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		m_spec.globalDeclarations = "#extension GL_EXT_gpu_shader5 : require\n";
23832f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
23842f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
23852f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	TestInstance* createInstance (Context& ctx) const
23862f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
2387b95a9d798050499a8720ec4ada9a70a2093e24f0Pyry Haulos		return new FmaCaseInstance(ctx, m_shaderType, m_spec, m_numValues, getName());
23882f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
23892f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka};
23902f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
23912f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka} // anonymous
23922f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
23932f7ef42cc1930880dc119fd9659d673a2f15474eRobert SipkaShaderCommonFunctionTests::ShaderCommonFunctionTests (tcu::TestContext& testCtx)
23942f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	: tcu::TestCaseGroup	(testCtx, "common", "Common function tests")
23952f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
23962f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka}
23972f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
23982f7ef42cc1930880dc119fd9659d673a2f15474eRobert SipkaShaderCommonFunctionTests::~ShaderCommonFunctionTests (void)
23992f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
24002f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka}
24012f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
24022f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipkavoid ShaderCommonFunctionTests::init (void)
24032f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka{
24042f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	enum
24052f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
24062f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		VS = (1<<glu::SHADERTYPE_VERTEX),
24072f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		TC = (1<<glu::SHADERTYPE_TESSELLATION_CONTROL),
24082f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		TE = (1<<glu::SHADERTYPE_TESSELLATION_EVALUATION),
24092f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		GS = (1<<glu::SHADERTYPE_GEOMETRY),
24102f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		FS = (1<<glu::SHADERTYPE_FRAGMENT),
24112f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		CS = (1<<glu::SHADERTYPE_COMPUTE),
24122f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
24132f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		ALL_SHADERS = VS|TC|TE|GS|FS|CS,
24142f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		NEW_SHADERS = TC|TE|GS|CS,
24152f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	};
24162f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
24172f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	//																	Float?	Int?	Uint?	Shaders
24182f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	addFunctionCases<AbsCase>				(this,	"abs",				true,	true,	false,	ALL_SHADERS);
24192f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	addFunctionCases<SignCase>				(this,	"sign",				true,	true,	false,	ALL_SHADERS);
24202f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	addFunctionCases<FloorCase>				(this,	"floor",			true,	false,	false,	ALL_SHADERS);
24212f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	addFunctionCases<TruncCase>				(this,	"trunc",			true,	false,	false,	ALL_SHADERS);
24222f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	addFunctionCases<RoundCase>				(this,	"round",			true,	false,	false,	ALL_SHADERS);
24232f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	addFunctionCases<RoundEvenCase>			(this,	"roundeven",		true,	false,	false,	ALL_SHADERS);
24242f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	addFunctionCases<CeilCase>				(this,	"ceil",				true,	false,	false,	ALL_SHADERS);
24252f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	addFunctionCases<FractCase>				(this,	"fract",			true,	false,	false,	ALL_SHADERS);
24262f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	// mod
24272f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	addFunctionCases<ModfCase>				(this,	"modf",				true,	false,	false,	ALL_SHADERS);
24282f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	// min
24292f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	// max
24302f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	// clamp
24312f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	// mix
24322f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	// step
24332f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	// smoothstep
24342f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	addFunctionCases<IsnanCase>				(this,	"isnan",			true,	false,	false,	ALL_SHADERS);
24352f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	addFunctionCases<IsinfCase>				(this,	"isinf",			true,	false,	false,	ALL_SHADERS);
24362f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	addFunctionCases<FloatBitsToIntCase>	(this,	"floatbitstoint",	true,	false,	false,	ALL_SHADERS);
24372f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	addFunctionCases<FloatBitsToUintCase>	(this,	"floatbitstouint",	true,	false,	false,	ALL_SHADERS);
24382f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
24392f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	addFunctionCases<FrexpCase>				(this,	"frexp",			true,	false,	false,	ALL_SHADERS);
24402f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	addFunctionCases<LdexpCase>				(this,	"ldexp",			true,	false,	false,	ALL_SHADERS);
24412f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	addFunctionCases<FmaCase>				(this,	"fma",				true,	false,	false,	ALL_SHADERS);
24422f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
24432f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	// (u)intBitsToFloat()
24442f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	{
24452f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		const deUint32		shaderBits	= NEW_SHADERS;
24462f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		tcu::TestCaseGroup* intGroup	= new tcu::TestCaseGroup(m_testCtx, "intbitstofloat",	"intBitsToFloat() Tests");
24472f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		tcu::TestCaseGroup* uintGroup	= new tcu::TestCaseGroup(m_testCtx, "uintbitstofloat",	"uintBitsToFloat() Tests");
24482f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
24492f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		addChild(intGroup);
24502f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		addChild(uintGroup);
24512f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
24522f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		for (int vecSize = 1; vecSize < 4; vecSize++)
24532f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		{
24542f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const glu::DataType		intType		= vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
24552f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			const glu::DataType		uintType	= vecSize > 1 ? glu::getDataTypeUintVec(vecSize) : glu::TYPE_UINT;
24562f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
24572f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++)
24582f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			{
24592f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				if (shaderBits & (1<<shaderType))
24602f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				{
24612f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					intGroup->addChild(new BitsToFloatCase(getTestContext(), intType, glu::ShaderType(shaderType)));
24622f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka					uintGroup->addChild(new BitsToFloatCase(getTestContext(), uintType, glu::ShaderType(shaderType)));
24632f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka				}
24642f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka			}
24652f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka		}
24662f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka	}
24672f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka}
24682f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka
24692f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka} // shaderexecutor
24702f7ef42cc1930880dc119fd9659d673a2f15474eRobert Sipka} // vkt
2471