glsBuiltinPrecisionTests.cpp revision 1cc61b7d03cad727bbddd00cea8d78f4f6cc9047
13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program OpenGL (ES) Module
33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * -----------------------------------------------
43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project
63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License");
83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License.
93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at
103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *      http://www.apache.org/licenses/LICENSE-2.0
123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software
143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS,
153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and
173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License.
183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*!
203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file
213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Precision and range tests for GLSL builtins and types.
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glsBuiltinPrecisionTests.hpp"
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deMath.h"
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deMemory.h"
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deDefs.hpp"
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deRandom.hpp"
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deSTLUtil.hpp"
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deStringUtil.hpp"
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deUniquePtr.hpp"
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deSharedPtr.hpp"
35d6148171f88da1301f053e2e0236afc69416137cJarkko Pöyry#include "deArrayUtil.hpp"
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuCommandLine.hpp"
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuFloatFormat.hpp"
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuInterval.hpp"
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTestCase.hpp"
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTestLog.hpp"
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuVector.hpp"
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuMatrix.hpp"
44ab44fc6da25bb126919615ad2ded101695251161Jarkko Pöyry#include "tcuResultCollector.hpp"
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluContextInfo.hpp"
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluVarType.hpp"
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluRenderContext.hpp"
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwDefs.hpp"
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glsShaderExecUtil.hpp"
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <cmath>
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <string>
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <sstream>
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <iostream>
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <map>
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <utility>
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Uncomment this to get evaluation trace dumps to std::cerr
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// #define GLS_ENABLE_TRACE
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// set this to true to dump even passing results
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#define GLS_LOG_ALL_RESULTS false
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace deqp
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace gls
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace BuiltinPrecisionTests
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::string;
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::map;
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::ostream;
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::ostringstream;
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::pair;
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::vector;
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::set;
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing de::MovePtr;
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing de::Random;
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing de::SharedPtr;
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing de::UniquePtr;
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::Interval;
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::FloatFormat;
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::MessageBuilder;
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::TestCase;
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::TestLog;
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::Vector;
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::Matrix;
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace matrix = tcu::matrix;
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing glu::Precision;
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing glu::RenderContext;
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing glu::VarType;
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing glu::DataType;
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing glu::ShaderType;
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing glu::ContextInfo;
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing gls::ShaderExecUtil::Symbol;
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytypedef TestCase::IterateResult IterateResult;
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing namespace glw;
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing namespace tcu;
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Generic singleton creator.
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * instance<T>() returns a reference to a unique default-constructed instance
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * of T. This is mainly used for our GLSL function implementations: each
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * function is implemented by an object, and each of the objects has a
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distinct class. It would be extremely toilsome to maintain a separate
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * context object that contained individual instances of the function classes,
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * so we have to resort to global singleton instances.
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst T& instance (void)
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const T s_instance = T();
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return s_instance;
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Dummy placeholder type for unused template parameters.
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * In the precision tests we are dealing with functions of different arities.
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * To minimize code duplication, we only define templates with the maximum
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * number of arguments, currently four. If a function's arity is less than the
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * maximum, Void us used as the type for unused arguments.
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Although Voids are not used at run-time, they still must be compilable, so
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * they must support all operations that other types do.
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct Void
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef	Void		Element;
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enum
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		SIZE = 0,
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	template <typename T>
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	explicit			Void			(const T&)		{}
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						Void			(void)			{}
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						operator double	(void)	const	{ return TCU_NAN; }
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// These are used to make Voids usable as containers in container-generic code.
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Void&				operator[]		(int)			{ return *this; }
1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const Void&			operator[]		(int)	const	{ return *this; }
1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyryostream& operator<< (ostream& os, Void) { return os << "()"; }
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Returns true for all other types except Void
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>	bool isTypeValid		(void)	{ return true;	}
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <>				bool isTypeValid<Void>	(void)	{ return false;	}
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Utility function for getting the name of a data type.
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! This is used in vector and matrix constructors.
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst char* dataTypeNameOf (void)
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return glu::getDataTypeName(glu::dataTypeOf<T>());
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <>
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst char* dataTypeNameOf<Void> (void)
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1711cc61b7d03cad727bbddd00cea8d78f4f6cc9047Jarkko Pöyry	DE_FATAL("Impossible");
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return DE_NULL;
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! A hack to get Void support for VarType.
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
1773c827367444ee418f129b2c238299f49d3264554Jarkko PoyryVarType getVarTypeOf (Precision prec = glu::PRECISION_LAST)
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return glu::varTypeOf<T>(prec);
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <>
1833c827367444ee418f129b2c238299f49d3264554Jarkko PoyryVarType getVarTypeOf<Void> (Precision)
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1851cc61b7d03cad727bbddd00cea8d78f4f6cc9047Jarkko Pöyry	DE_FATAL("Impossible");
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return VarType();
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Type traits for generalized interval types.
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * We are trying to compute sets of acceptable values not only for
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * float-valued expressions but also for compound values: vectors and
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * matrices. We approximate a set of vectors as a vector of intervals and
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * likewise for matrices.
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * We now need generalized operations for each type and its interval
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * approximation. These are given in the type Traits<T>.
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * The type Traits<T>::IVal is the approximation of T: it is `Interval` for
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * scalar types, and a vector or matrix of intervals for container types.
2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * To allow template inference to take place, there are function wrappers for
2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * the actual operations in Traits<T>. Hence we can just use:
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * makeIVal(someFloat)
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * instead of:
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Traits<float>::doMakeIVal(value)
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T> struct Traits;
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Create container from elementwise singleton values.
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytypename Traits<T>::IVal makeIVal (const T& value)
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return Traits<T>::doMakeIVal(value);
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Elementwise union of intervals.
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytypename Traits<T>::IVal unionIVal (const typename Traits<T>::IVal& a,
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									const typename Traits<T>::IVal& b)
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return Traits<T>::doUnion(a, b);
2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Returns true iff every element of `ival` contains the corresponding element of `value`.
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool contains (const typename Traits<T>::IVal& ival, const T& value)
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return Traits<T>::doContains(ival, value);
2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Print out an interval with the precision of `fmt`.
2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid printIVal (const FloatFormat& fmt, const typename Traits<T>::IVal& ival, ostream& os)
2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Traits<T>::doPrintIVal(fmt, ival, os);
2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystring intervalToString (const FloatFormat& fmt, const typename Traits<T>::IVal& ival)
2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ostringstream oss;
2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	printIVal<T>(fmt, ival, oss);
2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return oss.str();
2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Print out a value with the precision of `fmt`.
2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid printValue (const FloatFormat& fmt, const T& value, ostream& os)
2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Traits<T>::doPrintValue(fmt, value, os);
2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystring valueToString (const FloatFormat& fmt, const T& val)
2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ostringstream oss;
2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	printValue(fmt, val, oss);
2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return oss.str();
2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Approximate `value` elementwise to the float precision defined in `fmt`.
2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! The resulting interval might not be a singleton if rounding in both
2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! directions is allowed.
2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytypename Traits<T>::IVal round (const FloatFormat& fmt, const T& value)
2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return Traits<T>::doRound(fmt, value);
2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytypename Traits<T>::IVal convert (const FloatFormat&				fmt,
2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								  const typename Traits<T>::IVal&	value)
2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return Traits<T>::doConvert(fmt, value);
2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Common traits for scalar types.
2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct ScalarTraits
2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef 			Interval		IVal;
2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static Interval		doMakeIVal		(const T& value)
2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Thankfully all scalar types have a well-defined conversion to `double`,
2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// hence Interval can represent their ranges without problems.
2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return Interval(double(value));
2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static Interval		doUnion			(const Interval& a, const Interval& b)
2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return a | b;
3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static bool			doContains		(const Interval& a, T value)
3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return a.contains(double(value));
3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static Interval		doConvert		(const FloatFormat& fmt, const IVal& ival)
3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return fmt.convert(ival);
3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static Interval		doRound			(const FloatFormat& fmt, T value)
3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3142e751e3e77060f699c560104e82379d3ce54f67aPyry Haulos		return fmt.roundOut(double(value), false);
3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<>
3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct Traits<float> : ScalarTraits<float>
3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static void			doPrintIVal		(const FloatFormat&	fmt,
3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 const Interval&	ival,
3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 ostream&			os)
3243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		os << fmt.intervalToHex(ival);
3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static void			doPrintValue	(const FloatFormat&	fmt,
3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 const float&		value,
3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 ostream&			os)
3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		os << fmt.floatToHex(value);
3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<>
3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct Traits<bool> : ScalarTraits<bool>
3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static void			doPrintValue	(const FloatFormat&,
3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 const float&		value,
3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 ostream&			os)
3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
34324ceed3e1acf66512ee25ee75002198b6672879dJarkko Pöyry		os << (value != 0.0f ? "true" : "false");
3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static void			doPrintIVal		(const FloatFormat&,
3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 const Interval&	ival,
3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 ostream&			os)
3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		os << "{";
3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (ival.contains(false))
3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			os << "false";
3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (ival.contains(false) && ival.contains(true))
3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			os << ", ";
3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (ival.contains(true))
3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			os << "true";
3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		os << "}";
3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<>
3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct Traits<int> : ScalarTraits<int>
3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static void			doPrintValue 	(const FloatFormat&,
3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 const int&			value,
3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 ostream&			os)
3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		os << value;
3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static void			doPrintIVal		(const FloatFormat&,
3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 const Interval&	ival,
3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 ostream&			os)
3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		os << "[" << int(ival.lo()) << ", " << int(ival.hi()) << "]";
3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Common traits for containers, i.e. vectors and matrices.
3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! T is the container type itself, I is the same type with interval elements.
3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T, typename I>
3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct ContainerTraits
3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename	T::Element		Element;
3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef				I				IVal;
3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static IVal			doMakeIVal		(const T& value)
3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		IVal ret;
3903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < T::SIZE; ++ndx)
3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			ret[ndx] = makeIVal(value[ndx]);
3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return ret;
3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static IVal			doUnion			(const IVal& a, const IVal& b)
3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		IVal ret;
4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < T::SIZE; ++ndx)
4023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			ret[ndx] = unionIVal<Element>(a[ndx], b[ndx]);
4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return ret;
4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static bool			doContains		(const IVal& ival, const T& value)
4083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < T::SIZE; ++ndx)
4103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!contains(ival[ndx], value[ndx]))
4113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return false;
4123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
4143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static void			doPrintIVal		(const FloatFormat& fmt, const IVal ival, ostream& os)
4173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		os << "(";
4193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < T::SIZE; ++ndx)
4213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (ndx > 0)
4233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				os << ", ";
4243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			printIVal<Element>(fmt, ival[ndx], os);
4263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		os << ")";
4293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static void			doPrintValue	(const FloatFormat& fmt, const T& value, ostream& os)
4323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		os << dataTypeNameOf<T>() << "(";
4343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < T::SIZE; ++ndx)
4363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (ndx > 0)
4383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				os << ", ";
4393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			printValue<Element>(fmt, value[ndx], os);
4413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		os << ")";
4443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static IVal			doConvert		(const FloatFormat& fmt, const IVal& value)
4473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		IVal ret;
4493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < T::SIZE; ++ndx)
4513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			ret[ndx] = convert<Element>(fmt, value[ndx]);
4523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return ret;
4543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static IVal			doRound			(const FloatFormat& fmt, T value)
4573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		IVal ret;
4593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < T::SIZE; ++ndx)
4613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			ret[ndx] = round(fmt, value[ndx]);
4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return ret;
4643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
4663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4673c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T, int Size>
4683c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct Traits<Vector<T, Size> > :
4693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ContainerTraits<Vector<T, Size>, Vector<typename Traits<T>::IVal, Size> >
4703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
4723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4733c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T, int Rows, int Cols>
4743c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct Traits<Matrix<T, Rows, Cols> > :
4753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ContainerTraits<Matrix<T, Rows, Cols>, Matrix<typename Traits<T>::IVal, Rows, Cols> >
4763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
4783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Void traits. These are just dummies, but technically valid: a Void is a
4803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! unit type with a single possible value.
4813c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<>
4823c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct Traits<Void>
4833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef		Void			IVal;
4853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static Void	doMakeIVal		(const Void& value) 					{ return value; }
4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static Void	doUnion			(const Void&, const Void&)				{ return Void(); }
4883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static bool	doContains		(const Void&, Void) 					{ return true; }
4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static Void	doRound			(const FloatFormat&, const Void& value)	{ return value; }
4903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static Void	doConvert		(const FloatFormat&, const Void& value)	{ return value; }
4913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static void	doPrintValue 	(const FloatFormat&, const Void&, ostream& os)
4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		os << "()";
4953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static void	doPrintIVal		(const FloatFormat&, const Void&, ostream& os)
4983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		os << "()";
5003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! This is needed for container-generic operations.
5043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! We want a scalar type T to be its own "one-element vector".
5053c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T, int Size> struct ContainerOf	{ typedef Vector<T, Size>	Container; };
5063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5073c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>			struct ContainerOf<T, 1>		{ typedef T		Container; };
5083c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <int Size> 			struct ContainerOf<Void, Size>	{ typedef Void	Container; };
5093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// This is a kludge that is only needed to get the ExprP::operator[] syntactic sugar to work.
5113c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>	struct ElementOf		{ typedef	typename T::Element	Element; };
5123c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <>				struct ElementOf<float>	{ typedef	void				Element; };
5133c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <>				struct ElementOf<bool>	{ typedef	void				Element; };
5143c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <>				struct ElementOf<int>	{ typedef	void				Element; };
5153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
5173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
5183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \name Abstract syntax for expressions and statements.
5193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
5203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * We represent GLSL programs as syntax objects: an Expr<T> represents an
5213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * expression whose GLSL type corresponds to the C++ type T, and a Statement
5223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * represents a statement.
5233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
5243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * To ease memory management, we use shared pointers to refer to expressions
5253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * and statements. ExprP<T> is a shared pointer to an Expr<T>, and StatementP
5263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * is a shared pointer to a Statement.
5273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
5283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \{
5293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
5303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
5313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5323c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ExprBase;
5333c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ExpandContext;
5343c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Statement;
5353c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass StatementP;
5363c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FuncBase;
5373c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T> class ExprP;
5383c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T> class Variable;
5393c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T> class VariableP;
5403c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T> class DefaultSampling;
5413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5423c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytypedef set<const FuncBase*> FuncSet;
5433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5443c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
5453c827367444ee418f129b2c238299f49d3264554Jarkko PoyryVariableP<T>	variable			(const string& name);
5463c827367444ee418f129b2c238299f49d3264554Jarkko PoyryStatementP		compoundStatement	(const vector<StatementP>& statements);
5473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
5493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief A variable environment.
5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
5513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * An Environment object maintains the mapping between variables of the
5523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * abstract syntax tree and their values.
5533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
5543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \todo [2014-03-28 lauri] At least run-time type safety.
5553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
5563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
5573c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Environment
5583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5593c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
5603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	template<typename T>
5613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void						bind	(const Variable<T>&					variable,
5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 const typename Traits<T>::IVal&	value)
5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint8* const data = new deUint8[sizeof(value)];
5653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deMemcpy(data, &value, sizeof(value));
5676801c0680107ff001b065db07b125d622926f311Mika Isojärvi		de::insert(m_map, variable.getName(), SharedPtr<deUint8>(data, de::ArrayDeleter<deUint8>()));
5683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	template<typename T>
5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typename Traits<T>::IVal&	lookup	(const Variable<T>& variable) const
5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint8* const data = de::lookup(m_map, variable.getName()).get();
5743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return *reinterpret_cast<typename Traits<T>::IVal*>(data);
5763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5783c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
5796801c0680107ff001b065db07b125d622926f311Mika Isojärvi	map<string, SharedPtr<deUint8> >	m_map;
5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
5813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
5833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Evaluation context.
5843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
5853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * The evaluation context contains everything that separates one execution of
5863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * an expression from the next. Currently this means the desired floating
5873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * point precision and the current variable environment.
5883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
5893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
5903c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct EvalContext
5913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	EvalContext (const FloatFormat&	format_,
5933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				 Precision			floatPrecision_,
5943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				 Environment&		env_,
5953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				 int				callDepth_ = 0)
5963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: format			(format_)
5973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, floatPrecision	(floatPrecision_)
5983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, env				(env_)
5993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, callDepth			(callDepth_) {}
6003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FloatFormat		format;
6023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Precision		floatPrecision;
6033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Environment&	env;
6043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int				callDepth;
6053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
6063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
6083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Simple incremental counter.
6093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
6103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * This is used to make sure that different ExpandContexts will not produce
6113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * overlapping temporary names.
6123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
6133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
6143c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Counter
6153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6163c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
6173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Counter		(int count = 0) : m_count(count) {}
6183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int		operator()	(void) { return m_count++; }
6193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6203c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
6213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int		m_count;
6223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
6233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6243c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ExpandContext
6253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6263c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
6273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						ExpandContext	(Counter& symCounter) : m_symCounter(symCounter) {}
6283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						ExpandContext	(const ExpandContext& parent)
6293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							: m_symCounter(parent.m_symCounter) {}
6303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	template<typename T>
6323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VariableP<T>		genSym			(const string& baseName)
6333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return variable<T>(baseName + de::toString(m_symCounter()));
6353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void				addStatement	(const StatementP& stmt)
6383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_statements.push_back(stmt);
6403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<StatementP>	getStatements	(void) const
6433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return m_statements;
6453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6463c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
6473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Counter&			m_symCounter;
6483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<StatementP>	m_statements;
6493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
6503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
6523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief A statement or declaration.
6533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
6543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Statements have no values. Instead, they are executed for their side
6553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * effects only: the execute() method should modify at least one variable in
6563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * the environment.
6573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
6583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * As a bit of a kludge, a Statement object can also represent a declaration:
6593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * when it is evaluated, it can add a variable binding to the environment
6603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * instead of modifying a current one.
6613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
6623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
6633c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Statement
6643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6653c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
6663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual	~Statement		(void) 							{								 }
6673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	//! Execute the statement, modifying the environment of `ctx`
6683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void	execute			(EvalContext&	ctx)	const	{ this->doExecute(ctx);			 }
6693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void	print			(ostream&		os)		const	{ this->doPrint(os);			 }
6703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	//! Add the functions used in this statement to `dst`.
6713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void	getUsedFuncs	(FuncSet& dst)			const	{ this->doGetUsedFuncs(dst);	 }
6723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6733c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
6743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual void	doPrint			(ostream& os)			const	= 0;
6753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual void	doExecute		(EvalContext& ctx)		const	= 0;
6763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual void	doGetUsedFuncs	(FuncSet& dst)			const	= 0;
6773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
6783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6793c827367444ee418f129b2c238299f49d3264554Jarkko Poyryostream& operator<<(ostream& os, const Statement& stmt)
6803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	stmt.print(os);
6823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return os;
6833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
6863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Smart pointer for statements (and declarations)
6873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
6883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
6893c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass StatementP : public SharedPtr<const Statement>
6903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6913c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
6923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef		SharedPtr<const Statement>	Super;
6933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				StatementP			(void) {}
6953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	explicit	StatementP			(const Statement* ptr)	: Super(ptr) {}
6963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				StatementP			(const Super& ptr)		: Super(ptr) {}
6973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
6983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
7003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief
7013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
7023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * A statement that modifies a variable or a declaration that binds a variable.
7033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
7043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
7053c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
7063c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass VariableStatement : public Statement
7073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7083c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
7093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					VariableStatement	(const VariableP<T>& variable, const ExprP<T>& value,
7103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 bool isDeclaration)
7113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						: m_variable		(variable)
7123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						, m_value			(value)
7133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						, m_isDeclaration	(isDeclaration) {}
7143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7153c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
7163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void			doPrint				(ostream& os)							const
7173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_isDeclaration)
7193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			os << glu::declare(getVarTypeOf<T>(), m_variable->getName());
7203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
7213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			os << m_variable->getName();
7223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		os << " = " << *m_value << ";\n";
7243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void			doExecute			(EvalContext& ctx)						const
7273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_isDeclaration)
7293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			ctx.env.bind(*m_variable, m_value->evaluate(ctx));
7303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
7313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			ctx.env.lookup(*m_variable) = m_value->evaluate(ctx);
7323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void			doGetUsedFuncs		(FuncSet& dst)							const
7353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_value->getUsedFuncs(dst);
7373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VariableP<T>	m_variable;
7403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ExprP<T>		m_value;
7413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool			m_isDeclaration;
7423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
7433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7443c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
7453c827367444ee418f129b2c238299f49d3264554Jarkko PoyryStatementP variableStatement (const VariableP<T>&	variable,
7463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const ExprP<T>&		value,
7473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  bool					isDeclaration)
7483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return StatementP(new VariableStatement<T>(variable, value, isDeclaration));
7503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7523c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
7533c827367444ee418f129b2c238299f49d3264554Jarkko PoyryStatementP variableDeclaration (const VariableP<T>& variable, const ExprP<T>& definiens)
7543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return variableStatement(variable, definiens, true);
7563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7583c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
7593c827367444ee418f129b2c238299f49d3264554Jarkko PoyryStatementP variableAssignment (const VariableP<T>& variable, const ExprP<T>& value)
7603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return variableStatement(variable, value, false);
7623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
7653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief A compound statement, i.e. a block.
7663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
7673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * A compound statement is executed by executing its constituent statements in
7683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * sequence.
7693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
7703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
7713c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass CompoundStatement : public Statement
7723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7733c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
7743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						CompoundStatement	(const vector<StatementP>& statements)
7753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							: m_statements	(statements) {}
7763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7773c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
7783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void				doPrint				(ostream&		os)						const
7793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		os << "{\n";
7813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (size_t ndx = 0; ndx < m_statements.size(); ++ndx)
7833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			os << *m_statements[ndx];
7843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		os << "}\n";
7863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void				doExecute			(EvalContext&	ctx)					const
7893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (size_t ndx = 0; ndx < m_statements.size(); ++ndx)
7913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_statements[ndx]->execute(ctx);
7923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void				doGetUsedFuncs		(FuncSet& dst)							const
7953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (size_t ndx = 0; ndx < m_statements.size(); ++ndx)
7973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_statements[ndx]->getUsedFuncs(dst);
7983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<StatementP>	m_statements;
8013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
8023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8033c827367444ee418f129b2c238299f49d3264554Jarkko PoyryStatementP compoundStatement(const vector<StatementP>& statements)
8043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return StatementP(new CompoundStatement(statements));
8063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Common base class for all expressions regardless of their type.
8093c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ExprBase
8103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8113c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
8123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual				~ExprBase		(void)									{}
8133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void				printExpr		(ostream& os) const { this->doPrintExpr(os); }
8143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	//! Output the functions that this expression refers to
8163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void				getUsedFuncs	(FuncSet& dst) const
8173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		this->doGetUsedFuncs(dst);
8193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8213c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
8223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual void		doPrintExpr		(ostream&)	const	{}
8233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual void		doGetUsedFuncs	(FuncSet&)	const	{}
8243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
8253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Type-specific operations for an expression representing type T.
8273c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
8283c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Expr : public ExprBase
8293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8303c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
8313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef 			T				Val;
8323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename 	Traits<T>::IVal	IVal;
8333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IVal				evaluate		(const EvalContext&	ctx) const;
8353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8363c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
8373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual IVal		doEvaluate		(const EvalContext&	ctx) const = 0;
8383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
8393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Evaluate an expression with the given context, optionally tracing the calls to stderr.
8413c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
8423c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytypename Traits<T>::IVal Expr<T>::evaluate (const EvalContext& ctx) const
8433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#ifdef GLS_ENABLE_TRACE
8458852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	static const FloatFormat	highpFmt	(-126, 127, 23, true,
8468852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry											 tcu::MAYBE,
8478852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry											 tcu::YES,
8488852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry											 tcu::MAYBE);
8498852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	EvalContext					newCtx		(ctx.format, ctx.floatPrecision,
8508852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry											 ctx.env, ctx.callDepth + 1);
8518852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const IVal					ret			= this->doEvaluate(newCtx);
8523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (isTypeValid<T>())
8543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		std::cerr << string(ctx.callDepth, ' ');
8563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		this->printExpr(std::cerr);
8578852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		std::cerr << " -> " << intervalToString<T>(highpFmt, ret) << std::endl;
8583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return ret;
8603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#else
8613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return this->doEvaluate(ctx);
8623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
8633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8653c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
8663c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ExprPBase : public SharedPtr<const Expr<T> >
8673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8683c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
8693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
8703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8713c827367444ee418f129b2c238299f49d3264554Jarkko Poyryostream& operator<< (ostream& os, const ExprBase& expr)
8723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	expr.printExpr(os);
8743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return os;
8753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
8783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Shared pointer to an expression of a container type.
8793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
8803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Container types (i.e. vectors and matrices) support the subscription
8813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * operator. This class provides a bit of syntactic sugar to allow us to use
8823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * the C++ subscription operator to create a subscription expression.
8833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
8843c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
8853c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ContainerExprPBase : public ExprPBase<T>
8863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8873c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
8883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ExprP<typename T::Element>	operator[]	(int i) const;
8893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
8903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8913c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
8923c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ExprP : public ExprPBase<T> {};
8933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// We treat Voids as containers since the dummy parameters in generalized
8953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// vector functions are represented as Voids.
8963c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <>
8973c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ExprP<Void> : public ContainerExprPBase<Void> {};
8983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8993c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T, int Size>
9003c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ExprP<Vector<T, Size> > : public ContainerExprPBase<Vector<T, Size> > {};
9013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9023c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T, int Rows, int Cols>
9033c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ExprP<Matrix<T, Rows, Cols> > : public ContainerExprPBase<Matrix<T, Rows, Cols> > {};
9043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9053c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T> ExprP<T> exprP (void)
9063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return ExprP<T>();
9083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9103c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
9113c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<T> exprP (const SharedPtr<const Expr<T> >& ptr)
9123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ExprP<T> ret;
9143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static_cast<SharedPtr<const Expr<T> >&>(ret) = ptr;
9153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return ret;
9163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9183c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
9193c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<T> exprP (const Expr<T>* ptr)
9203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return exprP(SharedPtr<const Expr<T> >(ptr));
9223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
9253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief A shared pointer to a variable expression.
9263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
9273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * This is just a narrowing of ExprP for the operations that require a variable
9283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * instead of an arbitrary expression.
9293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
9303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
9313c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
9323c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass VariableP : public SharedPtr<const Variable<T> >
9333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9343c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
9353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef		SharedPtr<const Variable<T> >	Super;
9363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	explicit	VariableP	(const Variable<T>* ptr) : Super(ptr) {}
9373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				VariableP	(void) {}
9383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				VariableP	(const Super& ptr) : Super(ptr) {}
9393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	operator	ExprP<T>	(void) const { return exprP(SharedPtr<const Expr<T> >(*this)); }
9413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
9423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
9443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \name Syntactic sugar operators for expressions.
9453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
9463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * @{
9473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
9483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * These operators allow the use of C++ syntax to construct GLSL expressions
9493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * containing operators: e.g. "a+b" creates an addition expression with
9503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * operands a and b, and so on.
9513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
9523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
9533c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<float>						operator-(const ExprP<float>&						arg0);
9543c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<float>						operator+(const ExprP<float>&						arg0,
9553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											  const ExprP<float>&						arg1);
9563c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<float>						operator-(const ExprP<float>&						arg0,
9573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											  const ExprP<float>&						arg1);
9583c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<float> 						operator*(const ExprP<float>&						arg0,
9593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											  const ExprP<float>&						arg1);
9603c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<float> 						operator/(const ExprP<float>&						arg0,
9613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											  const ExprP<float>&						arg1);
9623c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<int Size>
9633c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<Vector<float, Size> >			operator-(const ExprP<Vector<float, Size> >&		arg0);
9643c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<int Size>
9653c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<Vector<float, Size> >			operator*(const ExprP<Vector<float, Size> >&		arg0,
9663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											  const ExprP<float>&						arg1);
9673c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<int Size>
9683c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<Vector<float, Size> >			operator*(const ExprP<Vector<float, Size> >&		arg0,
9693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											  const ExprP<Vector<float, Size> >&		arg1);
9703c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<int Size>
9713c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<Vector<float, Size> >			operator-(const ExprP<Vector<float, Size> >&		arg0,
9723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											  const ExprP<Vector<float, Size> >&		arg1);
9733c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<int Left, int Mid, int Right>
9743c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<Matrix<float, Left, Right> >	operator* (const ExprP<Matrix<float, Left, Mid> >&	left,
9753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											   const ExprP<Matrix<float, Mid, Right> >&	right);
9763c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<int Rows, int Cols>
9773c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<Vector<float, Rows> >			operator* (const ExprP<Vector<float, Cols> >&		left,
9783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											   const ExprP<Matrix<float, Rows, Cols> >&	right);
9793c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<int Rows, int Cols>
9803c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<Vector<float, Cols> >			operator* (const ExprP<Matrix<float, Rows, Cols> >&	left,
9813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											   const ExprP<Vector<float, Rows> >&		right);
9823c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<int Rows, int Cols>
9833c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<Matrix<float, Rows, Cols> >	operator* (const ExprP<Matrix<float, Rows, Cols> >&	left,
9843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											   const ExprP<float>&						right);
9853c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<int Rows, int Cols>
9863c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<Matrix<float, Rows, Cols> > 	operator+ (const ExprP<Matrix<float, Rows, Cols> >&	left,
9873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											   const ExprP<Matrix<float, Rows, Cols> >&	right);
9883c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<int Rows, int Cols>
9893c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<Matrix<float, Rows, Cols> > 	operator- (const ExprP<Matrix<float, Rows, Cols> >&	mat);
9903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! @}
9923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
9943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Variable expression.
9953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
9963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * A variable is evaluated by looking up its range of possible values from an
9973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * environment.
9983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
9993c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
10003c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Variable : public Expr<T>
10013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10023c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
10033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Expr<T>::IVal IVal;
10043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					Variable	(const string& name) : m_name (name) {}
10063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string			getName		(void)							const { return m_name; }
10073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10083c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
10093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void			doPrintExpr	(ostream& os)					const { os << m_name; }
10103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IVal			doEvaluate	(const EvalContext& ctx)		const
10113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return ctx.env.lookup<T>(*this);
10133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10153c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
10163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string	m_name;
10173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
10183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10193c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
10203c827367444ee418f129b2c238299f49d3264554Jarkko PoyryVariableP<T> variable (const string& name)
10213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return VariableP<T>(new Variable<T>(name));
10233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10253c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
10263c827367444ee418f129b2c238299f49d3264554Jarkko PoyryVariableP<T> bindExpression (const string& name, ExpandContext& ctx, const ExprP<T>& expr)
10273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VariableP<T> var = ctx.genSym<T>(name);
10293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ctx.addStatement(variableDeclaration(var, expr));
10303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return var;
10313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
10343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Constant expression.
10353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
10363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * A constant is evaluated by rounding it to a set of possible values allowed
10373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * by the current floating point precision.
10383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
10393c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
10403c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Constant : public Expr<T>
10413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10423c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
10433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Expr<T>::IVal IVal;
10443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Constant		(const T& value) : m_value(value) {}
10463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10473c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
10483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void	doPrintExpr		(ostream& os) const 		{ os << m_value; }
10493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IVal	doEvaluate		(const EvalContext&) const	{ return makeIVal(m_value); }
10503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10513c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
10523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	T		m_value;
10533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
10543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10553c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
10563c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<T> constant (const T& value)
10573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return exprP(new Constant<T>(value));
10593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Return a reference to a singleton void constant.
10623c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst ExprP<Void>& voidP (void)
10633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const ExprP<Void> singleton = constant(Void());
10653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return singleton;
10673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
10703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Four-element tuple.
10713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
10723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * This is used for various things where we need one thing for each possible
10733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * function parameter. Currently the maximum supported number of parameters is
10743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * four.
10753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
10763c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T0 = Void, typename T1 = Void, typename T2 = Void, typename T3 = Void>
10773c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct Tuple4
10783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	explicit Tuple4 (const T0& e0 = T0(),
10803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					 const T1& e1 = T1(),
10813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					 const T2& e2 = T2(),
10823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					 const T3& e3 = T3())
10833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: a	(e0)
10843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, b	(e1)
10853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, c	(e2)
10863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, d	(e3)
10873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	T0 a;
10913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	T1 b;
10923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	T2 c;
10933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	T3 d;
10943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
10953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
10973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Function signature.
10983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
10993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * This is a purely compile-time structure used to bundle all types in a
11003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * function signature together. This makes passing the signature around in
11013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * templates easier, since we only need to take and pass a single Sig instead
11023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * of a bunch of parameter types and a return type.
11033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
11043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
11053c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename R,
11063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		  typename P0 = Void, typename P1 = Void,
11073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		  typename P2 = Void, typename P3 = Void>
11083c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct Signature
11093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef R							Ret;
11113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef P0							Arg0;
11123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef P1							Arg1;
11133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef P2							Arg2;
11143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef P3							Arg3;
11153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Traits<Ret>::IVal	IRet;
11163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Traits<Arg0>::IVal	IArg0;
11173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Traits<Arg1>::IVal	IArg1;
11183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Traits<Arg2>::IVal	IArg2;
11193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Traits<Arg3>::IVal	IArg3;
11203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef Tuple4<	const Arg0&,	const Arg1&,	const Arg2&,	const Arg3&>	Args;
11223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef Tuple4<	const IArg0&,	const IArg1&,	const IArg2&,	const IArg3&> 	IArgs;
11233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef Tuple4<	ExprP<Arg0>,	ExprP<Arg1>,	ExprP<Arg2>,	ExprP<Arg3> >	ArgExprs;
11243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
11253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11263c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytypedef vector<const ExprBase*> BaseArgExprs;
11273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
11293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Type-independent operations for function objects.
11303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
11313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
11323c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FuncBase
11333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11343c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
11353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual			~FuncBase				(void)					{}
11363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual string	getName					(void) 					const = 0;
11373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	//! Name of extension that this function requires, or empty.
11383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual string	getRequiredExtension	(void) 					const { return ""; }
11393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual void	print					(ostream&,
11403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 const BaseArgExprs&)	const = 0;
11413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	//! Index of output parameter, or -1 if none of the parameters is output.
11423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual int		getOutParamIndex		(void)					const { return -1; }
11433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void			printDefinition			(ostream& os)			const
11453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		doPrintDefinition(os);
11473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void				getUsedFuncs		(FuncSet& dst) const
11503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		this->doGetUsedFuncs(dst);
11523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11543c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
11553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual void	doPrintDefinition		(ostream& os)			const = 0;
11563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual void	doGetUsedFuncs			(FuncSet& dst)			const = 0;
11573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
11583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11593c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytypedef Tuple4<string, string, string, string> ParamNames;
11603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
11623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Function objects.
11633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
11643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Each Func object represents a GLSL function. It can be applied to interval
11653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * arguments, and it returns the an interval that is a conservative
11663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * approximation of the image of the GLSL function over the argument
11673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * intervals. That is, it is given a set of possible arguments and it returns
11683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * the set of possible values.
11693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
11703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
11713c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename Sig_>
11723c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Func : public FuncBase
11733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11743c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
11753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef Sig_										Sig;
11763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Sig::Ret							Ret;
11773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Sig::Arg0							Arg0;
11783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Sig::Arg1							Arg1;
11793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Sig::Arg2							Arg2;
11803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Sig::Arg3							Arg3;
11813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Sig::IRet							IRet;
11823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Sig::IArg0							IArg0;
11833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Sig::IArg1							IArg1;
11843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Sig::IArg2							IArg2;
11853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Sig::IArg3							IArg3;
11863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Sig::Args							Args;
11873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Sig::IArgs							IArgs;
11883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Sig::ArgExprs						ArgExprs;
11893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void				print			(ostream&			os,
11913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 const BaseArgExprs& args)				const
11923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		this->doPrint(os, args);
11943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IRet				apply			(const EvalContext&	ctx,
11973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 const IArg0&		arg0 = IArg0(),
11983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 const IArg1&		arg1 = IArg1(),
11993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 const IArg2&		arg2 = IArg2(),
12003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 const IArg3&		arg3 = IArg3())		const
12013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return this->applyArgs(ctx, IArgs(arg0, arg1, arg2, arg3));
12033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IRet				applyArgs		(const EvalContext&	ctx,
12053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 const IArgs&		args)				const
12063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return this->doApply(ctx, args);
12083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ExprP<Ret>			operator()		(const ExprP<Arg0>&		arg0 = voidP(),
12103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 const ExprP<Arg1>&		arg1 = voidP(),
12113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 const ExprP<Arg2>&		arg2 = voidP(),
12123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 const ExprP<Arg3>&		arg3 = voidP())		const;
12133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const ParamNames&	getParamNames	(void)									const
12153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return this->doGetParamNames();
12173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12193c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
12203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual IRet		doApply			(const EvalContext&,
12213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 const IArgs&)							const = 0;
12223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual void		doPrint			(ostream& os, const BaseArgExprs& args)	const
12233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		os << getName() << "(";
12253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (isTypeValid<Arg0>())
12273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			os << *args[0];
12283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (isTypeValid<Arg1>())
12303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			os << ", " << *args[1];
12313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (isTypeValid<Arg2>())
12333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			os << ", " << *args[2];
12343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (isTypeValid<Arg3>())
12363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			os << ", " << *args[3];
12373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		os << ")";
12393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual const ParamNames&	doGetParamNames	(void)							const
12423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		static ParamNames	names	("a", "b", "c", "d");
12443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return names;
12453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
12473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12483c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename Sig>
12493c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Apply : public Expr<typename Sig::Ret>
12503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
12513c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
12523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Sig::Ret				Ret;
12533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Sig::Arg0				Arg0;
12543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Sig::Arg1				Arg1;
12553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Sig::Arg2				Arg2;
12563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Sig::Arg3				Arg3;
12573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Expr<Ret>::Val			Val;
12583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Expr<Ret>::IVal		IVal;
12593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef Func<Sig>						ApplyFunc;
12603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename ApplyFunc::ArgExprs	ArgExprs;
12613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						Apply	(const ApplyFunc&		func,
12633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 const ExprP<Arg0>&		arg0 = voidP(),
12643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 const ExprP<Arg1>&		arg1 = voidP(),
12653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 const ExprP<Arg2>&		arg2 = voidP(),
12663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 const ExprP<Arg3>&		arg3 = voidP())
12673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							: m_func	(func),
12683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  m_args	(arg0, arg1, arg2, arg3) {}
12693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						Apply	(const ApplyFunc&	func,
12713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 const ArgExprs&	args)
12723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							: m_func	(func),
12733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  m_args	(args) {}
12743c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
12753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void				doPrintExpr			(ostream& os) const
12763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		BaseArgExprs	args;
12783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		args.push_back(m_args.a.get());
12793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		args.push_back(m_args.b.get());
12803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		args.push_back(m_args.c.get());
12813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		args.push_back(m_args.d.get());
12823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_func.print(os, args);
12833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IVal				doEvaluate		(const EvalContext& ctx) const
12863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return m_func.apply(ctx,
12883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							m_args.a->evaluate(ctx), m_args.b->evaluate(ctx),
12893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							m_args.c->evaluate(ctx), m_args.d->evaluate(ctx));
12903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void				doGetUsedFuncs	(FuncSet& dst) const
12933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_func.getUsedFuncs(dst);
12953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_args.a->getUsedFuncs(dst);
12963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_args.b->getUsedFuncs(dst);
12973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_args.c->getUsedFuncs(dst);
12983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_args.d->getUsedFuncs(dst);
12993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const ApplyFunc&	m_func;
13023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ArgExprs			m_args;
13033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
13043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13050557a707716b8a8722fa509455badf81633ad83bPyry Haulostemplate<typename T>
13060557a707716b8a8722fa509455badf81633ad83bPyry Haulosclass Alternatives : public Func<Signature<T, T, T> >
13070557a707716b8a8722fa509455badf81633ad83bPyry Haulos{
13080557a707716b8a8722fa509455badf81633ad83bPyry Haulospublic:
13090557a707716b8a8722fa509455badf81633ad83bPyry Haulos	typedef typename	Alternatives::Sig		Sig;
13100557a707716b8a8722fa509455badf81633ad83bPyry Haulos
13110557a707716b8a8722fa509455badf81633ad83bPyry Haulosprotected:
13120557a707716b8a8722fa509455badf81633ad83bPyry Haulos	typedef typename	Alternatives::IRet		IRet;
13130557a707716b8a8722fa509455badf81633ad83bPyry Haulos	typedef typename	Alternatives::IArgs		IArgs;
13140557a707716b8a8722fa509455badf81633ad83bPyry Haulos
13150557a707716b8a8722fa509455badf81633ad83bPyry Haulos	virtual string		getName				(void) const			{ return "alternatives"; }
13160557a707716b8a8722fa509455badf81633ad83bPyry Haulos	virtual void		doPrintDefinition	(std::ostream&) const	{}
13170557a707716b8a8722fa509455badf81633ad83bPyry Haulos	void				doGetUsedFuncs		(FuncSet&) const		{}
13180557a707716b8a8722fa509455badf81633ad83bPyry Haulos
13190557a707716b8a8722fa509455badf81633ad83bPyry Haulos	virtual IRet		doApply				(const EvalContext&, const IArgs& args) const
13200557a707716b8a8722fa509455badf81633ad83bPyry Haulos	{
13210557a707716b8a8722fa509455badf81633ad83bPyry Haulos		return unionIVal<T>(args.a, args.b);
13220557a707716b8a8722fa509455badf81633ad83bPyry Haulos	}
13230557a707716b8a8722fa509455badf81633ad83bPyry Haulos
13240557a707716b8a8722fa509455badf81633ad83bPyry Haulos	virtual void		doPrint				(ostream& os, const BaseArgExprs& args)	const
13250557a707716b8a8722fa509455badf81633ad83bPyry Haulos	{
13260557a707716b8a8722fa509455badf81633ad83bPyry Haulos		os << "{" << *args[0] << " | " << *args[1] << "}";
13270557a707716b8a8722fa509455badf81633ad83bPyry Haulos	}
13280557a707716b8a8722fa509455badf81633ad83bPyry Haulos};
13290557a707716b8a8722fa509455badf81633ad83bPyry Haulos
13303c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename Sig>
13313c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<typename Sig::Ret> createApply (const Func<Sig>&						func,
13323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									  const typename Func<Sig>::ArgExprs&	args)
13333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return exprP(new Apply<Sig>(func, args));
13353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13373c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename Sig>
13383c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<typename Sig::Ret> createApply (
13393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const Func<Sig>&			func,
13403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const ExprP<typename Sig::Arg0>&	arg0 = voidP(),
13413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const ExprP<typename Sig::Arg1>&	arg1 = voidP(),
13423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const ExprP<typename Sig::Arg2>&	arg2 = voidP(),
13433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const ExprP<typename Sig::Arg3>&	arg3 = voidP())
13443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return exprP(new Apply<Sig>(func, arg0, arg1, arg2, arg3));
13463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13483c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename Sig>
13493c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<typename Sig::Ret> Func<Sig>::operator() (const ExprP<typename Sig::Arg0>& arg0,
13503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												const ExprP<typename Sig::Arg1>& arg1,
13513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												const ExprP<typename Sig::Arg2>& arg2,
13523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												const ExprP<typename Sig::Arg3>& arg3) const
13533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return createApply(*this, arg0, arg1, arg2, arg3);
13553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13573c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename F>
13583c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<typename F::Ret> app (const ExprP<typename F::Arg0>& arg0 = voidP(),
13593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							const ExprP<typename F::Arg1>& arg1 = voidP(),
13603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							const ExprP<typename F::Arg2>& arg2 = voidP(),
13613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							const ExprP<typename F::Arg3>& arg3 = voidP())
13623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return createApply(instance<F>(), arg0, arg1, arg2, arg3);
13643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13663c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename F>
13673c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytypename F::IRet call (const EvalContext&			ctx,
13683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					   const typename F::IArg0&		arg0 = Void(),
13693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					   const typename F::IArg1&		arg1 = Void(),
13703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					   const typename F::IArg2&		arg2 = Void(),
13713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					   const typename F::IArg3&		arg3 = Void())
13723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return instance<F>().apply(ctx, arg0, arg1, arg2, arg3);
13743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13760557a707716b8a8722fa509455badf81633ad83bPyry Haulostemplate <typename T>
13770557a707716b8a8722fa509455badf81633ad83bPyry HaulosExprP<T> alternatives (const ExprP<T>& arg0,
13780557a707716b8a8722fa509455badf81633ad83bPyry Haulos					   const ExprP<T>& arg1)
13790557a707716b8a8722fa509455badf81633ad83bPyry Haulos{
13800557a707716b8a8722fa509455badf81633ad83bPyry Haulos	return createApply<typename Alternatives<T>::Sig>(instance<Alternatives<T> >(), arg0, arg1);
13810557a707716b8a8722fa509455badf81633ad83bPyry Haulos}
13820557a707716b8a8722fa509455badf81633ad83bPyry Haulos
13833c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename Sig>
13843c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ApplyVar : public Apply<Sig>
13853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13863c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
13873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Sig::Ret				Ret;
13883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Sig::Arg0				Arg0;
13893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Sig::Arg1				Arg1;
13903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Sig::Arg2				Arg2;
13913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Sig::Arg3				Arg3;
13923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Expr<Ret>::Val			Val;
13933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Expr<Ret>::IVal		IVal;
13943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef Func<Sig>						ApplyFunc;
13953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename ApplyFunc::ArgExprs	ArgExprs;
13963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						ApplyVar	(const ApplyFunc&			func,
13983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 const VariableP<Arg0>&		arg0,
13993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 const VariableP<Arg1>&		arg1,
14003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 const VariableP<Arg2>&		arg2,
14013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 const VariableP<Arg3>&		arg3)
14023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							: Apply<Sig> (func, arg0, arg1, arg2, arg3) {}
14033c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
14043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IVal				doEvaluate		(const EvalContext& ctx) const
14053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Variable<Arg0>&	var0 = static_cast<const Variable<Arg0>&>(*this->m_args.a);
14073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Variable<Arg1>&	var1 = static_cast<const Variable<Arg1>&>(*this->m_args.b);
14083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Variable<Arg2>&	var2 = static_cast<const Variable<Arg2>&>(*this->m_args.c);
14093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Variable<Arg3>&	var3 = static_cast<const Variable<Arg3>&>(*this->m_args.d);
14103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return this->m_func.apply(ctx,
14113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								  ctx.env.lookup(var0), ctx.env.lookup(var1),
14123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								  ctx.env.lookup(var2), ctx.env.lookup(var3));
14133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
14153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14163c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename Sig>
14173c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<typename Sig::Ret> applyVar (const Func<Sig>&						func,
14183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								   const VariableP<typename Sig::Arg0>&	arg0,
14193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								   const VariableP<typename Sig::Arg1>&	arg1,
14203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								   const VariableP<typename Sig::Arg2>&	arg2,
14213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								   const VariableP<typename Sig::Arg3>&	arg3)
14223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
14233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return exprP(new ApplyVar<Sig>(func, arg0, arg1, arg2, arg3));
14243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
14253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14263c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename Sig_>
14273c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass DerivedFunc : public Func<Sig_>
14283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
14293c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
14303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename DerivedFunc::ArgExprs		ArgExprs;
14313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename DerivedFunc::IRet			IRet;
14323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename DerivedFunc::IArgs			IArgs;
14333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename DerivedFunc::Ret			Ret;
14343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename DerivedFunc::Arg0			Arg0;
14353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename DerivedFunc::Arg1			Arg1;
14363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename DerivedFunc::Arg2			Arg2;
14373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename DerivedFunc::Arg3			Arg3;
14383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename DerivedFunc::IArg0			IArg0;
14393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename DerivedFunc::IArg1			IArg1;
14403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename DerivedFunc::IArg2			IArg2;
14413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename DerivedFunc::IArg3			IArg3;
14423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14433c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
14443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void						doPrintDefinition	(ostream& os) const
14453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const ParamNames&	paramNames	= this->getParamNames();
14473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		initialize();
14493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		os << dataTypeNameOf<Ret>() << " " << this->getName()
14513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "(";
14523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (isTypeValid<Arg0>())
14533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			os << dataTypeNameOf<Arg0>() << " " << paramNames.a;
14543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (isTypeValid<Arg1>())
14553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			os << ", " << dataTypeNameOf<Arg1>() << " " << paramNames.b;
14563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (isTypeValid<Arg2>())
14573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			os << ", " << dataTypeNameOf<Arg2>() << " " << paramNames.c;
14583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (isTypeValid<Arg3>())
14593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			os << ", " << dataTypeNameOf<Arg3>() << " " << paramNames.d;
14603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		os << ")\n{\n";
14613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (size_t ndx = 0; ndx < m_body.size(); ++ndx)
14633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			os << *m_body[ndx];
14643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		os << "return " << *m_ret << ";\n";
14653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		os << "}\n";
14663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IRet						doApply			(const EvalContext&	ctx,
14693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 const IArgs&		args) const
14703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		Environment	funEnv;
14723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		IArgs&		mutArgs		= const_cast<IArgs&>(args);
14733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		IRet		ret;
14743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		initialize();
14763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		funEnv.bind(*m_var0, args.a);
14783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		funEnv.bind(*m_var1, args.b);
14793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		funEnv.bind(*m_var2, args.c);
14803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		funEnv.bind(*m_var3, args.d);
14813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
14833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			EvalContext	funCtx(ctx.format, ctx.floatPrecision, funEnv, ctx.callDepth);
14843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (size_t ndx = 0; ndx < m_body.size(); ++ndx)
14863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_body[ndx]->execute(funCtx);
14873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			ret = m_ret->evaluate(funCtx);
14893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
14903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// \todo [lauri] Store references instead of values in environment
14923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const_cast<IArg0&>(mutArgs.a) = funEnv.lookup(*m_var0);
14933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const_cast<IArg1&>(mutArgs.b) = funEnv.lookup(*m_var1);
14943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const_cast<IArg2&>(mutArgs.c) = funEnv.lookup(*m_var2);
14953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const_cast<IArg3&>(mutArgs.d) = funEnv.lookup(*m_var3);
14963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return ret;
14983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void						doGetUsedFuncs	(FuncSet& dst) const
15013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		initialize();
15033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (dst.insert(this).second)
15043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
15053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (size_t ndx = 0; ndx < m_body.size(); ++ndx)
15063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_body[ndx]->getUsedFuncs(dst);
15073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_ret->getUsedFuncs(dst);
15083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
15093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual ExprP<Ret>			doExpand		(ExpandContext& ctx, const ArgExprs& args_) const = 0;
15123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// These are transparently initialized when first needed. They cannot be
15143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// initialized in the constructor because they depend on the doExpand
15153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// method of the subclass.
15163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	mutable VariableP<Arg0>		m_var0;
15183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	mutable VariableP<Arg1>		m_var1;
15193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	mutable VariableP<Arg2>		m_var2;
15203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	mutable VariableP<Arg3>		m_var3;
15213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	mutable vector<StatementP>	m_body;
15223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	mutable ExprP<Ret>			m_ret;
15233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15243c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
15253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void				initialize		(void)	const
15273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!m_ret)
15293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
15303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const ParamNames&	paramNames	= this->getParamNames();
15313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Counter				symCounter;
15323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			ExpandContext		ctx			(symCounter);
15333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			ArgExprs			args;
15343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			args.a	= m_var0 = variable<Arg0>(paramNames.a);
15363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			args.b	= m_var1 = variable<Arg1>(paramNames.b);
15373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			args.c	= m_var2 = variable<Arg2>(paramNames.c);
15383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			args.d	= m_var3 = variable<Arg3>(paramNames.d);
15393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_ret	= this->doExpand(ctx, args);
15413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_body	= ctx.getStatements();
15423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
15433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
15453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15463c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename Sig>
15473c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass PrimitiveFunc : public Func<Sig>
15483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15493c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
15503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename PrimitiveFunc::Ret			Ret;
15513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename PrimitiveFunc::ArgExprs	ArgExprs;
15523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15533c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
15543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void	doPrintDefinition	(ostream&) const	{}
15553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void	doGetUsedFuncs		(FuncSet&) const	{}
15563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
15573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15583c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
15593c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Cond : public PrimitiveFunc<Signature<T, bool, T, T> >
15603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15613c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
15623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Cond::IArgs	IArgs;
15633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Cond::IRet		IRet;
15643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string	getName	(void) const
15663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return "_cond";
15683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15703c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
15713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void	doPrint	(ostream& os, const BaseArgExprs& args) const
15733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		os << "(" << *args[0] << " ? " << *args[1] << " : " << *args[2] << ")";
15753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IRet	doApply	(const EvalContext&, const IArgs& iargs)const
15783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		IRet	ret;
15803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (iargs.a.contains(true))
15823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			ret = unionIVal<T>(ret, iargs.b);
15833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (iargs.a.contains(false))
15853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			ret = unionIVal<T>(ret, iargs.c);
15863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return ret;
15883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
15903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15913c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
15923c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass CompareOperator : public PrimitiveFunc<Signature<bool, T, T> >
15933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15943c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
15953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename CompareOperator::IArgs	IArgs;
15963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename CompareOperator::IArg0	IArg0;
15973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename CompareOperator::IArg1	IArg1;
15983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename CompareOperator::IRet	IRet;
15993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16003c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
16013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void			doPrint	(ostream& os, const BaseArgExprs& args) const
16023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		os << "(" << *args[0] << getSymbol() << *args[1] << ")";
16043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Interval		doApply	(const EvalContext&, const IArgs& iargs) const
16073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const IArg0&	arg0 = iargs.a;
16093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const IArg1&	arg1 = iargs.b;
16103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		IRet	ret;
16113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (canSucceed(arg0, arg1))
16133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			ret |= true;
16143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (canFail(arg0, arg1))
16153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			ret |= false;
16163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return ret;
16183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual string	getSymbol	(void) const = 0;
16213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual bool	canSucceed	(const IArg0&, const IArg1&) const = 0;
16223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual bool	canFail		(const IArg0&, const IArg1&) const = 0;
16233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
16243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16253c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
16263c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass LessThan : public CompareOperator<T>
16273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
16283c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
16293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string	getName		(void) const									{ return "lessThan"; }
16303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16313c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
16323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string	getSymbol	(void) const									{ return "<";		}
16333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool	canSucceed	(const Interval& a, const Interval& b) const
16353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return (a.lo() < b.hi());
16373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool	canFail		(const Interval& a, const Interval& b) const
16403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return !(a.hi() < b.lo());
16423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
16443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16453c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
16463c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<bool> operator< (const ExprP<T>& a, const ExprP<T>& b)
16473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
16483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return app<LessThan<T> >(a, b);
16493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
16503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16513c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
16523c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<T> cond (const ExprP<bool>&	test,
16533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			   const ExprP<T>&		consequent,
16543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			   const ExprP<T>&		alternative)
16553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
16563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return app<Cond<T> >(test, consequent, alternative);
16573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
16583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
16603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
16613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * @}
16623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
16633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
16643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16653c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FloatFunc1 : public PrimitiveFunc<Signature<float, float> >
16663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
16673c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
16683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Interval			doApply			(const EvalContext& ctx, const IArgs& iargs) const
16693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return this->applyMonotone(ctx, iargs.a);
16713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Interval			applyMonotone	(const EvalContext& ctx, const Interval& iarg0) const
16743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		Interval ret;
16763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TCU_INTERVAL_APPLY_MONOTONE1(ret, arg0, iarg0, val,
16783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 TCU_SET_INTERVAL(val, point,
16793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  point = this->applyPoint(ctx, arg0)));
16803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ret |= innerExtrema(ctx, iarg0);
16823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ret &= (this->getCodomain() | TCU_NAN);
16833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return ctx.format.convert(ret);
16853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual Interval	innerExtrema	(const EvalContext&, const Interval&) const
16883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return Interval(); // empty interval, i.e. no extrema
16903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual Interval	applyPoint		(const EvalContext& ctx, double arg0) const
16933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const double	exact	= this->applyExact(arg0);
16953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const double	prec	= this->precision(ctx, exact, arg0);
16963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return exact + Interval(-prec, prec);
16983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual double		applyExact		(double) const
17013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
17023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TCU_THROW(InternalError, "Cannot apply");
17033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
17043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual Interval	getCodomain		(void) const
17063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
17073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return Interval::unbounded(true);
17083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
17093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual double		precision		(const EvalContext& ctx, double, double) const = 0;
17113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
17123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17133c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass CFloatFunc1 : public FloatFunc1
17143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
17153c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
17163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			CFloatFunc1	(const string& name, DoubleFunc1& func)
17173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				: m_name(name), m_func(func) {}
17183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string			getName		(void) const		{ return m_name; }
17203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17213c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
17223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	double			applyExact	(double x) const	{ return m_func(x); }
17233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string	m_name;
17253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DoubleFunc1&	m_func;
17263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
17273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17283c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FloatFunc2 : public PrimitiveFunc<Signature<float, float, float> >
17293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
17303c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
17313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Interval			doApply			(const EvalContext&	ctx, const IArgs& iargs) const
17323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
17333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return this->applyMonotone(ctx, iargs.a, iargs.b);
17343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
17353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Interval			applyMonotone	(const EvalContext&	ctx,
17373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 const Interval&	xi,
17383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 const Interval&	yi) const
17393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
17403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		Interval reti;
17413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TCU_INTERVAL_APPLY_MONOTONE2(reti, x, xi, y, yi, ret,
17433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 TCU_SET_INTERVAL(ret, point,
17443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  point = this->applyPoint(ctx, x, y)));
17453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		reti |= innerExtrema(ctx, xi, yi);
17463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		reti &= (this->getCodomain() | TCU_NAN);
17473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return ctx.format.convert(reti);
17493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
17503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual Interval	innerExtrema	(const EvalContext&,
17523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 const Interval&,
17533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 const Interval&) const
17543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
17553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return Interval(); // empty interval, i.e. no extrema
17563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
17573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual Interval	applyPoint		(const EvalContext&	ctx,
17593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 double 			x,
17603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 double 			y) const
17613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
17623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const double exact	= this->applyExact(x, y);
17633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const double prec	= this->precision(ctx, exact, x, y);
17643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return exact + Interval(-prec, prec);
17663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
17673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual double		applyExact		(double, double) const
17693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
17703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TCU_THROW(InternalError, "Cannot apply");
17713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
17723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual Interval	getCodomain		(void) const
17743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
17753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return Interval::unbounded(true);
17763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
17773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual double		precision		(const EvalContext&	ctx,
17793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 double				ret,
17803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 double				x,
17813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 double				y) const = 0;
17823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
17833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17843c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass CFloatFunc2 : public FloatFunc2
17853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
17863c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
17873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					CFloatFunc2	(const string&	name,
17883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 DoubleFunc2&	func)
17893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						: m_name(name)
17903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						, m_func(func)
17913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
17923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
17933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string			getName		(void) const						{ return m_name; }
17953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17963c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
17973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	double			applyExact	(double x, double y) const			{ return m_func(x, y); }
17983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string	m_name;
18003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DoubleFunc2&	m_func;
18013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
18023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18033c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass InfixOperator : public FloatFunc2
18043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
18053c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
18063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual string	getSymbol		(void) const = 0;
18073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void			doPrint			(ostream& os, const BaseArgExprs& args) const
18093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
18103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		os << "(" << *args[0] << " " << getSymbol() << " " << *args[1] << ")";
18113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
18123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Interval		applyPoint		(const EvalContext&	ctx,
18143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 double 			x,
18153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 double 			y) const
18163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
18173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const double exact	= this->applyExact(x, y);
18183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Allow either representable number on both sides of the exact value,
18203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// but require exactly representable values to be preserved.
18212e751e3e77060f699c560104e82379d3ce54f67aPyry Haulos		return ctx.format.roundOut(exact, !deIsInf(x) && !deIsInf(y));
18223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
18233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	double			precision		(const EvalContext&, double, double, double) const
18253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
18263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 0.0;
18273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
18283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
18293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18303c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FloatFunc3 : public PrimitiveFunc<Signature<float, float, float, float> >
18313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
18323c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
18333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Interval			doApply			(const EvalContext&	ctx, const IArgs& iargs) const
18343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
18353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return this->applyMonotone(ctx, iargs.a, iargs.b, iargs.c);
18363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
18373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Interval			applyMonotone	(const EvalContext&	ctx,
18393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 const Interval&	xi,
18403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 const Interval&	yi,
18413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 const Interval&	zi) const
18423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
18433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		Interval reti;
18443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TCU_INTERVAL_APPLY_MONOTONE3(reti, x, xi, y, yi, z, zi, ret,
18453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 TCU_SET_INTERVAL(ret, point,
18463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  point = this->applyPoint(ctx, x, y, z)));
18473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return ctx.format.convert(reti);
18483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
18493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual Interval	applyPoint		(const EvalContext&	ctx,
18513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 double 			x,
18523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 double 			y,
18533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 double 			z) const
18543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
18553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const double exact	= this->applyExact(x, y, z);
18563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const double prec	= this->precision(ctx, exact, x, y, z);
18573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return exact + Interval(-prec, prec);
18583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
18593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual double		applyExact		(double, double, double) const
18613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
18623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TCU_THROW(InternalError, "Cannot apply");
18633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
18643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual double		precision		(const EvalContext&	ctx,
18663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 double				result,
18673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 double				x,
18683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 double				y,
18693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 double				z) const = 0;
18703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
18713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// We define syntactic sugar functions for expression constructors. Since
18733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// these have the same names as ordinary mathematical operations (sin, log
18743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// etc.), it's better to give them a dedicated namespace.
18753c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace Functions
18763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
18773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18783c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing namespace tcu;
18793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18803c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Add : public InfixOperator
18813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
18823c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
18833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string		getName		(void) const 						{ return "add"; }
18843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string		getSymbol	(void) const 						{ return "+"; }
18853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Interval	doApply		(const EvalContext&	ctx,
18873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							 const IArgs&		iargs) const
18883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
18893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Fast-path for common case
18903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (iargs.a.isOrdinary() && iargs.b.isOrdinary())
18913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
18923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Interval ret;
18933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TCU_SET_INTERVAL_BOUNDS(ret, sum,
18943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									sum = iargs.a.lo() + iargs.b.lo(),
18953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									sum = iargs.a.hi() + iargs.b.hi());
18962e751e3e77060f699c560104e82379d3ce54f67aPyry Haulos			return ctx.format.convert(ctx.format.roundOut(ret, true));
18973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
18983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return this->applyMonotone(ctx, iargs.a, iargs.b);
18993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
19003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19013c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
19023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	double		applyExact	(double x, double y) const 			{ return x + y; }
19033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
19043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19053c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Mul : public InfixOperator
19063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
19073c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
19083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string		getName		(void) const 									{ return "mul"; }
19093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string		getSymbol	(void) const 									{ return "*"; }
19103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Interval	doApply		(const EvalContext&	ctx, const IArgs& iargs) const
19123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
19133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		Interval a = iargs.a;
19143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		Interval b = iargs.b;
19153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Fast-path for common case
19173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (a.isOrdinary() && b.isOrdinary())
19183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
19193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Interval ret;
19203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (a.hi() < 0)
19213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
19223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				a = -a;
19233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				b = -b;
19243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
19253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (a.lo() >= 0 && b.lo() >= 0)
19263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
19273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				TCU_SET_INTERVAL_BOUNDS(ret, prod,
19283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										prod = iargs.a.lo() * iargs.b.lo(),
19293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										prod = iargs.a.hi() * iargs.b.hi());
19302e751e3e77060f699c560104e82379d3ce54f67aPyry Haulos				return ctx.format.convert(ctx.format.roundOut(ret, true));
19313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
19323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (a.lo() >= 0 && b.hi() <= 0)
19333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
19343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				TCU_SET_INTERVAL_BOUNDS(ret, prod,
19353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										prod = iargs.a.hi() * iargs.b.lo(),
19363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										prod = iargs.a.lo() * iargs.b.hi());
19372e751e3e77060f699c560104e82379d3ce54f67aPyry Haulos				return ctx.format.convert(ctx.format.roundOut(ret, true));
19383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
19393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
19403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return this->applyMonotone(ctx, iargs.a, iargs.b);
19413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
19423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19433c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
19443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	double		applyExact	(double x, double y) const						{ return x * y; }
19453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Interval	innerExtrema(const EvalContext&, const Interval& xi, const Interval& yi) const
19473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
19483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (((xi.contains(-TCU_INFINITY) || xi.contains(TCU_INFINITY)) && yi.contains(0.0)) ||
19493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			((yi.contains(-TCU_INFINITY) || yi.contains(TCU_INFINITY)) && xi.contains(0.0)))
19503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return Interval(TCU_NAN);
19513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return Interval();
19533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
19543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
19553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19563c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Sub : public InfixOperator
19573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
19583c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
19593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string		getName		(void) const 				{ return "sub"; }
19603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string		getSymbol	(void) const 				{ return "-"; }
19613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Interval	doApply		(const EvalContext&	ctx, const IArgs& iargs) const
19633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
19643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Fast-path for common case
19653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (iargs.a.isOrdinary() && iargs.b.isOrdinary())
19663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
19673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Interval ret;
19683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TCU_SET_INTERVAL_BOUNDS(ret, diff,
19703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									diff = iargs.a.lo() - iargs.b.hi(),
19713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									diff = iargs.a.hi() - iargs.b.lo());
19722e751e3e77060f699c560104e82379d3ce54f67aPyry Haulos			return ctx.format.convert(ctx.format.roundOut(ret, true));
19733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
19753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
19763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
19773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return this->applyMonotone(ctx, iargs.a, iargs.b);
19783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
19793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
19803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19813c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
19823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	double		applyExact	(double x, double y) const	{ return x - y; }
19833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
19843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19853c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Negate : public FloatFunc1
19863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
19873c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
19883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string	getName		(void) const									{ return "_negate"; }
19893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void	doPrint		(ostream& os, const BaseArgExprs& args) const	{ os << "-" << *args[0]; }
19903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19913c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
19923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	double	precision	(const EvalContext&, double, double) const		{ return 0.0; }
19933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	double	applyExact	(double x) const								{ return -x; }
19943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
19953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19963c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Div : public InfixOperator
19973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
19983c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
19993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string		getName			(void) const 						{ return "div"; }
20003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20013c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
20023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string		getSymbol		(void) const 						{ return "/"; }
20033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Interval	innerExtrema	(const EvalContext&,
20053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 const Interval&		nom,
20063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 const Interval&		den) const
20073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
20083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		Interval ret;
20093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (den.contains(0.0))
20113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
20123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (nom.contains(0.0))
20133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				ret |= TCU_NAN;
20143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (nom.lo() < 0.0 || nom.hi() > 0.0)
20163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				ret |= Interval::unbounded();
20173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
20183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return ret;
20203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
20213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20224fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos	double		applyExact		(double x, double y) const { return x / y; }
20233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20244fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos	Interval	applyPoint		(const EvalContext&	ctx, double x, double y) const
20253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
20264fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos		Interval ret = FloatFunc2::applyPoint(ctx, x, y);
20274fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos
20284fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos		if (!deIsInf(x) && !deIsInf(y) && y != 0.0)
20294fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos		{
20304fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos			const Interval dst = ctx.format.convert(ret);
20314fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos			if (dst.contains(-TCU_INFINITY)) ret |= -ctx.format.getMaxValue();
20324fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos			if (dst.contains(+TCU_INFINITY)) ret |= +ctx.format.getMaxValue();
20334fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos		}
20344fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos
20354fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos		return ret;
20363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
20373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20384fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos	double		precision		(const EvalContext& ctx, double ret, double, double den) const
20393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
20403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const FloatFormat&	fmt		= ctx.format;
20413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// \todo [2014-03-05 lauri] Check that the limits in GLSL 3.10 are actually correct.
20433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// For now, we assume that division's precision is 2.5 ULP when the value is within
20443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// [2^MINEXP, 2^MAXEXP-1]
20453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (den == 0.0)
20473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return 0.0; // Result must be exactly inf
20483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (de::inBounds(deAbs(den),
20493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  deLdExp(1.0, fmt.getMinExp()),
20503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  deLdExp(1.0, fmt.getMaxExp() - 1)))
20513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return fmt.ulp(ret, 2.5);
20523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
20533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return TCU_INFINITY; // Can be any number, but must be a number.
20543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
20553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
20563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20573c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass InverseSqrt : public FloatFunc1
20583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
20593c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
20603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string		getName		(void) const							{ return "inversesqrt"; }
20613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20623c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
20633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	double		applyExact	(double x) const						{ return 1.0 / deSqrt(x); }
20643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	double		precision	(const EvalContext& ctx, double ret, double x) const
20663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
20673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return x <= 0 ? TCU_NAN : ctx.format.ulp(ret, 2.0);
20683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
20693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Interval	getCodomain	(void) const
20713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
20723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return Interval(0.0, TCU_INFINITY);
20733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
20743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
20753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20763c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ExpFunc : public CFloatFunc1
20773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
20783c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
20793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				ExpFunc		(const string& name, DoubleFunc1& func)
20803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					: CFloatFunc1(name, func) {}
20813c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
20823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	double		precision	(const EvalContext& ctx, double ret, double x) const
20833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
20843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (ctx.floatPrecision)
20853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
20863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case glu::PRECISION_HIGHP:
20873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return ctx.format.ulp(ret, 3.0 + 2.0 * deAbs(x));
20883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case glu::PRECISION_MEDIUMP:
20893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return ctx.format.ulp(ret, 2.0 + 2.0 * deAbs(x));
20903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case glu::PRECISION_LOWP:
20913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return ctx.format.ulp(ret, 2.0);
20923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:
20931cc61b7d03cad727bbddd00cea8d78f4f6cc9047Jarkko Pöyry				DE_FATAL("Impossible");
20943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
20953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 0;
20963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
20973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Interval	getCodomain	(void) const
20993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
21003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return Interval(0.0, TCU_INFINITY);
21013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
21023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
21033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21043c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Exp2	: public ExpFunc	{ public: Exp2 (void)	: ExpFunc("exp2", deExp2) {} };
21053c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Exp	: public ExpFunc	{ public: Exp (void)	: ExpFunc("exp", deExp) {} };
21063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21073c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<float> exp2	(const ExprP<float>& x)	{ return app<Exp2>(x); }
21083c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<float> exp	(const ExprP<float>& x)	{ return app<Exp>(x); }
21093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21103c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass LogFunc : public CFloatFunc1
21113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
21123c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
21133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				LogFunc		(const string& name, DoubleFunc1& func)
21143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					: CFloatFunc1(name, func) {}
21153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21163c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
21173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	double		precision	(const EvalContext& ctx, double ret, double x) const
21183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
21193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (x <= 0)
21203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return TCU_NAN;
21213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (ctx.floatPrecision)
21233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
21243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case glu::PRECISION_HIGHP:
21253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return (0.5 <= x && x <= 2.0) ? deLdExp(1.0, -21) : ctx.format.ulp(ret, 3.0);
21263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case glu::PRECISION_MEDIUMP:
21273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return (0.5 <= x && x <= 2.0) ? deLdExp(1.0, -7) : ctx.format.ulp(ret, 2.0);
21283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case glu::PRECISION_LOWP:
21293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return ctx.format.ulp(ret, 2.0);
21303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:
21311cc61b7d03cad727bbddd00cea8d78f4f6cc9047Jarkko Pöyry				DE_FATAL("Impossible");
21323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
21333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 0;
21353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
21363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
21373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21383c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Log2	: public LogFunc		{ public: Log2	(void) : LogFunc("log2", deLog2) {} };
21393c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Log	: public LogFunc		{ public: Log	(void) : LogFunc("log", deLog) {} };
21403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21413c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<float> log2	(const ExprP<float>& x)	{ return app<Log2>(x); }
21423c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<float> log	(const ExprP<float>& x)	{ return app<Log>(x); }
21433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#define DEFINE_CONSTRUCTOR1(CLASS, TRET, NAME, T0) \
21453c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<TRET> NAME (const ExprP<T0>& arg0) { return app<CLASS>(arg0); }
21463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#define DEFINE_DERIVED1(CLASS, TRET, NAME, T0, ARG0, EXPANSION)			\
21483c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass CLASS : public DerivedFunc<Signature<TRET, T0> >		 			\
21493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{																		\
21503c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:																	\
21513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string			getName		(void) const		{ return #NAME; }	\
21523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																		\
21533c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:																\
21543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ExprP<TRET>		doExpand		(ExpandContext&,					\
21553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 const CLASS::ArgExprs& args_) const \
21563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{																	\
21573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const ExprP<float>& ARG0 = args_.a;								\
21583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return EXPANSION;												\
21593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}																	\
21603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};																		\
21613c827367444ee418f129b2c238299f49d3264554Jarkko PoyryDEFINE_CONSTRUCTOR1(CLASS, TRET, NAME, T0)
21623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#define DEFINE_DERIVED_FLOAT1(CLASS, NAME, ARG0, EXPANSION) \
21643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DEFINE_DERIVED1(CLASS, float, NAME, float, ARG0, EXPANSION)
21653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#define DEFINE_CONSTRUCTOR2(CLASS, TRET, NAME, T0, T1)				\
21673c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<TRET> NAME (const ExprP<T0>& arg0, const ExprP<T1>& arg1)		\
21683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{																	\
21693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return app<CLASS>(arg0, arg1);									\
21703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
21713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#define DEFINE_DERIVED2(CLASS, TRET, NAME, T0, Arg0, T1, Arg1, EXPANSION) \
21733c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass CLASS : public DerivedFunc<Signature<TRET, T0, T1> >		 		\
21743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{																		\
21753c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:																	\
21763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string			getName		(void) const		{ return #NAME; }	\
21773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																		\
21783c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:																\
21793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ExprP<TRET>		doExpand	(ExpandContext&, const ArgExprs& args_) const \
21803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{																	\
21813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const ExprP<T0>& Arg0 = args_.a;								\
21823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const ExprP<T1>& Arg1 = args_.b;								\
21833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return EXPANSION;												\
21843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}																	\
21853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};																		\
21863c827367444ee418f129b2c238299f49d3264554Jarkko PoyryDEFINE_CONSTRUCTOR2(CLASS, TRET, NAME, T0, T1)
21873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#define DEFINE_DERIVED_FLOAT2(CLASS, NAME, Arg0, Arg1, EXPANSION)		\
21893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DEFINE_DERIVED2(CLASS, float, NAME, float, Arg0, float, Arg1, EXPANSION)
21903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#define DEFINE_CONSTRUCTOR3(CLASS, TRET, NAME, T0, T1, T2)				\
21923c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<TRET> NAME (const ExprP<T0>& arg0, const ExprP<T1>& arg1, const ExprP<T2>& arg2) \
21933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{																		\
21943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return app<CLASS>(arg0, arg1, arg2);								\
21953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
21963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#define DEFINE_DERIVED3(CLASS, TRET, NAME, T0, ARG0, T1, ARG1, T2, ARG2, EXPANSION) \
21983c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass CLASS : public DerivedFunc<Signature<TRET, T0, T1, T2> >					\
21993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{																				\
22003c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:																			\
22013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string			getName		(void) const	{ return #NAME; }				\
22023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																				\
22033c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:																		\
22043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ExprP<TRET>		doExpand	(ExpandContext&, const ArgExprs& args_) const	\
22053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{																			\
22063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const ExprP<T0>& ARG0 = args_.a;										\
22073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const ExprP<T1>& ARG1 = args_.b;										\
22083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const ExprP<T2>& ARG2 = args_.c;										\
22093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return EXPANSION;														\
22103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}																			\
22113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};																				\
22123c827367444ee418f129b2c238299f49d3264554Jarkko PoyryDEFINE_CONSTRUCTOR3(CLASS, TRET, NAME, T0, T1, T2)
22133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#define DEFINE_DERIVED_FLOAT3(CLASS, NAME, ARG0, ARG1, ARG2, EXPANSION)			\
22153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DEFINE_DERIVED3(CLASS, float, NAME, float, ARG0, float, ARG1, float, ARG2, EXPANSION)
22163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#define DEFINE_CONSTRUCTOR4(CLASS, TRET, NAME, T0, T1, T2, T3)			\
22183c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<TRET> NAME (const ExprP<T0>& arg0, const ExprP<T1>& arg1,			\
22193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				  const ExprP<T2>& arg2, const ExprP<T3>& arg3)			\
22203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{																		\
22213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return app<CLASS>(arg0, arg1, arg2, arg3);							\
22223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
22233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22243c827367444ee418f129b2c238299f49d3264554Jarkko PoyryDEFINE_DERIVED_FLOAT1(Sqrt,		sqrt,		x, 		constant(1.0f) / app<InverseSqrt>(x));
22253c827367444ee418f129b2c238299f49d3264554Jarkko PoyryDEFINE_DERIVED_FLOAT2(Pow,		pow,		x,	y,	exp2(y * log2(x)));
22263c827367444ee418f129b2c238299f49d3264554Jarkko PoyryDEFINE_DERIVED_FLOAT1(Radians,	radians,	d, 		(constant(DE_PI) / constant(180.0f)) * d);
22273c827367444ee418f129b2c238299f49d3264554Jarkko PoyryDEFINE_DERIVED_FLOAT1(Degrees,	degrees,	r,	 	(constant(180.0f) / constant(DE_PI)) * r);
22283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22293c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass TrigFunc : public CFloatFunc1
22303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
22313c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
22323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					TrigFunc		(const string&		name,
22333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 DoubleFunc1&		func,
22343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 const Interval&	loEx,
22353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 const Interval&	hiEx)
22363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						: CFloatFunc1	(name, func)
22373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						, m_loExtremum	(loEx)
22383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						, m_hiExtremum	(hiEx) {}
22393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22403c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
22413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Interval		innerExtrema	(const EvalContext&, const Interval& angle) const
22423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
22433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const double		lo		= angle.lo();
22443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const double		hi		= angle.hi();
22453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int			loSlope	= doGetSlope(lo);
22463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int			hiSlope	= doGetSlope(hi);
22473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Detect the high and low values the function can take between the
22493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// interval endpoints.
22503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (angle.length() >= 2.0 * DE_PI_DOUBLE)
22513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
22523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// The interval is longer than a full cycle, so it must get all possible values.
22533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return m_hiExtremum | m_loExtremum;
22543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
22553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (loSlope == 1 && hiSlope == -1)
22563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
22573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// The slope can change from positive to negative only at the maximum value.
22583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return m_hiExtremum;
22593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
22603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (loSlope == -1 && hiSlope == 1)
22613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
22623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// The slope can change from negative to positive only at the maximum value.
22633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return m_loExtremum;
22643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
22653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (loSlope == hiSlope &&
22663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				 deIntSign(applyExact(hi) - applyExact(lo)) * loSlope == -1)
22673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
22683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// The slope has changed twice between the endpoints, so both extrema are included.
22693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return m_hiExtremum | m_loExtremum;
22703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
22713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return Interval();
22733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
22743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Interval	getCodomain			(void) const
22763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
22773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Ensure that result is always within [-1, 1], or NaN (for +-inf)
22783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return Interval(-1.0, 1.0) | TCU_NAN;
22793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
22803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	double		precision			(const EvalContext& ctx, double ret, double arg) const
22823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
22833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (ctx.floatPrecision == glu::PRECISION_HIGHP)
22843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
22853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Use precision from OpenCL fast relaxed math
22863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (-DE_PI_DOUBLE <= arg && arg <= DE_PI_DOUBLE)
22873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
22883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return deLdExp(1.0, -11);
22893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
22903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
22913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
22923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// "larger otherwise", let's pick |x| * 2^-12 , which is slightly over
22933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// 2^-11 at x == pi.
22943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return deLdExp(deAbs(arg), -12);
22953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
22963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
22974fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos		else if (ctx.floatPrecision == glu::PRECISION_MEDIUMP)
22984fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos		{
22994fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos			if (-DE_PI_DOUBLE <= arg && arg <= DE_PI_DOUBLE)
23004fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos			{
23014fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos				// from OpenCL half-float extension specification
23024fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos				return ctx.format.ulp(ret, 2.0);
23034fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos			}
23044fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos			else
23054fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos			{
23064fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos				// |x| * 2^-10, slightly larger than 2 ULP at x == pi
23074fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos				return deLdExp(deAbs(DE_PI_DOUBLE), -10);
23084fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos			}
23094fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos		}
23103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
23113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
23124fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos			DE_ASSERT(ctx.floatPrecision == glu::PRECISION_LOWP);
23134fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos
23143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// from OpenCL half-float extension specification
23153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return ctx.format.ulp(ret, 2.0);
23163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
23173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
23183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual int		doGetSlope		(double angle) const = 0;
23203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Interval		m_loExtremum;
23223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Interval		m_hiExtremum;
23233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
23243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23253c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Sin : public TrigFunc
23263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
23273c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
23283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				Sin			(void) : TrigFunc("sin", deSin, -1.0, 1.0) {}
23293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23303c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
23313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			doGetSlope	(double angle) const { return deIntSign(deCos(angle)); }
23323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
23333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23343c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<float> sin (const ExprP<float>& x) { return app<Sin>(x); }
23353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23363c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Cos : public TrigFunc
23373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
23383c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
23393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				Cos			(void) : TrigFunc("cos", deCos, -1.0, 1.0) {}
23403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23413c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
23423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			doGetSlope	(double angle) const { return -deIntSign(deSin(angle)); }
23433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
23443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23453c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<float> cos (const ExprP<float>& x) { return app<Cos>(x); }
23463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23473c827367444ee418f129b2c238299f49d3264554Jarkko PoyryDEFINE_DERIVED_FLOAT1(Tan, tan, x, sin(x) * (constant(1.0f) / cos(x)));
23483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23493c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ArcTrigFunc : public CFloatFunc1
23503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
23513c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
23523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					ArcTrigFunc	(const string&		name,
23533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 DoubleFunc1&		func,
23543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 double				precisionULPs,
23553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 const Interval&	domain,
23563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 const Interval&	codomain)
23573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						: CFloatFunc1		(name, func)
23583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						, m_precision		(precisionULPs)
23593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						, m_domain			(domain)
23603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						, m_codomain		(codomain) {}
23613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23623c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
23633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	double			precision	(const EvalContext& ctx, double ret, double x) const
23643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
23653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!m_domain.contains(x))
23663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return TCU_NAN;
23673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (ctx.floatPrecision == glu::PRECISION_HIGHP)
23693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
23704fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos			// Use OpenCL's fast relaxed math precision
23713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return ctx.format.ulp(ret, m_precision);
23723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
23733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
23743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
23753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Use OpenCL half-float spec
23763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return ctx.format.ulp(ret, 2.0);
23773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
23783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
23793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// We could implement getCodomain with m_codomain, but choose not to,
23813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// because it seems too strict with trascendental constants like pi.
23823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const double	m_precision;
23843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const Interval	m_domain;
23853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const Interval	m_codomain;
23863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
23873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23883c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ASin : public ArcTrigFunc
23893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
23903c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
23914fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos	ASin (void) : ArcTrigFunc("asin", deAsin, 4096.0,
23923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  Interval(-1.0, 1.0),
23933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  Interval(-DE_PI_DOUBLE * 0.5, DE_PI_DOUBLE * 0.5)) {}
23943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
23953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23963c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ACos : public ArcTrigFunc
23973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
23983c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
23994fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos	ACos (void) : ArcTrigFunc("acos", deAcos, 4096.0,
24003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  Interval(-1.0, 1.0),
24013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  Interval(0.0, DE_PI_DOUBLE)) {}
24023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
24033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24043c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ATan : public ArcTrigFunc
24053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
24063c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
24074fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos	ATan (void) : ArcTrigFunc("atan", deAtanOver, 4096.0,
24083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  Interval::unbounded(),
24093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  Interval(-DE_PI_DOUBLE * 0.5, DE_PI_DOUBLE * 0.5)) {}
24103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
24113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24123c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ATan2 : public CFloatFunc2
24133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
24143c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
24153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				ATan2			(void) : CFloatFunc2 ("atan", deAtan2) {}
24163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24173c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
24184fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos	Interval	innerExtrema	(const EvalContext&		ctx,
24193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 const Interval&		yi,
24203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 const Interval& 		xi) const
24213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
24223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		Interval ret;
24233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (yi.contains(0.0))
24253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
24263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (xi.contains(0.0))
24273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				ret |= TCU_NAN;
24283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (xi.intersects(Interval(-TCU_INFINITY, 0.0)))
24293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				ret |= Interval(-DE_PI_DOUBLE, DE_PI_DOUBLE);
24303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
24313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24324fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos		if (ctx.format.hasInf() != YES && (!yi.isFinite() || !xi.isFinite()))
24334fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos		{
24344fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos			// Infinities may not be supported, allow anything, including NaN
24354fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos			ret |= TCU_NAN;
24364fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos		}
24374fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos
24383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return ret;
24393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
24403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	double		precision		(const EvalContext& ctx, double ret, double, double) const
24423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
24433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (ctx.floatPrecision == glu::PRECISION_HIGHP)
24444fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos			return ctx.format.ulp(ret, 4096.0);
24453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
24463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return ctx.format.ulp(ret, 2.0);
24473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
24483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Codomain could be [-pi, pi], but that would probably be too strict.
24503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
24513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24523c827367444ee418f129b2c238299f49d3264554Jarkko PoyryDEFINE_DERIVED_FLOAT1(Sinh, sinh, x, (exp(x) - exp(-x)) / constant(2.0f));
24533c827367444ee418f129b2c238299f49d3264554Jarkko PoyryDEFINE_DERIVED_FLOAT1(Cosh, cosh, x, (exp(x) + exp(-x)) / constant(2.0f));
24543c827367444ee418f129b2c238299f49d3264554Jarkko PoyryDEFINE_DERIVED_FLOAT1(Tanh, tanh, x, sinh(x) / cosh(x));
24553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// These are not defined as derived forms in the GLSL ES spec, but
24573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// that gives us a reasonable precision.
24583c827367444ee418f129b2c238299f49d3264554Jarkko PoyryDEFINE_DERIVED_FLOAT1(ASinh, asinh, x, log(x + sqrt(x * x + constant(1.0f))));
24593c827367444ee418f129b2c238299f49d3264554Jarkko PoyryDEFINE_DERIVED_FLOAT1(ACosh, acosh, x, log(x + sqrt((x + constant(1.0f)) *
24603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													(x - constant(1.0f)))));
24613c827367444ee418f129b2c238299f49d3264554Jarkko PoyryDEFINE_DERIVED_FLOAT1(ATanh, atanh, x, constant(0.5f) * log((constant(1.0f) + x) /
24623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															(constant(1.0f) - x)));
24633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24643c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
24653c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass GetComponent : public PrimitiveFunc<Signature<typename T::Element, T, int> >
24663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
24673c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
24683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef		typename GetComponent::IRet	IRet;
24693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string		getName		(void) const { return "_getComponent"; }
24713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void		print		(ostream&				os,
24733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							 const BaseArgExprs&	args) const
24743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
24753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		os << *args[0] << "[" << *args[1] << "]";
24763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
24773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24783c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
24793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IRet		doApply 	(const EvalContext&,
24803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							 const typename GetComponent::IArgs& iargs) const
24813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
24823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		IRet ret;
24833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int compNdx = 0; compNdx < T::SIZE; ++compNdx)
24853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
24863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (iargs.b.contains(compNdx))
24873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				ret = unionIVal<typename T::Element>(ret, iargs.a[compNdx]);
24883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
24893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return ret;
24913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
24923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
24943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24953c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
24963c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<typename T::Element> getComponent (const ExprP<T>& container, int ndx)
24973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
24983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(0 <= ndx && ndx < T::SIZE);
24993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return app<GetComponent<T> >(container, constant(ndx));
25003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
25013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25023c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>	string	vecNamePrefix			(void);
25033c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <>				string	vecNamePrefix<float>	(void) { return ""; }
25043c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <>				string	vecNamePrefix<int>		(void) { return "i"; }
25053c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <>				string	vecNamePrefix<bool>		(void) { return "b"; }
25063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25073c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T, int Size>
25083c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystring vecName (void) { return vecNamePrefix<T>() + "vec" + de::toString(Size); }
25093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25103c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T, int Size> class GenVec;
25113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25123c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
25133c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass GenVec<T, 1> : public DerivedFunc<Signature<T, T> >
25143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
25153c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
25163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename GenVec<T, 1>::ArgExprs ArgExprs;
25173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string		getName		(void) const
25193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
25203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return "_" + vecName<T, 1>();
25213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
25223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25233c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
25243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ExprP<T>	doExpand	(ExpandContext&, const ArgExprs& args) const { return args.a; }
25263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
25273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25283c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
25293c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass GenVec<T, 2> : public PrimitiveFunc<Signature<Vector<T, 2>, T, T> >
25303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
25313c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
25323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename GenVec::IRet	IRet;
25333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename GenVec::IArgs	IArgs;
25343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string		getName		(void) const
25363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
25373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return vecName<T, 2>();
25383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
25393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25403c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
25413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IRet		doApply		(const EvalContext&, const IArgs& iargs) const
25423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
25433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return IRet(iargs.a, iargs.b);
25443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
25453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
25463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25473c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
25483c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass GenVec<T, 3> : public PrimitiveFunc<Signature<Vector<T, 3>, T, T, T> >
25493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
25503c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
25513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename GenVec::IRet	IRet;
25523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename GenVec::IArgs	IArgs;
25533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string	getName		(void) const
25553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
25563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return vecName<T, 3>();
25573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
25583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25593c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
25603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IRet	doApply		(const EvalContext&, const IArgs& iargs) const
25613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
25623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return IRet(iargs.a, iargs.b, iargs.c);
25633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
25643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
25653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25663c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
25673c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass GenVec<T, 4> : public PrimitiveFunc<Signature<Vector<T, 4>, T, T, T, T> >
25683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
25693c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
25703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename GenVec::IRet	IRet;
25713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename GenVec::IArgs	IArgs;
25723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string		getName		(void) const { return vecName<T, 4>(); }
25743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25753c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
25763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IRet		doApply		(const EvalContext&, const IArgs& iargs) const
25773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
25783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return IRet(iargs.a, iargs.b, iargs.c, iargs.d);
25793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
25803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
25813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25843c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T, int Rows, int Columns>
25853c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass GenMat;
25863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25873c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T, int Rows>
25883c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass GenMat<T, Rows, 2> : public PrimitiveFunc<
25893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Signature<Matrix<T, Rows, 2>, Vector<T, Rows>, Vector<T, Rows> > >
25903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
25913c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
25923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename GenMat::Ret	Ret;
25933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename GenMat::IRet	IRet;
25943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename GenMat::IArgs	IArgs;
25953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string		getName		(void) const
25973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
25983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return dataTypeNameOf<Ret>();
25993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
26003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26013c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
26023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IRet		doApply		(const EvalContext&, const IArgs& iargs) const
26043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
26053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		IRet	ret;
26063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ret[0] = iargs.a;
26073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ret[1] = iargs.b;
26083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return ret;
26093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
26103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
26113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26123c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T, int Rows>
26133c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass GenMat<T, Rows, 3> : public PrimitiveFunc<
26143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Signature<Matrix<T, Rows, 3>, Vector<T, Rows>, Vector<T, Rows>, Vector<T, Rows> > >
26153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
26163c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
26173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename GenMat::Ret	Ret;
26183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename GenMat::IRet	IRet;
26193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename GenMat::IArgs	IArgs;
26203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string	getName	(void) const
26223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
26233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return dataTypeNameOf<Ret>();
26243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
26253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26263c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
26273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IRet	doApply	(const EvalContext&, const IArgs& iargs) const
26293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
26303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		IRet	ret;
26313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ret[0] = iargs.a;
26323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ret[1] = iargs.b;
26333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ret[2] = iargs.c;
26343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return ret;
26353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
26363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
26373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26383c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T, int Rows>
26393c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass GenMat<T, Rows, 4> : public PrimitiveFunc<
26403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Signature<Matrix<T, Rows, 4>,
26413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  Vector<T, Rows>, Vector<T, Rows>, Vector<T, Rows>, Vector<T, Rows> > >
26423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
26433c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
26443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename GenMat::Ret	Ret;
26453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename GenMat::IRet	IRet;
26463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename GenMat::IArgs	IArgs;
26473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string	getName	(void) const
26493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
26503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return dataTypeNameOf<Ret>();
26513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
26523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26533c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
26543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IRet	doApply	(const EvalContext&, const IArgs& iargs) const
26553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
26563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		IRet	ret;
26573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ret[0] = iargs.a;
26583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ret[1] = iargs.b;
26593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ret[2] = iargs.c;
26603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ret[3] = iargs.d;
26613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return ret;
26623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
26633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
26643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26653c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T, int Rows>
26663c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<Matrix<T, Rows, 2> > mat2 (const ExprP<Vector<T, Rows> >& arg0,
26673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 const ExprP<Vector<T, Rows> >& arg1)
26683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
26693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return app<GenMat<T, Rows, 2> >(arg0, arg1);
26703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
26713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26723c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T, int Rows>
26733c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<Matrix<T, Rows, 3> > mat3 (const ExprP<Vector<T, Rows> >& arg0,
26743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 const ExprP<Vector<T, Rows> >& arg1,
26753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 const ExprP<Vector<T, Rows> >& arg2)
26763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
26773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return app<GenMat<T, Rows, 3> >(arg0, arg1, arg2);
26783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
26793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26803c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T, int Rows>
26813c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<Matrix<T, Rows, 4> > mat4 (const ExprP<Vector<T, Rows> >& arg0,
26823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 const ExprP<Vector<T, Rows> >& arg1,
26833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 const ExprP<Vector<T, Rows> >& arg2,
26843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 const ExprP<Vector<T, Rows> >& arg3)
26853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
26863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return app<GenMat<T, Rows, 4> >(arg0, arg1, arg2, arg3);
26873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
26883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26903c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <int Rows, int Cols>
26913c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass MatNeg : public PrimitiveFunc<Signature<Matrix<float, Rows, Cols>,
26923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											  Matrix<float, Rows, Cols> > >
26933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
26943c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
26953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename MatNeg::IRet		IRet;
26963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename MatNeg::IArgs		IArgs;
26973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string	getName	(void) const
26993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
27003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return "_matNeg";
27013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
27023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27033c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
27043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void	doPrint	(ostream& os, const BaseArgExprs& args) const
27053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
27063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		os << "-(" << *args[0] << ")";
27073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
27083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IRet	doApply	(const EvalContext&, const IArgs& iargs)			const
27103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
27113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		IRet	ret;
27123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int col = 0; col < Cols; ++col)
27143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
27153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int row = 0; row < Rows; ++row)
27163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				ret[col][row] = -iargs.a[col][row];
27173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
27183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return ret;
27203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
27213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
27223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27233c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T, typename Sig>
27243c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass CompWiseFunc : public PrimitiveFunc<Sig>
27253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
27263c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
27273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef Func<Signature<T, T, T> >	ScalarFunc;
27283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string				getName			(void)									const
27303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
27313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return doGetScalarFunc().getName();
27323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
27333c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
27343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void				doPrint			(ostream&				os,
27353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 const BaseArgExprs&	args)			const
27363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
27373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		doGetScalarFunc().print(os, args);
27383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
27393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual
27413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const ScalarFunc&	doGetScalarFunc	(void)									const = 0;
27423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
27433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27443c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <int Rows, int Cols>
27453c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass CompMatFuncBase : public CompWiseFunc<float, Signature<Matrix<float, Rows, Cols>,
27463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 Matrix<float, Rows, Cols>,
27473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															 Matrix<float, Rows, Cols> > >
27483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
27493c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
27503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename CompMatFuncBase::IRet		IRet;
27513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename CompMatFuncBase::IArgs		IArgs;
27523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27533c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
27543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IRet	doApply	(const EvalContext& ctx, const IArgs& iargs) const
27563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
27573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		IRet			ret;
27583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int col = 0; col < Cols; ++col)
27603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
27613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int row = 0; row < Rows; ++row)
27623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				ret[col][row] = this->doGetScalarFunc().apply(ctx,
27633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															  iargs.a[col][row],
27643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															  iargs.b[col][row]);
27653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
27663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return ret;
27683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
27693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
27703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27713c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename F, int Rows, int Cols>
27723c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass CompMatFunc : public CompMatFuncBase<Rows, Cols>
27733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
27743c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
27753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const typename CompMatFunc::ScalarFunc&	doGetScalarFunc	(void) const
27763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
27773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return instance<F>();
27783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
27793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
27803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27813c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ScalarMatrixCompMult : public Mul
27823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
27833c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
27843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string	getName	(void) const
27853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
27863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return "matrixCompMult";
27873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
27883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void	doPrint	(ostream& os, const BaseArgExprs& args) const
27903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
27913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		Func<Sig>::doPrint(os, args);
27923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
27933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
27943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27953c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <int Rows, int Cols>
27963c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass MatrixCompMult : public CompMatFunc<ScalarMatrixCompMult, Rows, Cols>
27973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
27983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
27993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28003c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <int Rows, int Cols>
28013c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ScalarMatFuncBase : public CompWiseFunc<float, Signature<Matrix<float, Rows, Cols>,
28023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															   Matrix<float, Rows, Cols>,
28033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															   float> >
28043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
28053c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
28063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename ScalarMatFuncBase::IRet	IRet;
28073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename ScalarMatFuncBase::IArgs	IArgs;
28083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28093c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
28103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IRet	doApply	(const EvalContext& ctx, const IArgs& iargs) const
28123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
28133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		IRet	ret;
28143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int col = 0; col < Cols; ++col)
28163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
28173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int row = 0; row < Rows; ++row)
28183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				ret[col][row] = this->doGetScalarFunc().apply(ctx, iargs.a[col][row], iargs.b);
28193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
28203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return ret;
28223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
28233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
28243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28253c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename F, int Rows, int Cols>
28263c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ScalarMatFunc : public ScalarMatFuncBase<Rows, Cols>
28273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
28283c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
28293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const typename ScalarMatFunc::ScalarFunc&	doGetScalarFunc	(void)	const
28303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
28313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return instance<F>();
28323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
28333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
28343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28353c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename T, int Size> struct GenXType;
28363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28373c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename T>
28383c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct GenXType<T, 1>
28393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
28403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static ExprP<T>	genXType	(const ExprP<T>& x) { return x; }
28413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
28423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28433c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename T>
28443c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct GenXType<T, 2>
28453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
28463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static ExprP<Vector<T, 2> >	genXType	(const ExprP<T>& x)
28473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
28483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return app<GenVec<T, 2> >(x, x);
28493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
28503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
28513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28523c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename T>
28533c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct GenXType<T, 3>
28543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
28553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static ExprP<Vector<T, 3> >	genXType	(const ExprP<T>& x)
28563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
28573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return app<GenVec<T, 3> >(x, x, x);
28583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
28593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
28603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28613c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename T>
28623c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct GenXType<T, 4>
28633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
28643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static ExprP<Vector<T, 4> >	genXType	(const ExprP<T>& x)
28653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
28663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return app<GenVec<T, 4> >(x, x, x, x);
28673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
28683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
28693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Returns an expression of vector of size `Size` (or scalar if Size == 1),
28713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! with each element initialized with the expression `x`.
28723c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename T, int Size>
28733c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<typename ContainerOf<T, Size>::Container> genXType (const ExprP<T>& x)
28743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
28753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return GenXType<T, Size>::genXType(x);
28763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
28773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28783c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytypedef GenVec<float, 2> FloatVec2;
28793c827367444ee418f129b2c238299f49d3264554Jarkko PoyryDEFINE_CONSTRUCTOR2(FloatVec2, Vec2, vec2, float, float)
28803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28813c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytypedef GenVec<float, 3> FloatVec3;
28823c827367444ee418f129b2c238299f49d3264554Jarkko PoyryDEFINE_CONSTRUCTOR3(FloatVec3, Vec3, vec3, float, float, float)
28833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28843c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytypedef GenVec<float, 4> FloatVec4;
28853c827367444ee418f129b2c238299f49d3264554Jarkko PoyryDEFINE_CONSTRUCTOR4(FloatVec4, Vec4, vec4, float, float, float, float)
28863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28873c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <int Size>
28883c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Dot : public DerivedFunc<Signature<float, Vector<float, Size>, Vector<float, Size> > >
28893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
28903c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
28913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Dot::ArgExprs ArgExprs;
28923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string			getName		(void) const
28943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
28953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return "dot";
28963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
28973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28983c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
28993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ExprP<float>	doExpand 	(ExpandContext&, const ArgExprs& args) const
29003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
29013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ExprP<float> val = args.a[0] * args.b[0];
29023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 1; ndx < Size; ++ndx)
29043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			val = val + args.a[ndx] * args.b[ndx];
29053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return val;
29073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
29083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
29093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29103c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <>
29113c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Dot<1> : public DerivedFunc<Signature<float, float, float> >
29123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
29133c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
29143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string			getName		(void) const
29153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
29163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return "dot";
29173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
29183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ExprP<float>	doExpand 	(ExpandContext&, const ArgExprs& args) const
29203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
29213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return args.a * args.b;
29223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
29233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
29243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29253c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <int Size>
29263c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<float> dot (const ExprP<Vector<float, Size> >& x, const ExprP<Vector<float, Size> >& y)
29273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
29283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return app<Dot<Size> >(x, y);
29293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
29303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29313c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<float> dot (const ExprP<float>& x, const ExprP<float>& y)
29323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
29333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return app<Dot<1> >(x, y);
29343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
29353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29363c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <int Size>
29373c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Length : public DerivedFunc<
29383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Signature<float, typename ContainerOf<float, Size>::Container> >
29393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
29403c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
29413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Length::ArgExprs ArgExprs;
29423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string			getName		(void) const
29443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
29453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return "length";
29463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
29473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29483c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
29493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ExprP<float>	doExpand	(ExpandContext&, const ArgExprs& args) const
29503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
29513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return sqrt(dot(args.a, args.a));
29523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
29533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
29543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29553c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <int Size>
29563c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<float> length (const ExprP<typename ContainerOf<float, Size>::Container>& x)
29573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
29583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return app<Length<Size> >(x);
29593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
29603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29613c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <int Size>
29623c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Distance : public DerivedFunc<
29633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Signature<float,
29643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  typename ContainerOf<float, Size>::Container,
29653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  typename ContainerOf<float, Size>::Container> >
29663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
29673c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
29683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename	Distance::Ret		Ret;
29693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename	Distance::ArgExprs	ArgExprs;
29703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string		getName		(void) const
29723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
29733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return "distance";
29743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
29753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29763c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
29773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ExprP<Ret>	doExpand 	(ExpandContext&, const ArgExprs& args) const
29783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
29793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return length<Size>(args.a - args.b);
29803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
29813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
29823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// cross
29843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29853c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Cross : public DerivedFunc<Signature<Vec3, Vec3, Vec3> >
29863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
29873c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
29883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string			getName		(void) const
29893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
29903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return "cross";
29913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
29923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29933c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
29943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ExprP<Vec3>		doExpand 	(ExpandContext&, const ArgExprs& x) const
29953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
29963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return vec3(x.a[1] * x.b[2] - x.b[1] * x.a[2],
29973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					x.a[2] * x.b[0] - x.b[2] * x.a[0],
29983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					x.a[0] * x.b[1] - x.b[0] * x.a[1]);
29993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
30003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
30013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30023c827367444ee418f129b2c238299f49d3264554Jarkko PoyryDEFINE_CONSTRUCTOR2(Cross, Vec3, cross, Vec3, Vec3)
30033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30043c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<int Size>
30053c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Normalize : public DerivedFunc<
30063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Signature<typename ContainerOf<float, Size>::Container,
30073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  typename ContainerOf<float, Size>::Container> >
30083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
30093c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
30103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename	Normalize::Ret		Ret;
30113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename	Normalize::ArgExprs	ArgExprs;
30123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string		getName		(void) const
30143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
30153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return "normalize";
30163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
30173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30183c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
30193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ExprP<Ret>	doExpand	(ExpandContext&, const ArgExprs& args) const
30203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
30213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return args.a / length<Size>(args.a);
30223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
30233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
30243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30253c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <int Size>
30263c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FaceForward : public DerivedFunc<
30273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Signature<typename ContainerOf<float, Size>::Container,
30283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  typename ContainerOf<float, Size>::Container,
30293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  typename ContainerOf<float, Size>::Container,
30303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  typename ContainerOf<float, Size>::Container> >
30313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
30323c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
30333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename	FaceForward::Ret		Ret;
30343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename	FaceForward::ArgExprs	ArgExprs;
30353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string		getName		(void) const
30373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
30383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return "faceforward";
30393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
30403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30413c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
30423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ExprP<Ret>	doExpand	(ExpandContext&, const ArgExprs& args) const
30453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
30463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return cond(dot(args.c, args.b) < constant(0.0f), args.a, -args.a);
30473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
30483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
30493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30503c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <int Size>
30513c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Reflect : public DerivedFunc<
30523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Signature<typename ContainerOf<float, Size>::Container,
30533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  typename ContainerOf<float, Size>::Container,
30543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  typename ContainerOf<float, Size>::Container> >
30553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
30563c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
30573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename	Reflect::Ret		Ret;
3058123c801f106dd1157fc889eaec934272ac6be937Pyry Haulos	typedef typename	Reflect::Arg0		Arg0;
3059123c801f106dd1157fc889eaec934272ac6be937Pyry Haulos	typedef typename	Reflect::Arg1		Arg1;
30603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename	Reflect::ArgExprs	ArgExprs;
30613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string		getName		(void) const
30633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
30643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return "reflect";
30653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
30663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30673c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
3068123c801f106dd1157fc889eaec934272ac6be937Pyry Haulos	ExprP<Ret>	doExpand	(ExpandContext& ctx, const ArgExprs& args) const
30693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3070123c801f106dd1157fc889eaec934272ac6be937Pyry Haulos		const ExprP<Arg0>&	i		= args.a;
3071123c801f106dd1157fc889eaec934272ac6be937Pyry Haulos		const ExprP<Arg1>&	n		= args.b;
3072123c801f106dd1157fc889eaec934272ac6be937Pyry Haulos		const ExprP<float>	dotNI	= bindExpression("dotNI", ctx, dot(n, i));
3073123c801f106dd1157fc889eaec934272ac6be937Pyry Haulos
3074123c801f106dd1157fc889eaec934272ac6be937Pyry Haulos		return i - alternatives((n * dotNI) * constant(2.0f),
3075123c801f106dd1157fc889eaec934272ac6be937Pyry Haulos								n * (dotNI * constant(2.0f)));
30763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
30773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
30783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30793c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <int Size>
30803c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Refract : public DerivedFunc<
30813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Signature<typename ContainerOf<float, Size>::Container,
30823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  typename ContainerOf<float, Size>::Container,
30833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  typename ContainerOf<float, Size>::Container,
30843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  float> >
30853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
30863c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
30873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename	Refract::Ret		Ret;
30883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename	Refract::Arg0		Arg0;
30893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename	Refract::Arg1		Arg1;
30903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename	Refract::ArgExprs	ArgExprs;
30913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string		getName		(void) const
30933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
30943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return "refract";
30953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
30963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30973c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
30983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ExprP<Ret>	doExpand	(ExpandContext&	ctx, const ArgExprs& args) const
30993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
31003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const ExprP<Arg0>&	i		= args.a;
31013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const ExprP<Arg1>&	n		= args.b;
31023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const ExprP<float>&	eta		= args.c;
31033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const ExprP<float>	dotNI	= bindExpression("dotNI", ctx, dot(n, i));
31043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const ExprP<float>	k		= bindExpression("k", ctx, constant(1.0f) - eta * eta *
31053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 (constant(1.0f) - dotNI * dotNI));
31063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return cond(k < constant(0.0f),
31083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					genXType<float, Size>(constant(0.0f)),
31093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					i * eta - n * (eta * dotNI + sqrt(k)));
31103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
31113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
31123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31133c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass PreciseFunc1 : public CFloatFunc1
31143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
31153c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
31163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			PreciseFunc1	(const string& name, DoubleFunc1& func) : CFloatFunc1(name, func) {}
31173c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
31183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	double	precision		(const EvalContext&, double, double) const	{ return 0.0; }
31193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
31203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31213c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Abs : public PreciseFunc1
31223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
31233c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
31243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Abs (void) : PreciseFunc1("abs", deAbs) {}
31253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
31263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31273c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Sign : public PreciseFunc1
31283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
31293c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
31303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Sign (void) : PreciseFunc1("sign", deSign) {}
31313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
31323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31333c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Floor : public PreciseFunc1
31343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
31353c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
31363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Floor (void) : PreciseFunc1("floor", deFloor) {}
31373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
31383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31393c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Trunc : public PreciseFunc1
31403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
31413c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
31423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Trunc (void) : PreciseFunc1("trunc", deTrunc) {}
31433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
31443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31453c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Round : public FloatFunc1
31463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
31473c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
31483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string		getName		(void) const								{ return "round"; }
31493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31503c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
31513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Interval	applyPoint	(const EvalContext&, double x) const
31523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
31533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		double			truncated	= 0.0;
31543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const double	fract		= deModf(x, &truncated);
31553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		Interval		ret;
31563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (fabs(fract) <= 0.5)
31583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			ret |= truncated;
31593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (fabs(fract) >= 0.5)
31603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			ret |= truncated + deSign(fract);
31613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return ret;
31633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
31643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	double		precision	(const EvalContext&, double, double) const	{ return 0.0; }
31663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
31673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31683c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass RoundEven : public PreciseFunc1
31693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
31703c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
31713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	RoundEven (void) : PreciseFunc1("roundEven", deRoundEven) {}
31723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
31733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31743c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Ceil : public PreciseFunc1
31753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
31763c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
31773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Ceil (void) : PreciseFunc1("ceil", deCeil) {}
31783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
31793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31803c827367444ee418f129b2c238299f49d3264554Jarkko PoyryDEFINE_DERIVED_FLOAT1(Fract, fract, x, x - app<Floor>(x));
31813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31823c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass PreciseFunc2 : public CFloatFunc2
31833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
31843c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
31853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			PreciseFunc2	(const string& name, DoubleFunc2& func) : CFloatFunc2(name, func) {}
31863c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
31873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	double	precision		(const EvalContext&, double, double, double) const { return 0.0; }
31883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
31893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31903c827367444ee418f129b2c238299f49d3264554Jarkko PoyryDEFINE_DERIVED_FLOAT2(Mod, mod, x, y, x - y * app<Floor>(x / y));
31913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31923c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Modf : public PrimitiveFunc<Signature<float, float, float> >
31933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
31943c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
31953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string	getName				(void) const
31963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
31973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return "modf";
31983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
31993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32003c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
32014fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos	IRet	doApply				(const EvalContext& ctx, const IArgs& iargs) const
32023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
32033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		Interval	fracIV;
32043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		Interval&	wholeIV		= const_cast<Interval&>(iargs.b);
32053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		double		intPart		= 0;
32063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TCU_INTERVAL_APPLY_MONOTONE1(fracIV, x, iargs.a, frac, frac = deModf(x, &intPart));
32083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TCU_INTERVAL_APPLY_MONOTONE1(wholeIV, x, iargs.a, whole,
32093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 deModf(x, &intPart); whole = intPart);
32104fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos
32114fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos		if ((ctx.format.hasInf() != YES) && !iargs.a.isFinite())
32124fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos		{
32134fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos			// Behavior on modf(Inf) not well-defined, allow anything as a fractional part
32144fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos			fracIV |= TCU_NAN;
32154fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos		}
32164fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos
32173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return fracIV;
32183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
32193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int		getOutParamIndex	(void) const
32213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
32223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 1;
32233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
32243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
32253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32263c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Min : public PreciseFunc2 { public: Min (void) : PreciseFunc2("min", deMin) {} };
32273c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Max : public PreciseFunc2 { public: Max (void) : PreciseFunc2("max", deMax) {} };
32283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32293c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Clamp : public FloatFunc3
32303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
32313c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
32323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string	getName		(void) const { return "clamp"; }
32333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	double	applyExact	(double x, double minVal, double maxVal) const
32353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
32363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return de::min(de::max(x, minVal), maxVal);
32373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
32383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	double	precision	(const EvalContext&, double, double, double minVal, double maxVal) const
32403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
32413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return minVal > maxVal ? TCU_NAN : 0.0;
32423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
32433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
32443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32453c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<float> clamp(const ExprP<float>& x, const ExprP<float>& minVal, const ExprP<float>& maxVal)
32463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
32473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return app<Clamp>(x, minVal, maxVal);
32483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
32493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32506c1b3db5fb439806b9b67442f1042615ffa32816Pyry HaulosDEFINE_DERIVED_FLOAT3(Mix, mix, x, y, a, alternatives((x * (constant(1.0f) - a)) + y * a,
32516c1b3db5fb439806b9b67442f1042615ffa32816Pyry Haulos													  x + (y - x) * a));
32523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32533c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic double step (double edge, double x)
32543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
32553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return x < edge ? 0.0 : 1.0;
32563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
32573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32583c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Step : public PreciseFunc2 { public: Step (void) : PreciseFunc2("step", step) {} };
32593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32603c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass SmoothStep : public DerivedFunc<Signature<float, float, float, float> >
32613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
32623c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
32633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string		getName		(void) const
32643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
32653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return "smoothstep";
32663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
32673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32683c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
32693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ExprP<Ret>	doExpand 	(ExpandContext& ctx, const ArgExprs& args) const
32713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
32723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const ExprP<float>&		edge0	= args.a;
32733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const ExprP<float>&		edge1	= args.b;
32743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const ExprP<float>&		x		= args.c;
32753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const ExprP<float>		tExpr	= clamp((x - edge0) / (edge1 - edge0),
32763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											constant(0.0f), constant(1.0f));
32773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const ExprP<float>		t		= bindExpression("t", ctx, tExpr);
32783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return (t * t * (constant(3.0f) - constant(2.0f) * t));
32803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
32813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
32823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32833c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FrExp : public PrimitiveFunc<Signature<float, float, int> >
32843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
32853c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
32863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string	getName			(void) const
32873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
32883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return "frexp";
32893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
32903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32913c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
32923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IRet	doApply			(const EvalContext&, const IArgs& iargs) const
32933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
32943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		IRet			ret;
32953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const IArg0&	x			= iargs.a;
32963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		IArg1&			exponent	= const_cast<IArg1&>(iargs.b);
32973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (x.hasNaN() || x.contains(TCU_INFINITY) || x.contains(-TCU_INFINITY))
32993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
33003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// GLSL (in contrast to IEEE) says that result of applying frexp
33013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// to infinity is undefined
33023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			ret = Interval::unbounded() | TCU_NAN;
33033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			exponent = Interval(-deLdExp(1.0, 31), deLdExp(1.0, 31)-1);
33043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
33053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (!x.empty())
33063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
33073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int				loExp	= 0;
33083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const double	loFrac	= deFrExp(x.lo(), &loExp);
33093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int				hiExp	= 0;
33103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const double	hiFrac	= deFrExp(x.hi(), &hiExp);
33113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (deSign(loFrac) != deSign(hiFrac))
33133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
33143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				exponent = Interval(-TCU_INFINITY, de::max(loExp, hiExp));
33153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				ret = Interval();
33163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (deSign(loFrac) < 0)
33173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					ret |= Interval(-1.0 + DBL_EPSILON*0.5, 0.0);
33183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (deSign(hiFrac) > 0)
33193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					ret |= Interval(0.0, 1.0 - DBL_EPSILON*0.5);
33203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
33213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
33223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
33233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				exponent = Interval(loExp, hiExp);
33243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (loExp == hiExp)
33253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					ret = Interval(loFrac, hiFrac);
33263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else
33273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					ret = deSign(loFrac) * Interval(0.5, 1.0 - DBL_EPSILON*0.5);
33283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
33293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
33303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return ret;
33323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
33333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int	getOutParamIndex	(void) const
33353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
33363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 1;
33373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
33383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
33393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33403c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass LdExp : public PrimitiveFunc<Signature<float, float, int> >
33413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
33423c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
33433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string		getName			(void) const
33443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
33453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return "ldexp";
33463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
33473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33483c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
33493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Interval	doApply			(const EvalContext& ctx, const IArgs& iargs) const
33503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
33513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		Interval	ret = call<Exp2>(ctx, iargs.b);
33523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Khronos bug 11180 consensus: if exp2(exponent) cannot be represented,
33533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// the result is undefined.
33543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (ret.contains(TCU_INFINITY) | ret.contains(-TCU_INFINITY))
33563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			ret |= TCU_NAN;
33573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return call<Mul>(ctx, iargs.a, ret);
33593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
33603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
33613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33623c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<int Rows, int Columns>
33633c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Transpose : public PrimitiveFunc<Signature<Matrix<float, Rows, Columns>,
33643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 Matrix<float, Columns, Rows> > >
33653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
33663c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
33673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Transpose::IRet	IRet;
33683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Transpose::IArgs	IArgs;
33693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string		getName		(void) const
33713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
33723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return "transpose";
33733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
33743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33753c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
33763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IRet		doApply		(const EvalContext&, const IArgs& iargs) const
33773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
33783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		IRet ret;
33793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int rowNdx = 0; rowNdx < Rows; ++rowNdx)
33813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
33823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int colNdx = 0; colNdx < Columns; ++colNdx)
33833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				ret(rowNdx, colNdx) = iargs.a(colNdx, rowNdx);
33843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
33853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return ret;
33873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
33883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
33893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33903c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename Ret, typename Arg0, typename Arg1>
33913c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass MulFunc : public PrimitiveFunc<Signature<Ret, Arg0, Arg1> >
33923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
33933c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
33943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string	getName	(void) const 									{ return "mul"; }
33953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33963c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
33973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void	doPrint	(ostream& os, const BaseArgExprs& args) const
33983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
33993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		os << "(" << *args[0] << " * " << *args[1] << ")";
34003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
34013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
34023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34033c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<int LeftRows, int Middle, int RightCols>
34043c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass MatMul : public MulFunc<Matrix<float, LeftRows, RightCols>,
34053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  Matrix<float, LeftRows, Middle>,
34063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  Matrix<float, Middle, RightCols> >
34073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
34083c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
34093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename MatMul::IRet	IRet;
34103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename MatMul::IArgs	IArgs;
34113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename MatMul::IArg0	IArg0;
34123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename MatMul::IArg1	IArg1;
34133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IRet	doApply	(const EvalContext&	ctx, const IArgs& iargs) const
34153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
34163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const IArg0&	left	= iargs.a;
34173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const IArg1&	right	= iargs.b;
34183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		IRet			ret;
34193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int row = 0; row < LeftRows; ++row)
34213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
34223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int col = 0; col < RightCols; ++col)
34233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
34243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				Interval	element	(0.0);
34253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int ndx = 0; ndx < Middle; ++ndx)
34273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					element = call<Add>(ctx, element,
34283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										call<Mul>(ctx, left[ndx][row], right[col][ndx]));
34293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				ret[col][row] = element;
34313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
34323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
34333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return ret;
34353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
34363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
34373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34383c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<int Rows, int Cols>
34393c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass VecMatMul : public MulFunc<Vector<float, Cols>,
34403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 Vector<float, Rows>,
34413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 Matrix<float, Rows, Cols> >
34423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
34433c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
34443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename VecMatMul::IRet	IRet;
34453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename VecMatMul::IArgs	IArgs;
34463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename VecMatMul::IArg0	IArg0;
34473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename VecMatMul::IArg1	IArg1;
34483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34493c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
34503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IRet	doApply	(const EvalContext& ctx, const IArgs& iargs) const
34513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
34523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const IArg0&	left	= iargs.a;
34533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const IArg1&	right	= iargs.b;
34543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		IRet			ret;
34553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int col = 0; col < Cols; ++col)
34573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
34583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Interval	element	(0.0);
34593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int row = 0; row < Rows; ++row)
34613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				element = call<Add>(ctx, element, call<Mul>(ctx, left[row], right[col][row]));
34623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			ret[col] = element;
34643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
34653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return ret;
34673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
34683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
34693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34703c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<int Rows, int Cols>
34713c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass MatVecMul : public MulFunc<Vector<float, Rows>,
34723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 Matrix<float, Rows, Cols>,
34733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 Vector<float, Cols> >
34743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
34753c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
34763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename MatVecMul::IRet	IRet;
34773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename MatVecMul::IArgs	IArgs;
34783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename MatVecMul::IArg0	IArg0;
34793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename MatVecMul::IArg1	IArg1;
34803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34813c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
34823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IRet	doApply	(const EvalContext& ctx, const IArgs& iargs) const
34833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
34843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const IArg0&	left	= iargs.a;
34853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const IArg1&	right	= iargs.b;
34863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return call<VecMatMul<Cols, Rows> >(ctx, right,
34883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											call<Transpose<Rows, Cols> >(ctx, left));
34893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
34903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
34913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34923c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<int Rows, int Cols>
34933c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass OuterProduct : public PrimitiveFunc<Signature<Matrix<float, Rows, Cols>,
34943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													Vector<float, Rows>,
34953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													Vector<float, Cols> > >
34963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
34973c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
34983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename OuterProduct::IRet		IRet;
34993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename OuterProduct::IArgs	IArgs;
35003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
35013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string	getName	(void) const
35023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
35033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return "outerProduct";
35043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
35053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
35063c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
35073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IRet	doApply	(const EvalContext& ctx, const IArgs& iargs) const
35083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
35093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		IRet	ret;
35103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
35113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int row = 0; row < Rows; ++row)
35123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
35133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int col = 0; col < Cols; ++col)
35143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				ret[col][row] = call<Mul>(ctx, iargs.a[row], iargs.b[col]);
35153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
35163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
35173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return ret;
35183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
35193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
35203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
35213c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<int Rows, int Cols>
35223c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<Matrix<float, Rows, Cols> > outerProduct (const ExprP<Vector<float, Rows> >& left,
35233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												const ExprP<Vector<float, Cols> >& right)
35243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
35253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return app<OuterProduct<Rows, Cols> >(left, right);
35263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
35273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
35283c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<int Size>
35293c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass DeterminantBase : public DerivedFunc<Signature<float, Matrix<float, Size, Size> > >
35303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
35313c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
35323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string	getName	(void) const { return "determinant"; }
35333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
35343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
35353c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<int Size>
35363c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Determinant;
35373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
35383c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<int Size>
35393c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<float> determinant (ExprP<Matrix<float, Size, Size> > mat)
35403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
35413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return app<Determinant<Size> >(mat);
35423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
35433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
35443c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<>
35453c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Determinant<2> : public DeterminantBase<2>
35463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
35473c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
35483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ExprP<Ret>	doExpand (ExpandContext&, const ArgExprs& args)	const
35493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
35503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ExprP<Mat2>	mat	= args.a;
35513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
35523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return mat[0][0] * mat[1][1] - mat[1][0] * mat[0][1];
35533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
35543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
35553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
35563c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<>
35573c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Determinant<3> : public DeterminantBase<3>
35583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
35593c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
35603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ExprP<Ret> doExpand (ExpandContext&, const ArgExprs& args) const
35613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
35623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ExprP<Mat3>	mat	= args.a;
35633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
35643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return (mat[0][0] * (mat[1][1] * mat[2][2] - mat[1][2] * mat[2][1]) +
35653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				mat[0][1] * (mat[1][2] * mat[2][0] - mat[1][0] * mat[2][2]) +
35663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				mat[0][2] * (mat[1][0] * mat[2][1] - mat[1][1] * mat[2][0]));
35673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
35683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
35693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
35703c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<>
35713c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Determinant<4> : public DeterminantBase<4>
35723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
35733c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
35743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	 ExprP<Ret>	doExpand	(ExpandContext& ctx, const ArgExprs& args) const
35753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
35763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ExprP<Mat4>	mat	= args.a;
35773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ExprP<Mat3>	minors[4];
35783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
35793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < 4; ++ndx)
35803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
35813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			ExprP<Vec4>		minorColumns[3];
35823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			ExprP<Vec3>		columns[3];
35833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
35843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int col = 0; col < 3; ++col)
35853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				minorColumns[col] = mat[col < ndx ? col : col + 1];
35863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
35873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int col = 0; col < 3; ++col)
35883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				columns[col] = vec3(minorColumns[0][col+1],
35893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									minorColumns[1][col+1],
35903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									minorColumns[2][col+1]);
35913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
35923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			minors[ndx] = bindExpression("minor", ctx,
35933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 mat3(columns[0], columns[1], columns[2]));
35943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
35953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
35963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return (mat[0][0] * determinant(minors[0]) -
35973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				mat[1][0] * determinant(minors[1]) +
35983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				mat[2][0] * determinant(minors[2]) -
35993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				mat[3][0] * determinant(minors[3]));
36003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
36013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
36023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
36033c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<int Size> class Inverse;
36043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
36053c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <int Size>
36063c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<Matrix<float, Size, Size> > inverse (ExprP<Matrix<float, Size, Size> > mat)
36073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
36083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return app<Inverse<Size> >(mat);
36093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
36103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
36113c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<>
36123c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Inverse<2> : public DerivedFunc<Signature<Mat2, Mat2> >
36133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
36143c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
36153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string		getName	(void) const
36163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
36173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return "inverse";
36183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
36193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
36203c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
36213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ExprP<Ret>	doExpand (ExpandContext& ctx, const ArgExprs& args) const
36223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
36233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ExprP<Mat2>		mat = args.a;
36243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ExprP<float>	det	= bindExpression("det", ctx, determinant(mat));
36253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
36263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return mat2(vec2(mat[1][1] / det, -mat[0][1] / det),
36273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					vec2(-mat[1][0] / det, mat[0][0] / det));
36283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
36293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
36303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
36313c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<>
36323c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Inverse<3> : public DerivedFunc<Signature<Mat3, Mat3> >
36333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
36343c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
36353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string		getName		(void) const
36363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
36373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return "inverse";
36383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
36393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
36403c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
36413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ExprP<Ret>	doExpand 	(ExpandContext& ctx, const ArgExprs& args)			const
36423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
36433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ExprP<Mat3>		mat		= args.a;
36443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ExprP<Mat2>		invA	= bindExpression("invA", ctx,
36453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 inverse(mat2(vec2(mat[0][0], mat[0][1]),
36463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															  vec2(mat[1][0], mat[1][1]))));
36473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
36483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ExprP<Vec2>		matB	= bindExpression("matB", ctx, vec2(mat[2][0], mat[2][1]));
36493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ExprP<Vec2>		matC	= bindExpression("matC", ctx, vec2(mat[0][2], mat[1][2]));
36503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ExprP<float>	matD	= bindExpression("matD", ctx, mat[2][2]);
36513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
36523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ExprP<float>	schur	= bindExpression("schur", ctx,
36533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 constant(1.0f) /
36543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 (matD - dot(matC * invA, matB)));
36553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
36563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ExprP<Vec2>		t1		= invA * matB;
36573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ExprP<Vec2>		t2		= t1 * schur;
36583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ExprP<Mat2>		t3		= outerProduct(t2, matC);
36593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ExprP<Mat2>		t4		= t3 * invA;
36603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ExprP<Mat2>		t5		= invA + t4;
36613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ExprP<Mat2>		blockA	= bindExpression("blockA", ctx, t5);
36623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ExprP<Vec2>		blockB	= bindExpression("blockB", ctx,
36633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 (invA * matB) * -schur);
36643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ExprP<Vec2>		blockC	= bindExpression("blockC", ctx,
36653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 (matC * invA) * -schur);
36663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
36673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return mat3(vec3(blockA[0][0], blockA[0][1], blockC[0]),
36683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					vec3(blockA[1][0], blockA[1][1], blockC[1]),
36693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					vec3(blockB[0], blockB[1], schur));
36703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
36713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
36723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
36733c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<>
36743c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Inverse<4> : public DerivedFunc<Signature<Mat4, Mat4> >
36753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
36763c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
36773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string		getName		(void) const { return "inverse"; }
36783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
36793c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
36803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ExprP<Ret>			doExpand 			(ExpandContext&		ctx,
36813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 const ArgExprs&	args)			const
36823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
36833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ExprP<Mat4>	mat		= args.a;
36843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ExprP<Mat2>	invA	= bindExpression("invA", ctx,
36853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 inverse(mat2(vec2(mat[0][0], mat[0][1]),
36863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														  vec2(mat[1][0], mat[1][1]))));
36873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ExprP<Mat2>	matB	= bindExpression("matB", ctx,
36883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 mat2(vec2(mat[2][0], mat[2][1]),
36893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												  vec2(mat[3][0], mat[3][1])));
36903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ExprP<Mat2>	matC	= bindExpression("matC", ctx,
36913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 mat2(vec2(mat[0][2], mat[0][3]),
36923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												  vec2(mat[1][2], mat[1][3])));
36933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ExprP<Mat2>	matD	= bindExpression("matD", ctx,
36943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 mat2(vec2(mat[2][2], mat[2][3]),
36953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												  vec2(mat[3][2], mat[3][3])));
36963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ExprP<Mat2>	schur	= bindExpression("schur", ctx,
36973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 inverse(matD + -(matC * invA * matB)));
36983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ExprP<Mat2>	blockA	= bindExpression("blockA", ctx,
36993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 invA + (invA * matB * schur * matC * invA));
37003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ExprP<Mat2>	blockB	= bindExpression("blockB", ctx,
37013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 (-invA) * matB * schur);
37023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ExprP<Mat2>	blockC	= bindExpression("blockC", ctx,
37033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 (-schur) * matC * invA);
37043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
37053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return mat4(vec4(blockA[0][0], blockA[0][1], blockC[0][0], blockC[0][1]),
37063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					vec4(blockA[1][0], blockA[1][1], blockC[1][0], blockC[1][1]),
37073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					vec4(blockB[0][0], blockB[0][1], schur[0][0], schur[0][1]),
37083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					vec4(blockB[1][0], blockB[1][1], schur[1][0], schur[1][1]));
37093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
37103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
37113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
37123c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Fma : public DerivedFunc<Signature<float, float, float, float> >
37133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
37143c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
37153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string			getName					(void) const
37163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
37173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return "fma";
37183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
37193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
37203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string			getRequiredExtension	(void) const
37213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
37228852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		return "GL_EXT_gpu_shader5";
37233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
37243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
37253c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
37263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ExprP<float>	doExpand 				(ExpandContext&, const ArgExprs& x) const
37273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
37283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return x.a * x.b + x.c;
37293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
37303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
37313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
37323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // Functions
37333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
37343c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing namespace Functions;
37353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
37363c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
37373c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<typename T::Element> ContainerExprPBase<T>::operator[] (int i) const
37383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
37393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return Functions::getComponent(exprP<T>(*this), i);
37403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
37413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
37423c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<float> operator+ (const ExprP<float>& arg0, const ExprP<float>& arg1)
37433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
37443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return app<Add>(arg0, arg1);
37453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
37463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
37473c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<float> operator- (const ExprP<float>& arg0, const ExprP<float>& arg1)
37483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
37493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return app<Sub>(arg0, arg1);
37503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
37513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
37523c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<float> operator- (const ExprP<float>& arg0)
37533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
37543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return app<Negate>(arg0);
37553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
37563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
37573c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<float> operator* (const ExprP<float>& arg0, const ExprP<float>& arg1)
37583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
37593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return app<Mul>(arg0, arg1);
37603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
37613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
37623c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<float> operator/ (const ExprP<float>& arg0, const ExprP<float>& arg1)
37633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
37643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return app<Div>(arg0, arg1);
37653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
37663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
37673c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename Sig_, int Size>
37683c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass GenFunc : public PrimitiveFunc<Signature<
37693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typename ContainerOf<typename Sig_::Ret, Size>::Container,
37703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typename ContainerOf<typename Sig_::Arg0, Size>::Container,
37713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typename ContainerOf<typename Sig_::Arg1, Size>::Container,
37723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typename ContainerOf<typename Sig_::Arg2, Size>::Container,
37733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typename ContainerOf<typename Sig_::Arg3, Size>::Container> >
37743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
37753c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
37763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename GenFunc::IArgs		IArgs;
37773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename GenFunc::IRet		IRet;
37783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
37793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GenFunc					(const Func<Sig_>&	scalarFunc) : m_func (scalarFunc) {}
37803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
37813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string	getName					(void) const
37823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
37833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return m_func.getName();
37843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
37853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
37863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int		getOutParamIndex		(void) const
37873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
37883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return m_func.getOutParamIndex();
37893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
37903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
37913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string	getRequiredExtension	(void) const
37923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
37933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return m_func.getRequiredExtension();
37943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
37953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
37963c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
37973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void	doPrint					(ostream& os, const BaseArgExprs& args) const
37983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
37993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_func.print(os, args);
38003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
38013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
38023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IRet	doApply					(const EvalContext& ctx, const IArgs& iargs) const
38033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
38043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		IRet ret;
38053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
38063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < Size; ++ndx)
38073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
38083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			ret[ndx] =
38093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_func.apply(ctx, iargs.a[ndx], iargs.b[ndx], iargs.c[ndx], iargs.d[ndx]);
38103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
38113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
38123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return ret;
38133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
38143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
38153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void	doGetUsedFuncs			(FuncSet& dst) const
38163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
38173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_func.getUsedFuncs(dst);
38183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
38193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
38203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const Func<Sig_>&	m_func;
38213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
38223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
38233c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename F, int Size>
38243c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass VectorizedFunc : public GenFunc<typename F::Sig, Size>
38253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
38263c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
38273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VectorizedFunc	(void) : GenFunc<typename F::Sig, Size>(instance<F>()) {}
38283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
38293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
38303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
38313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
38323c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename Sig_, int Size>
38333c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FixedGenFunc : public PrimitiveFunc <Signature<
38343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typename ContainerOf<typename Sig_::Ret, Size>::Container,
38353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typename ContainerOf<typename Sig_::Arg0, Size>::Container,
38363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typename Sig_::Arg1,
38373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typename ContainerOf<typename Sig_::Arg2, Size>::Container,
38383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typename ContainerOf<typename Sig_::Arg3, Size>::Container> >
38393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
38403c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
38413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename FixedGenFunc::IArgs		IArgs;
38423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename FixedGenFunc::IRet			IRet;
38433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
38443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string						getName			(void) const
38453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
38463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return this->doGetScalarFunc().getName();
38473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
38483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
38493c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
38503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void						doPrint			(ostream& os, const BaseArgExprs& args) const
38513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
38523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		this->doGetScalarFunc().print(os, args);
38533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
38543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
38553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IRet						doApply			(const EvalContext& ctx,
38563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 const IArgs&		iargs) const
38573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
38583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		IRet				ret;
38593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Func<Sig_>&	func	= this->doGetScalarFunc();
38603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
38613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < Size; ++ndx)
38623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			ret[ndx] = func.apply(ctx, iargs.a[ndx], iargs.b, iargs.c[ndx], iargs.d[ndx]);
38633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
38643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return ret;
38653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
38663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
38673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual const Func<Sig_>&	doGetScalarFunc	(void) const = 0;
38683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
38693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
38703c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename F, int Size>
38713c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FixedVecFunc : public FixedGenFunc<typename F::Sig, Size>
38723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
38733c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
38743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const Func<typename F::Sig>& doGetScalarFunc	(void) const { return instance<F>(); }
38753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
38763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
38773c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename Sig>
38783c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct GenFuncs
38793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
38803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GenFuncs (const Func<Sig>&			func_,
38813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  const GenFunc<Sig, 2>&	func2_,
38823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  const GenFunc<Sig, 3>&	func3_,
38833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  const GenFunc<Sig, 4>&	func4_)
38843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: func	(func_)
38853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, func2	(func2_)
38863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, func3	(func3_)
38873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, func4	(func4_)
38883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{}
38893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
38903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const Func<Sig>&		func;
38913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const GenFunc<Sig, 2>&	func2;
38923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const GenFunc<Sig, 3>&	func3;
38933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const GenFunc<Sig, 4>&	func4;
38943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
38953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
38963c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename F>
38973c827367444ee418f129b2c238299f49d3264554Jarkko PoyryGenFuncs<typename F::Sig> makeVectorizedFuncs (void)
38983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
38993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return GenFuncs<typename F::Sig>(instance<F>(),
39003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 instance<VectorizedFunc<F, 2> >(),
39013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 instance<VectorizedFunc<F, 3> >(),
39023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 instance<VectorizedFunc<F, 4> >());
39033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
39043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
39053c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<int Size>
39063c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<Vector<float, Size> > operator*(const ExprP<Vector<float, Size> >& arg0,
39073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									  const ExprP<Vector<float, Size> >& arg1)
39083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
39093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return app<VectorizedFunc<Mul, Size> >(arg0, arg1);
39103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
39113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
39123c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<int Size>
39133c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<Vector<float, Size> > operator*(const ExprP<Vector<float, Size> >&	arg0,
39143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									  const ExprP<float>&					arg1)
39153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
39163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return app<FixedVecFunc<Mul, Size> >(arg0, arg1);
39173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
39183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
39193c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<int Size>
39203c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<Vector<float, Size> > operator/(const ExprP<Vector<float, Size> >&	arg0,
39213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									  const ExprP<float>&					arg1)
39223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
39233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return app<FixedVecFunc<Div, Size> >(arg0, arg1);
39243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
39253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
39263c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<int Size>
39273c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<Vector<float, Size> > operator-(const ExprP<Vector<float, Size> >& arg0)
39283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
39293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return app<VectorizedFunc<Negate, Size> >(arg0);
39303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
39313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
39323c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<int Size>
39333c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<Vector<float, Size> > operator-(const ExprP<Vector<float, Size> >& arg0,
39343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									  const ExprP<Vector<float, Size> >& arg1)
39353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
39363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return app<VectorizedFunc<Sub, Size> >(arg0, arg1);
39373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
39383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
39393c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<int LeftRows, int Middle, int RightCols>
39403c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<Matrix<float, LeftRows, RightCols> >
39413c827367444ee418f129b2c238299f49d3264554Jarkko Poyryoperator* (const ExprP<Matrix<float, LeftRows, Middle> >&	left,
39423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   const ExprP<Matrix<float, Middle, RightCols> >&	right)
39433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
39443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return app<MatMul<LeftRows, Middle, RightCols> >(left, right);
39453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
39463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
39473c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<int Rows, int Cols>
39483c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<Vector<float, Rows> > operator* (const ExprP<Vector<float, Cols> >&		left,
39493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									   const ExprP<Matrix<float, Rows, Cols> >&	right)
39503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
39513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return app<VecMatMul<Rows, Cols> >(left, right);
39523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
39533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
39543c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<int Rows, int Cols>
39553c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<Vector<float, Cols> > operator* (const ExprP<Matrix<float, Rows, Cols> >&	left,
39563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									   const ExprP<Vector<float, Rows> >&		right)
39573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
39583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return app<MatVecMul<Rows, Cols> >(left, right);
39593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
39603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
39613c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<int Rows, int Cols>
39623c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<Matrix<float, Rows, Cols> > operator* (const ExprP<Matrix<float, Rows, Cols> >&	left,
39633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 const ExprP<float>&						right)
39643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
39653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return app<ScalarMatFunc<Mul, Rows, Cols> >(left, right);
39663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
39673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
39683c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<int Rows, int Cols>
39693c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<Matrix<float, Rows, Cols> > operator+ (const ExprP<Matrix<float, Rows, Cols> >&	left,
39703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 const ExprP<Matrix<float, Rows, Cols> >&	right)
39713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
39723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return app<CompMatFunc<Add, Rows, Cols> >(left, right);
39733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
39743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
39753c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<int Rows, int Cols>
39763c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExprP<Matrix<float, Rows, Cols> > operator- (const ExprP<Matrix<float, Rows, Cols> >&	mat)
39773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
39783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return app<MatNeg<Rows, Cols> >(mat);
39793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
39803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
39813c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
39823c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Sampling
39833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
39843c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
39858852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	virtual void	genFixeds	(const FloatFormat&, vector<T>&)			const {}
39868852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	virtual T		genRandom	(const FloatFormat&, Precision, Random&)	const { return T(); }
39878852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	virtual double	getWeight	(void)										const { return 0.0; }
39883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
39893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
39903c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <>
39913c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass DefaultSampling<Void> : public Sampling<Void>
39923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
39933c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
39943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void	genFixeds	(const FloatFormat&, vector<Void>& dst) const { dst.push_back(Void()); }
39953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
39963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
39973c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <>
39983c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass DefaultSampling<bool> : public Sampling<bool>
39993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
40003c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
40013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void	genFixeds	(const FloatFormat&, vector<bool>& dst) const
40023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
40033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		dst.push_back(true);
40043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		dst.push_back(false);
40053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
40063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
40073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
40083c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <>
40093c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass DefaultSampling<int> : public Sampling<int>
40103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
40113c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
40128852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	int		genRandom	(const FloatFormat&, Precision prec, Random& rnd) const
40133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
40148852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		const int	exp		= rnd.getInt(0, getNumBits(prec)-2);
40153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int	sign	= rnd.getBool() ? -1 : 1;
40163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4017c8e526bfc2141e1cb7a269483fb55dc2a8e77c11Jarkko Pöyry		return sign * rnd.getInt(0, (deInt32)1 << exp);
40183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
40193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
40203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void	genFixeds	(const FloatFormat&, vector<int>& dst) const
40213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
40223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		dst.push_back(0);
40233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		dst.push_back(-1);
40243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		dst.push_back(1);
40253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
40263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	double	getWeight	(void) const { return 1.0; }
40278852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
40288852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyryprivate:
40298852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	static inline int getNumBits (Precision prec)
40308852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	{
40318852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		switch (prec)
40328852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		{
40338852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			case glu::PRECISION_LOWP:		return 8;
40348852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			case glu::PRECISION_MEDIUMP:	return 16;
40358852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			case glu::PRECISION_HIGHP:		return 32;
40368852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			default:
40378852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				DE_ASSERT(false);
40388852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				return 0;
40398852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		}
40408852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	}
40413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
40423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
40433c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <>
40443c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass DefaultSampling<float> : public Sampling<float>
40453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
40463c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
40478852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	float	genRandom	(const FloatFormat& format, Precision prec, Random& rnd) const;
40483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void	genFixeds	(const FloatFormat& format, vector<float>& dst) const;
40493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	double	getWeight	(void) const { return 1.0; }
40503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
40513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
40523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Generate a random float from a reasonable general-purpose distribution.
40533c827367444ee418f129b2c238299f49d3264554Jarkko Poyryfloat DefaultSampling<float>::genRandom (const FloatFormat& format,
40548852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry										 Precision,
40553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 Random&			rnd) const
40563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
40573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		minExp			= format.getMinExp();
40583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		maxExp			= format.getMaxExp();
40593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool		haveSubnormal	= format.hasSubnormal() != tcu::NO;
40603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
40613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Choose exponent so that the cumulative distribution is cubic.
40623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// This makes the probability distribution quadratic, with the peak centered on zero.
40633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const double	minRoot			= deCbrt(minExp - 0.5 - (haveSubnormal ? 1.0 : 0.0));
40643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const double	maxRoot			= deCbrt(maxExp + 0.5);
40653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		fractionBits	= format.getFractionBits();
40663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		exp				= int(deRoundEven(dePow(rnd.getDouble(minRoot, maxRoot),
40673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															3.0)));
40683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float			base			= 0.0f; // integral power of two
40693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float			quantum			= 0.0f; // smallest representable difference in the binade
40703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float			significand		= 0.0f; // Significand.
40713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
40723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(fractionBits < std::numeric_limits<float>::digits);
40733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
40743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Generate some occasional special numbers
40753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (rnd.getInt(0, 64))
40763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
40773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case 0: 	return 0;
40783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case 1:		return TCU_INFINITY;
40793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case 2:		return -TCU_INFINITY;
40803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case 3:		return TCU_NAN;
40813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:	break;
40823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
40833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
40843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (exp >= minExp)
40853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
40863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Normal number
40873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		base = deFloatLdExp(1.0f, exp);
40883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		quantum = deFloatLdExp(1.0f, exp - fractionBits);
40893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
40903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
40913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
40923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Subnormal
40933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		base = 0.0f;
40943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		quantum = deFloatLdExp(1.0f, minExp - fractionBits);
40953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
40963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
40973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (rnd.getInt(0, 16))
40983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
40993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case 0: // The highest number in this binade, significand is all bits one.
41003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			significand = base - quantum;
41013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
41023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case 1: // Significand is one.
41033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			significand = quantum;
41043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
41053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case 2: // Significand is zero.
41063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			significand = 0.0;
41073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
41083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default: // Random (evenly distributed) significand.
41093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
41103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint64 intFraction = rnd.getUint64() & ((1 << fractionBits) - 1);
41113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			significand = float(intFraction) * quantum;
41123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
41133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
41143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
41153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Produce positive numbers more often than negative.
41163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return (rnd.getInt(0,3) == 0 ? -1.0f : 1.0f) * (base + significand);
41173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
41183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
41193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Generate a standard set of floats that should always be tested.
41203c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid DefaultSampling<float>::genFixeds (const FloatFormat& format, vector<float>& dst) const
41213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
41223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int			minExp			= format.getMinExp();
41233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int			maxExp			= format.getMaxExp();
41243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int			fractionBits	= format.getFractionBits();
41253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float			minQuantum		= deFloatLdExp(1.0f, minExp - fractionBits);
41263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float			minNormalized	= deFloatLdExp(1.0f, minExp);
41273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float			maxQuantum		= deFloatLdExp(1.0f, maxExp - fractionBits);
41283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
41293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// NaN
41303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst.push_back(TCU_NAN);
41313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Zero
41323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst.push_back(0.0f);
41333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
41343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int sign = -1; sign <= 1; sign += 2)
41353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
41363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Smallest subnormal
4137c8e526bfc2141e1cb7a269483fb55dc2a8e77c11Jarkko Pöyry		dst.push_back((float)sign * minQuantum);
41383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
41393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Largest subnormal
4140c8e526bfc2141e1cb7a269483fb55dc2a8e77c11Jarkko Pöyry		dst.push_back((float)sign * (minNormalized - minQuantum));
41413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
41423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Smallest normalized
4143c8e526bfc2141e1cb7a269483fb55dc2a8e77c11Jarkko Pöyry		dst.push_back((float)sign * minNormalized);
41443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
41453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Next smallest normalized
4146c8e526bfc2141e1cb7a269483fb55dc2a8e77c11Jarkko Pöyry		dst.push_back((float)sign * (minNormalized + minQuantum));
41473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4148c8e526bfc2141e1cb7a269483fb55dc2a8e77c11Jarkko Pöyry		dst.push_back((float)sign * 0.5f);
4149c8e526bfc2141e1cb7a269483fb55dc2a8e77c11Jarkko Pöyry		dst.push_back((float)sign * 1.0f);
4150c8e526bfc2141e1cb7a269483fb55dc2a8e77c11Jarkko Pöyry		dst.push_back((float)sign * 2.0f);
41513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
41523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Largest number
4153c8e526bfc2141e1cb7a269483fb55dc2a8e77c11Jarkko Pöyry		dst.push_back((float)sign * (deFloatLdExp(1.0f, maxExp) +
4154c8e526bfc2141e1cb7a269483fb55dc2a8e77c11Jarkko Pöyry									(deFloatLdExp(1.0f, maxExp) - maxQuantum)));
41553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4156c8e526bfc2141e1cb7a269483fb55dc2a8e77c11Jarkko Pöyry		dst.push_back((float)sign * TCU_INFINITY);
41573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
41583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
41593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
41603c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T, int Size>
41613c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass DefaultSampling<Vector<T, Size> > : public Sampling<Vector<T, Size> >
41623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
41633c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
41643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef Vector<T, Size>		Value;
41653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
41668852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	Value	genRandom	(const FloatFormat& fmt, Precision prec, Random& rnd) const
41673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
41683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		Value ret;
41693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
41703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < Size; ++ndx)
41718852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			ret[ndx] = instance<DefaultSampling<T> >().genRandom(fmt, prec, rnd);
41723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
41733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return ret;
41743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
41753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
41763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void	genFixeds	(const FloatFormat& fmt, vector<Value>& dst) const
41773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
41783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vector<T> scalars;
41793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
41803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		instance<DefaultSampling<T> >().genFixeds(fmt, scalars);
41813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
41823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (size_t scalarNdx = 0; scalarNdx < scalars.size(); ++scalarNdx)
41833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dst.push_back(Value(scalars[scalarNdx]));
41843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
41853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
41863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	double	getWeight	(void) const
41873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
41883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return dePow(instance<DefaultSampling<T> >().getWeight(), Size);
41893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
41903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
41913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
41923c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T, int Rows, int Columns>
41933c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass DefaultSampling<Matrix<T, Rows, Columns> > : public Sampling<Matrix<T, Rows, Columns> >
41943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
41953c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
41963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef Matrix<T, Rows, Columns>		Value;
41973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
41988852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	Value	genRandom	(const FloatFormat& fmt, Precision prec, Random& rnd) const
41993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
42003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		Value ret;
42013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
42023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int rowNdx = 0; rowNdx < Rows; ++rowNdx)
42033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int colNdx = 0; colNdx < Columns; ++colNdx)
42048852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				ret(rowNdx, colNdx) = instance<DefaultSampling<T> >().genRandom(fmt, prec, rnd);
42053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
42063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return ret;
42073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
42083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
42093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void	genFixeds	(const FloatFormat& fmt, vector<Value>& dst) const
42103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
42113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vector<T> scalars;
42123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
42133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		instance<DefaultSampling<T> >().genFixeds(fmt, scalars);
42143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
42153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (size_t scalarNdx = 0; scalarNdx < scalars.size(); ++scalarNdx)
42163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dst.push_back(Value(scalars[scalarNdx]));
42173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
42183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (Columns == Rows)
42193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
42203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Value	mat	(0.0);
42213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			T		x	= T(1.0f);
42223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			mat[0][0] = x;
42233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int ndx = 0; ndx < Columns; ++ndx)
42243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
42253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				mat[Columns-1-ndx][ndx] = x;
42263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				x *= T(2.0f);
42273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
42283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dst.push_back(mat);
42293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
42303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
42313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
42323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	double	getWeight	(void) const
42333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
42343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return dePow(instance<DefaultSampling<T> >().getWeight(), Rows * Columns);
42353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
42363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
42373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
42383c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct Context
42393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
42403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Context		(const string&		name_,
42413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				 TestContext&		testContext_,
42423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				 RenderContext&		renderContext_,
42433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				 const FloatFormat&	floatFormat_,
42443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				 const FloatFormat&	highpFormat_,
42453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				 Precision			precision_,
42463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				 ShaderType			shaderType_,
42473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				 size_t				numRandoms_)
42483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: name				(name_)
42493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, testContext		(testContext_)
42503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, renderContext		(renderContext_)
42513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, floatFormat		(floatFormat_)
42523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, highpFormat		(highpFormat_)
42533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, precision			(precision_)
42543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, shaderType		(shaderType_)
42553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, numRandoms		(numRandoms_) {}
42563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
42573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string				name;
42583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestContext&		testContext;
42593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	RenderContext&		renderContext;
42603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FloatFormat			floatFormat;
42613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FloatFormat			highpFormat;
42623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Precision			precision;
42633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ShaderType			shaderType;
42643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	size_t				numRandoms;
42653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
42663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
42673c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename In0_ = Void, typename In1_ = Void, typename In2_ = Void, typename In3_ = Void>
42683c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct InTypes
42693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
42703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef	In0_	In0;
42713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef	In1_	In1;
42723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef	In2_	In2;
42733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef	In3_	In3;
42743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
42753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
42763c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename In>
42773c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint numInputs (void)
42783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
42793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return (!isTypeValid<typename In::In0>() ? 0 :
42803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			!isTypeValid<typename In::In1>() ? 1 :
42813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			!isTypeValid<typename In::In2>() ? 2 :
42823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			!isTypeValid<typename In::In3>() ? 3 :
42833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			4);
42843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
42853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
42863c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename Out0_, typename Out1_ = Void>
42873c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct OutTypes
42883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
42893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef	Out0_	Out0;
42903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef	Out1_	Out1;
42913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
42923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
42933c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename Out>
42943c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint numOutputs (void)
42953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
42963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return (!isTypeValid<typename Out::Out0>() ? 0 :
42973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			!isTypeValid<typename Out::Out1>() ? 1 :
42983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			2);
42993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
43003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
43013c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename In>
43023c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct Inputs
43033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
43043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<typename In::In0>	in0;
43053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<typename In::In1>	in1;
43063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<typename In::In2>	in2;
43073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<typename In::In3>	in3;
43083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
43093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
43103c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename Out>
43113c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct Outputs
43123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
43133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Outputs	(size_t size) : out0(size), out1(size) {}
43143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
43153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<typename Out::Out0>	out0;
43163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<typename Out::Out1>	out1;
43173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
43183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
43193c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename In, typename Out>
43203c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct Variables
43213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
43223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VariableP<typename In::In0>		in0;
43233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VariableP<typename In::In1>		in1;
43243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VariableP<typename In::In2>		in2;
43253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VariableP<typename In::In3>		in3;
43263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VariableP<typename Out::Out0>	out0;
43273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VariableP<typename Out::Out1>	out1;
43283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
43293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
43303c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename In>
43313c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct Samplings
43323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
43333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Samplings	(const Sampling<typename In::In0>&	in0_,
43343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				 const Sampling<typename In::In1>&	in1_,
43353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				 const Sampling<typename In::In2>&	in2_,
43363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				 const Sampling<typename In::In3>&	in3_)
43373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: in0 (in0_), in1 (in1_), in2 (in2_), in3 (in3_) {}
43383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
43393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const Sampling<typename In::In0>&	in0;
43403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const Sampling<typename In::In1>&	in1;
43413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const Sampling<typename In::In2>&	in2;
43423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const Sampling<typename In::In3>&	in3;
43433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
43443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
43453c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename In>
43463c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct DefaultSamplings : Samplings<In>
43473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
43483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DefaultSamplings	(void)
43493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: Samplings<In>(instance<DefaultSampling<typename In::In0> >(),
43503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						instance<DefaultSampling<typename In::In1> >(),
43513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						instance<DefaultSampling<typename In::In2> >(),
43523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						instance<DefaultSampling<typename In::In3> >()) {}
43533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
43543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
43553c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass PrecisionCase : public TestCase
43563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
43573c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
43583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult		iterate			(void);
43593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
43603c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
43613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						PrecisionCase	(const Context&		context,
43628852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry										 const string&		name,
43638852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry										 const string&		extension	= "")
43648852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry							: TestCase		(context.testContext,
43658852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry											 name.c_str(),
43668852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry											 name.c_str())
43678852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry							, m_ctx			(context)
43688852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry							, m_status		()
43698852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry							, m_rnd			(0xdeadbeefu +
43708852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry											 context.testContext.getCommandLine().getBaseSeed())
43718852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry							, m_extension	(extension)
43723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
43733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
43743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
43753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	RenderContext&		getRenderContext(void) const 			{ return m_ctx.renderContext; }
43763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
43773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const FloatFormat&	getFormat		(void) const 			{ return m_ctx.floatFormat; }
43783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
43793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestLog&			log				(void) const 			{ return m_testCtx.getLog(); }
43803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
43813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual void		runTest			(void) = 0;
43823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
43833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	template <typename In, typename Out>
43843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void				testStatement	(const Variables<In, Out>&	variables,
43853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 const Inputs<In>&			inputs,
43863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 const Statement&			stmt);
43873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
43883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	template<typename T>
43893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Symbol				makeSymbol		(const Variable<T>& variable)
43903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
43913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return Symbol(variable.getName(), getVarTypeOf<T>(m_ctx.precision));
43923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
43933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
43943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Context				m_ctx;
43953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ResultCollector		m_status;
43963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Random				m_rnd;
43978852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const string		m_extension;
43983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
43993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
44003c827367444ee418f129b2c238299f49d3264554Jarkko PoyryIterateResult PrecisionCase::iterate (void)
44013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
44023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	runTest();
44033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_status.setTestContextResult(m_testCtx);
44043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
44053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
44063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
44073c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename In, typename Out>
44083c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid PrecisionCase::testStatement (const Variables<In, Out>&	variables,
44093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								   const Inputs<In>&			inputs,
44103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								   const Statement&				stmt)
44113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
44123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	using namespace ShaderExecUtil;
44133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
44143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename 	In::In0		In0;
44153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename 	In::In1		In1;
44163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename 	In::In2		In2;
44173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename 	In::In3		In3;
44183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename 	Out::Out0	Out0;
44193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename 	Out::Out1	Out1;
44203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
44213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const FloatFormat&	fmt			= getFormat();
44223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int			inCount		= numInputs<In>();
44233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int			outCount	= numOutputs<Out>();
44243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const size_t		numValues	= (inCount > 0) ? inputs.in0.size() : 1;
44253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Outputs<Out>		outputs		(numValues);
44263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ShaderSpec			spec;
44273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const FloatFormat	highpFmt	= m_ctx.highpFormat;
44283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int			maxMsgs		= 100;
44293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					numErrors	= 0;
44303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Environment			env; 		// Hoisted out of the inner loop for optimization.
44313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
44323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (inCount)
44333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
44343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case 4: DE_ASSERT(inputs.in3.size() == numValues);
44353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case 3: DE_ASSERT(inputs.in2.size() == numValues);
44363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case 2: DE_ASSERT(inputs.in1.size() == numValues);
44373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case 1: DE_ASSERT(inputs.in0.size() == numValues);
44383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default: break;
44393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
44403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
44413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Print out the statement and its definitions
44423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log() << TestLog::Message << "Statement: " << stmt << TestLog::EndMessage;
44433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
44443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ostringstream	oss;
44453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		FuncSet			funcs;
44463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
44473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		stmt.getUsedFuncs(funcs);
44483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (FuncSet::const_iterator it = funcs.begin(); it != funcs.end(); ++it)
44493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
44503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			(*it)->printDefinition(oss);
44513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
44523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!funcs.empty())
44533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log() << TestLog::Message << "Reference definitions:\n" << oss.str()
44543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				  << TestLog::EndMessage;
44553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
44563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
44573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Initialize ShaderSpec from precision, variables and statement.
44583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
44593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ostringstream os;
44603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		os << "precision " << glu::getPrecisionName(m_ctx.precision) << " float;\n";
44613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		spec.globalDeclarations = os.str();
44623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
44633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
44643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	spec.version = getContextTypeGLSLVersion(getRenderContext().getType());
44658852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
44668852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	if (!m_extension.empty())
44678852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		spec.globalDeclarations = "#extension " + m_extension + " : require\n";
44688852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
44693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	spec.inputs.resize(inCount);
44703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
44713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (inCount)
44723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
44733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case 4: spec.inputs[3] = makeSymbol(*variables.in3);
44743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case 3:	spec.inputs[2] = makeSymbol(*variables.in2);
44753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case 2:	spec.inputs[1] = makeSymbol(*variables.in1);
44763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case 1:	spec.inputs[0] = makeSymbol(*variables.in0);
44773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default: break;
44783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
44793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
44803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	spec.outputs.resize(outCount);
44813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
44823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (outCount)
44833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
44843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case 2:	spec.outputs[1] = makeSymbol(*variables.out1);
44853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case 1:	spec.outputs[0] = makeSymbol(*variables.out0);
44863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default: break;
44873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
44883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
44893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	spec.source = de::toString(stmt);
44903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
44913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Run the shader with inputs.
44923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
44933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		UniquePtr<ShaderExecutor>	executor		(createExecutor(getRenderContext(),
44943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	m_ctx.shaderType,
44953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	spec));
44963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const void*					inputArr[]		=
44973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
44983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			&inputs.in0.front(), &inputs.in1.front(), &inputs.in2.front(), &inputs.in3.front(),
44993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
45003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		void*						outputArr[]		=
45013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
45023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			&outputs.out0.front(), &outputs.out1.front(),
45033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
45043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
45053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		executor->log(log());
45063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!executor->isOk())
45073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TCU_FAIL("Shader compilation failed");
45083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
45093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		executor->useProgram();
45103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		executor->execute(int(numValues), inputArr, outputArr);
45113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
45123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
45133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Initialize environment with dummy values so we don't need to bind in inner loop.
45143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
45153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const typename Traits<In0>::IVal		in0;
45163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const typename Traits<In1>::IVal		in1;
45173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const typename Traits<In2>::IVal		in2;
45183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const typename Traits<In3>::IVal		in3;
45193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const typename Traits<Out0>::IVal		reference0;
45203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const typename Traits<Out1>::IVal		reference1;
45213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
45223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		env.bind(*variables.in0, in0);
45233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		env.bind(*variables.in1, in1);
45243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		env.bind(*variables.in2, in2);
45253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		env.bind(*variables.in3, in3);
45263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		env.bind(*variables.out0, reference0);
45273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		env.bind(*variables.out1, reference1);
45283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
45293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
45303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// For each input tuple, compute output reference interval and compare
45313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// shader output to the reference.
45323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (size_t valueNdx = 0; valueNdx < numValues; valueNdx++)
45333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
45343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool						result		= true;
45353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		typename Traits<Out0>::IVal	reference0;
45363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		typename Traits<Out1>::IVal	reference1;
45373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
45383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		env.lookup(*variables.in0) = convert<In0>(fmt, round(fmt, inputs.in0[valueNdx]));
45393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		env.lookup(*variables.in1) = convert<In1>(fmt, round(fmt, inputs.in1[valueNdx]));
45403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		env.lookup(*variables.in2) = convert<In2>(fmt, round(fmt, inputs.in2[valueNdx]));
45413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		env.lookup(*variables.in3) = convert<In3>(fmt, round(fmt, inputs.in3[valueNdx]));
45423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
45433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
45443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			EvalContext	ctx (fmt, m_ctx.precision, env);
45453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			stmt.execute(ctx);
45463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
45473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
45483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (outCount)
45493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
45503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case 2:
45513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				reference1 = convert<Out1>(highpFmt, env.lookup(*variables.out1));
45523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!m_status.check(contains(reference1, outputs.out1[valueNdx]),
45533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									"Shader output 1 is outside acceptable range"))
45543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					result = false;
45553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case 1:
45563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				reference0 = convert<Out0>(highpFmt, env.lookup(*variables.out0));
45573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!m_status.check(contains(reference0, outputs.out0[valueNdx]),
45583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									"Shader output 0 is outside acceptable range"))
45593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					result = false;
45603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default: break;
45613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
45623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
45633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!result)
45643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			++numErrors;
45653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
45663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if ((!result && numErrors <= maxMsgs) || GLS_LOG_ALL_RESULTS)
45673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
45683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			MessageBuilder	builder	= log().message();
45693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
45703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			builder << (result ? "Passed" : "Failed") << " sample:\n";
45713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
45723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (inCount > 0)
45733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
45743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				builder << "\t" << variables.in0->getName() << " = "
45753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						<< valueToString(highpFmt, inputs.in0[valueNdx]) << "\n";
45763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
45773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
45783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (inCount > 1)
45793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
45803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				builder << "\t" << variables.in1->getName() << " = "
45813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						<< valueToString(highpFmt, inputs.in1[valueNdx]) << "\n";
45823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
45833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
45843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (inCount > 2)
45853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
45863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				builder << "\t" << variables.in2->getName() << " = "
45873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						<< valueToString(highpFmt, inputs.in2[valueNdx]) << "\n";
45883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
45893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
45903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (inCount > 3)
45913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
45923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				builder << "\t" << variables.in3->getName() << " = "
45933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						<< valueToString(highpFmt, inputs.in3[valueNdx]) << "\n";
45943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
45953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
45963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (outCount > 0)
45973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
45983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				builder << "\t" << variables.out0->getName() << " = "
45993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						<< valueToString(highpFmt, outputs.out0[valueNdx]) << "\n"
46003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						<< "\tExpected range: "
46013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						<< intervalToString<typename Out::Out0>(highpFmt, reference0) << "\n";
46023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
46033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
46043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (outCount > 1)
46053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
46063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				builder << "\t" << variables.out1->getName() << " = "
46073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						<< valueToString(highpFmt, outputs.out1[valueNdx]) << "\n"
46083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						<< "\tExpected range: "
46093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						<< intervalToString<typename Out::Out1>(highpFmt, reference1) << "\n";
46103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
46113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
46123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			builder << TestLog::EndMessage;
46133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
46143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
46153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
46163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numErrors > maxMsgs)
46173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
46183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log() << TestLog::Message << "(Skipped " << (numErrors - maxMsgs) << " messages.)"
46193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  << TestLog::EndMessage;
46203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
46213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
46223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numErrors == 0)
46233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
46243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log() << TestLog::Message << "All " << numValues << " inputs passed."
46253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  << TestLog::EndMessage;
46263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
46273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
46283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
46293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log() << TestLog::Message << numErrors << "/" << numValues << " inputs failed."
46303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  << TestLog::EndMessage;
46313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
46323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
46333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
46343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
46353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
46363c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
46373c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct InputLess
46383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
46393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool operator() (const T& val1, const T& val2) const
46403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
46413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return val1 < val2;
46423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
46433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
46443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
46453c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
46463c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool inputLess (const T& val1, const T& val2)
46473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
46483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return InputLess<T>()(val1, val2);
46493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
46503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
46513c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <>
46523c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct InputLess<float>
46533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
46543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool operator() (const float& val1, const float& val2) const
46553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
46563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (deIsNaN(val1))
46573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
46583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (deIsNaN(val2))
46593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return true;
46603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return val1 < val2;
46613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
46623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
46633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
46643c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T, int Size>
46653c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct InputLess<Vector<T, Size> >
46663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
46673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool operator() (const Vector<T, Size>& vec1, const Vector<T, Size>& vec2) const
46683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
46693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < Size; ++ndx)
46703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
46713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (inputLess(vec1[ndx], vec2[ndx]))
46723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return true;
46733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (inputLess(vec2[ndx], vec1[ndx]))
46743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return false;
46753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
46763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
46773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
46783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
46793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
46803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
46813c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T, int Rows, int Cols>
46823c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct InputLess<Matrix<T, Rows, Cols> >
46833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
46843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool operator() (const Matrix<T, Rows, Cols>& mat1,
46853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					 const Matrix<T, Rows, Cols>& mat2) const
46863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
46873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int col = 0; col < Cols; ++col)
46883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
46893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (inputLess(mat1[col], mat2[col]))
46903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return true;
46913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (inputLess(mat2[col], mat1[col]))
46923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return false;
46933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
46943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
46953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
46963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
46973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
46983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
46993c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename In>
47003c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct InTuple :
47013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	public Tuple4<typename In::In0, typename In::In1, typename In::In2, typename In::In3>
47023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
47033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	InTuple	(const typename In::In0& in0,
47043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			 const typename In::In1& in1,
47053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			 const typename In::In2& in2,
47063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			 const typename In::In3& in3)
47073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: Tuple4<typename In::In0, typename In::In1, typename In::In2, typename In::In3>
47083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		  (in0, in1, in2, in3) {}
47093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
47103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
47113c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename In>
47123c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct InputLess<InTuple<In> >
47133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
47143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool operator() (const InTuple<In>& in1, const InTuple<In>& in2) const
47153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
47163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (inputLess(in1.a, in2.a))
47173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return true;
47183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (inputLess(in2.a, in1.a))
47193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
47203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (inputLess(in1.b, in2.b))
47213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return true;
47223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (inputLess(in2.b, in1.b))
47233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
47243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (inputLess(in1.c, in2.c))
47253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return true;
47263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (inputLess(in2.c, in1.c))
47273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
47283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (inputLess(in1.d, in2.d))
47293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return true;
47303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
47313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
47323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
47333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
47343c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename In>
47353c827367444ee418f129b2c238299f49d3264554Jarkko PoyryInputs<In> generateInputs (const Samplings<In>&	samplings,
47363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						   const FloatFormat&	floatFormat,
47378852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						   Precision			intPrecision,
47383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						   size_t				numSamples,
47393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						   Random&				rnd)
47403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
47413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Inputs<In>									ret;
47423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Inputs<In>									fixedInputs;
47433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	set<InTuple<In>, InputLess<InTuple<In> > >	seenInputs;
47443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
47453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	samplings.in0.genFixeds(floatFormat, fixedInputs.in0);
47463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	samplings.in1.genFixeds(floatFormat, fixedInputs.in1);
47473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	samplings.in2.genFixeds(floatFormat, fixedInputs.in2);
47483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	samplings.in3.genFixeds(floatFormat, fixedInputs.in3);
47493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
47503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (size_t ndx0 = 0; ndx0 < fixedInputs.in0.size(); ++ndx0)
47513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
47523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (size_t ndx1 = 0; ndx1 < fixedInputs.in1.size(); ++ndx1)
47533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
47543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (size_t ndx2 = 0; ndx2 < fixedInputs.in2.size(); ++ndx2)
47553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
47563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (size_t ndx3 = 0; ndx3 < fixedInputs.in3.size(); ++ndx3)
47573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
47583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const InTuple<In>	tuple	(fixedInputs.in0[ndx0],
47593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 fixedInputs.in1[ndx1],
47603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 fixedInputs.in2[ndx2],
47613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 fixedInputs.in3[ndx3]);
47623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
47633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					seenInputs.insert(tuple);
47643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					ret.in0.push_back(tuple.a);
47653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					ret.in1.push_back(tuple.b);
47663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					ret.in2.push_back(tuple.c);
47673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					ret.in3.push_back(tuple.d);
47683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
47693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
47703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
47713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
47723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
47733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (size_t ndx = 0; ndx < numSamples; ++ndx)
47743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
47758852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		const typename In::In0	in0		= samplings.in0.genRandom(floatFormat, intPrecision, rnd);
47768852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		const typename In::In1	in1		= samplings.in1.genRandom(floatFormat, intPrecision, rnd);
47778852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		const typename In::In2	in2		= samplings.in2.genRandom(floatFormat, intPrecision, rnd);
47788852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		const typename In::In3	in3		= samplings.in3.genRandom(floatFormat, intPrecision, rnd);
47793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const InTuple<In>		tuple	(in0, in1, in2, in3);
47803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
47813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (de::contains(seenInputs, tuple))
47823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			continue;
47833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
47843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		seenInputs.insert(tuple);
47853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ret.in0.push_back(in0);
47863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ret.in1.push_back(in1);
47873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ret.in2.push_back(in2);
47883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ret.in3.push_back(in3);
47893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
47903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
47913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return ret;
47923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
47933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
47943c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FuncCaseBase : public PrecisionCase
47953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
47963c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
47973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult	iterate			(void);
47983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
47993c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
48003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					FuncCaseBase	(const Context&		context,
48013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 const string&		name,
48023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 const FuncBase&	func)
48038852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						: PrecisionCase	(context, name, func.getRequiredExtension()) {}
48043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
48053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
48063c827367444ee418f129b2c238299f49d3264554Jarkko PoyryIterateResult FuncCaseBase::iterate (void)
48073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
48083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MovePtr<ContextInfo>	info	(ContextInfo::create(getRenderContext()));
48093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
48103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_extension.empty() && !info->isExtensionSupported(m_extension.c_str()))
48113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw NotSupportedError("Unsupported extension: " + m_extension);
48123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
48133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	runTest();
48143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
48153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_status.setTestContextResult(m_testCtx);
48163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
48173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
48183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
48193c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename Sig>
48203c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FuncCase : public FuncCaseBase
48213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
48223c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
48233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef Func<Sig>						CaseFunc;
48243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Sig::Ret				Ret;
48253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Sig::Arg0				Arg0;
48263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Sig::Arg1				Arg1;
48273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Sig::Arg2				Arg2;
48283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Sig::Arg3				Arg3;
48293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef InTypes<Arg0, Arg1, Arg2, Arg3>	In;
48303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef OutTypes<Ret>					Out;
48313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
48323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					FuncCase	(const Context&		context,
48333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 const string&		name,
48343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 const CaseFunc&	func)
48353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						: FuncCaseBase	(context, name, func)
48363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						, m_func		(func) {}
48373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
48383c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
48393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void				runTest		(void);
48403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
48413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual const Samplings<In>&	getSamplings	(void)
48423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
48433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return instance<DefaultSamplings<In> >();
48443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
48453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
48463c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
48473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const CaseFunc&			m_func;
48483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
48493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
48503c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename Sig>
48513c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid FuncCase<Sig>::runTest (void)
48523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
48533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const Inputs<In>	inputs	(generateInputs(getSamplings(),
48543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												m_ctx.floatFormat,
48558852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry												m_ctx.precision,
48563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												m_ctx.numRandoms,
48573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												m_rnd));
48583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Variables<In, Out>	variables;
48593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
48603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	variables.out0	= variable<Ret>("out0");
48613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	variables.out1	= variable<Void>("out1");
48623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	variables.in0	= variable<Arg0>("in0");
48633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	variables.in1	= variable<Arg1>("in1");
48643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	variables.in2	= variable<Arg2>("in2");
48653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	variables.in3	= variable<Arg3>("in3");
48663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
48673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
48683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ExprP<Ret>	expr	= applyVar(m_func,
48693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									   variables.in0, variables.in1,
48703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									   variables.in2, variables.in3);
48713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		StatementP	stmt	= variableAssignment(variables.out0, expr);
48723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
48733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		this->testStatement(variables, inputs, *stmt);
48743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
48753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
48763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
48773c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename Sig>
48783c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass InOutFuncCase : public FuncCaseBase
48793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
48803c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
48813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef Func<Sig>						CaseFunc;
48823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Sig::Ret				Ret;
48833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Sig::Arg0				Arg0;
48843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Sig::Arg1				Arg1;
48853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Sig::Arg2				Arg2;
48863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename Sig::Arg3				Arg3;
48873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef InTypes<Arg0, Arg2, Arg3>		In;
48883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef OutTypes<Ret, Arg1>				Out;
48893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
48903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					InOutFuncCase	(const Context&		context,
48913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 const string&		name,
48923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 const CaseFunc&	func)
48933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						: FuncCaseBase	(context, name, func)
48943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						, m_func		(func) {}
48953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
48963c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
48973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void				runTest		(void);
48983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
48993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual const Samplings<In>&	getSamplings	(void)
49003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
49013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return instance<DefaultSamplings<In> >();
49023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
49033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
49043c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
49053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const CaseFunc&			m_func;
49063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
49073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
49083c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename Sig>
49093c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid InOutFuncCase<Sig>::runTest (void)
49103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
49113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const Inputs<In>	inputs	(generateInputs(getSamplings(),
49123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												m_ctx.floatFormat,
49138852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry												m_ctx.precision,
49143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												m_ctx.numRandoms,
49153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												m_rnd));
49163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Variables<In, Out>	variables;
49173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
49183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	variables.out0	= variable<Ret>("out0");
49193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	variables.out1	= variable<Arg1>("out1");
49203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	variables.in0	= variable<Arg0>("in0");
49213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	variables.in1	= variable<Arg2>("in1");
49223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	variables.in2	= variable<Arg3>("in2");
49233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	variables.in3	= variable<Void>("in3");
49243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
49253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
49263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ExprP<Ret>	expr	= applyVar(m_func,
49273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									   variables.in0, variables.out1,
49283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									   variables.in1, variables.in2);
49293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		StatementP	stmt	= variableAssignment(variables.out0, expr);
49303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
49313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		this->testStatement(variables, inputs, *stmt);
49323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
49333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
49343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
49353c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename Sig>
49363c827367444ee418f129b2c238299f49d3264554Jarkko PoyryPrecisionCase* createFuncCase (const Context&	context,
49373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const string&	name,
49383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const Func<Sig>&	func)
49393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
49403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (func.getOutParamIndex())
49413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
49423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case -1:
49433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return new FuncCase<Sig>(context, name, func);
49443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case 1:
49453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return new InOutFuncCase<Sig>(context, name, func);
49463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
49471cc61b7d03cad727bbddd00cea8d78f4f6cc9047Jarkko Pöyry			DE_FATAL("Impossible");
49483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
49493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return DE_NULL;
49503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
49513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
49523c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass CaseFactory
49533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
49543c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
49553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual						~CaseFactory	(void) {}
49563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual MovePtr<TestNode>	createCase		(const Context& ctx) const = 0;
49573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual string				getName			(void) const = 0;
49583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual string				getDesc			(void) const = 0;
49593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
49603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
49613c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FuncCaseFactory : public CaseFactory
49623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
49633c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
49643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual const FuncBase&	getFunc		(void) const = 0;
49653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
49663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string					getName		(void) const
49673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
49683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return de::toLower(getFunc().getName());
49693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
49703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
49713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string					getDesc		(void) const
49723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
49733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return "Function '" + getFunc().getName() + "'";
49743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
49753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
49763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
49773c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename Sig>
49783c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass GenFuncCaseFactory : public CaseFactory
49793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
49803c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
49813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
49823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						GenFuncCaseFactory	(const GenFuncs<Sig>&	funcs,
49833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 const string&			name)
49843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							: m_funcs	(funcs)
49853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							, m_name	(de::toLower(name)) {}
49863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
49873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MovePtr<TestNode>	createCase			(const Context& ctx) const
49883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
49893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TestCaseGroup*	group = new TestCaseGroup(ctx.testContext,
49903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												  ctx.name.c_str(), ctx.name.c_str());
49913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
49923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		group->addChild(createFuncCase(ctx, "scalar", m_funcs.func));
49933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		group->addChild(createFuncCase(ctx, "vec2", m_funcs.func2));
49943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		group->addChild(createFuncCase(ctx, "vec3", m_funcs.func3));
49953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		group->addChild(createFuncCase(ctx, "vec4", m_funcs.func4));
49963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
49973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return MovePtr<TestNode>(group);
49983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
49993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
50003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string				getName				(void) const
50013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
50023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return m_name;
50033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
50043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
50053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string				getDesc				(void) const
50063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
50073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return "Function '" + m_funcs.func.getName() + "'";
50083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
50093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
50103c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
50113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const GenFuncs<Sig>	m_funcs;
50123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string				m_name;
50133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
50143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
50153c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <template <int> class GenF>
50163c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass TemplateFuncCaseFactory : public FuncCaseFactory
50173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
50183c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
50193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MovePtr<TestNode>	createCase		(const Context& ctx) const
50203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
50213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TestCaseGroup*	group = new TestCaseGroup(ctx.testContext,
50223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  ctx.name.c_str(), ctx.name.c_str());
50233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		group->addChild(createFuncCase(ctx, "scalar", instance<GenF<1> >()));
50243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		group->addChild(createFuncCase(ctx, "vec2", instance<GenF<2> >()));
50253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		group->addChild(createFuncCase(ctx, "vec3", instance<GenF<3> >()));
50263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		group->addChild(createFuncCase(ctx, "vec4", instance<GenF<4> >()));
50273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
50283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return MovePtr<TestNode>(group);
50293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
50303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
50313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const FuncBase&		getFunc			(void) const { return instance<GenF<1> >(); }
50323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
50333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
50343c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <template <int> class GenF>
50353c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass SquareMatrixFuncCaseFactory : public FuncCaseFactory
50363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
50373c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
50383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MovePtr<TestNode>	createCase		(const Context& ctx) const
50393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
50403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TestCaseGroup*	group = new TestCaseGroup(ctx.testContext,
50413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  ctx.name.c_str(), ctx.name.c_str());
50423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		group->addChild(createFuncCase(ctx, "mat2", instance<GenF<2> >()));
50433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if 0
50443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// disabled until we get reasonable results
50453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		group->addChild(createFuncCase(ctx, "mat3", instance<GenF<3> >()));
50463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		group->addChild(createFuncCase(ctx, "mat4", instance<GenF<4> >()));
50473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
50483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
50493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return MovePtr<TestNode>(group);
50503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
50513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
50523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const FuncBase&		getFunc			(void) const { return instance<GenF<2> >(); }
50533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
50543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
50553c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <template <int, int> class GenF>
50563c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass MatrixFuncCaseFactory : public FuncCaseFactory
50573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
50583c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
50593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MovePtr<TestNode>	createCase		(const Context& ctx) const
50603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
50613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TestCaseGroup*	const group = new TestCaseGroup(ctx.testContext,
50623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														ctx.name.c_str(), ctx.name.c_str());
50633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
50643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		this->addCase<2, 2>(ctx, group);
50653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		this->addCase<3, 2>(ctx, group);
50663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		this->addCase<4, 2>(ctx, group);
50673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		this->addCase<2, 3>(ctx, group);
50683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		this->addCase<3, 3>(ctx, group);
50693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		this->addCase<4, 3>(ctx, group);
50703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		this->addCase<2, 4>(ctx, group);
50713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		this->addCase<3, 4>(ctx, group);
50723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		this->addCase<4, 4>(ctx, group);
50733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
50743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return MovePtr<TestNode>(group);
50753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
50763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
50773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const FuncBase&		getFunc			(void) const { return instance<GenF<2,2> >(); }
50783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
50793c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
50803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	template <int Rows, int Cols>
50813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void				addCase			(const Context& ctx, TestCaseGroup* group) const
50823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
50833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*	const name = dataTypeNameOf<Matrix<float, Rows, Cols> >();
50843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
50853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		group->addChild(createFuncCase(ctx, name, instance<GenF<Rows, Cols> >()));
50863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
50873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
50883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
50893c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename Sig>
50903c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass SimpleFuncCaseFactory : public CaseFactory
50913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
50923c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
50933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						SimpleFuncCaseFactory	(const Func<Sig>& func) : m_func(func) {}
50943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
50953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MovePtr<TestNode>	createCase		(const Context& ctx) const
50963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
50973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return MovePtr<TestNode>(createFuncCase(ctx, ctx.name.c_str(), m_func));
50983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
50993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
51003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string				getName					(void) const
51013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
51023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return de::toLower(m_func.getName());
51033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
51043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
51053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string				getDesc					(void) const
51063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
51073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return "Function '" + getName() + "'";
51083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
51093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
51103c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
51113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const Func<Sig>&	m_func;
51123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
51133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
51143c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename F>
51153c827367444ee418f129b2c238299f49d3264554Jarkko PoyrySharedPtr<SimpleFuncCaseFactory<typename F::Sig> > createSimpleFuncCaseFactory (void)
51163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
51173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return SharedPtr<SimpleFuncCaseFactory<typename F::Sig> >(
51183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		new SimpleFuncCaseFactory<typename F::Sig>(instance<F>()));
51193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
51203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
51213c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass BuiltinFuncs : public CaseFactories
51223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
51233c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
51243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const vector<const CaseFactory*>	getFactories	(void) const
51253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
51263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vector<const CaseFactory*> ret;
51273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
51283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (size_t ndx = 0; ndx < m_factories.size(); ++ndx)
51293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			ret.push_back(m_factories[ndx].get());
51303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
51313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return ret;
51323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
51333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
51343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void								addFactory		(SharedPtr<const CaseFactory> fact)
51353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
51363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_factories.push_back(fact);
51373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
51383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
51393c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
51403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<SharedPtr<const CaseFactory> >			m_factories;
51413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
51423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
51433c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename F>
51443c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid addScalarFactory(BuiltinFuncs& funcs, string name = "")
51453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
51463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (name.empty())
51473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		name = instance<F>().getName();
51483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
51493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	funcs.addFactory(SharedPtr<const CaseFactory>(new GenFuncCaseFactory<typename F::Sig>(
51503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  makeVectorizedFuncs<F>(), name)));
51513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
51523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
51533c827367444ee418f129b2c238299f49d3264554Jarkko PoyryMovePtr<const CaseFactories> createES3BuiltinCases (void)
51543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
51553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MovePtr<BuiltinFuncs>	funcs	(new BuiltinFuncs());
51563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
51573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<Add>(*funcs);
51583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<Sub>(*funcs);
51593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<Mul>(*funcs);
51603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<Div>(*funcs);
51613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
51623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<Radians>(*funcs);
51633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<Degrees>(*funcs);
51643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<Sin>(*funcs);
51653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<Cos>(*funcs);
51663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<Tan>(*funcs);
51673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<ASin>(*funcs);
51683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<ACos>(*funcs);
51693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<ATan2>(*funcs, "atan2");
51703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<ATan>(*funcs);
51713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<Sinh>(*funcs);
51723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<Cosh>(*funcs);
51733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<Tanh>(*funcs);
51743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<ASinh>(*funcs);
51753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<ACosh>(*funcs);
51763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<ATanh>(*funcs);
51773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
51783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<Pow>(*funcs);
51793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<Exp>(*funcs);
51803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<Log>(*funcs);
51813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<Exp2>(*funcs);
51823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<Log2>(*funcs);
51833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<Sqrt>(*funcs);
51843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<InverseSqrt>(*funcs);
51853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
51863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<Abs>(*funcs);
51873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<Sign>(*funcs);
51883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<Floor>(*funcs);
51893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<Trunc>(*funcs);
51903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<Round>(*funcs);
51913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<RoundEven>(*funcs);
51923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<Ceil>(*funcs);
51933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<Fract>(*funcs);
51943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<Mod>(*funcs);
51953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	funcs->addFactory(createSimpleFuncCaseFactory<Modf>());
51963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<Min>(*funcs);
51973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<Max>(*funcs);
51983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<Clamp>(*funcs);
51993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<Mix>(*funcs);
52003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<Step>(*funcs);
52013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<SmoothStep>(*funcs);
52023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
52033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	funcs->addFactory(SharedPtr<const CaseFactory>(new TemplateFuncCaseFactory<Length>()));
52043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	funcs->addFactory(SharedPtr<const CaseFactory>(new TemplateFuncCaseFactory<Distance>()));
52053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	funcs->addFactory(SharedPtr<const CaseFactory>(new TemplateFuncCaseFactory<Dot>()));
52063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	funcs->addFactory(createSimpleFuncCaseFactory<Cross>());
52073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	funcs->addFactory(SharedPtr<const CaseFactory>(new TemplateFuncCaseFactory<Normalize>()));
52083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	funcs->addFactory(SharedPtr<const CaseFactory>(new TemplateFuncCaseFactory<FaceForward>()));
52093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	funcs->addFactory(SharedPtr<const CaseFactory>(new TemplateFuncCaseFactory<Reflect>()));
52103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	funcs->addFactory(SharedPtr<const CaseFactory>(new TemplateFuncCaseFactory<Refract>()));
52113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
52123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
52133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	funcs->addFactory(SharedPtr<const CaseFactory>(new MatrixFuncCaseFactory<MatrixCompMult>()));
52143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	funcs->addFactory(SharedPtr<const CaseFactory>(new MatrixFuncCaseFactory<OuterProduct>()));
52153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	funcs->addFactory(SharedPtr<const CaseFactory>(new MatrixFuncCaseFactory<Transpose>()));
52163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	funcs->addFactory(SharedPtr<const CaseFactory>(new SquareMatrixFuncCaseFactory<Determinant>()));
52173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	funcs->addFactory(SharedPtr<const CaseFactory>(new SquareMatrixFuncCaseFactory<Inverse>()));
52183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
52193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return MovePtr<const CaseFactories>(funcs.release());
52203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
52213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
52223c827367444ee418f129b2c238299f49d3264554Jarkko PoyryMovePtr<const CaseFactories> createES31BuiltinCases (void)
52233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
52243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MovePtr<BuiltinFuncs>	funcs	(new BuiltinFuncs());
52253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
52263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<FrExp>(*funcs);
52273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<LdExp>(*funcs);
52283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addScalarFactory<Fma>(*funcs);
52293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
52303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return MovePtr<const CaseFactories>(funcs.release());
52313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
52323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
52333c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct PrecisionTestContext
52343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
52353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	PrecisionTestContext	(TestContext&				testCtx_,
52363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							 RenderContext&				renderCtx_,
52373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							 const FloatFormat&			highp_,
52383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							 const FloatFormat&			mediump_,
52393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							 const FloatFormat&			lowp_,
52403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							 const vector<ShaderType>&	shaderTypes_,
52413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							 int						numRandoms_)
52423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: testCtx		(testCtx_)
52433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, renderCtx		(renderCtx_)
52443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, shaderTypes	(shaderTypes_)
52453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, numRandoms	(numRandoms_)
52463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
52473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		formats[glu::PRECISION_HIGHP]	= &highp_;
52483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		formats[glu::PRECISION_MEDIUMP]	= &mediump_;
52493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		formats[glu::PRECISION_LOWP]	= &lowp_;
52503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
52513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
52523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestContext&			testCtx;
52533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	RenderContext&			renderCtx;
52543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const FloatFormat*		formats[glu::PRECISION_LAST];
52553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<ShaderType>		shaderTypes;
52563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int						numRandoms;
52573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
52583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
52593c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTestCaseGroup* createFuncGroup (const PrecisionTestContext&	ctx,
52603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								const CaseFactory&			factory)
52613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
52623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestCaseGroup* const 	group	= new TestCaseGroup(ctx.testCtx,
52633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														factory.getName().c_str(),
52643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														factory.getDesc().c_str());
52653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
52663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int precNdx = 0; precNdx < glu::PRECISION_LAST; ++precNdx)
52673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
52683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Precision		precision	= Precision(precNdx);
52693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const string		precName	(glu::getPrecisionName(precision));
52705730719a54e92e0816ef2b4217a2277907d67bccJarkko Pöyry		const FloatFormat&	fmt			= *de::getSizedArrayElement<glu::PRECISION_LAST>(ctx.formats, precNdx);
52715730719a54e92e0816ef2b4217a2277907d67bccJarkko Pöyry		const FloatFormat&	highpFmt	= *de::getSizedArrayElement<glu::PRECISION_LAST>(ctx.formats,
52725730719a54e92e0816ef2b4217a2277907d67bccJarkko Pöyry																						 glu::PRECISION_HIGHP);
52733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
52743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (size_t shaderNdx = 0; shaderNdx < ctx.shaderTypes.size(); ++shaderNdx)
52753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
52763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const ShaderType	shaderType	= ctx.shaderTypes[shaderNdx];
52773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const string 		shaderName	(glu::getShaderTypeName(shaderType));
52783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const string		name		= precName + "_" + shaderName;
52793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const Context		caseCtx		(name, ctx.testCtx, ctx.renderCtx, fmt, highpFmt,
52803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 precision, shaderType, ctx.numRandoms);
52813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
52823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			group->addChild(factory.createCase(caseCtx).release());
52833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
52843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
52853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
52863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return group;
52873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
52883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
52893c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid addBuiltinPrecisionTests (TestContext&					testCtx,
52903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   RenderContext&				renderCtx,
52913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const CaseFactories&			cases,
52923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const vector<ShaderType>&	shaderTypes,
52933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   TestCaseGroup&				dstGroup)
52943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
52952fe928514327a48b70de83c293881347797da3e2Pyry Haulos	const int						userRandoms	= testCtx.getCommandLine().getTestIterationCount();
52962fe928514327a48b70de83c293881347797da3e2Pyry Haulos	const int						defRandoms	= 16384;
52972fe928514327a48b70de83c293881347797da3e2Pyry Haulos	const int						numRandoms	= userRandoms > 0 ? userRandoms : defRandoms;
52983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const FloatFormat				highp		(-126, 127, 23, true,
52993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 tcu::MAYBE,	// subnormals
53003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 tcu::YES,		// infinities
53013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 tcu::MAYBE);	// NaN
53023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// \todo [2014-04-01 lauri] Check these once Khronos bug 11840 is resolved.
53033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const FloatFormat				mediump		(-13, 13, 9, false);
53043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// A fixed-point format is just a floating point format with a fixed
53053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// exponent and support for subnormals.
53063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const FloatFormat				lowp		(0, 0, 7, false, tcu::YES);
53073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const PrecisionTestContext		ctx			(testCtx, renderCtx, highp, mediump, lowp,
53082fe928514327a48b70de83c293881347797da3e2Pyry Haulos												 shaderTypes, numRandoms);
53093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
53103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (size_t ndx = 0; ndx < cases.getFactories().size(); ++ndx)
53113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		dstGroup.addChild(createFuncGroup(ctx, *cases.getFactories()[ndx]));
53123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
53133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
53143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // BuiltinPrecisionTests
53153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // gls
53163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // deqp
5317