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