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