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