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