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