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