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