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