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