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