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