glsBuiltinPrecisionTests.cpp revision 9fd3acc3136860a7629ac9f1d70b602009d32d61
1dbb1735673ed177a85f04698b9cd89f2dc1b4e91Chris Lattner/*-------------------------------------------------------------------------
2fd93908ae8b9684fe71c239e3c6cfe13ff6a2663Misha Brukman * drawElements Quality Program OpenGL (ES) Module
3b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell * -----------------------------------------------
4b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell *
54ee451de366474b9c228b4e5fa573795a715216dChris Lattner * Copyright 2014 The Android Open Source Project
64ee451de366474b9c228b4e5fa573795a715216dChris Lattner *
7fd93908ae8b9684fe71c239e3c6cfe13ff6a2663Misha Brukman * Licensed under the Apache License, Version 2.0 (the "License");
8b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell * you may not use this file except in compliance with the License.
9dbb1735673ed177a85f04698b9cd89f2dc1b4e91Chris Lattner * You may obtain a copy of the License at
10dbb1735673ed177a85f04698b9cd89f2dc1b4e91Chris Lattner *
1155e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner *      http://www.apache.org/licenses/LICENSE-2.0
1255e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner *
13dbb1735673ed177a85f04698b9cd89f2dc1b4e91Chris Lattner * Unless required by applicable law or agreed to in writing, software
14dbb1735673ed177a85f04698b9cd89f2dc1b4e91Chris Lattner * distributed under the License is distributed on an "AS IS" BASIS,
15dbb1735673ed177a85f04698b9cd89f2dc1b4e91Chris Lattner * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1686453c52ba02e743d29c08456e51006500041456Chris Lattner * See the License for the specific language governing permissions and
17a2582da44dbe7204aac49cdaeccfd4e77ff7c408Duncan Sands * limitations under the License.
18568ddabc8f9015baf2d42cc425618412972f1b92Chris Lattner *
19dbb1735673ed177a85f04698b9cd89f2dc1b4e91Chris Lattner *//*!
20dbb1735673ed177a85f04698b9cd89f2dc1b4e91Chris Lattner * \file
21551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer * \brief Precision and range tests for GLSL builtins and types.
22551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer *
23ce63ffb52f249b62cdf2d250c128007b13f27e71Daniel Dunbar *//*--------------------------------------------------------------------*/
24551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer
25c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner#include "glsBuiltinPrecisionTests.hpp"
26c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner
271e2385b941242f2f96398dc62767420622856149Chris Lattner#include "deMath.h"
28d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke#include "deMemory.h"
2927a53009efcf1b0334dc17c3d54382798686ff59Duncan Sands#include "deDefs.hpp"
3086453c52ba02e743d29c08456e51006500041456Chris Lattner#include "deRandom.hpp"
3186453c52ba02e743d29c08456e51006500041456Chris Lattner#include "deSTLUtil.hpp"
3286453c52ba02e743d29c08456e51006500041456Chris Lattner#include "deStringUtil.hpp"
33844731a7f1909f55935e3514c9e713a62d67662eDan Gohman#include "deUniquePtr.hpp"
34844731a7f1909f55935e3514c9e713a62d67662eDan Gohman#include "deSharedPtr.hpp"
35844731a7f1909f55935e3514c9e713a62d67662eDan Gohman#include "deArrayUtil.hpp"
36844731a7f1909f55935e3514c9e713a62d67662eDan Gohman
37844731a7f1909f55935e3514c9e713a62d67662eDan Gohman#include "tcuCommandLine.hpp"
382345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner#include "tcuFloatFormat.hpp"
39844731a7f1909f55935e3514c9e713a62d67662eDan Gohman#include "tcuInterval.hpp"
40844731a7f1909f55935e3514c9e713a62d67662eDan Gohman#include "tcuTestCase.hpp"
41844731a7f1909f55935e3514c9e713a62d67662eDan Gohman#include "tcuTestLog.hpp"
42844731a7f1909f55935e3514c9e713a62d67662eDan Gohman#include "tcuVector.hpp"
43844731a7f1909f55935e3514c9e713a62d67662eDan Gohman#include "tcuMatrix.hpp"
44fd93908ae8b9684fe71c239e3c6cfe13ff6a2663Misha Brukman#include "tcuResultCollector.hpp"
45844731a7f1909f55935e3514c9e713a62d67662eDan Gohman
466726b6d75a8b679068a58cb954ba97cf9d1690baNick Lewycky#include "gluContextInfo.hpp"
47c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner#include "gluVarType.hpp"
48ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel#include "gluRenderContext.hpp"
49ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel#include "glwDefs.hpp"
50ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel
51c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner#include "glsShaderExecUtil.hpp"
52ecd94c804a563f2a86572dcf1d2e81f397e19daaNick Lewycky
534e78908b9453edf7d0907d4811c469a630aff560Matthijs Kooijman#include <cmath>
54c2bbfc18e9adbbdcf5b3375d8d25e2452f7df7f1Dan Gohman#include <string>
554eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner#include <sstream>
564eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner#include <iostream>
570483d018c4f15f206a83364e498957127e74f431Nuno Lopes#include <map>
580483d018c4f15f206a83364e498957127e74f431Nuno Lopes#include <utility>
590483d018c4f15f206a83364e498957127e74f431Nuno Lopes
60a2582da44dbe7204aac49cdaeccfd4e77ff7c408Duncan Sands// Uncomment this to get evaluation trace dumps to std::cerr
610483d018c4f15f206a83364e498957127e74f431Nuno Lopes// #define GLS_ENABLE_TRACE
624eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner
634eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner// set this to true to dump even passing results
6493fbd733e778c2623436ed5a0b9cf7f394407b1aChris Lattner#define GLS_LOG_ALL_RESULTS false
65844731a7f1909f55935e3514c9e713a62d67662eDan Gohman
66d13db2c59cc94162d6cf0a04187d408bfef6d4a7Owen Andersonnamespace deqp
67ce665bd2e2b581ab0858d1afe359192bac96b868Owen Anderson{
68844731a7f1909f55935e3514c9e713a62d67662eDan Gohmannamespace gls
69ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel{
7090c579de5a383cee278acc3f7e7b9d0a656e6a35Owen Andersonnamespace BuiltinPrecisionTests
71ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel{
724eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner
73ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patelusing std::string;
744eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattnerusing std::map;
754eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattnerusing std::ostream;
76c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattnerusing std::ostringstream;
772631ac3b5b4c2d7eaf8d1db178dc98071a708ad2Duncan Sandsusing std::pair;
7890c579de5a383cee278acc3f7e7b9d0a656e6a35Owen Andersonusing std::vector;
79753d94a1c8fe02f64eb4f482d396712c68db1d84Devang Patelusing std::set;
80bed2946a96ecb15b0b636fa74cb26ce61b1c648eAnton Korobeynikov
81753d94a1c8fe02f64eb4f482d396712c68db1d84Devang Patelusing de::MovePtr;
82753d94a1c8fe02f64eb4f482d396712c68db1d84Devang Patelusing de::Random;
83753d94a1c8fe02f64eb4f482d396712c68db1d84Devang Patelusing de::SharedPtr;
84753d94a1c8fe02f64eb4f482d396712c68db1d84Devang Patelusing de::UniquePtr;
854eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattnerusing tcu::Interval;
864eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattnerusing tcu::FloatFormat;
874eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattnerusing tcu::MessageBuilder;
884eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattnerusing tcu::TestCase;
894437ae213d5435390f0750213b53ec807c047f22Chris Lattnerusing tcu::TestLog;
90ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patelusing tcu::Vector;
91ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patelusing tcu::Matrix;
924eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattnernamespace matrix = tcu::matrix;
934eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattnerusing glu::Precision;
944eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattnerusing glu::RenderContext;
954eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattnerusing glu::VarType;
964eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattnerusing glu::DataType;
974eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattnerusing glu::ShaderType;
984eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattnerusing glu::ContextInfo;
994eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattnerusing gls::ShaderExecUtil::Symbol;
1004eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner
1014eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattnertypedef TestCase::IterateResult IterateResult;
1021465d61bdd36cfd6021036a527895f0dd358e97dDuncan Sands
103a2582da44dbe7204aac49cdaeccfd4e77ff7c408Duncan Sandsusing namespace glw;
104001dbfebcbbded8c8e74b19e838b50da2b6c6fb5Owen Andersonusing namespace tcu;
1054eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner
106ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel/*--------------------------------------------------------------------*//*!
107ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel * \brief Generic singleton creator.
1082631ac3b5b4c2d7eaf8d1db178dc98071a708ad2Duncan Sands *
109ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel * instance<T>() returns a reference to a unique default-constructed instance
110ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel * of T. This is mainly used for our GLSL function implementations: each
111ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel * function is implemented by an object, and each of the objects has a
112ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel * distinct class. It would be extremely toilsome to maintain a separate
113688b0490e22eb67623f5aaa24406209be74efcb2Reid Spencer * context object that contained individual instances of the function classes,
1145cbf985dcbc89fba3208e7baf8b6f488b06d3ec9Reid Spencer * so we have to resort to global singleton instances.
1154eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner *
1162631ac3b5b4c2d7eaf8d1db178dc98071a708ad2Duncan Sands *//*--------------------------------------------------------------------*/
1174eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattnertemplate <typename T>
1184eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattnerconst T& instance (void)
1194eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner{
1202631ac3b5b4c2d7eaf8d1db178dc98071a708ad2Duncan Sands	static const T s_instance = T();
1214eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner	return s_instance;
1222631ac3b5b4c2d7eaf8d1db178dc98071a708ad2Duncan Sands}
123ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel
124bb46f52027416598a662dc1c58f48d9d56b1a65bRafael Espindola/*--------------------------------------------------------------------*//*!
1254eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner * \brief Dummy placeholder type for unused template parameters.
1265cbf985dcbc89fba3208e7baf8b6f488b06d3ec9Reid Spencer *
127bb46f52027416598a662dc1c58f48d9d56b1a65bRafael Espindola * In the precision tests we are dealing with functions of different arities.
1284eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner * To minimize code duplication, we only define templates with the maximum
1294eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner * number of arguments, currently four. If a function's arity is less than the
130a2582da44dbe7204aac49cdaeccfd4e77ff7c408Duncan Sands * maximum, Void us used as the type for unused arguments.
131a2582da44dbe7204aac49cdaeccfd4e77ff7c408Duncan Sands *
1324eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner * Although Voids are not used at run-time, they still must be compilable, so
1334eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner * they must support all operations that other types do.
134fd2ab9ff4466cb2e07be536fc838d3520a0f8aa5David Greene *
1354eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner *//*--------------------------------------------------------------------*/
1362631ac3b5b4c2d7eaf8d1db178dc98071a708ad2Duncan Sandsstruct Void
1374eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner{
1384eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner	typedef	Void		Element;
139401e10c4fbfcdcfade5065093e2ca97f69a1d144Chris Lattner	enum
1404eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner	{
141401e10c4fbfcdcfade5065093e2ca97f69a1d144Chris Lattner		SIZE = 0,
1422631ac3b5b4c2d7eaf8d1db178dc98071a708ad2Duncan Sands	};
14344c3b9fdd416c79f4b67cde1aecfced5921efd81Jim Laskey
14444c3b9fdd416c79f4b67cde1aecfced5921efd81Jim Laskey	template <typename T>
145e8c3e3b51c21dad94f0b427d7e0d6722e663fc64Jim Laskey	explicit			Void			(const T&)		{}
146e8c3e3b51c21dad94f0b427d7e0d6722e663fc64Jim Laskey						Void			(void)			{}
147e8c3e3b51c21dad94f0b427d7e0d6722e663fc64Jim Laskey						operator double	(void)	const	{ return TCU_NAN; }
1484e2288b9de2fc30d4b88b437c86594cd8ec332faChris Lattner
1494e2288b9de2fc30d4b88b437c86594cd8ec332faChris Lattner	// These are used to make Voids usable as containers in container-generic code.
150bd14f58b765e994bf9a020575d517c5dc9bfbfe1Chris Lattner	Void&				operator[]		(int)			{ return *this; }
151088b5913ef6f91fccc3c931653e16bfeb330c90bTanya Lattner	const Void&			operator[]		(int)	const	{ return *this; }
1522631ac3b5b4c2d7eaf8d1db178dc98071a708ad2Duncan Sands};
153ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel
154ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patelostream& operator<< (ostream& os, Void) { return os << "()"; }
155bb46f52027416598a662dc1c58f48d9d56b1a65bRafael Espindola
1564eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner//! Returns true for all other types except Void
1574eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattnertemplate <typename T>	bool isTypeValid		(void)	{ return true;	}
158bb46f52027416598a662dc1c58f48d9d56b1a65bRafael Espindolatemplate <>				bool isTypeValid<Void>	(void)	{ return false;	}
1598e9c48a606acd5894407f73453448bb0911648c7Chris Lattner
1608e9c48a606acd5894407f73453448bb0911648c7Chris Lattner//! Utility function for getting the name of a data type.
1614eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner//! This is used in vector and matrix constructors.
1624eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattnertemplate <typename T>
1634eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattnerconst char* dataTypeNameOf (void)
1644eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner{
165fd2ab9ff4466cb2e07be536fc838d3520a0f8aa5David Greene	return glu::getDataTypeName(glu::dataTypeOf<T>());
16655e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner}
1672631ac3b5b4c2d7eaf8d1db178dc98071a708ad2Duncan Sands
16827a53009efcf1b0334dc17c3d54382798686ff59Duncan Sandstemplate <>
16927a53009efcf1b0334dc17c3d54382798686ff59Duncan Sandsconst char* dataTypeNameOf<Void> (void)
17027a53009efcf1b0334dc17c3d54382798686ff59Duncan Sands{
17127a53009efcf1b0334dc17c3d54382798686ff59Duncan Sands	DE_FATAL("Impossible");
1728e9c48a606acd5894407f73453448bb0911648c7Chris Lattner	return DE_NULL;
1738e9c48a606acd5894407f73453448bb0911648c7Chris Lattner}
17427a53009efcf1b0334dc17c3d54382798686ff59Duncan Sands
17527a53009efcf1b0334dc17c3d54382798686ff59Duncan Sands//! A hack to get Void support for VarType.
17627a53009efcf1b0334dc17c3d54382798686ff59Duncan Sandstemplate <typename T>
17727a53009efcf1b0334dc17c3d54382798686ff59Duncan SandsVarType getVarTypeOf (Precision prec = glu::PRECISION_LAST)
178fd2ab9ff4466cb2e07be536fc838d3520a0f8aa5David Greene{
17927a53009efcf1b0334dc17c3d54382798686ff59Duncan Sands	return glu::varTypeOf<T>(prec);
18027a53009efcf1b0334dc17c3d54382798686ff59Duncan Sands}
1814eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner
1824eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattnertemplate <>
183f629309f74cf1a64aa7fd1cd5784fd7db9a8f59eChris LattnerVarType getVarTypeOf<Void> (Precision)
1844e78908b9453edf7d0907d4811c469a630aff560Matthijs Kooijman{
1854e78908b9453edf7d0907d4811c469a630aff560Matthijs Kooijman	DE_FATAL("Impossible");
186dbb1735673ed177a85f04698b9cd89f2dc1b4e91Chris Lattner	return VarType();
187753d94a1c8fe02f64eb4f482d396712c68db1d84Devang Patel}
188d828a4b285339a2ae7d97428b64016628d9ef6dbDevang Patel
189d828a4b285339a2ae7d97428b64016628d9ef6dbDevang Patel/*--------------------------------------------------------------------*//*!
190753d94a1c8fe02f64eb4f482d396712c68db1d84Devang Patel * \brief Type traits for generalized interval types.
191 *
192 * We are trying to compute sets of acceptable values not only for
193 * float-valued expressions but also for compound values: vectors and
194 * matrices. We approximate a set of vectors as a vector of intervals and
195 * likewise for matrices.
196 *
197 * We now need generalized operations for each type and its interval
198 * approximation. These are given in the type Traits<T>.
199 *
200 * The type Traits<T>::IVal is the approximation of T: it is `Interval` for
201 * scalar types, and a vector or matrix of intervals for container types.
202 *
203 * To allow template inference to take place, there are function wrappers for
204 * the actual operations in Traits<T>. Hence we can just use:
205 *
206 * makeIVal(someFloat)
207 *
208 * instead of:
209 *
210 * Traits<float>::doMakeIVal(value)
211 *
212 *//*--------------------------------------------------------------------*/
213
214template <typename T> struct Traits;
215
216//! Create container from elementwise singleton values.
217template <typename T>
218typename Traits<T>::IVal makeIVal (const T& value)
219{
220	return Traits<T>::doMakeIVal(value);
221}
222
223//! Elementwise union of intervals.
224template <typename T>
225typename Traits<T>::IVal unionIVal (const typename Traits<T>::IVal& a,
226									const typename Traits<T>::IVal& b)
227{
228	return Traits<T>::doUnion(a, b);
229}
230
231//! Returns true iff every element of `ival` contains the corresponding element of `value`.
232template <typename T>
233bool contains (const typename Traits<T>::IVal& ival, const T& value)
234{
235	return Traits<T>::doContains(ival, value);
236}
237
238//! Print out an interval with the precision of `fmt`.
239template <typename T>
240void printIVal (const FloatFormat& fmt, const typename Traits<T>::IVal& ival, ostream& os)
241{
242	Traits<T>::doPrintIVal(fmt, ival, os);
243}
244
245template <typename T>
246string intervalToString (const FloatFormat& fmt, const typename Traits<T>::IVal& ival)
247{
248	ostringstream oss;
249	printIVal<T>(fmt, ival, oss);
250	return oss.str();
251}
252
253//! Print out a value with the precision of `fmt`.
254template <typename T>
255void printValue (const FloatFormat& fmt, const T& value, ostream& os)
256{
257	Traits<T>::doPrintValue(fmt, value, os);
258}
259
260template <typename T>
261string valueToString (const FloatFormat& fmt, const T& val)
262{
263	ostringstream oss;
264	printValue(fmt, val, oss);
265	return oss.str();
266}
267
268//! Approximate `value` elementwise to the float precision defined in `fmt`.
269//! The resulting interval might not be a singleton if rounding in both
270//! directions is allowed.
271template <typename T>
272typename Traits<T>::IVal round (const FloatFormat& fmt, const T& value)
273{
274	return Traits<T>::doRound(fmt, value);
275}
276
277template <typename T>
278typename Traits<T>::IVal convert (const FloatFormat&				fmt,
279								  const typename Traits<T>::IVal&	value)
280{
281	return Traits<T>::doConvert(fmt, value);
282}
283
284//! Common traits for scalar types.
285template <typename T>
286struct ScalarTraits
287{
288	typedef 			Interval		IVal;
289
290	static Interval		doMakeIVal		(const T& value)
291	{
292		// Thankfully all scalar types have a well-defined conversion to `double`,
293		// hence Interval can represent their ranges without problems.
294		return Interval(double(value));
295	}
296
297	static Interval		doUnion			(const Interval& a, const Interval& b)
298	{
299		return a | b;
300	}
301
302	static bool			doContains		(const Interval& a, T value)
303	{
304		return a.contains(double(value));
305	}
306
307	static Interval		doConvert		(const FloatFormat& fmt, const IVal& ival)
308	{
309		return fmt.convert(ival);
310	}
311
312	static Interval		doRound			(const FloatFormat& fmt, T value)
313	{
314		return fmt.roundOut(double(value), false);
315	}
316};
317
318template<>
319struct Traits<float> : ScalarTraits<float>
320{
321	static void			doPrintIVal		(const FloatFormat&	fmt,
322										 const Interval&	ival,
323										 ostream&			os)
324	{
325		os << fmt.intervalToHex(ival);
326	}
327
328	static void			doPrintValue	(const FloatFormat&	fmt,
329										 const float&		value,
330										 ostream&			os)
331	{
332		os << fmt.floatToHex(value);
333	}
334};
335
336template<>
337struct Traits<bool> : ScalarTraits<bool>
338{
339	static void			doPrintValue	(const FloatFormat&,
340										 const float&		value,
341										 ostream&			os)
342	{
343		os << (value != 0.0f ? "true" : "false");
344	}
345
346	static void			doPrintIVal		(const FloatFormat&,
347										 const Interval&	ival,
348										 ostream&			os)
349	{
350		os << "{";
351		if (ival.contains(false))
352			os << "false";
353		if (ival.contains(false) && ival.contains(true))
354			os << ", ";
355		if (ival.contains(true))
356			os << "true";
357		os << "}";
358	}
359};
360
361template<>
362struct Traits<int> : ScalarTraits<int>
363{
364	static void			doPrintValue 	(const FloatFormat&,
365										 const int&			value,
366										 ostream&			os)
367	{
368		os << value;
369	}
370
371	static void			doPrintIVal		(const FloatFormat&,
372										 const Interval&	ival,
373										 ostream&			os)
374	{
375		os << "[" << int(ival.lo()) << ", " << int(ival.hi()) << "]";
376	}
377};
378
379//! Common traits for containers, i.e. vectors and matrices.
380//! T is the container type itself, I is the same type with interval elements.
381template <typename T, typename I>
382struct ContainerTraits
383{
384	typedef typename	T::Element		Element;
385	typedef				I				IVal;
386
387	static IVal			doMakeIVal		(const T& value)
388	{
389		IVal ret;
390
391		for (int ndx = 0; ndx < T::SIZE; ++ndx)
392			ret[ndx] = makeIVal(value[ndx]);
393
394		return ret;
395	}
396
397	static IVal			doUnion			(const IVal& a, const IVal& b)
398	{
399		IVal ret;
400
401		for (int ndx = 0; ndx < T::SIZE; ++ndx)
402			ret[ndx] = unionIVal<Element>(a[ndx], b[ndx]);
403
404		return ret;
405	}
406
407	static bool			doContains		(const IVal& ival, const T& value)
408	{
409		for (int ndx = 0; ndx < T::SIZE; ++ndx)
410			if (!contains(ival[ndx], value[ndx]))
411				return false;
412
413		return true;
414	}
415
416	static void			doPrintIVal		(const FloatFormat& fmt, const IVal ival, ostream& os)
417	{
418		os << "(";
419
420		for (int ndx = 0; ndx < T::SIZE; ++ndx)
421		{
422			if (ndx > 0)
423				os << ", ";
424
425			printIVal<Element>(fmt, ival[ndx], os);
426		}
427
428		os << ")";
429	}
430
431	static void			doPrintValue	(const FloatFormat& fmt, const T& value, ostream& os)
432	{
433		os << dataTypeNameOf<T>() << "(";
434
435		for (int ndx = 0; ndx < T::SIZE; ++ndx)
436		{
437			if (ndx > 0)
438				os << ", ";
439
440			printValue<Element>(fmt, value[ndx], os);
441		}
442
443		os << ")";
444	}
445
446	static IVal			doConvert		(const FloatFormat& fmt, const IVal& value)
447	{
448		IVal ret;
449
450		for (int ndx = 0; ndx < T::SIZE; ++ndx)
451			ret[ndx] = convert<Element>(fmt, value[ndx]);
452
453		return ret;
454	}
455
456	static IVal			doRound			(const FloatFormat& fmt, T value)
457	{
458		IVal ret;
459
460		for (int ndx = 0; ndx < T::SIZE; ++ndx)
461			ret[ndx] = round(fmt, value[ndx]);
462
463		return ret;
464	}
465};
466
467template <typename T, int Size>
468struct Traits<Vector<T, Size> > :
469	ContainerTraits<Vector<T, Size>, Vector<typename Traits<T>::IVal, Size> >
470{
471};
472
473template <typename T, int Rows, int Cols>
474struct Traits<Matrix<T, Rows, Cols> > :
475	ContainerTraits<Matrix<T, Rows, Cols>, Matrix<typename Traits<T>::IVal, Rows, Cols> >
476{
477};
478
479//! Void traits. These are just dummies, but technically valid: a Void is a
480//! unit type with a single possible value.
481template<>
482struct Traits<Void>
483{
484	typedef		Void			IVal;
485
486	static Void	doMakeIVal		(const Void& value) 					{ return value; }
487	static Void	doUnion			(const Void&, const Void&)				{ return Void(); }
488	static bool	doContains		(const Void&, Void) 					{ return true; }
489	static Void	doRound			(const FloatFormat&, const Void& value)	{ return value; }
490	static Void	doConvert		(const FloatFormat&, const Void& value)	{ return value; }
491
492	static void	doPrintValue 	(const FloatFormat&, const Void&, ostream& os)
493	{
494		os << "()";
495	}
496
497	static void	doPrintIVal		(const FloatFormat&, const Void&, ostream& os)
498	{
499		os << "()";
500	}
501};
502
503//! This is needed for container-generic operations.
504//! We want a scalar type T to be its own "one-element vector".
505template <typename T, int Size> struct ContainerOf	{ typedef Vector<T, Size>	Container; };
506
507template <typename T>			struct ContainerOf<T, 1>		{ typedef T		Container; };
508template <int Size> 			struct ContainerOf<Void, Size>	{ typedef Void	Container; };
509
510// This is a kludge that is only needed to get the ExprP::operator[] syntactic sugar to work.
511template <typename T>	struct ElementOf		{ typedef	typename T::Element	Element; };
512template <>				struct ElementOf<float>	{ typedef	void				Element; };
513template <>				struct ElementOf<bool>	{ typedef	void				Element; };
514template <>				struct ElementOf<int>	{ typedef	void				Element; };
515
516/*--------------------------------------------------------------------*//*!
517 *
518 * \name Abstract syntax for expressions and statements.
519 *
520 * We represent GLSL programs as syntax objects: an Expr<T> represents an
521 * expression whose GLSL type corresponds to the C++ type T, and a Statement
522 * represents a statement.
523 *
524 * To ease memory management, we use shared pointers to refer to expressions
525 * and statements. ExprP<T> is a shared pointer to an Expr<T>, and StatementP
526 * is a shared pointer to a Statement.
527 *
528 * \{
529 *
530 *//*--------------------------------------------------------------------*/
531
532class ExprBase;
533class ExpandContext;
534class Statement;
535class StatementP;
536class FuncBase;
537template <typename T> class ExprP;
538template <typename T> class Variable;
539template <typename T> class VariableP;
540template <typename T> class DefaultSampling;
541
542typedef set<const FuncBase*> FuncSet;
543
544template <typename T>
545VariableP<T>	variable			(const string& name);
546StatementP		compoundStatement	(const vector<StatementP>& statements);
547
548/*--------------------------------------------------------------------*//*!
549 * \brief A variable environment.
550 *
551 * An Environment object maintains the mapping between variables of the
552 * abstract syntax tree and their values.
553 *
554 * \todo [2014-03-28 lauri] At least run-time type safety.
555 *
556 *//*--------------------------------------------------------------------*/
557class Environment
558{
559public:
560	template<typename T>
561	void						bind	(const Variable<T>&					variable,
562										 const typename Traits<T>::IVal&	value)
563	{
564		deUint8* const data = new deUint8[sizeof(value)];
565
566		deMemcpy(data, &value, sizeof(value));
567		de::insert(m_map, variable.getName(), SharedPtr<deUint8>(data, de::ArrayDeleter<deUint8>()));
568	}
569
570	template<typename T>
571	typename Traits<T>::IVal&	lookup	(const Variable<T>& variable) const
572	{
573		deUint8* const data = de::lookup(m_map, variable.getName()).get();
574
575		return *reinterpret_cast<typename Traits<T>::IVal*>(data);
576	}
577
578private:
579	map<string, SharedPtr<deUint8> >	m_map;
580};
581
582/*--------------------------------------------------------------------*//*!
583 * \brief Evaluation context.
584 *
585 * The evaluation context contains everything that separates one execution of
586 * an expression from the next. Currently this means the desired floating
587 * point precision and the current variable environment.
588 *
589 *//*--------------------------------------------------------------------*/
590struct EvalContext
591{
592	EvalContext (const FloatFormat&	format_,
593				 Precision			floatPrecision_,
594				 Environment&		env_,
595				 int				callDepth_ = 0)
596		: format			(format_)
597		, floatPrecision	(floatPrecision_)
598		, env				(env_)
599		, callDepth			(callDepth_) {}
600
601	FloatFormat		format;
602	Precision		floatPrecision;
603	Environment&	env;
604	int				callDepth;
605};
606
607/*--------------------------------------------------------------------*//*!
608 * \brief Simple incremental counter.
609 *
610 * This is used to make sure that different ExpandContexts will not produce
611 * overlapping temporary names.
612 *
613 *//*--------------------------------------------------------------------*/
614class Counter
615{
616public:
617			Counter		(int count = 0) : m_count(count) {}
618	int		operator()	(void) { return m_count++; }
619
620private:
621	int		m_count;
622};
623
624class ExpandContext
625{
626public:
627						ExpandContext	(Counter& symCounter) : m_symCounter(symCounter) {}
628						ExpandContext	(const ExpandContext& parent)
629							: m_symCounter(parent.m_symCounter) {}
630
631	template<typename T>
632	VariableP<T>		genSym			(const string& baseName)
633	{
634		return variable<T>(baseName + de::toString(m_symCounter()));
635	}
636
637	void				addStatement	(const StatementP& stmt)
638	{
639		m_statements.push_back(stmt);
640	}
641
642	vector<StatementP>	getStatements	(void) const
643	{
644		return m_statements;
645	}
646private:
647	Counter&			m_symCounter;
648	vector<StatementP>	m_statements;
649};
650
651/*--------------------------------------------------------------------*//*!
652 * \brief A statement or declaration.
653 *
654 * Statements have no values. Instead, they are executed for their side
655 * effects only: the execute() method should modify at least one variable in
656 * the environment.
657 *
658 * As a bit of a kludge, a Statement object can also represent a declaration:
659 * when it is evaluated, it can add a variable binding to the environment
660 * instead of modifying a current one.
661 *
662 *//*--------------------------------------------------------------------*/
663class Statement
664{
665public:
666	virtual	~Statement		(void) 							{								 }
667	//! Execute the statement, modifying the environment of `ctx`
668	void	execute			(EvalContext&	ctx)	const	{ this->doExecute(ctx);			 }
669	void	print			(ostream&		os)		const	{ this->doPrint(os);			 }
670	//! Add the functions used in this statement to `dst`.
671	void	getUsedFuncs	(FuncSet& dst)			const	{ this->doGetUsedFuncs(dst);	 }
672
673protected:
674	virtual void	doPrint			(ostream& os)			const	= 0;
675	virtual void	doExecute		(EvalContext& ctx)		const	= 0;
676	virtual void	doGetUsedFuncs	(FuncSet& dst)			const	= 0;
677};
678
679ostream& operator<<(ostream& os, const Statement& stmt)
680{
681	stmt.print(os);
682	return os;
683}
684
685/*--------------------------------------------------------------------*//*!
686 * \brief Smart pointer for statements (and declarations)
687 *
688 *//*--------------------------------------------------------------------*/
689class StatementP : public SharedPtr<const Statement>
690{
691public:
692	typedef		SharedPtr<const Statement>	Super;
693
694				StatementP			(void) {}
695	explicit	StatementP			(const Statement* ptr)	: Super(ptr) {}
696				StatementP			(const Super& ptr)		: Super(ptr) {}
697};
698
699/*--------------------------------------------------------------------*//*!
700 * \brief
701 *
702 * A statement that modifies a variable or a declaration that binds a variable.
703 *
704 *//*--------------------------------------------------------------------*/
705template <typename T>
706class VariableStatement : public Statement
707{
708public:
709					VariableStatement	(const VariableP<T>& variable, const ExprP<T>& value,
710										 bool isDeclaration)
711						: m_variable		(variable)
712						, m_value			(value)
713						, m_isDeclaration	(isDeclaration) {}
714
715protected:
716	void			doPrint				(ostream& os)							const
717	{
718		if (m_isDeclaration)
719			os << glu::declare(getVarTypeOf<T>(), m_variable->getName());
720		else
721			os << m_variable->getName();
722
723		os << " = " << *m_value << ";\n";
724	}
725
726	void			doExecute			(EvalContext& ctx)						const
727	{
728		if (m_isDeclaration)
729			ctx.env.bind(*m_variable, m_value->evaluate(ctx));
730		else
731			ctx.env.lookup(*m_variable) = m_value->evaluate(ctx);
732	}
733
734	void			doGetUsedFuncs		(FuncSet& dst)							const
735	{
736		m_value->getUsedFuncs(dst);
737	}
738
739	VariableP<T>	m_variable;
740	ExprP<T>		m_value;
741	bool			m_isDeclaration;
742};
743
744template <typename T>
745StatementP variableStatement (const VariableP<T>&	variable,
746							  const ExprP<T>&		value,
747							  bool					isDeclaration)
748{
749	return StatementP(new VariableStatement<T>(variable, value, isDeclaration));
750}
751
752template <typename T>
753StatementP variableDeclaration (const VariableP<T>& variable, const ExprP<T>& definiens)
754{
755	return variableStatement(variable, definiens, true);
756}
757
758template <typename T>
759StatementP variableAssignment (const VariableP<T>& variable, const ExprP<T>& value)
760{
761	return variableStatement(variable, value, false);
762}
763
764/*--------------------------------------------------------------------*//*!
765 * \brief A compound statement, i.e. a block.
766 *
767 * A compound statement is executed by executing its constituent statements in
768 * sequence.
769 *
770 *//*--------------------------------------------------------------------*/
771class CompoundStatement : public Statement
772{
773public:
774						CompoundStatement	(const vector<StatementP>& statements)
775							: m_statements	(statements) {}
776
777protected:
778	void				doPrint				(ostream&		os)						const
779	{
780		os << "{\n";
781
782		for (size_t ndx = 0; ndx < m_statements.size(); ++ndx)
783			os << *m_statements[ndx];
784
785		os << "}\n";
786	}
787
788	void				doExecute			(EvalContext&	ctx)					const
789	{
790		for (size_t ndx = 0; ndx < m_statements.size(); ++ndx)
791			m_statements[ndx]->execute(ctx);
792	}
793
794	void				doGetUsedFuncs		(FuncSet& dst)							const
795	{
796		for (size_t ndx = 0; ndx < m_statements.size(); ++ndx)
797			m_statements[ndx]->getUsedFuncs(dst);
798	}
799
800	vector<StatementP>	m_statements;
801};
802
803StatementP compoundStatement(const vector<StatementP>& statements)
804{
805	return StatementP(new CompoundStatement(statements));
806}
807
808//! Common base class for all expressions regardless of their type.
809class ExprBase
810{
811public:
812	virtual				~ExprBase		(void)									{}
813	void				printExpr		(ostream& os) const { this->doPrintExpr(os); }
814
815	//! Output the functions that this expression refers to
816	void				getUsedFuncs	(FuncSet& dst) const
817	{
818		this->doGetUsedFuncs(dst);
819	}
820
821protected:
822	virtual void		doPrintExpr		(ostream&)	const	{}
823	virtual void		doGetUsedFuncs	(FuncSet&)	const	{}
824};
825
826//! Type-specific operations for an expression representing type T.
827template <typename T>
828class Expr : public ExprBase
829{
830public:
831	typedef 			T				Val;
832	typedef typename 	Traits<T>::IVal	IVal;
833
834	IVal				evaluate		(const EvalContext&	ctx) const;
835
836protected:
837	virtual IVal		doEvaluate		(const EvalContext&	ctx) const = 0;
838};
839
840//! Evaluate an expression with the given context, optionally tracing the calls to stderr.
841template <typename T>
842typename Traits<T>::IVal Expr<T>::evaluate (const EvalContext& ctx) const
843{
844#ifdef GLS_ENABLE_TRACE
845	static const FloatFormat	highpFmt	(-126, 127, 23, true,
846											 tcu::MAYBE,
847											 tcu::YES,
848											 tcu::MAYBE);
849	EvalContext					newCtx		(ctx.format, ctx.floatPrecision,
850											 ctx.env, ctx.callDepth + 1);
851	const IVal					ret			= this->doEvaluate(newCtx);
852
853	if (isTypeValid<T>())
854	{
855		std::cerr << string(ctx.callDepth, ' ');
856		this->printExpr(std::cerr);
857		std::cerr << " -> " << intervalToString<T>(highpFmt, ret) << std::endl;
858	}
859	return ret;
860#else
861	return this->doEvaluate(ctx);
862#endif
863}
864
865template <typename T>
866class ExprPBase : public SharedPtr<const Expr<T> >
867{
868public:
869};
870
871ostream& operator<< (ostream& os, const ExprBase& expr)
872{
873	expr.printExpr(os);
874	return os;
875}
876
877/*--------------------------------------------------------------------*//*!
878 * \brief Shared pointer to an expression of a container type.
879 *
880 * Container types (i.e. vectors and matrices) support the subscription
881 * operator. This class provides a bit of syntactic sugar to allow us to use
882 * the C++ subscription operator to create a subscription expression.
883 *//*--------------------------------------------------------------------*/
884template <typename T>
885class ContainerExprPBase : public ExprPBase<T>
886{
887public:
888	ExprP<typename T::Element>	operator[]	(int i) const;
889};
890
891template <typename T>
892class ExprP : public ExprPBase<T> {};
893
894// We treat Voids as containers since the dummy parameters in generalized
895// vector functions are represented as Voids.
896template <>
897class ExprP<Void> : public ContainerExprPBase<Void> {};
898
899template <typename T, int Size>
900class ExprP<Vector<T, Size> > : public ContainerExprPBase<Vector<T, Size> > {};
901
902template <typename T, int Rows, int Cols>
903class ExprP<Matrix<T, Rows, Cols> > : public ContainerExprPBase<Matrix<T, Rows, Cols> > {};
904
905template <typename T> ExprP<T> exprP (void)
906{
907	return ExprP<T>();
908}
909
910template <typename T>
911ExprP<T> exprP (const SharedPtr<const Expr<T> >& ptr)
912{
913	ExprP<T> ret;
914	static_cast<SharedPtr<const Expr<T> >&>(ret) = ptr;
915	return ret;
916}
917
918template <typename T>
919ExprP<T> exprP (const Expr<T>* ptr)
920{
921	return exprP(SharedPtr<const Expr<T> >(ptr));
922}
923
924/*--------------------------------------------------------------------*//*!
925 * \brief A shared pointer to a variable expression.
926 *
927 * This is just a narrowing of ExprP for the operations that require a variable
928 * instead of an arbitrary expression.
929 *
930 *//*--------------------------------------------------------------------*/
931template <typename T>
932class VariableP : public SharedPtr<const Variable<T> >
933{
934public:
935	typedef		SharedPtr<const Variable<T> >	Super;
936	explicit	VariableP	(const Variable<T>* ptr) : Super(ptr) {}
937				VariableP	(void) {}
938				VariableP	(const Super& ptr) : Super(ptr) {}
939
940	operator	ExprP<T>	(void) const { return exprP(SharedPtr<const Expr<T> >(*this)); }
941};
942
943/*--------------------------------------------------------------------*//*!
944 * \name Syntactic sugar operators for expressions.
945 *
946 * @{
947 *
948 * These operators allow the use of C++ syntax to construct GLSL expressions
949 * containing operators: e.g. "a+b" creates an addition expression with
950 * operands a and b, and so on.
951 *
952 *//*--------------------------------------------------------------------*/
953ExprP<float>						operator-(const ExprP<float>&						arg0);
954ExprP<float>						operator+(const ExprP<float>&						arg0,
955											  const ExprP<float>&						arg1);
956ExprP<float>						operator-(const ExprP<float>&						arg0,
957											  const ExprP<float>&						arg1);
958ExprP<float> 						operator*(const ExprP<float>&						arg0,
959											  const ExprP<float>&						arg1);
960ExprP<float> 						operator/(const ExprP<float>&						arg0,
961											  const ExprP<float>&						arg1);
962template<int Size>
963ExprP<Vector<float, Size> >			operator-(const ExprP<Vector<float, Size> >&		arg0);
964template<int Size>
965ExprP<Vector<float, Size> >			operator*(const ExprP<Vector<float, Size> >&		arg0,
966											  const ExprP<float>&						arg1);
967template<int Size>
968ExprP<Vector<float, Size> >			operator*(const ExprP<Vector<float, Size> >&		arg0,
969											  const ExprP<Vector<float, Size> >&		arg1);
970template<int Size>
971ExprP<Vector<float, Size> >			operator-(const ExprP<Vector<float, Size> >&		arg0,
972											  const ExprP<Vector<float, Size> >&		arg1);
973template<int Left, int Mid, int Right>
974ExprP<Matrix<float, Left, Right> >	operator* (const ExprP<Matrix<float, Left, Mid> >&	left,
975											   const ExprP<Matrix<float, Mid, Right> >&	right);
976template<int Rows, int Cols>
977ExprP<Vector<float, Rows> >			operator* (const ExprP<Vector<float, Cols> >&		left,
978											   const ExprP<Matrix<float, Rows, Cols> >&	right);
979template<int Rows, int Cols>
980ExprP<Vector<float, Cols> >			operator* (const ExprP<Matrix<float, Rows, Cols> >&	left,
981											   const ExprP<Vector<float, Rows> >&		right);
982template<int Rows, int Cols>
983ExprP<Matrix<float, Rows, Cols> >	operator* (const ExprP<Matrix<float, Rows, Cols> >&	left,
984											   const ExprP<float>&						right);
985template<int Rows, int Cols>
986ExprP<Matrix<float, Rows, Cols> > 	operator+ (const ExprP<Matrix<float, Rows, Cols> >&	left,
987											   const ExprP<Matrix<float, Rows, Cols> >&	right);
988template<int Rows, int Cols>
989ExprP<Matrix<float, Rows, Cols> > 	operator- (const ExprP<Matrix<float, Rows, Cols> >&	mat);
990
991//! @}
992
993/*--------------------------------------------------------------------*//*!
994 * \brief Variable expression.
995 *
996 * A variable is evaluated by looking up its range of possible values from an
997 * environment.
998 *//*--------------------------------------------------------------------*/
999template <typename T>
1000class Variable : public Expr<T>
1001{
1002public:
1003	typedef typename Expr<T>::IVal IVal;
1004
1005					Variable	(const string& name) : m_name (name) {}
1006	string			getName		(void)							const { return m_name; }
1007
1008protected:
1009	void			doPrintExpr	(ostream& os)					const { os << m_name; }
1010	IVal			doEvaluate	(const EvalContext& ctx)		const
1011	{
1012		return ctx.env.lookup<T>(*this);
1013	}
1014
1015private:
1016	string	m_name;
1017};
1018
1019template <typename T>
1020VariableP<T> variable (const string& name)
1021{
1022	return VariableP<T>(new Variable<T>(name));
1023}
1024
1025template <typename T>
1026VariableP<T> bindExpression (const string& name, ExpandContext& ctx, const ExprP<T>& expr)
1027{
1028	VariableP<T> var = ctx.genSym<T>(name);
1029	ctx.addStatement(variableDeclaration(var, expr));
1030	return var;
1031}
1032
1033/*--------------------------------------------------------------------*//*!
1034 * \brief Constant expression.
1035 *
1036 * A constant is evaluated by rounding it to a set of possible values allowed
1037 * by the current floating point precision.
1038 *//*--------------------------------------------------------------------*/
1039template <typename T>
1040class Constant : public Expr<T>
1041{
1042public:
1043	typedef typename Expr<T>::IVal IVal;
1044
1045			Constant		(const T& value) : m_value(value) {}
1046
1047protected:
1048	void	doPrintExpr		(ostream& os) const 		{ os << m_value; }
1049	IVal	doEvaluate		(const EvalContext&) const	{ return makeIVal(m_value); }
1050
1051private:
1052	T		m_value;
1053};
1054
1055template <typename T>
1056ExprP<T> constant (const T& value)
1057{
1058	return exprP(new Constant<T>(value));
1059}
1060
1061//! Return a reference to a singleton void constant.
1062const ExprP<Void>& voidP (void)
1063{
1064	static const ExprP<Void> singleton = constant(Void());
1065
1066	return singleton;
1067}
1068
1069/*--------------------------------------------------------------------*//*!
1070 * \brief Four-element tuple.
1071 *
1072 * This is used for various things where we need one thing for each possible
1073 * function parameter. Currently the maximum supported number of parameters is
1074 * four.
1075 *//*--------------------------------------------------------------------*/
1076template <typename T0 = Void, typename T1 = Void, typename T2 = Void, typename T3 = Void>
1077struct Tuple4
1078{
1079	explicit Tuple4 (const T0& e0 = T0(),
1080					 const T1& e1 = T1(),
1081					 const T2& e2 = T2(),
1082					 const T3& e3 = T3())
1083		: a	(e0)
1084		, b	(e1)
1085		, c	(e2)
1086		, d	(e3)
1087	{
1088	}
1089
1090	T0 a;
1091	T1 b;
1092	T2 c;
1093	T3 d;
1094};
1095
1096/*--------------------------------------------------------------------*//*!
1097 * \brief Function signature.
1098 *
1099 * This is a purely compile-time structure used to bundle all types in a
1100 * function signature together. This makes passing the signature around in
1101 * templates easier, since we only need to take and pass a single Sig instead
1102 * of a bunch of parameter types and a return type.
1103 *
1104 *//*--------------------------------------------------------------------*/
1105template <typename R,
1106		  typename P0 = Void, typename P1 = Void,
1107		  typename P2 = Void, typename P3 = Void>
1108struct Signature
1109{
1110	typedef R							Ret;
1111	typedef P0							Arg0;
1112	typedef P1							Arg1;
1113	typedef P2							Arg2;
1114	typedef P3							Arg3;
1115	typedef typename Traits<Ret>::IVal	IRet;
1116	typedef typename Traits<Arg0>::IVal	IArg0;
1117	typedef typename Traits<Arg1>::IVal	IArg1;
1118	typedef typename Traits<Arg2>::IVal	IArg2;
1119	typedef typename Traits<Arg3>::IVal	IArg3;
1120
1121	typedef Tuple4<	const Arg0&,	const Arg1&,	const Arg2&,	const Arg3&>	Args;
1122	typedef Tuple4<	const IArg0&,	const IArg1&,	const IArg2&,	const IArg3&> 	IArgs;
1123	typedef Tuple4<	ExprP<Arg0>,	ExprP<Arg1>,	ExprP<Arg2>,	ExprP<Arg3> >	ArgExprs;
1124};
1125
1126typedef vector<const ExprBase*> BaseArgExprs;
1127
1128/*--------------------------------------------------------------------*//*!
1129 * \brief Type-independent operations for function objects.
1130 *
1131 *//*--------------------------------------------------------------------*/
1132class FuncBase
1133{
1134public:
1135	virtual			~FuncBase				(void)					{}
1136	virtual string	getName					(void) 					const = 0;
1137	//! Name of extension that this function requires, or empty.
1138	virtual string	getRequiredExtension	(void) 					const { return ""; }
1139	virtual void	print					(ostream&,
1140											 const BaseArgExprs&)	const = 0;
1141	//! Index of output parameter, or -1 if none of the parameters is output.
1142	virtual int		getOutParamIndex		(void)					const { return -1; }
1143
1144	void			printDefinition			(ostream& os)			const
1145	{
1146		doPrintDefinition(os);
1147	}
1148
1149	void				getUsedFuncs		(FuncSet& dst) const
1150	{
1151		this->doGetUsedFuncs(dst);
1152	}
1153
1154protected:
1155	virtual void	doPrintDefinition		(ostream& os)			const = 0;
1156	virtual void	doGetUsedFuncs			(FuncSet& dst)			const = 0;
1157};
1158
1159typedef Tuple4<string, string, string, string> ParamNames;
1160
1161/*--------------------------------------------------------------------*//*!
1162 * \brief Function objects.
1163 *
1164 * Each Func object represents a GLSL function. It can be applied to interval
1165 * arguments, and it returns the an interval that is a conservative
1166 * approximation of the image of the GLSL function over the argument
1167 * intervals. That is, it is given a set of possible arguments and it returns
1168 * the set of possible values.
1169 *
1170 *//*--------------------------------------------------------------------*/
1171template <typename Sig_>
1172class Func : public FuncBase
1173{
1174public:
1175	typedef Sig_										Sig;
1176	typedef typename Sig::Ret							Ret;
1177	typedef typename Sig::Arg0							Arg0;
1178	typedef typename Sig::Arg1							Arg1;
1179	typedef typename Sig::Arg2							Arg2;
1180	typedef typename Sig::Arg3							Arg3;
1181	typedef typename Sig::IRet							IRet;
1182	typedef typename Sig::IArg0							IArg0;
1183	typedef typename Sig::IArg1							IArg1;
1184	typedef typename Sig::IArg2							IArg2;
1185	typedef typename Sig::IArg3							IArg3;
1186	typedef typename Sig::Args							Args;
1187	typedef typename Sig::IArgs							IArgs;
1188	typedef typename Sig::ArgExprs						ArgExprs;
1189
1190	void				print			(ostream&			os,
1191										 const BaseArgExprs& args)				const
1192	{
1193		this->doPrint(os, args);
1194	}
1195
1196	IRet				apply			(const EvalContext&	ctx,
1197										 const IArg0&		arg0 = IArg0(),
1198										 const IArg1&		arg1 = IArg1(),
1199										 const IArg2&		arg2 = IArg2(),
1200										 const IArg3&		arg3 = IArg3())		const
1201	{
1202		return this->applyArgs(ctx, IArgs(arg0, arg1, arg2, arg3));
1203	}
1204	IRet				applyArgs		(const EvalContext&	ctx,
1205										 const IArgs&		args)				const
1206	{
1207		return this->doApply(ctx, args);
1208	}
1209	ExprP<Ret>			operator()		(const ExprP<Arg0>&		arg0 = voidP(),
1210										 const ExprP<Arg1>&		arg1 = voidP(),
1211										 const ExprP<Arg2>&		arg2 = voidP(),
1212										 const ExprP<Arg3>&		arg3 = voidP())		const;
1213
1214	const ParamNames&	getParamNames	(void)									const
1215	{
1216		return this->doGetParamNames();
1217	}
1218
1219protected:
1220	virtual IRet		doApply			(const EvalContext&,
1221										 const IArgs&)							const = 0;
1222	virtual void		doPrint			(ostream& os, const BaseArgExprs& args)	const
1223	{
1224		os << getName() << "(";
1225
1226		if (isTypeValid<Arg0>())
1227			os << *args[0];
1228
1229		if (isTypeValid<Arg1>())
1230			os << ", " << *args[1];
1231
1232		if (isTypeValid<Arg2>())
1233			os << ", " << *args[2];
1234
1235		if (isTypeValid<Arg3>())
1236			os << ", " << *args[3];
1237
1238		os << ")";
1239	}
1240
1241	virtual const ParamNames&	doGetParamNames	(void)							const
1242	{
1243		static ParamNames	names	("a", "b", "c", "d");
1244		return names;
1245	}
1246};
1247
1248template <typename Sig>
1249class Apply : public Expr<typename Sig::Ret>
1250{
1251public:
1252	typedef typename Sig::Ret				Ret;
1253	typedef typename Sig::Arg0				Arg0;
1254	typedef typename Sig::Arg1				Arg1;
1255	typedef typename Sig::Arg2				Arg2;
1256	typedef typename Sig::Arg3				Arg3;
1257	typedef typename Expr<Ret>::Val			Val;
1258	typedef typename Expr<Ret>::IVal		IVal;
1259	typedef Func<Sig>						ApplyFunc;
1260	typedef typename ApplyFunc::ArgExprs	ArgExprs;
1261
1262						Apply	(const ApplyFunc&		func,
1263								 const ExprP<Arg0>&		arg0 = voidP(),
1264								 const ExprP<Arg1>&		arg1 = voidP(),
1265								 const ExprP<Arg2>&		arg2 = voidP(),
1266								 const ExprP<Arg3>&		arg3 = voidP())
1267							: m_func	(func),
1268							  m_args	(arg0, arg1, arg2, arg3) {}
1269
1270						Apply	(const ApplyFunc&	func,
1271								 const ArgExprs&	args)
1272							: m_func	(func),
1273							  m_args	(args) {}
1274protected:
1275	void				doPrintExpr			(ostream& os) const
1276	{
1277		BaseArgExprs	args;
1278		args.push_back(m_args.a.get());
1279		args.push_back(m_args.b.get());
1280		args.push_back(m_args.c.get());
1281		args.push_back(m_args.d.get());
1282		m_func.print(os, args);
1283	}
1284
1285	IVal				doEvaluate		(const EvalContext& ctx) const
1286	{
1287		return m_func.apply(ctx,
1288							m_args.a->evaluate(ctx), m_args.b->evaluate(ctx),
1289							m_args.c->evaluate(ctx), m_args.d->evaluate(ctx));
1290	}
1291
1292	void				doGetUsedFuncs	(FuncSet& dst) const
1293	{
1294		m_func.getUsedFuncs(dst);
1295		m_args.a->getUsedFuncs(dst);
1296		m_args.b->getUsedFuncs(dst);
1297		m_args.c->getUsedFuncs(dst);
1298		m_args.d->getUsedFuncs(dst);
1299	}
1300
1301	const ApplyFunc&	m_func;
1302	ArgExprs			m_args;
1303};
1304
1305template<typename T>
1306class Alternatives : public Func<Signature<T, T, T> >
1307{
1308public:
1309	typedef typename	Alternatives::Sig		Sig;
1310
1311protected:
1312	typedef typename	Alternatives::IRet		IRet;
1313	typedef typename	Alternatives::IArgs		IArgs;
1314
1315	virtual string		getName				(void) const			{ return "alternatives"; }
1316	virtual void		doPrintDefinition	(std::ostream&) const	{}
1317	void				doGetUsedFuncs		(FuncSet&) const		{}
1318
1319	virtual IRet		doApply				(const EvalContext&, const IArgs& args) const
1320	{
1321		return unionIVal<T>(args.a, args.b);
1322	}
1323
1324	virtual void		doPrint				(ostream& os, const BaseArgExprs& args)	const
1325	{
1326		os << "{" << *args[0] << " | " << *args[1] << "}";
1327	}
1328};
1329
1330template <typename Sig>
1331ExprP<typename Sig::Ret> createApply (const Func<Sig>&						func,
1332									  const typename Func<Sig>::ArgExprs&	args)
1333{
1334	return exprP(new Apply<Sig>(func, args));
1335}
1336
1337template <typename Sig>
1338ExprP<typename Sig::Ret> createApply (
1339	const Func<Sig>&			func,
1340	const ExprP<typename Sig::Arg0>&	arg0 = voidP(),
1341	const ExprP<typename Sig::Arg1>&	arg1 = voidP(),
1342	const ExprP<typename Sig::Arg2>&	arg2 = voidP(),
1343	const ExprP<typename Sig::Arg3>&	arg3 = voidP())
1344{
1345	return exprP(new Apply<Sig>(func, arg0, arg1, arg2, arg3));
1346}
1347
1348template <typename Sig>
1349ExprP<typename Sig::Ret> Func<Sig>::operator() (const ExprP<typename Sig::Arg0>& arg0,
1350												const ExprP<typename Sig::Arg1>& arg1,
1351												const ExprP<typename Sig::Arg2>& arg2,
1352												const ExprP<typename Sig::Arg3>& arg3) const
1353{
1354	return createApply(*this, arg0, arg1, arg2, arg3);
1355}
1356
1357template <typename F>
1358ExprP<typename F::Ret> app (const ExprP<typename F::Arg0>& arg0 = voidP(),
1359							const ExprP<typename F::Arg1>& arg1 = voidP(),
1360							const ExprP<typename F::Arg2>& arg2 = voidP(),
1361							const ExprP<typename F::Arg3>& arg3 = voidP())
1362{
1363	return createApply(instance<F>(), arg0, arg1, arg2, arg3);
1364}
1365
1366template <typename F>
1367typename F::IRet call (const EvalContext&			ctx,
1368					   const typename F::IArg0&		arg0 = Void(),
1369					   const typename F::IArg1&		arg1 = Void(),
1370					   const typename F::IArg2&		arg2 = Void(),
1371					   const typename F::IArg3&		arg3 = Void())
1372{
1373	return instance<F>().apply(ctx, arg0, arg1, arg2, arg3);
1374}
1375
1376template <typename T>
1377ExprP<T> alternatives (const ExprP<T>& arg0,
1378					   const ExprP<T>& arg1)
1379{
1380	return createApply<typename Alternatives<T>::Sig>(instance<Alternatives<T> >(), arg0, arg1);
1381}
1382
1383template <typename Sig>
1384class ApplyVar : public Apply<Sig>
1385{
1386public:
1387	typedef typename Sig::Ret				Ret;
1388	typedef typename Sig::Arg0				Arg0;
1389	typedef typename Sig::Arg1				Arg1;
1390	typedef typename Sig::Arg2				Arg2;
1391	typedef typename Sig::Arg3				Arg3;
1392	typedef typename Expr<Ret>::Val			Val;
1393	typedef typename Expr<Ret>::IVal		IVal;
1394	typedef Func<Sig>						ApplyFunc;
1395	typedef typename ApplyFunc::ArgExprs	ArgExprs;
1396
1397						ApplyVar	(const ApplyFunc&			func,
1398									 const VariableP<Arg0>&		arg0,
1399									 const VariableP<Arg1>&		arg1,
1400									 const VariableP<Arg2>&		arg2,
1401									 const VariableP<Arg3>&		arg3)
1402							: Apply<Sig> (func, arg0, arg1, arg2, arg3) {}
1403protected:
1404	IVal				doEvaluate		(const EvalContext& ctx) const
1405	{
1406		const Variable<Arg0>&	var0 = static_cast<const Variable<Arg0>&>(*this->m_args.a);
1407		const Variable<Arg1>&	var1 = static_cast<const Variable<Arg1>&>(*this->m_args.b);
1408		const Variable<Arg2>&	var2 = static_cast<const Variable<Arg2>&>(*this->m_args.c);
1409		const Variable<Arg3>&	var3 = static_cast<const Variable<Arg3>&>(*this->m_args.d);
1410		return this->m_func.apply(ctx,
1411								  ctx.env.lookup(var0), ctx.env.lookup(var1),
1412								  ctx.env.lookup(var2), ctx.env.lookup(var3));
1413	}
1414};
1415
1416template <typename Sig>
1417ExprP<typename Sig::Ret> applyVar (const Func<Sig>&						func,
1418								   const VariableP<typename Sig::Arg0>&	arg0,
1419								   const VariableP<typename Sig::Arg1>&	arg1,
1420								   const VariableP<typename Sig::Arg2>&	arg2,
1421								   const VariableP<typename Sig::Arg3>&	arg3)
1422{
1423	return exprP(new ApplyVar<Sig>(func, arg0, arg1, arg2, arg3));
1424}
1425
1426template <typename Sig_>
1427class DerivedFunc : public Func<Sig_>
1428{
1429public:
1430	typedef typename DerivedFunc::ArgExprs		ArgExprs;
1431	typedef typename DerivedFunc::IRet			IRet;
1432	typedef typename DerivedFunc::IArgs			IArgs;
1433	typedef typename DerivedFunc::Ret			Ret;
1434	typedef typename DerivedFunc::Arg0			Arg0;
1435	typedef typename DerivedFunc::Arg1			Arg1;
1436	typedef typename DerivedFunc::Arg2			Arg2;
1437	typedef typename DerivedFunc::Arg3			Arg3;
1438	typedef typename DerivedFunc::IArg0			IArg0;
1439	typedef typename DerivedFunc::IArg1			IArg1;
1440	typedef typename DerivedFunc::IArg2			IArg2;
1441	typedef typename DerivedFunc::IArg3			IArg3;
1442
1443protected:
1444	void						doPrintDefinition	(ostream& os) const
1445	{
1446		const ParamNames&	paramNames	= this->getParamNames();
1447
1448		initialize();
1449
1450		os << dataTypeNameOf<Ret>() << " " << this->getName()
1451			<< "(";
1452		if (isTypeValid<Arg0>())
1453			os << dataTypeNameOf<Arg0>() << " " << paramNames.a;
1454		if (isTypeValid<Arg1>())
1455			os << ", " << dataTypeNameOf<Arg1>() << " " << paramNames.b;
1456		if (isTypeValid<Arg2>())
1457			os << ", " << dataTypeNameOf<Arg2>() << " " << paramNames.c;
1458		if (isTypeValid<Arg3>())
1459			os << ", " << dataTypeNameOf<Arg3>() << " " << paramNames.d;
1460		os << ")\n{\n";
1461
1462		for (size_t ndx = 0; ndx < m_body.size(); ++ndx)
1463			os << *m_body[ndx];
1464		os << "return " << *m_ret << ";\n";
1465		os << "}\n";
1466	}
1467
1468	IRet						doApply			(const EvalContext&	ctx,
1469												 const IArgs&		args) const
1470	{
1471		Environment	funEnv;
1472		IArgs&		mutArgs		= const_cast<IArgs&>(args);
1473		IRet		ret;
1474
1475		initialize();
1476
1477		funEnv.bind(*m_var0, args.a);
1478		funEnv.bind(*m_var1, args.b);
1479		funEnv.bind(*m_var2, args.c);
1480		funEnv.bind(*m_var3, args.d);
1481
1482		{
1483			EvalContext	funCtx(ctx.format, ctx.floatPrecision, funEnv, ctx.callDepth);
1484
1485			for (size_t ndx = 0; ndx < m_body.size(); ++ndx)
1486				m_body[ndx]->execute(funCtx);
1487
1488			ret = m_ret->evaluate(funCtx);
1489		}
1490
1491		// \todo [lauri] Store references instead of values in environment
1492		const_cast<IArg0&>(mutArgs.a) = funEnv.lookup(*m_var0);
1493		const_cast<IArg1&>(mutArgs.b) = funEnv.lookup(*m_var1);
1494		const_cast<IArg2&>(mutArgs.c) = funEnv.lookup(*m_var2);
1495		const_cast<IArg3&>(mutArgs.d) = funEnv.lookup(*m_var3);
1496
1497		return ret;
1498	}
1499
1500	void						doGetUsedFuncs	(FuncSet& dst) const
1501	{
1502		initialize();
1503		if (dst.insert(this).second)
1504		{
1505			for (size_t ndx = 0; ndx < m_body.size(); ++ndx)
1506				m_body[ndx]->getUsedFuncs(dst);
1507			m_ret->getUsedFuncs(dst);
1508		}
1509	}
1510
1511	virtual ExprP<Ret>			doExpand		(ExpandContext& ctx, const ArgExprs& args_) const = 0;
1512
1513	// These are transparently initialized when first needed. They cannot be
1514	// initialized in the constructor because they depend on the doExpand
1515	// method of the subclass.
1516
1517	mutable VariableP<Arg0>		m_var0;
1518	mutable VariableP<Arg1>		m_var1;
1519	mutable VariableP<Arg2>		m_var2;
1520	mutable VariableP<Arg3>		m_var3;
1521	mutable vector<StatementP>	m_body;
1522	mutable ExprP<Ret>			m_ret;
1523
1524private:
1525
1526	void				initialize		(void)	const
1527	{
1528		if (!m_ret)
1529		{
1530			const ParamNames&	paramNames	= this->getParamNames();
1531			Counter				symCounter;
1532			ExpandContext		ctx			(symCounter);
1533			ArgExprs			args;
1534
1535			args.a	= m_var0 = variable<Arg0>(paramNames.a);
1536			args.b	= m_var1 = variable<Arg1>(paramNames.b);
1537			args.c	= m_var2 = variable<Arg2>(paramNames.c);
1538			args.d	= m_var3 = variable<Arg3>(paramNames.d);
1539
1540			m_ret	= this->doExpand(ctx, args);
1541			m_body	= ctx.getStatements();
1542		}
1543	}
1544};
1545
1546template <typename Sig>
1547class PrimitiveFunc : public Func<Sig>
1548{
1549public:
1550	typedef typename PrimitiveFunc::Ret			Ret;
1551	typedef typename PrimitiveFunc::ArgExprs	ArgExprs;
1552
1553protected:
1554	void	doPrintDefinition	(ostream&) const	{}
1555	void	doGetUsedFuncs		(FuncSet&) const	{}
1556};
1557
1558template <typename T>
1559class Cond : public PrimitiveFunc<Signature<T, bool, T, T> >
1560{
1561public:
1562	typedef typename Cond::IArgs	IArgs;
1563	typedef typename Cond::IRet		IRet;
1564
1565	string	getName	(void) const
1566	{
1567		return "_cond";
1568	}
1569
1570protected:
1571
1572	void	doPrint	(ostream& os, const BaseArgExprs& args) const
1573	{
1574		os << "(" << *args[0] << " ? " << *args[1] << " : " << *args[2] << ")";
1575	}
1576
1577	IRet	doApply	(const EvalContext&, const IArgs& iargs)const
1578	{
1579		IRet	ret;
1580
1581		if (iargs.a.contains(true))
1582			ret = unionIVal<T>(ret, iargs.b);
1583
1584		if (iargs.a.contains(false))
1585			ret = unionIVal<T>(ret, iargs.c);
1586
1587		return ret;
1588	}
1589};
1590
1591template <typename T>
1592class CompareOperator : public PrimitiveFunc<Signature<bool, T, T> >
1593{
1594public:
1595	typedef typename CompareOperator::IArgs	IArgs;
1596	typedef typename CompareOperator::IArg0	IArg0;
1597	typedef typename CompareOperator::IArg1	IArg1;
1598	typedef typename CompareOperator::IRet	IRet;
1599
1600protected:
1601	void			doPrint	(ostream& os, const BaseArgExprs& args) const
1602	{
1603		os << "(" << *args[0] << getSymbol() << *args[1] << ")";
1604	}
1605
1606	Interval		doApply	(const EvalContext&, const IArgs& iargs) const
1607	{
1608		const IArg0&	arg0 = iargs.a;
1609		const IArg1&	arg1 = iargs.b;
1610		IRet	ret;
1611
1612		if (canSucceed(arg0, arg1))
1613			ret |= true;
1614		if (canFail(arg0, arg1))
1615			ret |= false;
1616
1617		return ret;
1618	}
1619
1620	virtual string	getSymbol	(void) const = 0;
1621	virtual bool	canSucceed	(const IArg0&, const IArg1&) const = 0;
1622	virtual bool	canFail		(const IArg0&, const IArg1&) const = 0;
1623};
1624
1625template <typename T>
1626class LessThan : public CompareOperator<T>
1627{
1628public:
1629	string	getName		(void) const									{ return "lessThan"; }
1630
1631protected:
1632	string	getSymbol	(void) const									{ return "<";		}
1633
1634	bool	canSucceed	(const Interval& a, const Interval& b) const
1635	{
1636		return (a.lo() < b.hi());
1637	}
1638
1639	bool	canFail		(const Interval& a, const Interval& b) const
1640	{
1641		return !(a.hi() < b.lo());
1642	}
1643};
1644
1645template <typename T>
1646ExprP<bool> operator< (const ExprP<T>& a, const ExprP<T>& b)
1647{
1648	return app<LessThan<T> >(a, b);
1649}
1650
1651template <typename T>
1652ExprP<T> cond (const ExprP<bool>&	test,
1653			   const ExprP<T>&		consequent,
1654			   const ExprP<T>&		alternative)
1655{
1656	return app<Cond<T> >(test, consequent, alternative);
1657}
1658
1659/*--------------------------------------------------------------------*//*!
1660 *
1661 * @}
1662 *
1663 *//*--------------------------------------------------------------------*/
1664
1665class FloatFunc1 : public PrimitiveFunc<Signature<float, float> >
1666{
1667protected:
1668	Interval			doApply			(const EvalContext& ctx, const IArgs& iargs) const
1669	{
1670		return this->applyMonotone(ctx, iargs.a);
1671	}
1672
1673	Interval			applyMonotone	(const EvalContext& ctx, const Interval& iarg0) const
1674	{
1675		Interval ret;
1676
1677		TCU_INTERVAL_APPLY_MONOTONE1(ret, arg0, iarg0, val,
1678									 TCU_SET_INTERVAL(val, point,
1679													  point = this->applyPoint(ctx, arg0)));
1680
1681		ret |= innerExtrema(ctx, iarg0);
1682		ret &= (this->getCodomain() | TCU_NAN);
1683
1684		return ctx.format.convert(ret);
1685	}
1686
1687	virtual Interval	innerExtrema	(const EvalContext&, const Interval&) const
1688	{
1689		return Interval(); // empty interval, i.e. no extrema
1690	}
1691
1692	virtual Interval	applyPoint		(const EvalContext& ctx, double arg0) const
1693	{
1694		const double	exact	= this->applyExact(arg0);
1695		const double	prec	= this->precision(ctx, exact, arg0);
1696
1697		return exact + Interval(-prec, prec);
1698	}
1699
1700	virtual double		applyExact		(double) const
1701	{
1702		TCU_THROW(InternalError, "Cannot apply");
1703	}
1704
1705	virtual Interval	getCodomain		(void) const
1706	{
1707		return Interval::unbounded(true);
1708	}
1709
1710	virtual double		precision		(const EvalContext& ctx, double, double) const = 0;
1711};
1712
1713class CFloatFunc1 : public FloatFunc1
1714{
1715public:
1716			CFloatFunc1	(const string& name, DoubleFunc1& func)
1717				: m_name(name), m_func(func) {}
1718
1719	string			getName		(void) const		{ return m_name; }
1720
1721protected:
1722	double			applyExact	(double x) const	{ return m_func(x); }
1723
1724	const string	m_name;
1725	DoubleFunc1&	m_func;
1726};
1727
1728class FloatFunc2 : public PrimitiveFunc<Signature<float, float, float> >
1729{
1730protected:
1731	Interval			doApply			(const EvalContext&	ctx, const IArgs& iargs) const
1732	{
1733		return this->applyMonotone(ctx, iargs.a, iargs.b);
1734	}
1735
1736	Interval			applyMonotone	(const EvalContext&	ctx,
1737										 const Interval&	xi,
1738										 const Interval&	yi) const
1739	{
1740		Interval reti;
1741
1742		TCU_INTERVAL_APPLY_MONOTONE2(reti, x, xi, y, yi, ret,
1743									 TCU_SET_INTERVAL(ret, point,
1744													  point = this->applyPoint(ctx, x, y)));
1745		reti |= innerExtrema(ctx, xi, yi);
1746		reti &= (this->getCodomain() | TCU_NAN);
1747
1748		return ctx.format.convert(reti);
1749	}
1750
1751	virtual Interval	innerExtrema	(const EvalContext&,
1752										 const Interval&,
1753										 const Interval&) const
1754	{
1755		return Interval(); // empty interval, i.e. no extrema
1756	}
1757
1758	virtual Interval	applyPoint		(const EvalContext&	ctx,
1759										 double 			x,
1760										 double 			y) const
1761	{
1762		const double exact	= this->applyExact(x, y);
1763		const double prec	= this->precision(ctx, exact, x, y);
1764
1765		return exact + Interval(-prec, prec);
1766	}
1767
1768	virtual double		applyExact		(double, double) const
1769	{
1770		TCU_THROW(InternalError, "Cannot apply");
1771	}
1772
1773	virtual Interval	getCodomain		(void) const
1774	{
1775		return Interval::unbounded(true);
1776	}
1777
1778	virtual double		precision		(const EvalContext&	ctx,
1779										 double				ret,
1780										 double				x,
1781										 double				y) const = 0;
1782};
1783
1784class CFloatFunc2 : public FloatFunc2
1785{
1786public:
1787					CFloatFunc2	(const string&	name,
1788								 DoubleFunc2&	func)
1789						: m_name(name)
1790						, m_func(func)
1791	{
1792	}
1793
1794	string			getName		(void) const						{ return m_name; }
1795
1796protected:
1797	double			applyExact	(double x, double y) const			{ return m_func(x, y); }
1798
1799	const string	m_name;
1800	DoubleFunc2&	m_func;
1801};
1802
1803class InfixOperator : public FloatFunc2
1804{
1805protected:
1806	virtual string	getSymbol		(void) const = 0;
1807
1808	void			doPrint			(ostream& os, const BaseArgExprs& args) const
1809	{
1810		os << "(" << *args[0] << " " << getSymbol() << " " << *args[1] << ")";
1811	}
1812
1813	Interval		applyPoint		(const EvalContext&	ctx,
1814									 double 			x,
1815									 double 			y) const
1816	{
1817		const double exact	= this->applyExact(x, y);
1818
1819		// Allow either representable number on both sides of the exact value,
1820		// but require exactly representable values to be preserved.
1821		return ctx.format.roundOut(exact, !deIsInf(x) && !deIsInf(y));
1822	}
1823
1824	double			precision		(const EvalContext&, double, double, double) const
1825	{
1826		return 0.0;
1827	}
1828};
1829
1830class FloatFunc3 : public PrimitiveFunc<Signature<float, float, float, float> >
1831{
1832protected:
1833	Interval			doApply			(const EvalContext&	ctx, const IArgs& iargs) const
1834	{
1835		return this->applyMonotone(ctx, iargs.a, iargs.b, iargs.c);
1836	}
1837
1838	Interval			applyMonotone	(const EvalContext&	ctx,
1839										 const Interval&	xi,
1840										 const Interval&	yi,
1841										 const Interval&	zi) const
1842	{
1843		Interval reti;
1844		TCU_INTERVAL_APPLY_MONOTONE3(reti, x, xi, y, yi, z, zi, ret,
1845									 TCU_SET_INTERVAL(ret, point,
1846													  point = this->applyPoint(ctx, x, y, z)));
1847		return ctx.format.convert(reti);
1848	}
1849
1850	virtual Interval	applyPoint		(const EvalContext&	ctx,
1851										 double 			x,
1852										 double 			y,
1853										 double 			z) const
1854	{
1855		const double exact	= this->applyExact(x, y, z);
1856		const double prec	= this->precision(ctx, exact, x, y, z);
1857		return exact + Interval(-prec, prec);
1858	}
1859
1860	virtual double		applyExact		(double, double, double) const
1861	{
1862		TCU_THROW(InternalError, "Cannot apply");
1863	}
1864
1865	virtual double		precision		(const EvalContext&	ctx,
1866										 double				result,
1867										 double				x,
1868										 double				y,
1869										 double				z) const = 0;
1870};
1871
1872// We define syntactic sugar functions for expression constructors. Since
1873// these have the same names as ordinary mathematical operations (sin, log
1874// etc.), it's better to give them a dedicated namespace.
1875namespace Functions
1876{
1877
1878using namespace tcu;
1879
1880class Add : public InfixOperator
1881{
1882public:
1883	string		getName		(void) const 						{ return "add"; }
1884	string		getSymbol	(void) const 						{ return "+"; }
1885
1886	Interval	doApply		(const EvalContext&	ctx,
1887							 const IArgs&		iargs) const
1888	{
1889		// Fast-path for common case
1890		if (iargs.a.isOrdinary() && iargs.b.isOrdinary())
1891		{
1892			Interval ret;
1893			TCU_SET_INTERVAL_BOUNDS(ret, sum,
1894									sum = iargs.a.lo() + iargs.b.lo(),
1895									sum = iargs.a.hi() + iargs.b.hi());
1896			return ctx.format.convert(ctx.format.roundOut(ret, true));
1897		}
1898		return this->applyMonotone(ctx, iargs.a, iargs.b);
1899	}
1900
1901protected:
1902	double		applyExact	(double x, double y) const 			{ return x + y; }
1903};
1904
1905class Mul : public InfixOperator
1906{
1907public:
1908	string		getName		(void) const 									{ return "mul"; }
1909	string		getSymbol	(void) const 									{ return "*"; }
1910
1911	Interval	doApply		(const EvalContext&	ctx, const IArgs& iargs) const
1912	{
1913		Interval a = iargs.a;
1914		Interval b = iargs.b;
1915
1916		// Fast-path for common case
1917		if (a.isOrdinary() && b.isOrdinary())
1918		{
1919			Interval ret;
1920			if (a.hi() < 0)
1921			{
1922				a = -a;
1923				b = -b;
1924			}
1925			if (a.lo() >= 0 && b.lo() >= 0)
1926			{
1927				TCU_SET_INTERVAL_BOUNDS(ret, prod,
1928										prod = iargs.a.lo() * iargs.b.lo(),
1929										prod = iargs.a.hi() * iargs.b.hi());
1930				return ctx.format.convert(ctx.format.roundOut(ret, true));
1931			}
1932			if (a.lo() >= 0 && b.hi() <= 0)
1933			{
1934				TCU_SET_INTERVAL_BOUNDS(ret, prod,
1935										prod = iargs.a.hi() * iargs.b.lo(),
1936										prod = iargs.a.lo() * iargs.b.hi());
1937				return ctx.format.convert(ctx.format.roundOut(ret, true));
1938			}
1939		}
1940		return this->applyMonotone(ctx, iargs.a, iargs.b);
1941	}
1942
1943protected:
1944	double		applyExact	(double x, double y) const						{ return x * y; }
1945
1946	Interval	innerExtrema(const EvalContext&, const Interval& xi, const Interval& yi) const
1947	{
1948		if (((xi.contains(-TCU_INFINITY) || xi.contains(TCU_INFINITY)) && yi.contains(0.0)) ||
1949			((yi.contains(-TCU_INFINITY) || yi.contains(TCU_INFINITY)) && xi.contains(0.0)))
1950			return Interval(TCU_NAN);
1951
1952		return Interval();
1953	}
1954};
1955
1956class Sub : public InfixOperator
1957{
1958public:
1959	string		getName		(void) const 				{ return "sub"; }
1960	string		getSymbol	(void) const 				{ return "-"; }
1961
1962	Interval	doApply		(const EvalContext&	ctx, const IArgs& iargs) const
1963	{
1964		// Fast-path for common case
1965		if (iargs.a.isOrdinary() && iargs.b.isOrdinary())
1966		{
1967			Interval ret;
1968
1969			TCU_SET_INTERVAL_BOUNDS(ret, diff,
1970									diff = iargs.a.lo() - iargs.b.hi(),
1971									diff = iargs.a.hi() - iargs.b.lo());
1972			return ctx.format.convert(ctx.format.roundOut(ret, true));
1973
1974		}
1975		else
1976		{
1977			return this->applyMonotone(ctx, iargs.a, iargs.b);
1978		}
1979	}
1980
1981protected:
1982	double		applyExact	(double x, double y) const	{ return x - y; }
1983};
1984
1985class Negate : public FloatFunc1
1986{
1987public:
1988	string	getName		(void) const									{ return "_negate"; }
1989	void	doPrint		(ostream& os, const BaseArgExprs& args) const	{ os << "-" << *args[0]; }
1990
1991protected:
1992	double	precision	(const EvalContext&, double, double) const		{ return 0.0; }
1993	double	applyExact	(double x) const								{ return -x; }
1994};
1995
1996class Div : public InfixOperator
1997{
1998public:
1999	string		getName			(void) const 						{ return "div"; }
2000
2001protected:
2002	string		getSymbol		(void) const 						{ return "/"; }
2003
2004	Interval	innerExtrema	(const EvalContext&,
2005								 const Interval&		nom,
2006								 const Interval&		den) const
2007	{
2008		Interval ret;
2009
2010		if (den.contains(0.0))
2011		{
2012			if (nom.contains(0.0))
2013				ret |= TCU_NAN;
2014
2015			if (nom.lo() < 0.0 || nom.hi() > 0.0)
2016				ret |= Interval::unbounded();
2017		}
2018
2019		return ret;
2020	}
2021
2022	double		applyExact		(double x, double y) const { return x / y; }
2023
2024	Interval	applyPoint		(const EvalContext&	ctx, double x, double y) const
2025	{
2026		Interval ret = FloatFunc2::applyPoint(ctx, x, y);
2027
2028		if (!deIsInf(x) && !deIsInf(y) && y != 0.0)
2029		{
2030			const Interval dst = ctx.format.convert(ret);
2031			if (dst.contains(-TCU_INFINITY)) ret |= -ctx.format.getMaxValue();
2032			if (dst.contains(+TCU_INFINITY)) ret |= +ctx.format.getMaxValue();
2033		}
2034
2035		return ret;
2036	}
2037
2038	double		precision		(const EvalContext& ctx, double ret, double, double den) const
2039	{
2040		const FloatFormat&	fmt		= ctx.format;
2041
2042		// \todo [2014-03-05 lauri] Check that the limits in GLSL 3.10 are actually correct.
2043		// For now, we assume that division's precision is 2.5 ULP when the value is within
2044		// [2^MINEXP, 2^MAXEXP-1]
2045
2046		if (den == 0.0)
2047			return 0.0; // Result must be exactly inf
2048		else if (de::inBounds(deAbs(den),
2049							  deLdExp(1.0, fmt.getMinExp()),
2050							  deLdExp(1.0, fmt.getMaxExp() - 1)))
2051			return fmt.ulp(ret, 2.5);
2052		else
2053			return TCU_INFINITY; // Can be any number, but must be a number.
2054	}
2055};
2056
2057class InverseSqrt : public FloatFunc1
2058{
2059public:
2060	string		getName		(void) const							{ return "inversesqrt"; }
2061
2062protected:
2063	double		applyExact	(double x) const						{ return 1.0 / deSqrt(x); }
2064
2065	double		precision	(const EvalContext& ctx, double ret, double x) const
2066	{
2067		return x <= 0 ? TCU_NAN : ctx.format.ulp(ret, 2.0);
2068	}
2069
2070	Interval	getCodomain	(void) const
2071	{
2072		return Interval(0.0, TCU_INFINITY);
2073	}
2074};
2075
2076class ExpFunc : public CFloatFunc1
2077{
2078public:
2079				ExpFunc		(const string& name, DoubleFunc1& func)
2080					: CFloatFunc1(name, func) {}
2081protected:
2082	double		precision	(const EvalContext& ctx, double ret, double x) const
2083	{
2084		switch (ctx.floatPrecision)
2085		{
2086			case glu::PRECISION_HIGHP:
2087				return ctx.format.ulp(ret, 3.0 + 2.0 * deAbs(x));
2088			case glu::PRECISION_MEDIUMP:
2089				return ctx.format.ulp(ret, 2.0 + 2.0 * deAbs(x));
2090			case glu::PRECISION_LOWP:
2091				return ctx.format.ulp(ret, 2.0);
2092			default:
2093				DE_FATAL("Impossible");
2094		}
2095		return 0;
2096	}
2097
2098	Interval	getCodomain	(void) const
2099	{
2100		return Interval(0.0, TCU_INFINITY);
2101	}
2102};
2103
2104class Exp2	: public ExpFunc	{ public: Exp2 (void)	: ExpFunc("exp2", deExp2) {} };
2105class Exp	: public ExpFunc	{ public: Exp (void)	: ExpFunc("exp", deExp) {} };
2106
2107ExprP<float> exp2	(const ExprP<float>& x)	{ return app<Exp2>(x); }
2108ExprP<float> exp	(const ExprP<float>& x)	{ return app<Exp>(x); }
2109
2110class LogFunc : public CFloatFunc1
2111{
2112public:
2113				LogFunc		(const string& name, DoubleFunc1& func)
2114					: CFloatFunc1(name, func) {}
2115
2116protected:
2117	double		precision	(const EvalContext& ctx, double ret, double x) const
2118	{
2119		if (x <= 0)
2120			return TCU_NAN;
2121
2122		switch (ctx.floatPrecision)
2123		{
2124			case glu::PRECISION_HIGHP:
2125				return (0.5 <= x && x <= 2.0) ? deLdExp(1.0, -21) : ctx.format.ulp(ret, 3.0);
2126			case glu::PRECISION_MEDIUMP:
2127				return (0.5 <= x && x <= 2.0) ? deLdExp(1.0, -7) : ctx.format.ulp(ret, 2.0);
2128			case glu::PRECISION_LOWP:
2129				return ctx.format.ulp(ret, 2.0);
2130			default:
2131				DE_FATAL("Impossible");
2132		}
2133
2134		return 0;
2135	}
2136};
2137
2138class Log2	: public LogFunc		{ public: Log2	(void) : LogFunc("log2", deLog2) {} };
2139class Log	: public LogFunc		{ public: Log	(void) : LogFunc("log", deLog) {} };
2140
2141ExprP<float> log2	(const ExprP<float>& x)	{ return app<Log2>(x); }
2142ExprP<float> log	(const ExprP<float>& x)	{ return app<Log>(x); }
2143
2144#define DEFINE_CONSTRUCTOR1(CLASS, TRET, NAME, T0) \
2145ExprP<TRET> NAME (const ExprP<T0>& arg0) { return app<CLASS>(arg0); }
2146
2147#define DEFINE_DERIVED1(CLASS, TRET, NAME, T0, ARG0, EXPANSION)			\
2148class CLASS : public DerivedFunc<Signature<TRET, T0> >		 			\
2149{																		\
2150public:																	\
2151	string			getName		(void) const		{ return #NAME; }	\
2152																		\
2153protected:																\
2154	ExprP<TRET>		doExpand		(ExpandContext&,					\
2155									 const CLASS::ArgExprs& args_) const \
2156	{																	\
2157		const ExprP<float>& ARG0 = args_.a;								\
2158		return EXPANSION;												\
2159	}																	\
2160};																		\
2161DEFINE_CONSTRUCTOR1(CLASS, TRET, NAME, T0)
2162
2163#define DEFINE_DERIVED_FLOAT1(CLASS, NAME, ARG0, EXPANSION) \
2164	DEFINE_DERIVED1(CLASS, float, NAME, float, ARG0, EXPANSION)
2165
2166#define DEFINE_CONSTRUCTOR2(CLASS, TRET, NAME, T0, T1)				\
2167ExprP<TRET> NAME (const ExprP<T0>& arg0, const ExprP<T1>& arg1)		\
2168{																	\
2169	return app<CLASS>(arg0, arg1);									\
2170}
2171
2172#define DEFINE_DERIVED2(CLASS, TRET, NAME, T0, Arg0, T1, Arg1, EXPANSION) \
2173class CLASS : public DerivedFunc<Signature<TRET, T0, T1> >		 		\
2174{																		\
2175public:																	\
2176	string			getName		(void) const		{ return #NAME; }	\
2177																		\
2178protected:																\
2179	ExprP<TRET>		doExpand	(ExpandContext&, const ArgExprs& args_) const \
2180	{																	\
2181		const ExprP<T0>& Arg0 = args_.a;								\
2182		const ExprP<T1>& Arg1 = args_.b;								\
2183		return EXPANSION;												\
2184	}																	\
2185};																		\
2186DEFINE_CONSTRUCTOR2(CLASS, TRET, NAME, T0, T1)
2187
2188#define DEFINE_DERIVED_FLOAT2(CLASS, NAME, Arg0, Arg1, EXPANSION)		\
2189	DEFINE_DERIVED2(CLASS, float, NAME, float, Arg0, float, Arg1, EXPANSION)
2190
2191#define DEFINE_CONSTRUCTOR3(CLASS, TRET, NAME, T0, T1, T2)				\
2192ExprP<TRET> NAME (const ExprP<T0>& arg0, const ExprP<T1>& arg1, const ExprP<T2>& arg2) \
2193{																		\
2194	return app<CLASS>(arg0, arg1, arg2);								\
2195}
2196
2197#define DEFINE_DERIVED3(CLASS, TRET, NAME, T0, ARG0, T1, ARG1, T2, ARG2, EXPANSION) \
2198class CLASS : public DerivedFunc<Signature<TRET, T0, T1, T2> >					\
2199{																				\
2200public:																			\
2201	string			getName		(void) const	{ return #NAME; }				\
2202																				\
2203protected:																		\
2204	ExprP<TRET>		doExpand	(ExpandContext&, const ArgExprs& args_) const	\
2205	{																			\
2206		const ExprP<T0>& ARG0 = args_.a;										\
2207		const ExprP<T1>& ARG1 = args_.b;										\
2208		const ExprP<T2>& ARG2 = args_.c;										\
2209		return EXPANSION;														\
2210	}																			\
2211};																				\
2212DEFINE_CONSTRUCTOR3(CLASS, TRET, NAME, T0, T1, T2)
2213
2214#define DEFINE_DERIVED_FLOAT3(CLASS, NAME, ARG0, ARG1, ARG2, EXPANSION)			\
2215	DEFINE_DERIVED3(CLASS, float, NAME, float, ARG0, float, ARG1, float, ARG2, EXPANSION)
2216
2217#define DEFINE_CONSTRUCTOR4(CLASS, TRET, NAME, T0, T1, T2, T3)			\
2218ExprP<TRET> NAME (const ExprP<T0>& arg0, const ExprP<T1>& arg1,			\
2219				  const ExprP<T2>& arg2, const ExprP<T3>& arg3)			\
2220{																		\
2221	return app<CLASS>(arg0, arg1, arg2, arg3);							\
2222}
2223
2224DEFINE_DERIVED_FLOAT1(Sqrt,		sqrt,		x, 		constant(1.0f) / app<InverseSqrt>(x));
2225DEFINE_DERIVED_FLOAT2(Pow,		pow,		x,	y,	exp2(y * log2(x)));
2226DEFINE_DERIVED_FLOAT1(Radians,	radians,	d, 		(constant(DE_PI) / constant(180.0f)) * d);
2227DEFINE_DERIVED_FLOAT1(Degrees,	degrees,	r,	 	(constant(180.0f) / constant(DE_PI)) * r);
2228
2229class TrigFunc : public CFloatFunc1
2230{
2231public:
2232					TrigFunc		(const string&		name,
2233									 DoubleFunc1&		func,
2234									 const Interval&	loEx,
2235									 const Interval&	hiEx)
2236						: CFloatFunc1	(name, func)
2237						, m_loExtremum	(loEx)
2238						, m_hiExtremum	(hiEx) {}
2239
2240protected:
2241	Interval		innerExtrema	(const EvalContext&, const Interval& angle) const
2242	{
2243		const double		lo		= angle.lo();
2244		const double		hi		= angle.hi();
2245		const int			loSlope	= doGetSlope(lo);
2246		const int			hiSlope	= doGetSlope(hi);
2247
2248		// Detect the high and low values the function can take between the
2249		// interval endpoints.
2250		if (angle.length() >= 2.0 * DE_PI_DOUBLE)
2251		{
2252			// The interval is longer than a full cycle, so it must get all possible values.
2253			return m_hiExtremum | m_loExtremum;
2254		}
2255		else if (loSlope == 1 && hiSlope == -1)
2256		{
2257			// The slope can change from positive to negative only at the maximum value.
2258			return m_hiExtremum;
2259		}
2260		else if (loSlope == -1 && hiSlope == 1)
2261		{
2262			// The slope can change from negative to positive only at the maximum value.
2263			return m_loExtremum;
2264		}
2265		else if (loSlope == hiSlope &&
2266				 deIntSign(applyExact(hi) - applyExact(lo)) * loSlope == -1)
2267		{
2268			// The slope has changed twice between the endpoints, so both extrema are included.
2269			return m_hiExtremum | m_loExtremum;
2270		}
2271
2272		return Interval();
2273	}
2274
2275	Interval	getCodomain			(void) const
2276	{
2277		// Ensure that result is always within [-1, 1], or NaN (for +-inf)
2278		return Interval(-1.0, 1.0) | TCU_NAN;
2279	}
2280
2281	double		precision			(const EvalContext& ctx, double ret, double arg) const
2282	{
2283		if (ctx.floatPrecision == glu::PRECISION_HIGHP)
2284		{
2285			// Use precision from OpenCL fast relaxed math
2286			if (-DE_PI_DOUBLE <= arg && arg <= DE_PI_DOUBLE)
2287			{
2288				return deLdExp(1.0, -11);
2289			}
2290			else
2291			{
2292				// "larger otherwise", let's pick |x| * 2^-12 , which is slightly over
2293				// 2^-11 at x == pi.
2294				return deLdExp(deAbs(arg), -12);
2295			}
2296		}
2297		else if (ctx.floatPrecision == glu::PRECISION_MEDIUMP)
2298		{
2299			if (-DE_PI_DOUBLE <= arg && arg <= DE_PI_DOUBLE)
2300			{
2301				// from OpenCL half-float extension specification
2302				return ctx.format.ulp(ret, 2.0);
2303			}
2304			else
2305			{
2306				// |x| * 2^-10, slightly larger than 2 ULP at x == pi
2307				return deLdExp(deAbs(arg), -10);
2308			}
2309		}
2310		else
2311		{
2312			DE_ASSERT(ctx.floatPrecision == glu::PRECISION_LOWP);
2313
2314			// from OpenCL half-float extension specification
2315			return ctx.format.ulp(ret, 2.0);
2316		}
2317	}
2318
2319	virtual int		doGetSlope		(double angle) const = 0;
2320
2321	Interval		m_loExtremum;
2322	Interval		m_hiExtremum;
2323};
2324
2325class Sin : public TrigFunc
2326{
2327public:
2328				Sin			(void) : TrigFunc("sin", deSin, -1.0, 1.0) {}
2329
2330protected:
2331	int			doGetSlope	(double angle) const { return deIntSign(deCos(angle)); }
2332};
2333
2334ExprP<float> sin (const ExprP<float>& x) { return app<Sin>(x); }
2335
2336class Cos : public TrigFunc
2337{
2338public:
2339				Cos			(void) : TrigFunc("cos", deCos, -1.0, 1.0) {}
2340
2341protected:
2342	int			doGetSlope	(double angle) const { return -deIntSign(deSin(angle)); }
2343};
2344
2345ExprP<float> cos (const ExprP<float>& x) { return app<Cos>(x); }
2346
2347DEFINE_DERIVED_FLOAT1(Tan, tan, x, sin(x) * (constant(1.0f) / cos(x)));
2348
2349class ASin : public CFloatFunc1
2350{
2351public:
2352					ASin		(void) : CFloatFunc1("asin", deAsin) {}
2353
2354protected:
2355	double			precision	(const EvalContext& ctx, double, double x) const
2356	{
2357		if (!de::inBounds(x, -1.0, 1.0))
2358			return TCU_NAN;
2359
2360		if (ctx.floatPrecision == glu::PRECISION_HIGHP)
2361		{
2362			// Absolute error of 2^-11
2363			return deLdExp(1.0, -11);
2364		}
2365		else
2366		{
2367			// Absolute error of 2^-8
2368			return deLdExp(1.0, -8);
2369		}
2370
2371	}
2372};
2373
2374class ArcTrigFunc : public CFloatFunc1
2375{
2376public:
2377					ArcTrigFunc	(const string&		name,
2378								 DoubleFunc1&		func,
2379								 double				precisionULPs,
2380								 const Interval&	domain,
2381								 const Interval&	codomain)
2382						: CFloatFunc1		(name, func)
2383						, m_precision		(precisionULPs)
2384						, m_domain			(domain)
2385						, m_codomain		(codomain) {}
2386
2387protected:
2388	double			precision	(const EvalContext& ctx, double ret, double x) const
2389	{
2390		if (!m_domain.contains(x))
2391			return TCU_NAN;
2392
2393		if (ctx.floatPrecision == glu::PRECISION_HIGHP)
2394		{
2395			// Use OpenCL's fast relaxed math precision
2396			return ctx.format.ulp(ret, m_precision);
2397		}
2398		else
2399		{
2400			// Use OpenCL half-float spec
2401			return ctx.format.ulp(ret, 2.0);
2402		}
2403	}
2404
2405	// We could implement getCodomain with m_codomain, but choose not to,
2406	// because it seems too strict with trascendental constants like pi.
2407
2408	const double	m_precision;
2409	const Interval	m_domain;
2410	const Interval	m_codomain;
2411};
2412
2413class ACos : public ArcTrigFunc
2414{
2415public:
2416	ACos (void) : ArcTrigFunc("acos", deAcos, 4096.0,
2417							  Interval(-1.0, 1.0),
2418							  Interval(0.0, DE_PI_DOUBLE)) {}
2419};
2420
2421class ATan : public ArcTrigFunc
2422{
2423public:
2424	ATan (void) : ArcTrigFunc("atan", deAtanOver, 4096.0,
2425							  Interval::unbounded(),
2426							  Interval(-DE_PI_DOUBLE * 0.5, DE_PI_DOUBLE * 0.5)) {}
2427};
2428
2429class ATan2 : public CFloatFunc2
2430{
2431public:
2432				ATan2			(void) : CFloatFunc2 ("atan", deAtan2) {}
2433
2434protected:
2435	Interval	innerExtrema	(const EvalContext&		ctx,
2436								 const Interval&		yi,
2437								 const Interval& 		xi) const
2438	{
2439		Interval ret;
2440
2441		if (yi.contains(0.0))
2442		{
2443			if (xi.contains(0.0))
2444				ret |= TCU_NAN;
2445			if (xi.intersects(Interval(-TCU_INFINITY, 0.0)))
2446				ret |= Interval(-DE_PI_DOUBLE, DE_PI_DOUBLE);
2447		}
2448
2449		if (ctx.format.hasInf() != YES && (!yi.isFinite() || !xi.isFinite()))
2450		{
2451			// Infinities may not be supported, allow anything, including NaN
2452			ret |= TCU_NAN;
2453		}
2454
2455		return ret;
2456	}
2457
2458	double		precision		(const EvalContext& ctx, double ret, double, double) const
2459	{
2460		if (ctx.floatPrecision == glu::PRECISION_HIGHP)
2461			return ctx.format.ulp(ret, 4096.0);
2462		else
2463			return ctx.format.ulp(ret, 2.0);
2464	}
2465
2466	// Codomain could be [-pi, pi], but that would probably be too strict.
2467};
2468
2469DEFINE_DERIVED_FLOAT1(Sinh, sinh, x, (exp(x) - exp(-x)) / constant(2.0f));
2470DEFINE_DERIVED_FLOAT1(Cosh, cosh, x, (exp(x) + exp(-x)) / constant(2.0f));
2471DEFINE_DERIVED_FLOAT1(Tanh, tanh, x, sinh(x) / cosh(x));
2472
2473// These are not defined as derived forms in the GLSL ES spec, but
2474// that gives us a reasonable precision.
2475DEFINE_DERIVED_FLOAT1(ASinh, asinh, x, log(x + sqrt(x * x + constant(1.0f))));
2476DEFINE_DERIVED_FLOAT1(ACosh, acosh, x, log(x + sqrt((x + constant(1.0f)) *
2477													(x - constant(1.0f)))));
2478DEFINE_DERIVED_FLOAT1(ATanh, atanh, x, constant(0.5f) * log((constant(1.0f) + x) /
2479															(constant(1.0f) - x)));
2480
2481template <typename T>
2482class GetComponent : public PrimitiveFunc<Signature<typename T::Element, T, int> >
2483{
2484public:
2485	typedef		typename GetComponent::IRet	IRet;
2486
2487	string		getName		(void) const { return "_getComponent"; }
2488
2489	void		print		(ostream&				os,
2490							 const BaseArgExprs&	args) const
2491	{
2492		os << *args[0] << "[" << *args[1] << "]";
2493	}
2494
2495protected:
2496	IRet		doApply 	(const EvalContext&,
2497							 const typename GetComponent::IArgs& iargs) const
2498	{
2499		IRet ret;
2500
2501		for (int compNdx = 0; compNdx < T::SIZE; ++compNdx)
2502		{
2503			if (iargs.b.contains(compNdx))
2504				ret = unionIVal<typename T::Element>(ret, iargs.a[compNdx]);
2505		}
2506
2507		return ret;
2508	}
2509
2510};
2511
2512template <typename T>
2513ExprP<typename T::Element> getComponent (const ExprP<T>& container, int ndx)
2514{
2515	DE_ASSERT(0 <= ndx && ndx < T::SIZE);
2516	return app<GetComponent<T> >(container, constant(ndx));
2517}
2518
2519template <typename T>	string	vecNamePrefix			(void);
2520template <>				string	vecNamePrefix<float>	(void) { return ""; }
2521template <>				string	vecNamePrefix<int>		(void) { return "i"; }
2522template <>				string	vecNamePrefix<bool>		(void) { return "b"; }
2523
2524template <typename T, int Size>
2525string vecName (void) { return vecNamePrefix<T>() + "vec" + de::toString(Size); }
2526
2527template <typename T, int Size> class GenVec;
2528
2529template <typename T>
2530class GenVec<T, 1> : public DerivedFunc<Signature<T, T> >
2531{
2532public:
2533	typedef typename GenVec<T, 1>::ArgExprs ArgExprs;
2534
2535	string		getName		(void) const
2536	{
2537		return "_" + vecName<T, 1>();
2538	}
2539
2540protected:
2541
2542	ExprP<T>	doExpand	(ExpandContext&, const ArgExprs& args) const { return args.a; }
2543};
2544
2545template <typename T>
2546class GenVec<T, 2> : public PrimitiveFunc<Signature<Vector<T, 2>, T, T> >
2547{
2548public:
2549	typedef typename GenVec::IRet	IRet;
2550	typedef typename GenVec::IArgs	IArgs;
2551
2552	string		getName		(void) const
2553	{
2554		return vecName<T, 2>();
2555	}
2556
2557protected:
2558	IRet		doApply		(const EvalContext&, const IArgs& iargs) const
2559	{
2560		return IRet(iargs.a, iargs.b);
2561	}
2562};
2563
2564template <typename T>
2565class GenVec<T, 3> : public PrimitiveFunc<Signature<Vector<T, 3>, T, T, T> >
2566{
2567public:
2568	typedef typename GenVec::IRet	IRet;
2569	typedef typename GenVec::IArgs	IArgs;
2570
2571	string	getName		(void) const
2572	{
2573		return vecName<T, 3>();
2574	}
2575
2576protected:
2577	IRet	doApply		(const EvalContext&, const IArgs& iargs) const
2578	{
2579		return IRet(iargs.a, iargs.b, iargs.c);
2580	}
2581};
2582
2583template <typename T>
2584class GenVec<T, 4> : public PrimitiveFunc<Signature<Vector<T, 4>, T, T, T, T> >
2585{
2586public:
2587	typedef typename GenVec::IRet	IRet;
2588	typedef typename GenVec::IArgs	IArgs;
2589
2590	string		getName		(void) const { return vecName<T, 4>(); }
2591
2592protected:
2593	IRet		doApply		(const EvalContext&, const IArgs& iargs) const
2594	{
2595		return IRet(iargs.a, iargs.b, iargs.c, iargs.d);
2596	}
2597};
2598
2599
2600
2601template <typename T, int Rows, int Columns>
2602class GenMat;
2603
2604template <typename T, int Rows>
2605class GenMat<T, Rows, 2> : public PrimitiveFunc<
2606	Signature<Matrix<T, Rows, 2>, Vector<T, Rows>, Vector<T, Rows> > >
2607{
2608public:
2609	typedef typename GenMat::Ret	Ret;
2610	typedef typename GenMat::IRet	IRet;
2611	typedef typename GenMat::IArgs	IArgs;
2612
2613	string		getName		(void) const
2614	{
2615		return dataTypeNameOf<Ret>();
2616	}
2617
2618protected:
2619
2620	IRet		doApply		(const EvalContext&, const IArgs& iargs) const
2621	{
2622		IRet	ret;
2623		ret[0] = iargs.a;
2624		ret[1] = iargs.b;
2625		return ret;
2626	}
2627};
2628
2629template <typename T, int Rows>
2630class GenMat<T, Rows, 3> : public PrimitiveFunc<
2631	Signature<Matrix<T, Rows, 3>, Vector<T, Rows>, Vector<T, Rows>, Vector<T, Rows> > >
2632{
2633public:
2634	typedef typename GenMat::Ret	Ret;
2635	typedef typename GenMat::IRet	IRet;
2636	typedef typename GenMat::IArgs	IArgs;
2637
2638	string	getName	(void) const
2639	{
2640		return dataTypeNameOf<Ret>();
2641	}
2642
2643protected:
2644
2645	IRet	doApply	(const EvalContext&, const IArgs& iargs) const
2646	{
2647		IRet	ret;
2648		ret[0] = iargs.a;
2649		ret[1] = iargs.b;
2650		ret[2] = iargs.c;
2651		return ret;
2652	}
2653};
2654
2655template <typename T, int Rows>
2656class GenMat<T, Rows, 4> : public PrimitiveFunc<
2657	Signature<Matrix<T, Rows, 4>,
2658			  Vector<T, Rows>, Vector<T, Rows>, Vector<T, Rows>, Vector<T, Rows> > >
2659{
2660public:
2661	typedef typename GenMat::Ret	Ret;
2662	typedef typename GenMat::IRet	IRet;
2663	typedef typename GenMat::IArgs	IArgs;
2664
2665	string	getName	(void) const
2666	{
2667		return dataTypeNameOf<Ret>();
2668	}
2669
2670protected:
2671	IRet	doApply	(const EvalContext&, const IArgs& iargs) const
2672	{
2673		IRet	ret;
2674		ret[0] = iargs.a;
2675		ret[1] = iargs.b;
2676		ret[2] = iargs.c;
2677		ret[3] = iargs.d;
2678		return ret;
2679	}
2680};
2681
2682template <typename T, int Rows>
2683ExprP<Matrix<T, Rows, 2> > mat2 (const ExprP<Vector<T, Rows> >& arg0,
2684								 const ExprP<Vector<T, Rows> >& arg1)
2685{
2686	return app<GenMat<T, Rows, 2> >(arg0, arg1);
2687}
2688
2689template <typename T, int Rows>
2690ExprP<Matrix<T, Rows, 3> > mat3 (const ExprP<Vector<T, Rows> >& arg0,
2691								 const ExprP<Vector<T, Rows> >& arg1,
2692								 const ExprP<Vector<T, Rows> >& arg2)
2693{
2694	return app<GenMat<T, Rows, 3> >(arg0, arg1, arg2);
2695}
2696
2697template <typename T, int Rows>
2698ExprP<Matrix<T, Rows, 4> > mat4 (const ExprP<Vector<T, Rows> >& arg0,
2699								 const ExprP<Vector<T, Rows> >& arg1,
2700								 const ExprP<Vector<T, Rows> >& arg2,
2701								 const ExprP<Vector<T, Rows> >& arg3)
2702{
2703	return app<GenMat<T, Rows, 4> >(arg0, arg1, arg2, arg3);
2704}
2705
2706
2707template <int Rows, int Cols>
2708class MatNeg : public PrimitiveFunc<Signature<Matrix<float, Rows, Cols>,
2709											  Matrix<float, Rows, Cols> > >
2710{
2711public:
2712	typedef typename MatNeg::IRet		IRet;
2713	typedef typename MatNeg::IArgs		IArgs;
2714
2715	string	getName	(void) const
2716	{
2717		return "_matNeg";
2718	}
2719
2720protected:
2721	void	doPrint	(ostream& os, const BaseArgExprs& args) const
2722	{
2723		os << "-(" << *args[0] << ")";
2724	}
2725
2726	IRet	doApply	(const EvalContext&, const IArgs& iargs)			const
2727	{
2728		IRet	ret;
2729
2730		for (int col = 0; col < Cols; ++col)
2731		{
2732			for (int row = 0; row < Rows; ++row)
2733				ret[col][row] = -iargs.a[col][row];
2734		}
2735
2736		return ret;
2737	}
2738};
2739
2740template <typename T, typename Sig>
2741class CompWiseFunc : public PrimitiveFunc<Sig>
2742{
2743public:
2744	typedef Func<Signature<T, T, T> >	ScalarFunc;
2745
2746	string				getName			(void)									const
2747	{
2748		return doGetScalarFunc().getName();
2749	}
2750protected:
2751	void				doPrint			(ostream&				os,
2752										 const BaseArgExprs&	args)			const
2753	{
2754		doGetScalarFunc().print(os, args);
2755	}
2756
2757	virtual
2758	const ScalarFunc&	doGetScalarFunc	(void)									const = 0;
2759};
2760
2761template <int Rows, int Cols>
2762class CompMatFuncBase : public CompWiseFunc<float, Signature<Matrix<float, Rows, Cols>,
2763															 Matrix<float, Rows, Cols>,
2764															 Matrix<float, Rows, Cols> > >
2765{
2766public:
2767	typedef typename CompMatFuncBase::IRet		IRet;
2768	typedef typename CompMatFuncBase::IArgs		IArgs;
2769
2770protected:
2771
2772	IRet	doApply	(const EvalContext& ctx, const IArgs& iargs) const
2773	{
2774		IRet			ret;
2775
2776		for (int col = 0; col < Cols; ++col)
2777		{
2778			for (int row = 0; row < Rows; ++row)
2779				ret[col][row] = this->doGetScalarFunc().apply(ctx,
2780															  iargs.a[col][row],
2781															  iargs.b[col][row]);
2782		}
2783
2784		return ret;
2785	}
2786};
2787
2788template <typename F, int Rows, int Cols>
2789class CompMatFunc : public CompMatFuncBase<Rows, Cols>
2790{
2791protected:
2792	const typename CompMatFunc::ScalarFunc&	doGetScalarFunc	(void) const
2793	{
2794		return instance<F>();
2795	}
2796};
2797
2798class ScalarMatrixCompMult : public Mul
2799{
2800public:
2801	string	getName	(void) const
2802	{
2803		return "matrixCompMult";
2804	}
2805
2806	void	doPrint	(ostream& os, const BaseArgExprs& args) const
2807	{
2808		Func<Sig>::doPrint(os, args);
2809	}
2810};
2811
2812template <int Rows, int Cols>
2813class MatrixCompMult : public CompMatFunc<ScalarMatrixCompMult, Rows, Cols>
2814{
2815};
2816
2817template <int Rows, int Cols>
2818class ScalarMatFuncBase : public CompWiseFunc<float, Signature<Matrix<float, Rows, Cols>,
2819															   Matrix<float, Rows, Cols>,
2820															   float> >
2821{
2822public:
2823	typedef typename ScalarMatFuncBase::IRet	IRet;
2824	typedef typename ScalarMatFuncBase::IArgs	IArgs;
2825
2826protected:
2827
2828	IRet	doApply	(const EvalContext& ctx, const IArgs& iargs) const
2829	{
2830		IRet	ret;
2831
2832		for (int col = 0; col < Cols; ++col)
2833		{
2834			for (int row = 0; row < Rows; ++row)
2835				ret[col][row] = this->doGetScalarFunc().apply(ctx, iargs.a[col][row], iargs.b);
2836		}
2837
2838		return ret;
2839	}
2840};
2841
2842template <typename F, int Rows, int Cols>
2843class ScalarMatFunc : public ScalarMatFuncBase<Rows, Cols>
2844{
2845protected:
2846	const typename ScalarMatFunc::ScalarFunc&	doGetScalarFunc	(void)	const
2847	{
2848		return instance<F>();
2849	}
2850};
2851
2852template<typename T, int Size> struct GenXType;
2853
2854template<typename T>
2855struct GenXType<T, 1>
2856{
2857	static ExprP<T>	genXType	(const ExprP<T>& x) { return x; }
2858};
2859
2860template<typename T>
2861struct GenXType<T, 2>
2862{
2863	static ExprP<Vector<T, 2> >	genXType	(const ExprP<T>& x)
2864	{
2865		return app<GenVec<T, 2> >(x, x);
2866	}
2867};
2868
2869template<typename T>
2870struct GenXType<T, 3>
2871{
2872	static ExprP<Vector<T, 3> >	genXType	(const ExprP<T>& x)
2873	{
2874		return app<GenVec<T, 3> >(x, x, x);
2875	}
2876};
2877
2878template<typename T>
2879struct GenXType<T, 4>
2880{
2881	static ExprP<Vector<T, 4> >	genXType	(const ExprP<T>& x)
2882	{
2883		return app<GenVec<T, 4> >(x, x, x, x);
2884	}
2885};
2886
2887//! Returns an expression of vector of size `Size` (or scalar if Size == 1),
2888//! with each element initialized with the expression `x`.
2889template<typename T, int Size>
2890ExprP<typename ContainerOf<T, Size>::Container> genXType (const ExprP<T>& x)
2891{
2892	return GenXType<T, Size>::genXType(x);
2893}
2894
2895typedef GenVec<float, 2> FloatVec2;
2896DEFINE_CONSTRUCTOR2(FloatVec2, Vec2, vec2, float, float)
2897
2898typedef GenVec<float, 3> FloatVec3;
2899DEFINE_CONSTRUCTOR3(FloatVec3, Vec3, vec3, float, float, float)
2900
2901typedef GenVec<float, 4> FloatVec4;
2902DEFINE_CONSTRUCTOR4(FloatVec4, Vec4, vec4, float, float, float, float)
2903
2904template <int Size>
2905class Dot : public DerivedFunc<Signature<float, Vector<float, Size>, Vector<float, Size> > >
2906{
2907public:
2908	typedef typename Dot::ArgExprs ArgExprs;
2909
2910	string			getName		(void) const
2911	{
2912		return "dot";
2913	}
2914
2915protected:
2916	ExprP<float>	doExpand 	(ExpandContext&, const ArgExprs& args) const
2917	{
2918		ExprP<float> val = args.a[0] * args.b[0];
2919
2920		for (int ndx = 1; ndx < Size; ++ndx)
2921			val = val + args.a[ndx] * args.b[ndx];
2922
2923		return val;
2924	}
2925};
2926
2927template <>
2928class Dot<1> : public DerivedFunc<Signature<float, float, float> >
2929{
2930public:
2931	string			getName		(void) const
2932	{
2933		return "dot";
2934	}
2935
2936	ExprP<float>	doExpand 	(ExpandContext&, const ArgExprs& args) const
2937	{
2938		return args.a * args.b;
2939	}
2940};
2941
2942template <int Size>
2943ExprP<float> dot (const ExprP<Vector<float, Size> >& x, const ExprP<Vector<float, Size> >& y)
2944{
2945	return app<Dot<Size> >(x, y);
2946}
2947
2948ExprP<float> dot (const ExprP<float>& x, const ExprP<float>& y)
2949{
2950	return app<Dot<1> >(x, y);
2951}
2952
2953template <int Size>
2954class Length : public DerivedFunc<
2955	Signature<float, typename ContainerOf<float, Size>::Container> >
2956{
2957public:
2958	typedef typename Length::ArgExprs ArgExprs;
2959
2960	string			getName		(void) const
2961	{
2962		return "length";
2963	}
2964
2965protected:
2966	ExprP<float>	doExpand	(ExpandContext&, const ArgExprs& args) const
2967	{
2968		return sqrt(dot(args.a, args.a));
2969	}
2970};
2971
2972template <int Size>
2973ExprP<float> length (const ExprP<typename ContainerOf<float, Size>::Container>& x)
2974{
2975	return app<Length<Size> >(x);
2976}
2977
2978template <int Size>
2979class Distance : public DerivedFunc<
2980	Signature<float,
2981			  typename ContainerOf<float, Size>::Container,
2982			  typename ContainerOf<float, Size>::Container> >
2983{
2984public:
2985	typedef typename	Distance::Ret		Ret;
2986	typedef typename	Distance::ArgExprs	ArgExprs;
2987
2988	string		getName		(void) const
2989	{
2990		return "distance";
2991	}
2992
2993protected:
2994	ExprP<Ret>	doExpand 	(ExpandContext&, const ArgExprs& args) const
2995	{
2996		return length<Size>(args.a - args.b);
2997	}
2998};
2999
3000// cross
3001
3002class Cross : public DerivedFunc<Signature<Vec3, Vec3, Vec3> >
3003{
3004public:
3005	string			getName		(void) const
3006	{
3007		return "cross";
3008	}
3009
3010protected:
3011	ExprP<Vec3>		doExpand 	(ExpandContext&, const ArgExprs& x) const
3012	{
3013		return vec3(x.a[1] * x.b[2] - x.b[1] * x.a[2],
3014					x.a[2] * x.b[0] - x.b[2] * x.a[0],
3015					x.a[0] * x.b[1] - x.b[0] * x.a[1]);
3016	}
3017};
3018
3019DEFINE_CONSTRUCTOR2(Cross, Vec3, cross, Vec3, Vec3)
3020
3021template<int Size>
3022class Normalize : public DerivedFunc<
3023	Signature<typename ContainerOf<float, Size>::Container,
3024			  typename ContainerOf<float, Size>::Container> >
3025{
3026public:
3027	typedef typename	Normalize::Ret		Ret;
3028	typedef typename	Normalize::ArgExprs	ArgExprs;
3029
3030	string		getName		(void) const
3031	{
3032		return "normalize";
3033	}
3034
3035protected:
3036	ExprP<Ret>	doExpand	(ExpandContext&, const ArgExprs& args) const
3037	{
3038		return args.a / length<Size>(args.a);
3039	}
3040};
3041
3042template <int Size>
3043class FaceForward : public DerivedFunc<
3044	Signature<typename ContainerOf<float, Size>::Container,
3045			  typename ContainerOf<float, Size>::Container,
3046			  typename ContainerOf<float, Size>::Container,
3047			  typename ContainerOf<float, Size>::Container> >
3048{
3049public:
3050	typedef typename	FaceForward::Ret		Ret;
3051	typedef typename	FaceForward::ArgExprs	ArgExprs;
3052
3053	string		getName		(void) const
3054	{
3055		return "faceforward";
3056	}
3057
3058protected:
3059
3060
3061	ExprP<Ret>	doExpand	(ExpandContext&, const ArgExprs& args) const
3062	{
3063		return cond(dot(args.c, args.b) < constant(0.0f), args.a, -args.a);
3064	}
3065};
3066
3067template <int Size>
3068class Reflect : public DerivedFunc<
3069	Signature<typename ContainerOf<float, Size>::Container,
3070			  typename ContainerOf<float, Size>::Container,
3071			  typename ContainerOf<float, Size>::Container> >
3072{
3073public:
3074	typedef typename	Reflect::Ret		Ret;
3075	typedef typename	Reflect::Arg0		Arg0;
3076	typedef typename	Reflect::Arg1		Arg1;
3077	typedef typename	Reflect::ArgExprs	ArgExprs;
3078
3079	string		getName		(void) const
3080	{
3081		return "reflect";
3082	}
3083
3084protected:
3085	ExprP<Ret>	doExpand	(ExpandContext& ctx, const ArgExprs& args) const
3086	{
3087		const ExprP<Arg0>&	i		= args.a;
3088		const ExprP<Arg1>&	n		= args.b;
3089		const ExprP<float>	dotNI	= bindExpression("dotNI", ctx, dot(n, i));
3090
3091		return i - alternatives((n * dotNI) * constant(2.0f),
3092								n * (dotNI * constant(2.0f)));
3093	}
3094};
3095
3096template <int Size>
3097class Refract : public DerivedFunc<
3098	Signature<typename ContainerOf<float, Size>::Container,
3099			  typename ContainerOf<float, Size>::Container,
3100			  typename ContainerOf<float, Size>::Container,
3101			  float> >
3102{
3103public:
3104	typedef typename	Refract::Ret		Ret;
3105	typedef typename	Refract::Arg0		Arg0;
3106	typedef typename	Refract::Arg1		Arg1;
3107	typedef typename	Refract::ArgExprs	ArgExprs;
3108
3109	string		getName		(void) const
3110	{
3111		return "refract";
3112	}
3113
3114protected:
3115	ExprP<Ret>	doExpand	(ExpandContext&	ctx, const ArgExprs& args) const
3116	{
3117		const ExprP<Arg0>&	i		= args.a;
3118		const ExprP<Arg1>&	n		= args.b;
3119		const ExprP<float>&	eta		= args.c;
3120		const ExprP<float>	dotNI	= bindExpression("dotNI", ctx, dot(n, i));
3121		const ExprP<float>	k		= bindExpression("k", ctx, constant(1.0f) - eta * eta *
3122												 (constant(1.0f) - dotNI * dotNI));
3123
3124		return cond(k < constant(0.0f),
3125					genXType<float, Size>(constant(0.0f)),
3126					i * eta - n * (eta * dotNI + sqrt(k)));
3127	}
3128};
3129
3130class PreciseFunc1 : public CFloatFunc1
3131{
3132public:
3133			PreciseFunc1	(const string& name, DoubleFunc1& func) : CFloatFunc1(name, func) {}
3134protected:
3135	double	precision		(const EvalContext&, double, double) const	{ return 0.0; }
3136};
3137
3138class Abs : public PreciseFunc1
3139{
3140public:
3141	Abs (void) : PreciseFunc1("abs", deAbs) {}
3142};
3143
3144class Sign : public PreciseFunc1
3145{
3146public:
3147	Sign (void) : PreciseFunc1("sign", deSign) {}
3148};
3149
3150class Floor : public PreciseFunc1
3151{
3152public:
3153	Floor (void) : PreciseFunc1("floor", deFloor) {}
3154};
3155
3156class Trunc : public PreciseFunc1
3157{
3158public:
3159	Trunc (void) : PreciseFunc1("trunc", deTrunc) {}
3160};
3161
3162class Round : public FloatFunc1
3163{
3164public:
3165	string		getName		(void) const								{ return "round"; }
3166
3167protected:
3168	Interval	applyPoint	(const EvalContext&, double x) const
3169	{
3170		double			truncated	= 0.0;
3171		const double	fract		= deModf(x, &truncated);
3172		Interval		ret;
3173
3174		if (fabs(fract) <= 0.5)
3175			ret |= truncated;
3176		if (fabs(fract) >= 0.5)
3177			ret |= truncated + deSign(fract);
3178
3179		return ret;
3180	}
3181
3182	double		precision	(const EvalContext&, double, double) const	{ return 0.0; }
3183};
3184
3185class RoundEven : public PreciseFunc1
3186{
3187public:
3188	RoundEven (void) : PreciseFunc1("roundEven", deRoundEven) {}
3189};
3190
3191class Ceil : public PreciseFunc1
3192{
3193public:
3194	Ceil (void) : PreciseFunc1("ceil", deCeil) {}
3195};
3196
3197DEFINE_DERIVED_FLOAT1(Fract, fract, x, x - app<Floor>(x));
3198
3199class PreciseFunc2 : public CFloatFunc2
3200{
3201public:
3202			PreciseFunc2	(const string& name, DoubleFunc2& func) : CFloatFunc2(name, func) {}
3203protected:
3204	double	precision		(const EvalContext&, double, double, double) const { return 0.0; }
3205};
3206
3207DEFINE_DERIVED_FLOAT2(Mod, mod, x, y, x - y * app<Floor>(x / y));
3208
3209class Modf : public PrimitiveFunc<Signature<float, float, float> >
3210{
3211public:
3212	string	getName				(void) const
3213	{
3214		return "modf";
3215	}
3216
3217protected:
3218	IRet	doApply				(const EvalContext& ctx, const IArgs& iargs) const
3219	{
3220		Interval	fracIV;
3221		Interval&	wholeIV		= const_cast<Interval&>(iargs.b);
3222		double		intPart		= 0;
3223
3224		TCU_INTERVAL_APPLY_MONOTONE1(fracIV, x, iargs.a, frac, frac = deModf(x, &intPart));
3225		TCU_INTERVAL_APPLY_MONOTONE1(wholeIV, x, iargs.a, whole,
3226									 deModf(x, &intPart); whole = intPart);
3227
3228		if ((ctx.format.hasInf() != YES) && !iargs.a.isFinite())
3229		{
3230			// Behavior on modf(Inf) not well-defined, allow anything as a fractional part
3231			fracIV |= TCU_NAN;
3232		}
3233
3234		return fracIV;
3235	}
3236
3237	int		getOutParamIndex	(void) const
3238	{
3239		return 1;
3240	}
3241};
3242
3243class Min : public PreciseFunc2 { public: Min (void) : PreciseFunc2("min", deMin) {} };
3244class Max : public PreciseFunc2 { public: Max (void) : PreciseFunc2("max", deMax) {} };
3245
3246class Clamp : public FloatFunc3
3247{
3248public:
3249	string	getName		(void) const { return "clamp"; }
3250
3251	double	applyExact	(double x, double minVal, double maxVal) const
3252	{
3253		return de::min(de::max(x, minVal), maxVal);
3254	}
3255
3256	double	precision	(const EvalContext&, double, double, double minVal, double maxVal) const
3257	{
3258		return minVal > maxVal ? TCU_NAN : 0.0;
3259	}
3260};
3261
3262ExprP<float> clamp(const ExprP<float>& x, const ExprP<float>& minVal, const ExprP<float>& maxVal)
3263{
3264	return app<Clamp>(x, minVal, maxVal);
3265}
3266
3267DEFINE_DERIVED_FLOAT3(Mix, mix, x, y, a, alternatives((x * (constant(1.0f) - a)) + y * a,
3268													  x + (y - x) * a));
3269
3270static double step (double edge, double x)
3271{
3272	return x < edge ? 0.0 : 1.0;
3273}
3274
3275class Step : public PreciseFunc2 { public: Step (void) : PreciseFunc2("step", step) {} };
3276
3277class SmoothStep : public DerivedFunc<Signature<float, float, float, float> >
3278{
3279public:
3280	string		getName		(void) const
3281	{
3282		return "smoothstep";
3283	}
3284
3285protected:
3286
3287	ExprP<Ret>	doExpand 	(ExpandContext& ctx, const ArgExprs& args) const
3288	{
3289		const ExprP<float>&		edge0	= args.a;
3290		const ExprP<float>&		edge1	= args.b;
3291		const ExprP<float>&		x		= args.c;
3292		const ExprP<float>		tExpr	= clamp((x - edge0) / (edge1 - edge0),
3293											constant(0.0f), constant(1.0f));
3294		const ExprP<float>		t		= bindExpression("t", ctx, tExpr);
3295
3296		return (t * t * (constant(3.0f) - constant(2.0f) * t));
3297	}
3298};
3299
3300class FrExp : public PrimitiveFunc<Signature<float, float, int> >
3301{
3302public:
3303	string	getName			(void) const
3304	{
3305		return "frexp";
3306	}
3307
3308protected:
3309	IRet	doApply			(const EvalContext&, const IArgs& iargs) const
3310	{
3311		IRet			ret;
3312		const IArg0&	x			= iargs.a;
3313		IArg1&			exponent	= const_cast<IArg1&>(iargs.b);
3314
3315		if (x.hasNaN() || x.contains(TCU_INFINITY) || x.contains(-TCU_INFINITY))
3316		{
3317			// GLSL (in contrast to IEEE) says that result of applying frexp
3318			// to infinity is undefined
3319			ret = Interval::unbounded() | TCU_NAN;
3320			exponent = Interval(-deLdExp(1.0, 31), deLdExp(1.0, 31)-1);
3321		}
3322		else if (!x.empty())
3323		{
3324			int				loExp	= 0;
3325			const double	loFrac	= deFrExp(x.lo(), &loExp);
3326			int				hiExp	= 0;
3327			const double	hiFrac	= deFrExp(x.hi(), &hiExp);
3328
3329			if (deSign(loFrac) != deSign(hiFrac))
3330			{
3331				exponent = Interval(-TCU_INFINITY, de::max(loExp, hiExp));
3332				ret = Interval();
3333				if (deSign(loFrac) < 0)
3334					ret |= Interval(-1.0 + DBL_EPSILON*0.5, 0.0);
3335				if (deSign(hiFrac) > 0)
3336					ret |= Interval(0.0, 1.0 - DBL_EPSILON*0.5);
3337			}
3338			else
3339			{
3340				exponent = Interval(loExp, hiExp);
3341				if (loExp == hiExp)
3342					ret = Interval(loFrac, hiFrac);
3343				else
3344					ret = deSign(loFrac) * Interval(0.5, 1.0 - DBL_EPSILON*0.5);
3345			}
3346		}
3347
3348		return ret;
3349	}
3350
3351	int	getOutParamIndex	(void) const
3352	{
3353		return 1;
3354	}
3355};
3356
3357class LdExp : public PrimitiveFunc<Signature<float, float, int> >
3358{
3359public:
3360	string		getName			(void) const
3361	{
3362		return "ldexp";
3363	}
3364
3365protected:
3366	Interval	doApply			(const EvalContext& ctx, const IArgs& iargs) const
3367	{
3368		Interval	ret = call<Exp2>(ctx, iargs.b);
3369		// Khronos bug 11180 consensus: if exp2(exponent) cannot be represented,
3370		// the result is undefined.
3371
3372		if (ret.contains(TCU_INFINITY) | ret.contains(-TCU_INFINITY))
3373			ret |= TCU_NAN;
3374
3375		return call<Mul>(ctx, iargs.a, ret);
3376	}
3377};
3378
3379template<int Rows, int Columns>
3380class Transpose : public PrimitiveFunc<Signature<Matrix<float, Rows, Columns>,
3381												 Matrix<float, Columns, Rows> > >
3382{
3383public:
3384	typedef typename Transpose::IRet	IRet;
3385	typedef typename Transpose::IArgs	IArgs;
3386
3387	string		getName		(void) const
3388	{
3389		return "transpose";
3390	}
3391
3392protected:
3393	IRet		doApply		(const EvalContext&, const IArgs& iargs) const
3394	{
3395		IRet ret;
3396
3397		for (int rowNdx = 0; rowNdx < Rows; ++rowNdx)
3398		{
3399			for (int colNdx = 0; colNdx < Columns; ++colNdx)
3400				ret(rowNdx, colNdx) = iargs.a(colNdx, rowNdx);
3401		}
3402
3403		return ret;
3404	}
3405};
3406
3407template<typename Ret, typename Arg0, typename Arg1>
3408class MulFunc : public PrimitiveFunc<Signature<Ret, Arg0, Arg1> >
3409{
3410public:
3411	string	getName	(void) const 									{ return "mul"; }
3412
3413protected:
3414	void	doPrint	(ostream& os, const BaseArgExprs& args) const
3415	{
3416		os << "(" << *args[0] << " * " << *args[1] << ")";
3417	}
3418};
3419
3420template<int LeftRows, int Middle, int RightCols>
3421class MatMul : public MulFunc<Matrix<float, LeftRows, RightCols>,
3422							  Matrix<float, LeftRows, Middle>,
3423							  Matrix<float, Middle, RightCols> >
3424{
3425protected:
3426	typedef typename MatMul::IRet	IRet;
3427	typedef typename MatMul::IArgs	IArgs;
3428	typedef typename MatMul::IArg0	IArg0;
3429	typedef typename MatMul::IArg1	IArg1;
3430
3431	IRet	doApply	(const EvalContext&	ctx, const IArgs& iargs) const
3432	{
3433		const IArg0&	left	= iargs.a;
3434		const IArg1&	right	= iargs.b;
3435		IRet			ret;
3436
3437		for (int row = 0; row < LeftRows; ++row)
3438		{
3439			for (int col = 0; col < RightCols; ++col)
3440			{
3441				Interval	element	(0.0);
3442
3443				for (int ndx = 0; ndx < Middle; ++ndx)
3444					element = call<Add>(ctx, element,
3445										call<Mul>(ctx, left[ndx][row], right[col][ndx]));
3446
3447				ret[col][row] = element;
3448			}
3449		}
3450
3451		return ret;
3452	}
3453};
3454
3455template<int Rows, int Cols>
3456class VecMatMul : public MulFunc<Vector<float, Cols>,
3457								 Vector<float, Rows>,
3458								 Matrix<float, Rows, Cols> >
3459{
3460public:
3461	typedef typename VecMatMul::IRet	IRet;
3462	typedef typename VecMatMul::IArgs	IArgs;
3463	typedef typename VecMatMul::IArg0	IArg0;
3464	typedef typename VecMatMul::IArg1	IArg1;
3465
3466protected:
3467	IRet	doApply	(const EvalContext& ctx, const IArgs& iargs) const
3468	{
3469		const IArg0&	left	= iargs.a;
3470		const IArg1&	right	= iargs.b;
3471		IRet			ret;
3472
3473		for (int col = 0; col < Cols; ++col)
3474		{
3475			Interval	element	(0.0);
3476
3477			for (int row = 0; row < Rows; ++row)
3478				element = call<Add>(ctx, element, call<Mul>(ctx, left[row], right[col][row]));
3479
3480			ret[col] = element;
3481		}
3482
3483		return ret;
3484	}
3485};
3486
3487template<int Rows, int Cols>
3488class MatVecMul : public MulFunc<Vector<float, Rows>,
3489								 Matrix<float, Rows, Cols>,
3490								 Vector<float, Cols> >
3491{
3492public:
3493	typedef typename MatVecMul::IRet	IRet;
3494	typedef typename MatVecMul::IArgs	IArgs;
3495	typedef typename MatVecMul::IArg0	IArg0;
3496	typedef typename MatVecMul::IArg1	IArg1;
3497
3498protected:
3499	IRet	doApply	(const EvalContext& ctx, const IArgs& iargs) const
3500	{
3501		const IArg0&	left	= iargs.a;
3502		const IArg1&	right	= iargs.b;
3503
3504		return call<VecMatMul<Cols, Rows> >(ctx, right,
3505											call<Transpose<Rows, Cols> >(ctx, left));
3506	}
3507};
3508
3509template<int Rows, int Cols>
3510class OuterProduct : public PrimitiveFunc<Signature<Matrix<float, Rows, Cols>,
3511													Vector<float, Rows>,
3512													Vector<float, Cols> > >
3513{
3514public:
3515	typedef typename OuterProduct::IRet		IRet;
3516	typedef typename OuterProduct::IArgs	IArgs;
3517
3518	string	getName	(void) const
3519	{
3520		return "outerProduct";
3521	}
3522
3523protected:
3524	IRet	doApply	(const EvalContext& ctx, const IArgs& iargs) const
3525	{
3526		IRet	ret;
3527
3528		for (int row = 0; row < Rows; ++row)
3529		{
3530			for (int col = 0; col < Cols; ++col)
3531				ret[col][row] = call<Mul>(ctx, iargs.a[row], iargs.b[col]);
3532		}
3533
3534		return ret;
3535	}
3536};
3537
3538template<int Rows, int Cols>
3539ExprP<Matrix<float, Rows, Cols> > outerProduct (const ExprP<Vector<float, Rows> >& left,
3540												const ExprP<Vector<float, Cols> >& right)
3541{
3542	return app<OuterProduct<Rows, Cols> >(left, right);
3543}
3544
3545template<int Size>
3546class DeterminantBase : public DerivedFunc<Signature<float, Matrix<float, Size, Size> > >
3547{
3548public:
3549	string	getName	(void) const { return "determinant"; }
3550};
3551
3552template<int Size>
3553class Determinant;
3554
3555template<int Size>
3556ExprP<float> determinant (ExprP<Matrix<float, Size, Size> > mat)
3557{
3558	return app<Determinant<Size> >(mat);
3559}
3560
3561template<>
3562class Determinant<2> : public DeterminantBase<2>
3563{
3564protected:
3565	ExprP<Ret>	doExpand (ExpandContext&, const ArgExprs& args)	const
3566	{
3567		ExprP<Mat2>	mat	= args.a;
3568
3569		return mat[0][0] * mat[1][1] - mat[1][0] * mat[0][1];
3570	}
3571};
3572
3573template<>
3574class Determinant<3> : public DeterminantBase<3>
3575{
3576protected:
3577	ExprP<Ret> doExpand (ExpandContext&, const ArgExprs& args) const
3578	{
3579		ExprP<Mat3>	mat	= args.a;
3580
3581		return (mat[0][0] * (mat[1][1] * mat[2][2] - mat[1][2] * mat[2][1]) +
3582				mat[0][1] * (mat[1][2] * mat[2][0] - mat[1][0] * mat[2][2]) +
3583				mat[0][2] * (mat[1][0] * mat[2][1] - mat[1][1] * mat[2][0]));
3584	}
3585};
3586
3587template<>
3588class Determinant<4> : public DeterminantBase<4>
3589{
3590protected:
3591	 ExprP<Ret>	doExpand	(ExpandContext& ctx, const ArgExprs& args) const
3592	{
3593		ExprP<Mat4>	mat	= args.a;
3594		ExprP<Mat3>	minors[4];
3595
3596		for (int ndx = 0; ndx < 4; ++ndx)
3597		{
3598			ExprP<Vec4>		minorColumns[3];
3599			ExprP<Vec3>		columns[3];
3600
3601			for (int col = 0; col < 3; ++col)
3602				minorColumns[col] = mat[col < ndx ? col : col + 1];
3603
3604			for (int col = 0; col < 3; ++col)
3605				columns[col] = vec3(minorColumns[0][col+1],
3606									minorColumns[1][col+1],
3607									minorColumns[2][col+1]);
3608
3609			minors[ndx] = bindExpression("minor", ctx,
3610										 mat3(columns[0], columns[1], columns[2]));
3611		}
3612
3613		return (mat[0][0] * determinant(minors[0]) -
3614				mat[1][0] * determinant(minors[1]) +
3615				mat[2][0] * determinant(minors[2]) -
3616				mat[3][0] * determinant(minors[3]));
3617	}
3618};
3619
3620template<int Size> class Inverse;
3621
3622template <int Size>
3623ExprP<Matrix<float, Size, Size> > inverse (ExprP<Matrix<float, Size, Size> > mat)
3624{
3625	return app<Inverse<Size> >(mat);
3626}
3627
3628template<>
3629class Inverse<2> : public DerivedFunc<Signature<Mat2, Mat2> >
3630{
3631public:
3632	string		getName	(void) const
3633	{
3634		return "inverse";
3635	}
3636
3637protected:
3638	ExprP<Ret>	doExpand (ExpandContext& ctx, const ArgExprs& args) const
3639	{
3640		ExprP<Mat2>		mat = args.a;
3641		ExprP<float>	det	= bindExpression("det", ctx, determinant(mat));
3642
3643		return mat2(vec2(mat[1][1] / det, -mat[0][1] / det),
3644					vec2(-mat[1][0] / det, mat[0][0] / det));
3645	}
3646};
3647
3648template<>
3649class Inverse<3> : public DerivedFunc<Signature<Mat3, Mat3> >
3650{
3651public:
3652	string		getName		(void) const
3653	{
3654		return "inverse";
3655	}
3656
3657protected:
3658	ExprP<Ret>	doExpand 	(ExpandContext& ctx, const ArgExprs& args)			const
3659	{
3660		ExprP<Mat3>		mat		= args.a;
3661		ExprP<Mat2>		invA	= bindExpression("invA", ctx,
3662												 inverse(mat2(vec2(mat[0][0], mat[0][1]),
3663															  vec2(mat[1][0], mat[1][1]))));
3664
3665		ExprP<Vec2>		matB	= bindExpression("matB", ctx, vec2(mat[2][0], mat[2][1]));
3666		ExprP<Vec2>		matC	= bindExpression("matC", ctx, vec2(mat[0][2], mat[1][2]));
3667		ExprP<float>	matD	= bindExpression("matD", ctx, mat[2][2]);
3668
3669		ExprP<float>	schur	= bindExpression("schur", ctx,
3670												 constant(1.0f) /
3671												 (matD - dot(matC * invA, matB)));
3672
3673		ExprP<Vec2>		t1		= invA * matB;
3674		ExprP<Vec2>		t2		= t1 * schur;
3675		ExprP<Mat2>		t3		= outerProduct(t2, matC);
3676		ExprP<Mat2>		t4		= t3 * invA;
3677		ExprP<Mat2>		t5		= invA + t4;
3678		ExprP<Mat2>		blockA	= bindExpression("blockA", ctx, t5);
3679		ExprP<Vec2>		blockB	= bindExpression("blockB", ctx,
3680												 (invA * matB) * -schur);
3681		ExprP<Vec2>		blockC	= bindExpression("blockC", ctx,
3682												 (matC * invA) * -schur);
3683
3684		return mat3(vec3(blockA[0][0], blockA[0][1], blockC[0]),
3685					vec3(blockA[1][0], blockA[1][1], blockC[1]),
3686					vec3(blockB[0], blockB[1], schur));
3687	}
3688};
3689
3690template<>
3691class Inverse<4> : public DerivedFunc<Signature<Mat4, Mat4> >
3692{
3693public:
3694	string		getName		(void) const { return "inverse"; }
3695
3696protected:
3697	ExprP<Ret>			doExpand 			(ExpandContext&		ctx,
3698											 const ArgExprs&	args)			const
3699	{
3700		ExprP<Mat4>	mat		= args.a;
3701		ExprP<Mat2>	invA	= bindExpression("invA", ctx,
3702											 inverse(mat2(vec2(mat[0][0], mat[0][1]),
3703														  vec2(mat[1][0], mat[1][1]))));
3704		ExprP<Mat2>	matB	= bindExpression("matB", ctx,
3705											 mat2(vec2(mat[2][0], mat[2][1]),
3706												  vec2(mat[3][0], mat[3][1])));
3707		ExprP<Mat2>	matC	= bindExpression("matC", ctx,
3708											 mat2(vec2(mat[0][2], mat[0][3]),
3709												  vec2(mat[1][2], mat[1][3])));
3710		ExprP<Mat2>	matD	= bindExpression("matD", ctx,
3711											 mat2(vec2(mat[2][2], mat[2][3]),
3712												  vec2(mat[3][2], mat[3][3])));
3713		ExprP<Mat2>	schur	= bindExpression("schur", ctx,
3714											 inverse(matD + -(matC * invA * matB)));
3715		ExprP<Mat2>	blockA	= bindExpression("blockA", ctx,
3716											 invA + (invA * matB * schur * matC * invA));
3717		ExprP<Mat2>	blockB	= bindExpression("blockB", ctx,
3718											 (-invA) * matB * schur);
3719		ExprP<Mat2>	blockC	= bindExpression("blockC", ctx,
3720											 (-schur) * matC * invA);
3721
3722		return mat4(vec4(blockA[0][0], blockA[0][1], blockC[0][0], blockC[0][1]),
3723					vec4(blockA[1][0], blockA[1][1], blockC[1][0], blockC[1][1]),
3724					vec4(blockB[0][0], blockB[0][1], schur[0][0], schur[0][1]),
3725					vec4(blockB[1][0], blockB[1][1], schur[1][0], schur[1][1]));
3726	}
3727};
3728
3729class Fma : public DerivedFunc<Signature<float, float, float, float> >
3730{
3731public:
3732	string			getName					(void) const
3733	{
3734		return "fma";
3735	}
3736
3737	string			getRequiredExtension	(void) const
3738	{
3739		return "GL_EXT_gpu_shader5";
3740	}
3741
3742protected:
3743	ExprP<float>	doExpand 				(ExpandContext&, const ArgExprs& x) const
3744	{
3745		return x.a * x.b + x.c;
3746	}
3747};
3748
3749} // Functions
3750
3751using namespace Functions;
3752
3753template <typename T>
3754ExprP<typename T::Element> ContainerExprPBase<T>::operator[] (int i) const
3755{
3756	return Functions::getComponent(exprP<T>(*this), i);
3757}
3758
3759ExprP<float> operator+ (const ExprP<float>& arg0, const ExprP<float>& arg1)
3760{
3761	return app<Add>(arg0, arg1);
3762}
3763
3764ExprP<float> operator- (const ExprP<float>& arg0, const ExprP<float>& arg1)
3765{
3766	return app<Sub>(arg0, arg1);
3767}
3768
3769ExprP<float> operator- (const ExprP<float>& arg0)
3770{
3771	return app<Negate>(arg0);
3772}
3773
3774ExprP<float> operator* (const ExprP<float>& arg0, const ExprP<float>& arg1)
3775{
3776	return app<Mul>(arg0, arg1);
3777}
3778
3779ExprP<float> operator/ (const ExprP<float>& arg0, const ExprP<float>& arg1)
3780{
3781	return app<Div>(arg0, arg1);
3782}
3783
3784template <typename Sig_, int Size>
3785class GenFunc : public PrimitiveFunc<Signature<
3786	typename ContainerOf<typename Sig_::Ret, Size>::Container,
3787	typename ContainerOf<typename Sig_::Arg0, Size>::Container,
3788	typename ContainerOf<typename Sig_::Arg1, Size>::Container,
3789	typename ContainerOf<typename Sig_::Arg2, Size>::Container,
3790	typename ContainerOf<typename Sig_::Arg3, Size>::Container> >
3791{
3792public:
3793	typedef typename GenFunc::IArgs		IArgs;
3794	typedef typename GenFunc::IRet		IRet;
3795
3796			GenFunc					(const Func<Sig_>&	scalarFunc) : m_func (scalarFunc) {}
3797
3798	string	getName					(void) const
3799	{
3800		return m_func.getName();
3801	}
3802
3803	int		getOutParamIndex		(void) const
3804	{
3805		return m_func.getOutParamIndex();
3806	}
3807
3808	string	getRequiredExtension	(void) const
3809	{
3810		return m_func.getRequiredExtension();
3811	}
3812
3813protected:
3814	void	doPrint					(ostream& os, const BaseArgExprs& args) const
3815	{
3816		m_func.print(os, args);
3817	}
3818
3819	IRet	doApply					(const EvalContext& ctx, const IArgs& iargs) const
3820	{
3821		IRet ret;
3822
3823		for (int ndx = 0; ndx < Size; ++ndx)
3824		{
3825			ret[ndx] =
3826				m_func.apply(ctx, iargs.a[ndx], iargs.b[ndx], iargs.c[ndx], iargs.d[ndx]);
3827		}
3828
3829		return ret;
3830	}
3831
3832	void	doGetUsedFuncs			(FuncSet& dst) const
3833	{
3834		m_func.getUsedFuncs(dst);
3835	}
3836
3837	const Func<Sig_>&	m_func;
3838};
3839
3840template <typename F, int Size>
3841class VectorizedFunc : public GenFunc<typename F::Sig, Size>
3842{
3843public:
3844	VectorizedFunc	(void) : GenFunc<typename F::Sig, Size>(instance<F>()) {}
3845};
3846
3847
3848
3849template <typename Sig_, int Size>
3850class FixedGenFunc : public PrimitiveFunc <Signature<
3851	typename ContainerOf<typename Sig_::Ret, Size>::Container,
3852	typename ContainerOf<typename Sig_::Arg0, Size>::Container,
3853	typename Sig_::Arg1,
3854	typename ContainerOf<typename Sig_::Arg2, Size>::Container,
3855	typename ContainerOf<typename Sig_::Arg3, Size>::Container> >
3856{
3857public:
3858	typedef typename FixedGenFunc::IArgs		IArgs;
3859	typedef typename FixedGenFunc::IRet			IRet;
3860
3861	string						getName			(void) const
3862	{
3863		return this->doGetScalarFunc().getName();
3864	}
3865
3866protected:
3867	void						doPrint			(ostream& os, const BaseArgExprs& args) const
3868	{
3869		this->doGetScalarFunc().print(os, args);
3870	}
3871
3872	IRet						doApply			(const EvalContext& ctx,
3873												 const IArgs&		iargs) const
3874	{
3875		IRet				ret;
3876		const Func<Sig_>&	func	= this->doGetScalarFunc();
3877
3878		for (int ndx = 0; ndx < Size; ++ndx)
3879			ret[ndx] = func.apply(ctx, iargs.a[ndx], iargs.b, iargs.c[ndx], iargs.d[ndx]);
3880
3881		return ret;
3882	}
3883
3884	virtual const Func<Sig_>&	doGetScalarFunc	(void) const = 0;
3885};
3886
3887template <typename F, int Size>
3888class FixedVecFunc : public FixedGenFunc<typename F::Sig, Size>
3889{
3890protected:
3891	const Func<typename F::Sig>& doGetScalarFunc	(void) const { return instance<F>(); }
3892};
3893
3894template<typename Sig>
3895struct GenFuncs
3896{
3897	GenFuncs (const Func<Sig>&			func_,
3898			  const GenFunc<Sig, 2>&	func2_,
3899			  const GenFunc<Sig, 3>&	func3_,
3900			  const GenFunc<Sig, 4>&	func4_)
3901		: func	(func_)
3902		, func2	(func2_)
3903		, func3	(func3_)
3904		, func4	(func4_)
3905	{}
3906
3907	const Func<Sig>&		func;
3908	const GenFunc<Sig, 2>&	func2;
3909	const GenFunc<Sig, 3>&	func3;
3910	const GenFunc<Sig, 4>&	func4;
3911};
3912
3913template<typename F>
3914GenFuncs<typename F::Sig> makeVectorizedFuncs (void)
3915{
3916	return GenFuncs<typename F::Sig>(instance<F>(),
3917									 instance<VectorizedFunc<F, 2> >(),
3918									 instance<VectorizedFunc<F, 3> >(),
3919									 instance<VectorizedFunc<F, 4> >());
3920}
3921
3922template<int Size>
3923ExprP<Vector<float, Size> > operator*(const ExprP<Vector<float, Size> >& arg0,
3924									  const ExprP<Vector<float, Size> >& arg1)
3925{
3926	return app<VectorizedFunc<Mul, Size> >(arg0, arg1);
3927}
3928
3929template<int Size>
3930ExprP<Vector<float, Size> > operator*(const ExprP<Vector<float, Size> >&	arg0,
3931									  const ExprP<float>&					arg1)
3932{
3933	return app<FixedVecFunc<Mul, Size> >(arg0, arg1);
3934}
3935
3936template<int Size>
3937ExprP<Vector<float, Size> > operator/(const ExprP<Vector<float, Size> >&	arg0,
3938									  const ExprP<float>&					arg1)
3939{
3940	return app<FixedVecFunc<Div, Size> >(arg0, arg1);
3941}
3942
3943template<int Size>
3944ExprP<Vector<float, Size> > operator-(const ExprP<Vector<float, Size> >& arg0)
3945{
3946	return app<VectorizedFunc<Negate, Size> >(arg0);
3947}
3948
3949template<int Size>
3950ExprP<Vector<float, Size> > operator-(const ExprP<Vector<float, Size> >& arg0,
3951									  const ExprP<Vector<float, Size> >& arg1)
3952{
3953	return app<VectorizedFunc<Sub, Size> >(arg0, arg1);
3954}
3955
3956template<int LeftRows, int Middle, int RightCols>
3957ExprP<Matrix<float, LeftRows, RightCols> >
3958operator* (const ExprP<Matrix<float, LeftRows, Middle> >&	left,
3959		   const ExprP<Matrix<float, Middle, RightCols> >&	right)
3960{
3961	return app<MatMul<LeftRows, Middle, RightCols> >(left, right);
3962}
3963
3964template<int Rows, int Cols>
3965ExprP<Vector<float, Rows> > operator* (const ExprP<Vector<float, Cols> >&		left,
3966									   const ExprP<Matrix<float, Rows, Cols> >&	right)
3967{
3968	return app<VecMatMul<Rows, Cols> >(left, right);
3969}
3970
3971template<int Rows, int Cols>
3972ExprP<Vector<float, Cols> > operator* (const ExprP<Matrix<float, Rows, Cols> >&	left,
3973									   const ExprP<Vector<float, Rows> >&		right)
3974{
3975	return app<MatVecMul<Rows, Cols> >(left, right);
3976}
3977
3978template<int Rows, int Cols>
3979ExprP<Matrix<float, Rows, Cols> > operator* (const ExprP<Matrix<float, Rows, Cols> >&	left,
3980											 const ExprP<float>&						right)
3981{
3982	return app<ScalarMatFunc<Mul, Rows, Cols> >(left, right);
3983}
3984
3985template<int Rows, int Cols>
3986ExprP<Matrix<float, Rows, Cols> > operator+ (const ExprP<Matrix<float, Rows, Cols> >&	left,
3987											 const ExprP<Matrix<float, Rows, Cols> >&	right)
3988{
3989	return app<CompMatFunc<Add, Rows, Cols> >(left, right);
3990}
3991
3992template<int Rows, int Cols>
3993ExprP<Matrix<float, Rows, Cols> > operator- (const ExprP<Matrix<float, Rows, Cols> >&	mat)
3994{
3995	return app<MatNeg<Rows, Cols> >(mat);
3996}
3997
3998template <typename T>
3999class Sampling
4000{
4001public:
4002	virtual void	genFixeds	(const FloatFormat&, vector<T>&)			const {}
4003	virtual T		genRandom	(const FloatFormat&, Precision, Random&)	const { return T(); }
4004	virtual double	getWeight	(void)										const { return 0.0; }
4005};
4006
4007template <>
4008class DefaultSampling<Void> : public Sampling<Void>
4009{
4010public:
4011	void	genFixeds	(const FloatFormat&, vector<Void>& dst) const { dst.push_back(Void()); }
4012};
4013
4014template <>
4015class DefaultSampling<bool> : public Sampling<bool>
4016{
4017public:
4018	void	genFixeds	(const FloatFormat&, vector<bool>& dst) const
4019	{
4020		dst.push_back(true);
4021		dst.push_back(false);
4022	}
4023};
4024
4025template <>
4026class DefaultSampling<int> : public Sampling<int>
4027{
4028public:
4029	int		genRandom	(const FloatFormat&, Precision prec, Random& rnd) const
4030	{
4031		const int	exp		= rnd.getInt(0, getNumBits(prec)-2);
4032		const int	sign	= rnd.getBool() ? -1 : 1;
4033
4034		return sign * rnd.getInt(0, (deInt32)1 << exp);
4035	}
4036
4037	void	genFixeds	(const FloatFormat&, vector<int>& dst) const
4038	{
4039		dst.push_back(0);
4040		dst.push_back(-1);
4041		dst.push_back(1);
4042	}
4043	double	getWeight	(void) const { return 1.0; }
4044
4045private:
4046	static inline int getNumBits (Precision prec)
4047	{
4048		switch (prec)
4049		{
4050			case glu::PRECISION_LOWP:		return 8;
4051			case glu::PRECISION_MEDIUMP:	return 16;
4052			case glu::PRECISION_HIGHP:		return 32;
4053			default:
4054				DE_ASSERT(false);
4055				return 0;
4056		}
4057	}
4058};
4059
4060template <>
4061class DefaultSampling<float> : public Sampling<float>
4062{
4063public:
4064	float	genRandom	(const FloatFormat& format, Precision prec, Random& rnd) const;
4065	void	genFixeds	(const FloatFormat& format, vector<float>& dst) const;
4066	double	getWeight	(void) const { return 1.0; }
4067};
4068
4069//! Generate a random float from a reasonable general-purpose distribution.
4070float DefaultSampling<float>::genRandom (const FloatFormat& format,
4071										 Precision,
4072										 Random&			rnd) const
4073{
4074	const int		minExp			= format.getMinExp();
4075	const int		maxExp			= format.getMaxExp();
4076	const bool		haveSubnormal	= format.hasSubnormal() != tcu::NO;
4077
4078	// Choose exponent so that the cumulative distribution is cubic.
4079	// This makes the probability distribution quadratic, with the peak centered on zero.
4080	const double	minRoot			= deCbrt(minExp - 0.5 - (haveSubnormal ? 1.0 : 0.0));
4081	const double	maxRoot			= deCbrt(maxExp + 0.5);
4082	const int		fractionBits	= format.getFractionBits();
4083	const int		exp				= int(deRoundEven(dePow(rnd.getDouble(minRoot, maxRoot),
4084															3.0)));
4085	float			base			= 0.0f; // integral power of two
4086	float			quantum			= 0.0f; // smallest representable difference in the binade
4087	float			significand		= 0.0f; // Significand.
4088
4089	DE_ASSERT(fractionBits < std::numeric_limits<float>::digits);
4090
4091	// Generate some occasional special numbers
4092	switch (rnd.getInt(0, 64))
4093	{
4094		case 0: 	return 0;
4095		case 1:		return TCU_INFINITY;
4096		case 2:		return -TCU_INFINITY;
4097		case 3:		return TCU_NAN;
4098		default:	break;
4099	}
4100
4101	if (exp >= minExp)
4102	{
4103		// Normal number
4104		base = deFloatLdExp(1.0f, exp);
4105		quantum = deFloatLdExp(1.0f, exp - fractionBits);
4106	}
4107	else
4108	{
4109		// Subnormal
4110		base = 0.0f;
4111		quantum = deFloatLdExp(1.0f, minExp - fractionBits);
4112	}
4113
4114	switch (rnd.getInt(0, 16))
4115	{
4116		case 0: // The highest number in this binade, significand is all bits one.
4117			significand = base - quantum;
4118			break;
4119		case 1: // Significand is one.
4120			significand = quantum;
4121			break;
4122		case 2: // Significand is zero.
4123			significand = 0.0;
4124			break;
4125		default: // Random (evenly distributed) significand.
4126		{
4127			deUint64 intFraction = rnd.getUint64() & ((1 << fractionBits) - 1);
4128			significand = float(intFraction) * quantum;
4129		}
4130	}
4131
4132	// Produce positive numbers more often than negative.
4133	return (rnd.getInt(0,3) == 0 ? -1.0f : 1.0f) * (base + significand);
4134}
4135
4136//! Generate a standard set of floats that should always be tested.
4137void DefaultSampling<float>::genFixeds (const FloatFormat& format, vector<float>& dst) const
4138{
4139	const int			minExp			= format.getMinExp();
4140	const int			maxExp			= format.getMaxExp();
4141	const int			fractionBits	= format.getFractionBits();
4142	const float			minQuantum		= deFloatLdExp(1.0f, minExp - fractionBits);
4143	const float			minNormalized	= deFloatLdExp(1.0f, minExp);
4144	const float			maxQuantum		= deFloatLdExp(1.0f, maxExp - fractionBits);
4145
4146	// NaN
4147	dst.push_back(TCU_NAN);
4148	// Zero
4149	dst.push_back(0.0f);
4150
4151	for (int sign = -1; sign <= 1; sign += 2)
4152	{
4153		// Smallest subnormal
4154		dst.push_back((float)sign * minQuantum);
4155
4156		// Largest subnormal
4157		dst.push_back((float)sign * (minNormalized - minQuantum));
4158
4159		// Smallest normalized
4160		dst.push_back((float)sign * minNormalized);
4161
4162		// Next smallest normalized
4163		dst.push_back((float)sign * (minNormalized + minQuantum));
4164
4165		dst.push_back((float)sign * 0.5f);
4166		dst.push_back((float)sign * 1.0f);
4167		dst.push_back((float)sign * 2.0f);
4168
4169		// Largest number
4170		dst.push_back((float)sign * (deFloatLdExp(1.0f, maxExp) +
4171									(deFloatLdExp(1.0f, maxExp) - maxQuantum)));
4172
4173		dst.push_back((float)sign * TCU_INFINITY);
4174	}
4175}
4176
4177template <typename T, int Size>
4178class DefaultSampling<Vector<T, Size> > : public Sampling<Vector<T, Size> >
4179{
4180public:
4181	typedef Vector<T, Size>		Value;
4182
4183	Value	genRandom	(const FloatFormat& fmt, Precision prec, Random& rnd) const
4184	{
4185		Value ret;
4186
4187		for (int ndx = 0; ndx < Size; ++ndx)
4188			ret[ndx] = instance<DefaultSampling<T> >().genRandom(fmt, prec, rnd);
4189
4190		return ret;
4191	}
4192
4193	void	genFixeds	(const FloatFormat& fmt, vector<Value>& dst) const
4194	{
4195		vector<T> scalars;
4196
4197		instance<DefaultSampling<T> >().genFixeds(fmt, scalars);
4198
4199		for (size_t scalarNdx = 0; scalarNdx < scalars.size(); ++scalarNdx)
4200			dst.push_back(Value(scalars[scalarNdx]));
4201	}
4202
4203	double	getWeight	(void) const
4204	{
4205		return dePow(instance<DefaultSampling<T> >().getWeight(), Size);
4206	}
4207};
4208
4209template <typename T, int Rows, int Columns>
4210class DefaultSampling<Matrix<T, Rows, Columns> > : public Sampling<Matrix<T, Rows, Columns> >
4211{
4212public:
4213	typedef Matrix<T, Rows, Columns>		Value;
4214
4215	Value	genRandom	(const FloatFormat& fmt, Precision prec, Random& rnd) const
4216	{
4217		Value ret;
4218
4219		for (int rowNdx = 0; rowNdx < Rows; ++rowNdx)
4220			for (int colNdx = 0; colNdx < Columns; ++colNdx)
4221				ret(rowNdx, colNdx) = instance<DefaultSampling<T> >().genRandom(fmt, prec, rnd);
4222
4223		return ret;
4224	}
4225
4226	void	genFixeds	(const FloatFormat& fmt, vector<Value>& dst) const
4227	{
4228		vector<T> scalars;
4229
4230		instance<DefaultSampling<T> >().genFixeds(fmt, scalars);
4231
4232		for (size_t scalarNdx = 0; scalarNdx < scalars.size(); ++scalarNdx)
4233			dst.push_back(Value(scalars[scalarNdx]));
4234
4235		if (Columns == Rows)
4236		{
4237			Value	mat	(0.0);
4238			T		x	= T(1.0f);
4239			mat[0][0] = x;
4240			for (int ndx = 0; ndx < Columns; ++ndx)
4241			{
4242				mat[Columns-1-ndx][ndx] = x;
4243				x *= T(2.0f);
4244			}
4245			dst.push_back(mat);
4246		}
4247	}
4248
4249	double	getWeight	(void) const
4250	{
4251		return dePow(instance<DefaultSampling<T> >().getWeight(), Rows * Columns);
4252	}
4253};
4254
4255struct Context
4256{
4257	Context		(const string&		name_,
4258				 TestContext&		testContext_,
4259				 RenderContext&		renderContext_,
4260				 const FloatFormat&	floatFormat_,
4261				 const FloatFormat&	highpFormat_,
4262				 Precision			precision_,
4263				 ShaderType			shaderType_,
4264				 size_t				numRandoms_)
4265		: name				(name_)
4266		, testContext		(testContext_)
4267		, renderContext		(renderContext_)
4268		, floatFormat		(floatFormat_)
4269		, highpFormat		(highpFormat_)
4270		, precision			(precision_)
4271		, shaderType		(shaderType_)
4272		, numRandoms		(numRandoms_) {}
4273
4274	string				name;
4275	TestContext&		testContext;
4276	RenderContext&		renderContext;
4277	FloatFormat			floatFormat;
4278	FloatFormat			highpFormat;
4279	Precision			precision;
4280	ShaderType			shaderType;
4281	size_t				numRandoms;
4282};
4283
4284template<typename In0_ = Void, typename In1_ = Void, typename In2_ = Void, typename In3_ = Void>
4285struct InTypes
4286{
4287	typedef	In0_	In0;
4288	typedef	In1_	In1;
4289	typedef	In2_	In2;
4290	typedef	In3_	In3;
4291};
4292
4293template <typename In>
4294int numInputs (void)
4295{
4296	return (!isTypeValid<typename In::In0>() ? 0 :
4297			!isTypeValid<typename In::In1>() ? 1 :
4298			!isTypeValid<typename In::In2>() ? 2 :
4299			!isTypeValid<typename In::In3>() ? 3 :
4300			4);
4301}
4302
4303template<typename Out0_, typename Out1_ = Void>
4304struct OutTypes
4305{
4306	typedef	Out0_	Out0;
4307	typedef	Out1_	Out1;
4308};
4309
4310template <typename Out>
4311int numOutputs (void)
4312{
4313	return (!isTypeValid<typename Out::Out0>() ? 0 :
4314			!isTypeValid<typename Out::Out1>() ? 1 :
4315			2);
4316}
4317
4318template<typename In>
4319struct Inputs
4320{
4321	vector<typename In::In0>	in0;
4322	vector<typename In::In1>	in1;
4323	vector<typename In::In2>	in2;
4324	vector<typename In::In3>	in3;
4325};
4326
4327template<typename Out>
4328struct Outputs
4329{
4330	Outputs	(size_t size) : out0(size), out1(size) {}
4331
4332	vector<typename Out::Out0>	out0;
4333	vector<typename Out::Out1>	out1;
4334};
4335
4336template<typename In, typename Out>
4337struct Variables
4338{
4339	VariableP<typename In::In0>		in0;
4340	VariableP<typename In::In1>		in1;
4341	VariableP<typename In::In2>		in2;
4342	VariableP<typename In::In3>		in3;
4343	VariableP<typename Out::Out0>	out0;
4344	VariableP<typename Out::Out1>	out1;
4345};
4346
4347template<typename In>
4348struct Samplings
4349{
4350	Samplings	(const Sampling<typename In::In0>&	in0_,
4351				 const Sampling<typename In::In1>&	in1_,
4352				 const Sampling<typename In::In2>&	in2_,
4353				 const Sampling<typename In::In3>&	in3_)
4354		: in0 (in0_), in1 (in1_), in2 (in2_), in3 (in3_) {}
4355
4356	const Sampling<typename In::In0>&	in0;
4357	const Sampling<typename In::In1>&	in1;
4358	const Sampling<typename In::In2>&	in2;
4359	const Sampling<typename In::In3>&	in3;
4360};
4361
4362template<typename In>
4363struct DefaultSamplings : Samplings<In>
4364{
4365	DefaultSamplings	(void)
4366		: Samplings<In>(instance<DefaultSampling<typename In::In0> >(),
4367						instance<DefaultSampling<typename In::In1> >(),
4368						instance<DefaultSampling<typename In::In2> >(),
4369						instance<DefaultSampling<typename In::In3> >()) {}
4370};
4371
4372class PrecisionCase : public TestCase
4373{
4374public:
4375	IterateResult		iterate			(void);
4376
4377protected:
4378						PrecisionCase	(const Context&		context,
4379										 const string&		name,
4380										 const string&		extension	= "")
4381							: TestCase		(context.testContext,
4382											 name.c_str(),
4383											 name.c_str())
4384							, m_ctx			(context)
4385							, m_status		()
4386							, m_rnd			(0xdeadbeefu +
4387											 context.testContext.getCommandLine().getBaseSeed())
4388							, m_extension	(extension)
4389	{
4390	}
4391
4392	RenderContext&		getRenderContext(void) const 			{ return m_ctx.renderContext; }
4393
4394	const FloatFormat&	getFormat		(void) const 			{ return m_ctx.floatFormat; }
4395
4396	TestLog&			log				(void) const 			{ return m_testCtx.getLog(); }
4397
4398	virtual void		runTest			(void) = 0;
4399
4400	template <typename In, typename Out>
4401	void				testStatement	(const Variables<In, Out>&	variables,
4402										 const Inputs<In>&			inputs,
4403										 const Statement&			stmt);
4404
4405	template<typename T>
4406	Symbol				makeSymbol		(const Variable<T>& variable)
4407	{
4408		return Symbol(variable.getName(), getVarTypeOf<T>(m_ctx.precision));
4409	}
4410
4411	Context				m_ctx;
4412	ResultCollector		m_status;
4413	Random				m_rnd;
4414	const string		m_extension;
4415};
4416
4417IterateResult PrecisionCase::iterate (void)
4418{
4419	runTest();
4420	m_status.setTestContextResult(m_testCtx);
4421	return STOP;
4422}
4423
4424template <typename In, typename Out>
4425void PrecisionCase::testStatement (const Variables<In, Out>&	variables,
4426								   const Inputs<In>&			inputs,
4427								   const Statement&				stmt)
4428{
4429	using namespace ShaderExecUtil;
4430
4431	typedef typename 	In::In0		In0;
4432	typedef typename 	In::In1		In1;
4433	typedef typename 	In::In2		In2;
4434	typedef typename 	In::In3		In3;
4435	typedef typename 	Out::Out0	Out0;
4436	typedef typename 	Out::Out1	Out1;
4437
4438	const FloatFormat&	fmt			= getFormat();
4439	const int			inCount		= numInputs<In>();
4440	const int			outCount	= numOutputs<Out>();
4441	const size_t		numValues	= (inCount > 0) ? inputs.in0.size() : 1;
4442	Outputs<Out>		outputs		(numValues);
4443	ShaderSpec			spec;
4444	const FloatFormat	highpFmt	= m_ctx.highpFormat;
4445	const int			maxMsgs		= 100;
4446	int					numErrors	= 0;
4447	Environment			env; 		// Hoisted out of the inner loop for optimization.
4448
4449	switch (inCount)
4450	{
4451		case 4: DE_ASSERT(inputs.in3.size() == numValues);
4452		case 3: DE_ASSERT(inputs.in2.size() == numValues);
4453		case 2: DE_ASSERT(inputs.in1.size() == numValues);
4454		case 1: DE_ASSERT(inputs.in0.size() == numValues);
4455		default: break;
4456	}
4457
4458	// Print out the statement and its definitions
4459	log() << TestLog::Message << "Statement: " << stmt << TestLog::EndMessage;
4460	{
4461		ostringstream	oss;
4462		FuncSet			funcs;
4463
4464		stmt.getUsedFuncs(funcs);
4465		for (FuncSet::const_iterator it = funcs.begin(); it != funcs.end(); ++it)
4466		{
4467			(*it)->printDefinition(oss);
4468		}
4469		if (!funcs.empty())
4470			log() << TestLog::Message << "Reference definitions:\n" << oss.str()
4471				  << TestLog::EndMessage;
4472	}
4473
4474	// Initialize ShaderSpec from precision, variables and statement.
4475	{
4476		ostringstream os;
4477		os << "precision " << glu::getPrecisionName(m_ctx.precision) << " float;\n";
4478		spec.globalDeclarations = os.str();
4479	}
4480
4481	spec.version = getContextTypeGLSLVersion(getRenderContext().getType());
4482
4483	if (!m_extension.empty())
4484		spec.globalDeclarations = "#extension " + m_extension + " : require\n";
4485
4486	spec.inputs.resize(inCount);
4487
4488	switch (inCount)
4489	{
4490		case 4: spec.inputs[3] = makeSymbol(*variables.in3);
4491		case 3:	spec.inputs[2] = makeSymbol(*variables.in2);
4492		case 2:	spec.inputs[1] = makeSymbol(*variables.in1);
4493		case 1:	spec.inputs[0] = makeSymbol(*variables.in0);
4494		default: break;
4495	}
4496
4497	spec.outputs.resize(outCount);
4498
4499	switch (outCount)
4500	{
4501		case 2:	spec.outputs[1] = makeSymbol(*variables.out1);
4502		case 1:	spec.outputs[0] = makeSymbol(*variables.out0);
4503		default: break;
4504	}
4505
4506	spec.source = de::toString(stmt);
4507
4508	// Run the shader with inputs.
4509	{
4510		UniquePtr<ShaderExecutor>	executor		(createExecutor(getRenderContext(),
4511																	m_ctx.shaderType,
4512																	spec));
4513		const void*					inputArr[]		=
4514		{
4515			&inputs.in0.front(), &inputs.in1.front(), &inputs.in2.front(), &inputs.in3.front(),
4516		};
4517		void*						outputArr[]		=
4518		{
4519			&outputs.out0.front(), &outputs.out1.front(),
4520		};
4521
4522		executor->log(log());
4523		if (!executor->isOk())
4524			TCU_FAIL("Shader compilation failed");
4525
4526		executor->useProgram();
4527		executor->execute(int(numValues), inputArr, outputArr);
4528	}
4529
4530	// Initialize environment with dummy values so we don't need to bind in inner loop.
4531	{
4532		const typename Traits<In0>::IVal		in0;
4533		const typename Traits<In1>::IVal		in1;
4534		const typename Traits<In2>::IVal		in2;
4535		const typename Traits<In3>::IVal		in3;
4536		const typename Traits<Out0>::IVal		reference0;
4537		const typename Traits<Out1>::IVal		reference1;
4538
4539		env.bind(*variables.in0, in0);
4540		env.bind(*variables.in1, in1);
4541		env.bind(*variables.in2, in2);
4542		env.bind(*variables.in3, in3);
4543		env.bind(*variables.out0, reference0);
4544		env.bind(*variables.out1, reference1);
4545	}
4546
4547	// For each input tuple, compute output reference interval and compare
4548	// shader output to the reference.
4549	for (size_t valueNdx = 0; valueNdx < numValues; valueNdx++)
4550	{
4551		bool						result		= true;
4552		typename Traits<Out0>::IVal	reference0;
4553		typename Traits<Out1>::IVal	reference1;
4554
4555		env.lookup(*variables.in0) = convert<In0>(fmt, round(fmt, inputs.in0[valueNdx]));
4556		env.lookup(*variables.in1) = convert<In1>(fmt, round(fmt, inputs.in1[valueNdx]));
4557		env.lookup(*variables.in2) = convert<In2>(fmt, round(fmt, inputs.in2[valueNdx]));
4558		env.lookup(*variables.in3) = convert<In3>(fmt, round(fmt, inputs.in3[valueNdx]));
4559
4560		{
4561			EvalContext	ctx (fmt, m_ctx.precision, env);
4562			stmt.execute(ctx);
4563		}
4564
4565		switch (outCount)
4566		{
4567			case 2:
4568				reference1 = convert<Out1>(highpFmt, env.lookup(*variables.out1));
4569				if (!m_status.check(contains(reference1, outputs.out1[valueNdx]),
4570									"Shader output 1 is outside acceptable range"))
4571					result = false;
4572			case 1:
4573				reference0 = convert<Out0>(highpFmt, env.lookup(*variables.out0));
4574				if (!m_status.check(contains(reference0, outputs.out0[valueNdx]),
4575									"Shader output 0 is outside acceptable range"))
4576					result = false;
4577			default: break;
4578		}
4579
4580		if (!result)
4581			++numErrors;
4582
4583		if ((!result && numErrors <= maxMsgs) || GLS_LOG_ALL_RESULTS)
4584		{
4585			MessageBuilder	builder	= log().message();
4586
4587			builder << (result ? "Passed" : "Failed") << " sample:\n";
4588
4589			if (inCount > 0)
4590			{
4591				builder << "\t" << variables.in0->getName() << " = "
4592						<< valueToString(highpFmt, inputs.in0[valueNdx]) << "\n";
4593			}
4594
4595			if (inCount > 1)
4596			{
4597				builder << "\t" << variables.in1->getName() << " = "
4598						<< valueToString(highpFmt, inputs.in1[valueNdx]) << "\n";
4599			}
4600
4601			if (inCount > 2)
4602			{
4603				builder << "\t" << variables.in2->getName() << " = "
4604						<< valueToString(highpFmt, inputs.in2[valueNdx]) << "\n";
4605			}
4606
4607			if (inCount > 3)
4608			{
4609				builder << "\t" << variables.in3->getName() << " = "
4610						<< valueToString(highpFmt, inputs.in3[valueNdx]) << "\n";
4611			}
4612
4613			if (outCount > 0)
4614			{
4615				builder << "\t" << variables.out0->getName() << " = "
4616						<< valueToString(highpFmt, outputs.out0[valueNdx]) << "\n"
4617						<< "\tExpected range: "
4618						<< intervalToString<typename Out::Out0>(highpFmt, reference0) << "\n";
4619			}
4620
4621			if (outCount > 1)
4622			{
4623				builder << "\t" << variables.out1->getName() << " = "
4624						<< valueToString(highpFmt, outputs.out1[valueNdx]) << "\n"
4625						<< "\tExpected range: "
4626						<< intervalToString<typename Out::Out1>(highpFmt, reference1) << "\n";
4627			}
4628
4629			builder << TestLog::EndMessage;
4630		}
4631	}
4632
4633	if (numErrors > maxMsgs)
4634	{
4635		log() << TestLog::Message << "(Skipped " << (numErrors - maxMsgs) << " messages.)"
4636			  << TestLog::EndMessage;
4637	}
4638
4639	if (numErrors == 0)
4640	{
4641		log() << TestLog::Message << "All " << numValues << " inputs passed."
4642			  << TestLog::EndMessage;
4643	}
4644	else
4645	{
4646		log() << TestLog::Message << numErrors << "/" << numValues << " inputs failed."
4647			  << TestLog::EndMessage;
4648	}
4649}
4650
4651
4652
4653template <typename T>
4654struct InputLess
4655{
4656	bool operator() (const T& val1, const T& val2) const
4657	{
4658		return val1 < val2;
4659	}
4660};
4661
4662template <typename T>
4663bool inputLess (const T& val1, const T& val2)
4664{
4665	return InputLess<T>()(val1, val2);
4666}
4667
4668template <>
4669struct InputLess<float>
4670{
4671	bool operator() (const float& val1, const float& val2) const
4672	{
4673		if (deIsNaN(val1))
4674			return false;
4675		if (deIsNaN(val2))
4676			return true;
4677		return val1 < val2;
4678	}
4679};
4680
4681template <typename T, int Size>
4682struct InputLess<Vector<T, Size> >
4683{
4684	bool operator() (const Vector<T, Size>& vec1, const Vector<T, Size>& vec2) const
4685	{
4686		for (int ndx = 0; ndx < Size; ++ndx)
4687		{
4688			if (inputLess(vec1[ndx], vec2[ndx]))
4689				return true;
4690			if (inputLess(vec2[ndx], vec1[ndx]))
4691				return false;
4692		}
4693
4694		return false;
4695	}
4696};
4697
4698template <typename T, int Rows, int Cols>
4699struct InputLess<Matrix<T, Rows, Cols> >
4700{
4701	bool operator() (const Matrix<T, Rows, Cols>& mat1,
4702					 const Matrix<T, Rows, Cols>& mat2) const
4703	{
4704		for (int col = 0; col < Cols; ++col)
4705		{
4706			if (inputLess(mat1[col], mat2[col]))
4707				return true;
4708			if (inputLess(mat2[col], mat1[col]))
4709				return false;
4710		}
4711
4712		return false;
4713	}
4714};
4715
4716template <typename In>
4717struct InTuple :
4718	public Tuple4<typename In::In0, typename In::In1, typename In::In2, typename In::In3>
4719{
4720	InTuple	(const typename In::In0& in0,
4721			 const typename In::In1& in1,
4722			 const typename In::In2& in2,
4723			 const typename In::In3& in3)
4724		: Tuple4<typename In::In0, typename In::In1, typename In::In2, typename In::In3>
4725		  (in0, in1, in2, in3) {}
4726};
4727
4728template <typename In>
4729struct InputLess<InTuple<In> >
4730{
4731	bool operator() (const InTuple<In>& in1, const InTuple<In>& in2) const
4732	{
4733		if (inputLess(in1.a, in2.a))
4734			return true;
4735		if (inputLess(in2.a, in1.a))
4736			return false;
4737		if (inputLess(in1.b, in2.b))
4738			return true;
4739		if (inputLess(in2.b, in1.b))
4740			return false;
4741		if (inputLess(in1.c, in2.c))
4742			return true;
4743		if (inputLess(in2.c, in1.c))
4744			return false;
4745		if (inputLess(in1.d, in2.d))
4746			return true;
4747		return false;
4748	};
4749};
4750
4751template<typename In>
4752Inputs<In> generateInputs (const Samplings<In>&	samplings,
4753						   const FloatFormat&	floatFormat,
4754						   Precision			intPrecision,
4755						   size_t				numSamples,
4756						   Random&				rnd)
4757{
4758	Inputs<In>									ret;
4759	Inputs<In>									fixedInputs;
4760	set<InTuple<In>, InputLess<InTuple<In> > >	seenInputs;
4761
4762	samplings.in0.genFixeds(floatFormat, fixedInputs.in0);
4763	samplings.in1.genFixeds(floatFormat, fixedInputs.in1);
4764	samplings.in2.genFixeds(floatFormat, fixedInputs.in2);
4765	samplings.in3.genFixeds(floatFormat, fixedInputs.in3);
4766
4767	for (size_t ndx0 = 0; ndx0 < fixedInputs.in0.size(); ++ndx0)
4768	{
4769		for (size_t ndx1 = 0; ndx1 < fixedInputs.in1.size(); ++ndx1)
4770		{
4771			for (size_t ndx2 = 0; ndx2 < fixedInputs.in2.size(); ++ndx2)
4772			{
4773				for (size_t ndx3 = 0; ndx3 < fixedInputs.in3.size(); ++ndx3)
4774				{
4775					const InTuple<In>	tuple	(fixedInputs.in0[ndx0],
4776												 fixedInputs.in1[ndx1],
4777												 fixedInputs.in2[ndx2],
4778												 fixedInputs.in3[ndx3]);
4779
4780					seenInputs.insert(tuple);
4781					ret.in0.push_back(tuple.a);
4782					ret.in1.push_back(tuple.b);
4783					ret.in2.push_back(tuple.c);
4784					ret.in3.push_back(tuple.d);
4785				}
4786			}
4787		}
4788	}
4789
4790	for (size_t ndx = 0; ndx < numSamples; ++ndx)
4791	{
4792		const typename In::In0	in0		= samplings.in0.genRandom(floatFormat, intPrecision, rnd);
4793		const typename In::In1	in1		= samplings.in1.genRandom(floatFormat, intPrecision, rnd);
4794		const typename In::In2	in2		= samplings.in2.genRandom(floatFormat, intPrecision, rnd);
4795		const typename In::In3	in3		= samplings.in3.genRandom(floatFormat, intPrecision, rnd);
4796		const InTuple<In>		tuple	(in0, in1, in2, in3);
4797
4798		if (de::contains(seenInputs, tuple))
4799			continue;
4800
4801		seenInputs.insert(tuple);
4802		ret.in0.push_back(in0);
4803		ret.in1.push_back(in1);
4804		ret.in2.push_back(in2);
4805		ret.in3.push_back(in3);
4806	}
4807
4808	return ret;
4809}
4810
4811class FuncCaseBase : public PrecisionCase
4812{
4813public:
4814	IterateResult	iterate			(void);
4815
4816protected:
4817					FuncCaseBase	(const Context&		context,
4818									 const string&		name,
4819									 const FuncBase&	func)
4820						: PrecisionCase	(context, name, func.getRequiredExtension()) {}
4821};
4822
4823IterateResult FuncCaseBase::iterate (void)
4824{
4825	MovePtr<ContextInfo>	info	(ContextInfo::create(getRenderContext()));
4826
4827	if (!m_extension.empty() && !info->isExtensionSupported(m_extension.c_str()))
4828		throw NotSupportedError("Unsupported extension: " + m_extension);
4829
4830	runTest();
4831
4832	m_status.setTestContextResult(m_testCtx);
4833	return STOP;
4834}
4835
4836template <typename Sig>
4837class FuncCase : public FuncCaseBase
4838{
4839public:
4840	typedef Func<Sig>						CaseFunc;
4841	typedef typename Sig::Ret				Ret;
4842	typedef typename Sig::Arg0				Arg0;
4843	typedef typename Sig::Arg1				Arg1;
4844	typedef typename Sig::Arg2				Arg2;
4845	typedef typename Sig::Arg3				Arg3;
4846	typedef InTypes<Arg0, Arg1, Arg2, Arg3>	In;
4847	typedef OutTypes<Ret>					Out;
4848
4849					FuncCase	(const Context&		context,
4850								 const string&		name,
4851								 const CaseFunc&	func)
4852						: FuncCaseBase	(context, name, func)
4853						, m_func		(func) {}
4854
4855protected:
4856	void				runTest		(void);
4857
4858	virtual const Samplings<In>&	getSamplings	(void)
4859	{
4860		return instance<DefaultSamplings<In> >();
4861	}
4862
4863private:
4864	const CaseFunc&			m_func;
4865};
4866
4867template <typename Sig>
4868void FuncCase<Sig>::runTest (void)
4869{
4870	const Inputs<In>	inputs	(generateInputs(getSamplings(),
4871												m_ctx.floatFormat,
4872												m_ctx.precision,
4873												m_ctx.numRandoms,
4874												m_rnd));
4875	Variables<In, Out>	variables;
4876
4877	variables.out0	= variable<Ret>("out0");
4878	variables.out1	= variable<Void>("out1");
4879	variables.in0	= variable<Arg0>("in0");
4880	variables.in1	= variable<Arg1>("in1");
4881	variables.in2	= variable<Arg2>("in2");
4882	variables.in3	= variable<Arg3>("in3");
4883
4884	{
4885		ExprP<Ret>	expr	= applyVar(m_func,
4886									   variables.in0, variables.in1,
4887									   variables.in2, variables.in3);
4888		StatementP	stmt	= variableAssignment(variables.out0, expr);
4889
4890		this->testStatement(variables, inputs, *stmt);
4891	}
4892}
4893
4894template <typename Sig>
4895class InOutFuncCase : public FuncCaseBase
4896{
4897public:
4898	typedef Func<Sig>						CaseFunc;
4899	typedef typename Sig::Ret				Ret;
4900	typedef typename Sig::Arg0				Arg0;
4901	typedef typename Sig::Arg1				Arg1;
4902	typedef typename Sig::Arg2				Arg2;
4903	typedef typename Sig::Arg3				Arg3;
4904	typedef InTypes<Arg0, Arg2, Arg3>		In;
4905	typedef OutTypes<Ret, Arg1>				Out;
4906
4907					InOutFuncCase	(const Context&		context,
4908									 const string&		name,
4909									 const CaseFunc&	func)
4910						: FuncCaseBase	(context, name, func)
4911						, m_func		(func) {}
4912
4913protected:
4914	void				runTest		(void);
4915
4916	virtual const Samplings<In>&	getSamplings	(void)
4917	{
4918		return instance<DefaultSamplings<In> >();
4919	}
4920
4921private:
4922	const CaseFunc&			m_func;
4923};
4924
4925template <typename Sig>
4926void InOutFuncCase<Sig>::runTest (void)
4927{
4928	const Inputs<In>	inputs	(generateInputs(getSamplings(),
4929												m_ctx.floatFormat,
4930												m_ctx.precision,
4931												m_ctx.numRandoms,
4932												m_rnd));
4933	Variables<In, Out>	variables;
4934
4935	variables.out0	= variable<Ret>("out0");
4936	variables.out1	= variable<Arg1>("out1");
4937	variables.in0	= variable<Arg0>("in0");
4938	variables.in1	= variable<Arg2>("in1");
4939	variables.in2	= variable<Arg3>("in2");
4940	variables.in3	= variable<Void>("in3");
4941
4942	{
4943		ExprP<Ret>	expr	= applyVar(m_func,
4944									   variables.in0, variables.out1,
4945									   variables.in1, variables.in2);
4946		StatementP	stmt	= variableAssignment(variables.out0, expr);
4947
4948		this->testStatement(variables, inputs, *stmt);
4949	}
4950}
4951
4952template <typename Sig>
4953PrecisionCase* createFuncCase (const Context&	context,
4954							   const string&	name,
4955							   const Func<Sig>&	func)
4956{
4957	switch (func.getOutParamIndex())
4958	{
4959		case -1:
4960			return new FuncCase<Sig>(context, name, func);
4961		case 1:
4962			return new InOutFuncCase<Sig>(context, name, func);
4963		default:
4964			DE_FATAL("Impossible");
4965	}
4966	return DE_NULL;
4967}
4968
4969class CaseFactory
4970{
4971public:
4972	virtual						~CaseFactory	(void) {}
4973	virtual MovePtr<TestNode>	createCase		(const Context& ctx) const = 0;
4974	virtual string				getName			(void) const = 0;
4975	virtual string				getDesc			(void) const = 0;
4976};
4977
4978class FuncCaseFactory : public CaseFactory
4979{
4980public:
4981	virtual const FuncBase&	getFunc		(void) const = 0;
4982
4983	string					getName		(void) const
4984	{
4985		return de::toLower(getFunc().getName());
4986	}
4987
4988	string					getDesc		(void) const
4989	{
4990		return "Function '" + getFunc().getName() + "'";
4991	}
4992};
4993
4994template <typename Sig>
4995class GenFuncCaseFactory : public CaseFactory
4996{
4997public:
4998
4999						GenFuncCaseFactory	(const GenFuncs<Sig>&	funcs,
5000											 const string&			name)
5001							: m_funcs	(funcs)
5002							, m_name	(de::toLower(name)) {}
5003
5004	MovePtr<TestNode>	createCase			(const Context& ctx) const
5005	{
5006		TestCaseGroup*	group = new TestCaseGroup(ctx.testContext,
5007												  ctx.name.c_str(), ctx.name.c_str());
5008
5009		group->addChild(createFuncCase(ctx, "scalar", m_funcs.func));
5010		group->addChild(createFuncCase(ctx, "vec2", m_funcs.func2));
5011		group->addChild(createFuncCase(ctx, "vec3", m_funcs.func3));
5012		group->addChild(createFuncCase(ctx, "vec4", m_funcs.func4));
5013
5014		return MovePtr<TestNode>(group);
5015	}
5016
5017	string				getName				(void) const
5018	{
5019		return m_name;
5020	}
5021
5022	string				getDesc				(void) const
5023	{
5024		return "Function '" + m_funcs.func.getName() + "'";
5025	}
5026
5027private:
5028	const GenFuncs<Sig>	m_funcs;
5029	string				m_name;
5030};
5031
5032template <template <int> class GenF>
5033class TemplateFuncCaseFactory : public FuncCaseFactory
5034{
5035public:
5036	MovePtr<TestNode>	createCase		(const Context& ctx) const
5037	{
5038		TestCaseGroup*	group = new TestCaseGroup(ctx.testContext,
5039							  ctx.name.c_str(), ctx.name.c_str());
5040		group->addChild(createFuncCase(ctx, "scalar", instance<GenF<1> >()));
5041		group->addChild(createFuncCase(ctx, "vec2", instance<GenF<2> >()));
5042		group->addChild(createFuncCase(ctx, "vec3", instance<GenF<3> >()));
5043		group->addChild(createFuncCase(ctx, "vec4", instance<GenF<4> >()));
5044
5045		return MovePtr<TestNode>(group);
5046	}
5047
5048	const FuncBase&		getFunc			(void) const { return instance<GenF<1> >(); }
5049};
5050
5051template <template <int> class GenF>
5052class SquareMatrixFuncCaseFactory : public FuncCaseFactory
5053{
5054public:
5055	MovePtr<TestNode>	createCase		(const Context& ctx) const
5056	{
5057		TestCaseGroup*	group = new TestCaseGroup(ctx.testContext,
5058							  ctx.name.c_str(), ctx.name.c_str());
5059		group->addChild(createFuncCase(ctx, "mat2", instance<GenF<2> >()));
5060#if 0
5061		// disabled until we get reasonable results
5062		group->addChild(createFuncCase(ctx, "mat3", instance<GenF<3> >()));
5063		group->addChild(createFuncCase(ctx, "mat4", instance<GenF<4> >()));
5064#endif
5065
5066		return MovePtr<TestNode>(group);
5067	}
5068
5069	const FuncBase&		getFunc			(void) const { return instance<GenF<2> >(); }
5070};
5071
5072template <template <int, int> class GenF>
5073class MatrixFuncCaseFactory : public FuncCaseFactory
5074{
5075public:
5076	MovePtr<TestNode>	createCase		(const Context& ctx) const
5077	{
5078		TestCaseGroup*	const group = new TestCaseGroup(ctx.testContext,
5079														ctx.name.c_str(), ctx.name.c_str());
5080
5081		this->addCase<2, 2>(ctx, group);
5082		this->addCase<3, 2>(ctx, group);
5083		this->addCase<4, 2>(ctx, group);
5084		this->addCase<2, 3>(ctx, group);
5085		this->addCase<3, 3>(ctx, group);
5086		this->addCase<4, 3>(ctx, group);
5087		this->addCase<2, 4>(ctx, group);
5088		this->addCase<3, 4>(ctx, group);
5089		this->addCase<4, 4>(ctx, group);
5090
5091		return MovePtr<TestNode>(group);
5092	}
5093
5094	const FuncBase&		getFunc			(void) const { return instance<GenF<2,2> >(); }
5095
5096private:
5097	template <int Rows, int Cols>
5098	void				addCase			(const Context& ctx, TestCaseGroup* group) const
5099	{
5100		const char*	const name = dataTypeNameOf<Matrix<float, Rows, Cols> >();
5101
5102		group->addChild(createFuncCase(ctx, name, instance<GenF<Rows, Cols> >()));
5103	}
5104};
5105
5106template <typename Sig>
5107class SimpleFuncCaseFactory : public CaseFactory
5108{
5109public:
5110						SimpleFuncCaseFactory	(const Func<Sig>& func) : m_func(func) {}
5111
5112	MovePtr<TestNode>	createCase		(const Context& ctx) const
5113	{
5114		return MovePtr<TestNode>(createFuncCase(ctx, ctx.name.c_str(), m_func));
5115	}
5116
5117	string				getName					(void) const
5118	{
5119		return de::toLower(m_func.getName());
5120	}
5121
5122	string				getDesc					(void) const
5123	{
5124		return "Function '" + getName() + "'";
5125	}
5126
5127private:
5128	const Func<Sig>&	m_func;
5129};
5130
5131template <typename F>
5132SharedPtr<SimpleFuncCaseFactory<typename F::Sig> > createSimpleFuncCaseFactory (void)
5133{
5134	return SharedPtr<SimpleFuncCaseFactory<typename F::Sig> >(
5135		new SimpleFuncCaseFactory<typename F::Sig>(instance<F>()));
5136}
5137
5138class BuiltinFuncs : public CaseFactories
5139{
5140public:
5141	const vector<const CaseFactory*>	getFactories	(void) const
5142	{
5143		vector<const CaseFactory*> ret;
5144
5145		for (size_t ndx = 0; ndx < m_factories.size(); ++ndx)
5146			ret.push_back(m_factories[ndx].get());
5147
5148		return ret;
5149	}
5150
5151	void								addFactory		(SharedPtr<const CaseFactory> fact)
5152	{
5153		m_factories.push_back(fact);
5154	}
5155
5156private:
5157	vector<SharedPtr<const CaseFactory> >			m_factories;
5158};
5159
5160template <typename F>
5161void addScalarFactory(BuiltinFuncs& funcs, string name = "")
5162{
5163	if (name.empty())
5164		name = instance<F>().getName();
5165
5166	funcs.addFactory(SharedPtr<const CaseFactory>(new GenFuncCaseFactory<typename F::Sig>(
5167													  makeVectorizedFuncs<F>(), name)));
5168}
5169
5170MovePtr<const CaseFactories> createES3BuiltinCases (void)
5171{
5172	MovePtr<BuiltinFuncs>	funcs	(new BuiltinFuncs());
5173
5174	addScalarFactory<Add>(*funcs);
5175	addScalarFactory<Sub>(*funcs);
5176	addScalarFactory<Mul>(*funcs);
5177	addScalarFactory<Div>(*funcs);
5178
5179	addScalarFactory<Radians>(*funcs);
5180	addScalarFactory<Degrees>(*funcs);
5181	addScalarFactory<Sin>(*funcs);
5182	addScalarFactory<Cos>(*funcs);
5183	addScalarFactory<Tan>(*funcs);
5184	addScalarFactory<ASin>(*funcs);
5185	addScalarFactory<ACos>(*funcs);
5186	addScalarFactory<ATan2>(*funcs, "atan2");
5187	addScalarFactory<ATan>(*funcs);
5188	addScalarFactory<Sinh>(*funcs);
5189	addScalarFactory<Cosh>(*funcs);
5190	addScalarFactory<Tanh>(*funcs);
5191	addScalarFactory<ASinh>(*funcs);
5192	addScalarFactory<ACosh>(*funcs);
5193	addScalarFactory<ATanh>(*funcs);
5194
5195	addScalarFactory<Pow>(*funcs);
5196	addScalarFactory<Exp>(*funcs);
5197	addScalarFactory<Log>(*funcs);
5198	addScalarFactory<Exp2>(*funcs);
5199	addScalarFactory<Log2>(*funcs);
5200	addScalarFactory<Sqrt>(*funcs);
5201	addScalarFactory<InverseSqrt>(*funcs);
5202
5203	addScalarFactory<Abs>(*funcs);
5204	addScalarFactory<Sign>(*funcs);
5205	addScalarFactory<Floor>(*funcs);
5206	addScalarFactory<Trunc>(*funcs);
5207	addScalarFactory<Round>(*funcs);
5208	addScalarFactory<RoundEven>(*funcs);
5209	addScalarFactory<Ceil>(*funcs);
5210	addScalarFactory<Fract>(*funcs);
5211	addScalarFactory<Mod>(*funcs);
5212	funcs->addFactory(createSimpleFuncCaseFactory<Modf>());
5213	addScalarFactory<Min>(*funcs);
5214	addScalarFactory<Max>(*funcs);
5215	addScalarFactory<Clamp>(*funcs);
5216	addScalarFactory<Mix>(*funcs);
5217	addScalarFactory<Step>(*funcs);
5218	addScalarFactory<SmoothStep>(*funcs);
5219
5220	funcs->addFactory(SharedPtr<const CaseFactory>(new TemplateFuncCaseFactory<Length>()));
5221	funcs->addFactory(SharedPtr<const CaseFactory>(new TemplateFuncCaseFactory<Distance>()));
5222	funcs->addFactory(SharedPtr<const CaseFactory>(new TemplateFuncCaseFactory<Dot>()));
5223	funcs->addFactory(createSimpleFuncCaseFactory<Cross>());
5224	funcs->addFactory(SharedPtr<const CaseFactory>(new TemplateFuncCaseFactory<Normalize>()));
5225	funcs->addFactory(SharedPtr<const CaseFactory>(new TemplateFuncCaseFactory<FaceForward>()));
5226	funcs->addFactory(SharedPtr<const CaseFactory>(new TemplateFuncCaseFactory<Reflect>()));
5227	funcs->addFactory(SharedPtr<const CaseFactory>(new TemplateFuncCaseFactory<Refract>()));
5228
5229
5230	funcs->addFactory(SharedPtr<const CaseFactory>(new MatrixFuncCaseFactory<MatrixCompMult>()));
5231	funcs->addFactory(SharedPtr<const CaseFactory>(new MatrixFuncCaseFactory<OuterProduct>()));
5232	funcs->addFactory(SharedPtr<const CaseFactory>(new MatrixFuncCaseFactory<Transpose>()));
5233	funcs->addFactory(SharedPtr<const CaseFactory>(new SquareMatrixFuncCaseFactory<Determinant>()));
5234	funcs->addFactory(SharedPtr<const CaseFactory>(new SquareMatrixFuncCaseFactory<Inverse>()));
5235
5236	return MovePtr<const CaseFactories>(funcs.release());
5237}
5238
5239MovePtr<const CaseFactories> createES31BuiltinCases (void)
5240{
5241	MovePtr<BuiltinFuncs>	funcs	(new BuiltinFuncs());
5242
5243	addScalarFactory<FrExp>(*funcs);
5244	addScalarFactory<LdExp>(*funcs);
5245	addScalarFactory<Fma>(*funcs);
5246
5247	return MovePtr<const CaseFactories>(funcs.release());
5248}
5249
5250struct PrecisionTestContext
5251{
5252	PrecisionTestContext	(TestContext&				testCtx_,
5253							 RenderContext&				renderCtx_,
5254							 const FloatFormat&			highp_,
5255							 const FloatFormat&			mediump_,
5256							 const FloatFormat&			lowp_,
5257							 const vector<ShaderType>&	shaderTypes_,
5258							 int						numRandoms_)
5259		: testCtx		(testCtx_)
5260		, renderCtx		(renderCtx_)
5261		, shaderTypes	(shaderTypes_)
5262		, numRandoms	(numRandoms_)
5263	{
5264		formats[glu::PRECISION_HIGHP]	= &highp_;
5265		formats[glu::PRECISION_MEDIUMP]	= &mediump_;
5266		formats[glu::PRECISION_LOWP]	= &lowp_;
5267	}
5268
5269	TestContext&			testCtx;
5270	RenderContext&			renderCtx;
5271	const FloatFormat*		formats[glu::PRECISION_LAST];
5272	vector<ShaderType>		shaderTypes;
5273	int						numRandoms;
5274};
5275
5276TestCaseGroup* createFuncGroup (const PrecisionTestContext&	ctx,
5277								const CaseFactory&			factory)
5278{
5279	TestCaseGroup* const 	group	= new TestCaseGroup(ctx.testCtx,
5280														factory.getName().c_str(),
5281														factory.getDesc().c_str());
5282
5283	for (int precNdx = 0; precNdx < glu::PRECISION_LAST; ++precNdx)
5284	{
5285		const Precision		precision	= Precision(precNdx);
5286		const string		precName	(glu::getPrecisionName(precision));
5287		const FloatFormat&	fmt			= *de::getSizedArrayElement<glu::PRECISION_LAST>(ctx.formats, precNdx);
5288		const FloatFormat&	highpFmt	= *de::getSizedArrayElement<glu::PRECISION_LAST>(ctx.formats,
5289																						 glu::PRECISION_HIGHP);
5290
5291		for (size_t shaderNdx = 0; shaderNdx < ctx.shaderTypes.size(); ++shaderNdx)
5292		{
5293			const ShaderType	shaderType	= ctx.shaderTypes[shaderNdx];
5294			const string 		shaderName	(glu::getShaderTypeName(shaderType));
5295			const string		name		= precName + "_" + shaderName;
5296			const Context		caseCtx		(name, ctx.testCtx, ctx.renderCtx, fmt, highpFmt,
5297											 precision, shaderType, ctx.numRandoms);
5298
5299			group->addChild(factory.createCase(caseCtx).release());
5300		}
5301	}
5302
5303	return group;
5304}
5305
5306void addBuiltinPrecisionTests (TestContext&					testCtx,
5307							   RenderContext&				renderCtx,
5308							   const CaseFactories&			cases,
5309							   const vector<ShaderType>&	shaderTypes,
5310							   TestCaseGroup&				dstGroup)
5311{
5312	const int						userRandoms	= testCtx.getCommandLine().getTestIterationCount();
5313	const int						defRandoms	= 16384;
5314	const int						numRandoms	= userRandoms > 0 ? userRandoms : defRandoms;
5315	const FloatFormat				highp		(-126, 127, 23, true,
5316												 tcu::MAYBE,	// subnormals
5317												 tcu::YES,		// infinities
5318												 tcu::MAYBE);	// NaN
5319	// \todo [2014-04-01 lauri] Check these once Khronos bug 11840 is resolved.
5320	const FloatFormat				mediump		(-13, 13, 9, false);
5321	// A fixed-point format is just a floating point format with a fixed
5322	// exponent and support for subnormals.
5323	const FloatFormat				lowp		(0, 0, 7, false, tcu::YES);
5324	const PrecisionTestContext		ctx			(testCtx, renderCtx, highp, mediump, lowp,
5325												 shaderTypes, numRandoms);
5326
5327	for (size_t ndx = 0; ndx < cases.getFactories().size(); ++ndx)
5328		dstGroup.addChild(createFuncGroup(ctx, *cases.getFactories()[ndx]));
5329}
5330
5331} // BuiltinPrecisionTests
5332} // gls
5333} // deqp
5334