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