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