/*-------------------------------------------------------------------------
 * drawElements Quality Program Random Shader Generator
 * ----------------------------------------------------
 *
 * Copyright 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief Binary ops.
 *//*--------------------------------------------------------------------*/

#include "rsgBinaryOps.hpp"
#include "rsgVariableManager.hpp"
#include "rsgUtils.hpp"
#include "deMath.h"

using std::vector;

namespace rsg
{

// CustomAbsOp and CustomBinaryOp are used to resolve float comparision corner case.
// This error happened when two floats with the same value were compared
// without using epsilon. If result of this comparisment influenced the
// output color then result and reference images could differ.
class CustomAbsOp : public Expression
{
public:
								CustomAbsOp		(void);
	virtual						~CustomAbsOp	(void);

	void						setChild				(Expression* expression);
	Expression*					createNextChild			(GeneratorState& state);
	void						tokenize				(GeneratorState& state, TokenStream& str) const;

	void						evaluate				(ExecutionContext& execCtx);
	ExecConstValueAccess		getValue				(void) const { return m_value.getValue(m_type); }

private:
	std::string					m_function;
	VariableType				m_type;
	ExecValueStorage			m_value;
	Expression*					m_child;
};

CustomAbsOp::CustomAbsOp (void)
	: m_function		("abs")
	, m_type			(VariableType::TYPE_FLOAT, 1)
	, m_child			(DE_NULL)
{
	m_value.setStorage(m_type);
}

CustomAbsOp::~CustomAbsOp (void)
{
	delete m_child;
}

void CustomAbsOp::setChild(Expression* expression)
{
	m_child = expression;
}

Expression* CustomAbsOp::createNextChild (GeneratorState&)
{
	DE_ASSERT(0);
	return DE_NULL;
}

void CustomAbsOp::tokenize (GeneratorState& state, TokenStream& str) const
{
	str << Token(m_function.c_str()) << Token::LEFT_PAREN;
	m_child->tokenize(state, str);
	str << Token::RIGHT_PAREN;
}

void CustomAbsOp::evaluate (ExecutionContext& execCtx)
{
	m_child->evaluate(execCtx);

	ExecConstValueAccess	srcValue	= m_child->getValue();
	ExecValueAccess			dstValue	= m_value.getValue(m_type);

	for (int elemNdx = 0; elemNdx < m_type.getNumElements(); elemNdx++)
	{
		ExecConstValueAccess	srcComp		= srcValue.component(elemNdx);
		ExecValueAccess			dstComp		= dstValue.component(elemNdx);

		for (int compNdx = 0; compNdx < EXEC_VEC_WIDTH; compNdx++)
			dstComp.asFloat(compNdx) = deFloatAbs(srcComp.asFloat(compNdx));
	}
}

typedef BinaryOp<5, ASSOCIATIVITY_LEFT> CustomBinaryBase;

// CustomBinaryOp and CustomAbsOp are used to resolve float comparision corner case.
// CustomBinaryOp supports addition and substraction as only those functionalities
// were needed.
template <typename ComputeValue>
class CustomBinaryOp: public CustomBinaryBase
{
public:
								CustomBinaryOp		();
	virtual						~CustomBinaryOp		(void) {}

	void						setLeftValue		(Expression* expression);
	void						setRightValue		(Expression* expression);

	void						evaluate			(ExecValueAccess dst, ExecConstValueAccess a, ExecConstValueAccess b);
};

template <typename ComputeValue>
CustomBinaryOp<ComputeValue>::CustomBinaryOp ()
	: CustomBinaryBase(Token::PLUS)
{
	// By default add operation is assumed, for every other operation
	// separate constructor specialization should be implemented
	m_type = VariableType(VariableType::TYPE_FLOAT, 1);
	m_value.setStorage(m_type);
}

template <>
CustomBinaryOp<EvaluateSub>::CustomBinaryOp ()
	: CustomBinaryBase(Token::MINUS)
{
	// Specialization for substraction
	m_type = VariableType(VariableType::TYPE_FLOAT, 1);
	m_leftValueRange =	ValueRange(m_type);
	m_rightValueRange = ValueRange(m_type);
	m_value.setStorage(m_type);
}

template <>
CustomBinaryOp<EvaluateLessThan>::CustomBinaryOp ()
	: CustomBinaryBase(Token::CMP_LT)
{
	// Specialization for less_then comparision
	m_type = VariableType(VariableType::TYPE_BOOL, 1);
	VariableType floatType = VariableType(VariableType::TYPE_FLOAT, 1);
	m_leftValueRange =	ValueRange(floatType);
	m_rightValueRange = ValueRange(floatType);
	m_value.setStorage(m_type);
}

template <typename ComputeValue>
void CustomBinaryOp<ComputeValue>::setLeftValue(Expression* expression)
{
	m_leftValueExpr = expression;
}

template <typename ComputeValue>
void CustomBinaryOp<ComputeValue>::setRightValue(Expression* expression)
{
	m_rightValueExpr = expression;
}

template <typename ComputeValue>
void CustomBinaryOp<ComputeValue>::evaluate(ExecValueAccess dst, ExecConstValueAccess a, ExecConstValueAccess b)
{
	DE_ASSERT(dst.getType() == a.getType());
	DE_ASSERT(dst.getType() == b.getType());
	DE_ASSERT(dst.getType().getBaseType() == VariableType::TYPE_FLOAT);

	for (int elemNdx = 0; elemNdx < dst.getType().getNumElements(); elemNdx++)
	{
		for (int compNdx = 0; compNdx < EXEC_VEC_WIDTH; compNdx++)
			dst.component(elemNdx).asFloat(compNdx) = ComputeValue()(a.component(elemNdx).asFloat(compNdx),b.component(elemNdx).asFloat(compNdx));
	}
}

template <>
void CustomBinaryOp<EvaluateLessThan>::evaluate(ExecValueAccess dst, ExecConstValueAccess a, ExecConstValueAccess b)
{
	DE_ASSERT(a.getType() == b.getType());
	DE_ASSERT(dst.getType().getBaseType() == VariableType::TYPE_BOOL);

	for (int elemNdx = 0; elemNdx < dst.getType().getNumElements(); elemNdx++)
	{
		for (int compNdx = 0; compNdx < EXEC_VEC_WIDTH; compNdx++)
			dst.component(elemNdx).asBool(compNdx) = EvaluateLessThan()(a.component(elemNdx).asFloat(compNdx),b.component(elemNdx).asFloat(compNdx));
	}
}

template <int Precedence, Associativity Assoc>
BinaryOp<Precedence, Assoc>::BinaryOp (Token::Type operatorToken)
	: m_operator		(operatorToken)
	, m_leftValueRange	(m_type)
	, m_rightValueRange	(m_type)
	, m_leftValueExpr	(DE_NULL)
	, m_rightValueExpr	(DE_NULL)
{
}

template <int Precedence, Associativity Assoc>
BinaryOp<Precedence, Assoc>::~BinaryOp (void)
{
	delete m_leftValueExpr;
	delete m_rightValueExpr;
}

template <int Precedence, Associativity Assoc>
Expression* BinaryOp<Precedence, Assoc>::createNextChild (GeneratorState& state)
{
	int leftPrec	= Assoc == ASSOCIATIVITY_LEFT ? Precedence : Precedence-1;
	int rightPrec	= Assoc == ASSOCIATIVITY_LEFT ? Precedence-1 : Precedence;

	if (m_rightValueExpr == DE_NULL)
	{
		state.pushPrecedence(rightPrec);
		m_rightValueExpr = Expression::createRandom(state, m_rightValueRange.asAccess());
		state.popPrecedence();
		return m_rightValueExpr;
	}
	else if (m_leftValueExpr == DE_NULL)
	{
		state.pushPrecedence(leftPrec);
		m_leftValueExpr = Expression::createRandom(state, m_leftValueRange.asAccess());
		state.popPrecedence();
		return m_leftValueExpr;
	}
	else
	{
		// Check for corrner cases
		switch (m_operator)
		{
		case Token::CMP_LE:
		{
			// When comparing two floats epsilon should be included
			// to eliminate the risk that we get different results
			// because of precission error
			VariableType floatType(VariableType::TYPE_FLOAT, 1);
			if (m_rightValueRange.getType() == floatType)
			{
				FloatLiteral* epsilonLiteral = new FloatLiteral(0.001f);

				typedef CustomBinaryOp<EvaluateAdd> CustomAddOp;
				CustomAddOp* addOperation = new CustomAddOp();
				addOperation->setLeftValue(m_rightValueExpr);
				addOperation->setRightValue(epsilonLiteral);

				// add epsilon to right-hand side
				m_rightValueExpr = addOperation;
			}
			break;
		}
		case Token::CMP_GE:
		{
			// When comparing two floats epsilon should be included
			// to eliminate the risk that we get different results
			// because of precission error
			VariableType floatType(VariableType::TYPE_FLOAT, 1);
			if (m_leftValueRange.getType() == floatType)
			{
				FloatLiteral* epsilonLiteral = new FloatLiteral(0.001f);

				typedef CustomBinaryOp<EvaluateAdd> CustomAddOp;
				CustomAddOp* addOperation = new CustomAddOp();
				addOperation->setLeftValue(m_leftValueExpr);
				addOperation->setRightValue(epsilonLiteral);

				// add epsilon to left-hand side
				m_leftValueExpr = addOperation;
			}
			break;
		}
		case Token::CMP_EQ:
		{
			// When comparing two floats epsilon should be included
			// to eliminate the risk that we get different results
			// because of precission error
			VariableType floatType(VariableType::TYPE_FLOAT, 1);
			if (m_leftValueRange.getType() == floatType)
			{
				VariableType boolType(VariableType::TYPE_BOOL, 1);
				const ValueRange boolRange(boolType);

				ParenOp* parenRight = new ParenOp(state, boolRange);
				parenRight->setChild(m_rightValueExpr);

				typedef CustomBinaryOp<EvaluateSub> CustomSubOp;
				CustomSubOp* subOperation = new CustomSubOp();
				subOperation->setLeftValue(m_leftValueExpr);
				subOperation->setRightValue(parenRight);

				CustomAbsOp* absOperation = new CustomAbsOp();
				absOperation->setChild(subOperation);
				FloatLiteral* epsilonLiteral = new FloatLiteral(0.001f);

				typedef CustomBinaryOp<EvaluateLessThan> CustomLessThanOp;
				CustomLessThanOp* lessOperation = new CustomLessThanOp();
				lessOperation->setLeftValue(absOperation);
				lessOperation->setRightValue(epsilonLiteral);

				ParenOp* parenOperation = new ParenOp(state, boolRange);
				parenOperation->setChild(lessOperation);
				BoolLiteral* trueLiteral = new BoolLiteral(true);

				// EQ operation cant be removed so it is replaced with:
				// ((abs(lhs-rhs) < epsilon) == true).
				m_leftValueExpr = parenOperation;
				m_rightValueExpr = trueLiteral;
			}
			break;
		}
		default:
			break;
		}

		return DE_NULL;
	}
}

template <int Precedence, Associativity Assoc>
float BinaryOp<Precedence, Assoc>::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
{
	if (state.getPrecedence() < Precedence)
		return 0.0f;

	int availableLevels = state.getShaderParameters().maxExpressionDepth - state.getExpressionDepth();

	if (valueRange.getType().isVoid())
		return availableLevels >= 2 ? unusedValueWeight : 0.0f;

	if (availableLevels < getConservativeValueExprDepth(state, valueRange) + 1)
		return 0.0f;

	return 1.0f;
}

template <int Precedence, Associativity Assoc>
void BinaryOp<Precedence, Assoc>::tokenize (GeneratorState& state, TokenStream& str) const
{
	m_leftValueExpr->tokenize(state, str);
	str << m_operator;
	m_rightValueExpr->tokenize(state, str);
}

template <int Precedence, Associativity Assoc>
void BinaryOp<Precedence, Assoc>::evaluate (ExecutionContext& execCtx)
{
	m_leftValueExpr->evaluate(execCtx);
	m_rightValueExpr->evaluate(execCtx);

	ExecConstValueAccess	leftVal		= m_leftValueExpr->getValue();
	ExecConstValueAccess	rightVal	= m_rightValueExpr->getValue();
	ExecValueAccess			dst			= m_value.getValue(m_type);

	evaluate(dst, leftVal, rightVal);
}

template <int Precedence, bool Float, bool Int, bool Bool, class ComputeValueRange, class EvaluateComp>
BinaryVecOp<Precedence, Float, Int, Bool, ComputeValueRange, EvaluateComp>::BinaryVecOp (GeneratorState& state, Token::Type operatorToken, ConstValueRangeAccess inValueRange)
	: BinaryOp<Precedence, ASSOCIATIVITY_LEFT>(operatorToken)
{
	ValueRange valueRange = inValueRange;

	if (valueRange.getType().isVoid())
	{
		int							availableLevels	= state.getShaderParameters().maxExpressionDepth - state.getExpressionDepth();
		vector<VariableType::Type>	baseTypes;

		if (Float)	baseTypes.push_back(VariableType::TYPE_FLOAT);
		if (Int)	baseTypes.push_back(VariableType::TYPE_INT);
		if (Bool)	baseTypes.push_back(VariableType::TYPE_BOOL);

		VariableType::Type	baseType	= state.getRandom().choose<VariableType::Type>(baseTypes.begin(), baseTypes.end());
		int					numElements	= state.getRandom().getInt(1, availableLevels >= 3 ? 4 : 1);

		valueRange = ValueRange(VariableType(baseType, numElements));
		computeRandomValueRange(state, valueRange.asAccess());
	}

	// Choose type, allocate storage for execution
	this->m_type = valueRange.getType();
	this->m_value.setStorage(this->m_type);

	// Initialize storage for value ranges
	this->m_rightValueRange	= ValueRange(this->m_type);
	this->m_leftValueRange	= ValueRange(this->m_type);

	VariableType::Type baseType = this->m_type.getBaseType();

	// Compute range for b that satisfies requested value range
	for (int elemNdx = 0; elemNdx < this->m_type.getNumElements(); elemNdx++)
	{
		ConstValueRangeAccess	dst		= valueRange.asAccess().component(elemNdx);
		ValueRangeAccess		a		= this->m_leftValueRange.asAccess().component(elemNdx); // \todo [2011-03-25 pyry] Commutative: randomize inputs
		ValueRangeAccess		b		= this->m_rightValueRange.asAccess().component(elemNdx);

		// Just pass undefined ranges
		if ((baseType == VariableType::TYPE_FLOAT || baseType == VariableType::TYPE_INT) && isUndefinedValueRange(dst))
		{
			a.getMin() = dst.getMin().value();
			b.getMin() = dst.getMin().value();
			a.getMax() = dst.getMax().value();
			b.getMax() = dst.getMax().value();
			continue;
		}

		if (baseType == VariableType::TYPE_FLOAT)
			ComputeValueRange()(state.getRandom(), dst.getMin().asFloat(), dst.getMax().asFloat(),
								a.getMin().asFloat(), a.getMax().asFloat(),
								b.getMin().asFloat(), b.getMax().asFloat());
		else if (baseType == VariableType::TYPE_INT)
			ComputeValueRange()(state.getRandom(), dst.getMin().asInt(), dst.getMax().asInt(),
								a.getMin().asInt(), a.getMax().asInt(),
								b.getMin().asInt(), b.getMax().asInt());
		else
		{
			DE_ASSERT(baseType == VariableType::TYPE_BOOL);
			ComputeValueRange()(state.getRandom(), dst.getMin().asBool(), dst.getMax().asBool(),
								a.getMin().asBool(), a.getMax().asBool(),
								b.getMin().asBool(), b.getMax().asBool());
		}
	}
}

template <int Precedence, bool Float, bool Int, bool Bool, class ComputeValueRange, class EvaluateComp>
BinaryVecOp<Precedence, Float, Int, Bool, ComputeValueRange, EvaluateComp>::~BinaryVecOp (void)
{
}

template <int Precedence, bool Float, bool Int, bool Bool, class ComputeValueRange, class EvaluateComp>
void BinaryVecOp<Precedence, Float, Int, Bool, ComputeValueRange, EvaluateComp>::evaluate (ExecValueAccess dst, ExecConstValueAccess a, ExecConstValueAccess b)
{
	DE_ASSERT(dst.getType() == a.getType());
	DE_ASSERT(dst.getType() == b.getType());
	switch (dst.getType().getBaseType())
	{
		case VariableType::TYPE_FLOAT:
			for (int elemNdx = 0; elemNdx < dst.getType().getNumElements(); elemNdx++)
			{
				for (int compNdx = 0; compNdx < EXEC_VEC_WIDTH; compNdx++)
					dst.component(elemNdx).asFloat(compNdx) = EvaluateComp()(a.component(elemNdx).asFloat(compNdx), b.component(elemNdx).asFloat(compNdx));
			}
			break;

		case VariableType::TYPE_INT:
			for (int elemNdx = 0; elemNdx < dst.getType().getNumElements(); elemNdx++)
			{
				for (int compNdx = 0; compNdx < EXEC_VEC_WIDTH; compNdx++)
					dst.component(elemNdx).asInt(compNdx) = EvaluateComp()(a.component(elemNdx).asInt(compNdx), b.component(elemNdx).asInt(compNdx));
			}
			break;

		default:
			DE_ASSERT(DE_FALSE); // Invalid type for multiplication
	}
}

void ComputeMulRange::operator() (de::Random& rnd, float dstMin, float dstMax, float& aMin, float& aMax, float& bMin, float& bMax) const
{
	const float minScale	 = 0.25f;
	const float maxScale	 = 2.0f;
	const float subRangeStep = 0.25f;
	const float scaleStep	 = 0.25f;

	float scale		= getQuantizedFloat(rnd, minScale, maxScale, scaleStep);
	float scaledMin	= dstMin/scale;
	float scaledMax	= dstMax/scale;

	// Quantize scaled value range if possible
	if (!quantizeFloatRange(scaledMin, scaledMax))
	{
		// Fall back to 1.0 as a scale
		scale		= 1.0f;
		scaledMin	= dstMin;
		scaledMax	= dstMax;
	}

	float subRangeLen = getQuantizedFloat(rnd, 0.0f, scaledMax-scaledMin, subRangeStep);
	aMin = scaledMin + getQuantizedFloat(rnd, 0.0f, (scaledMax-scaledMin)-subRangeLen, subRangeStep);
	aMax = aMin + subRangeLen;

	// Find scale range
	bMin = scale;
	bMax = scale;
	for (int i = 0; i < 5; i++)
	{
		if (de::inBounds(aMin*(scale-(float)i*scaleStep), dstMin, dstMax) &&
			de::inBounds(aMax*(scale-(float)i*scaleStep), dstMin, dstMax))
			bMin = scale-(float)i*scaleStep;

		if (de::inBounds(aMin*(scale+(float)i*scaleStep), dstMin, dstMax) &&
			de::inBounds(aMax*(scale+(float)i*scaleStep), dstMin, dstMax))
			bMax = scale+(float)i*scaleStep;
	}

	// Negative scale?
	if (rnd.getBool())
	{
		std::swap(aMin, aMax);
		std::swap(bMin, bMax);
		aMin	*= -1.0f;
		aMax	*= -1.0f;
		bMin	*= -1.0f;
		bMax	*= -1.0f;
	}

#if defined(DE_DEBUG)
	const float eps = 0.001f;
	DE_ASSERT(aMin <= aMax && bMin <= bMax);
	DE_ASSERT(de::inRange(aMin*bMin, dstMin-eps, dstMax+eps));
	DE_ASSERT(de::inRange(aMin*bMax, dstMin-eps, dstMax+eps));
	DE_ASSERT(de::inRange(aMax*bMin, dstMin-eps, dstMax+eps));
	DE_ASSERT(de::inRange(aMax*bMax, dstMin-eps, dstMax+eps));
#endif
}

void ComputeMulRange::operator() (de::Random& rnd, int dstMin, int dstMax, int& aMin, int& aMax, int& bMin, int& bMax) const
{
	DE_UNREF(rnd);
	aMin	= dstMin;
	aMax	= dstMax;
	bMin	= 1;
	bMax	= 1;
}

MulOp::MulOp (GeneratorState& state, ConstValueRangeAccess valueRange)
	: MulBase(state, Token::MUL, valueRange)
{
}

float MulOp::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
{
	if (valueRange.getType().isVoid() ||
		valueRange.getType().isFloatOrVec() ||
		valueRange.getType().isIntOrVec())
		return MulBase::getWeight(state, valueRange);
	else
		return 0.0f;
}

template <typename T>
void ComputeAddRange::operator() (de::Random& random, T dstMin, T dstMax, T& aMin, T& aMax, T& bMin, T& bMax) const
{
	struct GetRandom
	{
		int		operator() (de::Random& rnd, int min, int max) const		{ return rnd.getInt(min, max); }
		float	operator() (de::Random& rnd, float min, float max) const	{ return getQuantizedFloat(rnd, min, max, 0.5f); }
	};

	T rangeLen		= dstMax-dstMin;
	T subRangeLen	= GetRandom()(random, T(0), rangeLen);
	T aOffset		= GetRandom()(random, T(-8), T(8));

	aMin			= dstMin+aOffset;
	aMax			= aMin+subRangeLen;

	bMin			= -aOffset;
	bMax			= -aOffset+(rangeLen-subRangeLen);

#if defined(DE_DEBUG)
	T eps = T(0.001);
	DE_ASSERT(aMin <= aMax && bMin <= bMax);
	DE_ASSERT(de::inRange(aMin+bMin, dstMin-eps, dstMax+eps));
	DE_ASSERT(de::inRange(aMin+bMax, dstMin-eps, dstMax+eps));
	DE_ASSERT(de::inRange(aMax+bMin, dstMin-eps, dstMax+eps));
	DE_ASSERT(de::inRange(aMax+bMax, dstMin-eps, dstMax+eps));
#endif
}

template <>
void ComputeAddRange::operator()<bool> (de::Random&, bool, bool, bool&, bool&, bool&, bool&) const
{
	DE_ASSERT(DE_FALSE);
}

AddOp::AddOp (GeneratorState& state, ConstValueRangeAccess valueRange)
	: AddBase(state, Token::PLUS, valueRange)
{
}

float AddOp::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
{
	if (valueRange.getType().isVoid() ||
		valueRange.getType().isFloatOrVec() ||
		valueRange.getType().isIntOrVec())
		return AddBase::getWeight(state, valueRange);
	else
		return 0.0f;
}

template <typename T>
void ComputeSubRange::operator() (de::Random& random, T dstMin, T dstMax, T& aMin, T& aMax, T& bMin, T& bMax) const
{
	struct GetRandom
	{
		int		operator() (de::Random& rnd, int min, int max) const		{ return rnd.getInt(min, max); }
		float	operator() (de::Random& rnd, float min, float max) const	{ return getQuantizedFloat(rnd, min, max, 0.5f); }
	};

	T rangeLen		= dstMax-dstMin;
	T subRangeLen	= GetRandom()(random, T(0), rangeLen);
	T aOffset		= GetRandom()(random, T(-8), T(8));

	aMin			= dstMin+aOffset;
	aMax			= aMin+subRangeLen;

	bMin			= aOffset-(rangeLen-subRangeLen);
	bMax			= aOffset;

#if defined(DE_DEBUG)
	T eps = T(0.001);
	DE_ASSERT(aMin <= aMax && bMin <= bMax);
	DE_ASSERT(de::inRange(aMin-bMin, dstMin-eps, dstMax+eps));
	DE_ASSERT(de::inRange(aMin-bMax, dstMin-eps, dstMax+eps));
	DE_ASSERT(de::inRange(aMax-bMin, dstMin-eps, dstMax+eps));
	DE_ASSERT(de::inRange(aMax-bMax, dstMin-eps, dstMax+eps));
#endif
}

template <>
void ComputeSubRange::operator()<bool> (de::Random&, bool, bool, bool&, bool&, bool&, bool&) const
{
	DE_ASSERT(DE_FALSE);
}

SubOp::SubOp (GeneratorState& state, ConstValueRangeAccess valueRange)
	: SubBase(state, Token::MINUS, valueRange)
{
}

float SubOp::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
{
	if (valueRange.getType().isVoid() ||
		valueRange.getType().isFloatOrVec() ||
		valueRange.getType().isIntOrVec())
		return SubBase::getWeight(state, valueRange);
	else
		return 0.0f;
}

template <class ComputeValueRange, class EvaluateComp>
RelationalOp<ComputeValueRange, EvaluateComp>::RelationalOp (GeneratorState& state, Token::Type operatorToken, ConstValueRangeAccess inValueRange)
	: BinaryOp<7, ASSOCIATIVITY_LEFT>(operatorToken)
{
	ValueRange valueRange = inValueRange;

	if (valueRange.getType().isVoid())
	{
		valueRange = ValueRange(VariableType(VariableType::TYPE_BOOL, 1));
		computeRandomValueRange(state, valueRange.asAccess());
	}

	// Choose type, allocate storage for execution
	this->m_type = valueRange.getType();
	this->m_value.setStorage(this->m_type);

	// Choose random input type
	VariableType::Type inBaseTypes[]	= { VariableType::TYPE_FLOAT, VariableType::TYPE_INT };
	VariableType::Type inBaseType		= state.getRandom().choose<VariableType::Type>(&inBaseTypes[0], &inBaseTypes[DE_LENGTH_OF_ARRAY(inBaseTypes)]);

	// Initialize storage for input value ranges
	this->m_rightValueRange	= ValueRange(VariableType(inBaseType, 1));
	this->m_leftValueRange	= ValueRange(VariableType(inBaseType, 1));

	// Compute range for b that satisfies requested value range
	{
		bool					dstMin	= valueRange.getMin().asBool();
		bool					dstMax	= valueRange.getMax().asBool();
		ValueRangeAccess		a		= this->m_leftValueRange.asAccess();
		ValueRangeAccess		b		= this->m_rightValueRange.asAccess();

		if (inBaseType == VariableType::TYPE_FLOAT)
			ComputeValueRange()(state.getRandom(), dstMin, dstMax,
								a.getMin().asFloat(), a.getMax().asFloat(),
								b.getMin().asFloat(), b.getMax().asFloat());
		else if (inBaseType == VariableType::TYPE_INT)
			ComputeValueRange()(state.getRandom(), dstMin, dstMax,
								a.getMin().asInt(), a.getMax().asInt(),
								b.getMin().asInt(), b.getMax().asInt());
	}
}

template <class ComputeValueRange, class EvaluateComp>
RelationalOp<ComputeValueRange, EvaluateComp>::~RelationalOp (void)
{
}

template <class ComputeValueRange, class EvaluateComp>
void RelationalOp<ComputeValueRange, EvaluateComp>::evaluate (ExecValueAccess dst, ExecConstValueAccess a, ExecConstValueAccess b)
{
	DE_ASSERT(a.getType() == b.getType());
	switch (a.getType().getBaseType())
	{
		case VariableType::TYPE_FLOAT:
			for (int compNdx = 0; compNdx < EXEC_VEC_WIDTH; compNdx++)
				dst.asBool(compNdx) = EvaluateComp()(a.asFloat(compNdx), b.asFloat(compNdx));
			break;

		case VariableType::TYPE_INT:
			for (int compNdx = 0; compNdx < EXEC_VEC_WIDTH; compNdx++)
				dst.asBool(compNdx) = EvaluateComp()(a.asInt(compNdx), b.asInt(compNdx));
			break;

		default:
			DE_ASSERT(DE_FALSE);
	}
}

template <class ComputeValueRange, class EvaluateComp>
float RelationalOp<ComputeValueRange, EvaluateComp>::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
{
	if (!state.getProgramParameters().useComparisonOps)
		return 0.0f;

	if (valueRange.getType().isVoid() ||
		(valueRange.getType().getBaseType() == VariableType::TYPE_BOOL && valueRange.getType().getNumElements() == 1))
		return BinaryOp<7, ASSOCIATIVITY_LEFT>::getWeight(state, valueRange);
	else
		return 0.0f;
}

namespace
{

template <typename T>	T		getStep (void);
template <> inline		float	getStep (void) { return 0.25f;	}
template <> inline		int		getStep (void) { return 1;		}

} // anonymous

template <typename T>
void ComputeLessThanRange::operator () (de::Random& rnd, bool dstMin, bool dstMax, T& aMin, T& aMax, T& bMin, T& bMax) const
{
	struct GetRandom
	{
		int		operator() (de::Random& random, int min, int max) const		{ return random.getInt(min, max); }
		float	operator() (de::Random& random, float min, float max) const	{ return getQuantizedFloat(random, min, max, getStep<float>()); }
	};

	// One random range
	T	rLen	= GetRandom()(rnd, T(0), T(8));
	T	rMin	= GetRandom()(rnd, T(-4), T(4));
	T	rMax	= rMin+rLen;

	if (dstMin == false && dstMax == true)
	{
		// Both values are possible, use same range for both inputs
		aMin	= rMin;
		aMax	= rMax;
		bMin	= rMin;
		bMax	= rMax;
	}
	else if (dstMin == true && dstMax == true)
	{
		// Compute range that is less than rMin..rMax
		T aLen = GetRandom()(rnd, T(0), T(8)-rLen);

		aMax	= rMin - getStep<T>();
		aMin	= aMax - aLen;

		bMin	= rMin;
		bMax	= rMax;
	}
	else
	{
		// Compute range that is greater than or equal to rMin..rMax
		T aLen = GetRandom()(rnd, T(0), T(8)-rLen);

		aMin	= rMax;
		aMax	= aMin + aLen;

		bMin	= rMin;
		bMax	= rMax;
	}
}

LessThanOp::LessThanOp (GeneratorState& state, ConstValueRangeAccess valueRange)
	: LessThanBase(state, Token::CMP_LT, valueRange)
{
}

float LessThanOp::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
{
	return LessThanBase::getWeight(state, valueRange);
}

template <typename T>
void ComputeLessOrEqualRange::operator () (de::Random& rnd, bool dstMin, bool dstMax, T& aMin, T& aMax, T& bMin, T& bMax) const
{
	struct GetRandom
	{
		int		operator() (de::Random& random, int min, int max) const		{ return random.getInt(min, max); }
		float	operator() (de::Random& random, float min, float max) const	{ return getQuantizedFloat(random, min, max, getStep<float>()); }
	};

	// One random range
	T	rLen	= GetRandom()(rnd, T(0), T(8));
	T	rMin	= GetRandom()(rnd, T(-4), T(4));
	T	rMax	= rMin+rLen;

	if (dstMin == false && dstMax == true)
	{
		// Both values are possible, use same range for both inputs
		aMin	= rMin;
		aMax	= rMax;
		bMin	= rMin;
		bMax	= rMax;
	}
	else if (dstMin == true && dstMax == true)
	{
		// Compute range that is less than or equal to rMin..rMax
		T aLen = GetRandom()(rnd, T(0), T(8)-rLen);

		aMax	= rMin;
		aMin	= aMax - aLen;

		bMin	= rMin;
		bMax	= rMax;
	}
	else
	{
		// Compute range that is greater than rMin..rMax
		T aLen = GetRandom()(rnd, T(0), T(8)-rLen);

		aMin	= rMax + getStep<T>();
		aMax	= aMin + aLen;

		bMin	= rMin;
		bMax	= rMax;
	}
}

LessOrEqualOp::LessOrEqualOp (GeneratorState& state, ConstValueRangeAccess valueRange)
	: LessOrEqualBase(state, Token::CMP_LE, valueRange)
{
}

float LessOrEqualOp::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
{
	return LessOrEqualBase::getWeight(state, valueRange);
}

GreaterThanOp::GreaterThanOp (GeneratorState& state, ConstValueRangeAccess valueRange)
	: GreaterThanBase(state, Token::CMP_GT, valueRange)
{
}

float GreaterThanOp::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
{
	return GreaterThanBase::getWeight(state, valueRange);
}

GreaterOrEqualOp::GreaterOrEqualOp (GeneratorState& state, ConstValueRangeAccess valueRange)
	: GreaterOrEqualBase(state, Token::CMP_GE, valueRange)
{
}

float GreaterOrEqualOp::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
{
	return GreaterOrEqualBase::getWeight(state, valueRange);
}

namespace
{

template <bool IsEqual, typename T>
void computeEqualityValueRange (de::Random& rnd, bool dstMin, bool dstMax, T& aMin, T& aMax, T& bMin, T& bMax)
{
	if (dstMin == false && dstMax == true)
		ComputeLessThanRange()(rnd, false, true, aMin, aMax, bMin, bMax);
	else if (IsEqual && dstMin == false)
		ComputeLessThanRange()(rnd, true, true, aMin, aMax, bMin, bMax);
	else if (!IsEqual && dstMin == true)
		ComputeLessThanRange()(rnd, true, true, aMin, aMax, bMin, bMax);
	else
	{
		// Must have exactly same values.
		struct GetRandom
		{
			int		operator() (de::Random& random, int min, int max) const		{ return random.getInt(min, max); }
			float	operator() (de::Random& random, float min, float max) const	{ return getQuantizedFloat(random, min, max, 0.5f); }
		};

		T val = GetRandom()(rnd, T(-1), T(1));

		aMin	= val;
		aMax	= val;
		bMin	= val;
		bMax	= val;
	}
}

template <>
void computeEqualityValueRange<true, bool> (de::Random& rnd, bool dstMin, bool dstMax, bool& aMin, bool& aMax, bool& bMin, bool& bMax)
{
	if (dstMin == false && dstMax == true)
	{
		aMin	= false;
		aMax	= true;
		bMin	= false;
		bMax	= true;
	}
	else if (dstMin == false)
	{
		DE_ASSERT(dstMax == false);
		bool val = rnd.getBool();

		aMin	= val;
		aMax	= val;
		bMin	= !val;
		bMax	= !val;
	}
	else
	{
		DE_ASSERT(dstMin == true && dstMax == true);
		bool val = rnd.getBool();

		aMin	= val;
		aMax	= val;
		bMin	= val;
		bMax	= val;
	}
}

template <>
void computeEqualityValueRange<false, bool> (de::Random& rnd, bool dstMin, bool dstMax, bool& aMin, bool& aMax, bool& bMin, bool& bMax)
{
	if (dstMin == false && dstMax == true)
		computeEqualityValueRange<true>(rnd, dstMin, dstMax, aMin, aMax, bMin, bMax);
	else
		computeEqualityValueRange<true>(rnd, !dstMin, !dstMax, aMin, aMax, bMin, bMax);
}

} // anonymous

template <bool IsEqual>
EqualityComparisonOp<IsEqual>::EqualityComparisonOp (GeneratorState& state, ConstValueRangeAccess inValueRange)
	: BinaryOp<8, ASSOCIATIVITY_LEFT>(IsEqual ? Token::CMP_EQ : Token::CMP_NE)
{
	ValueRange valueRange = inValueRange;

	if (valueRange.getType().isVoid())
	{
		valueRange = ValueRange(VariableType(VariableType::TYPE_BOOL, 1));
		computeRandomValueRange(state, valueRange.asAccess());
	}

	// Choose type, allocate storage for execution
	this->m_type = valueRange.getType();
	this->m_value.setStorage(this->m_type);

	// Choose random input type
	VariableType::Type inBaseTypes[]	= { VariableType::TYPE_FLOAT, VariableType::TYPE_INT };
	VariableType::Type inBaseType		= state.getRandom().choose<VariableType::Type>(&inBaseTypes[0], &inBaseTypes[DE_LENGTH_OF_ARRAY(inBaseTypes)]);
	int					availableLevels	= state.getShaderParameters().maxExpressionDepth - state.getExpressionDepth();
	int					numElements		= state.getRandom().getInt(1, availableLevels >= 3 ? 4 : 1);

	// Initialize storage for input value ranges
	this->m_rightValueRange	= ValueRange(VariableType(inBaseType, numElements));
	this->m_leftValueRange	= ValueRange(VariableType(inBaseType, numElements));

	// Compute range for b that satisfies requested value range
	for (int elementNdx = 0; elementNdx < numElements; elementNdx++)
	{
		bool					dstMin	= valueRange.getMin().asBool();
		bool					dstMax	= valueRange.getMax().asBool();

		ValueRangeAccess		a		= this->m_leftValueRange.asAccess().component(elementNdx);
		ValueRangeAccess		b		= this->m_rightValueRange.asAccess().component(elementNdx);

		if (inBaseType == VariableType::TYPE_FLOAT)
			computeEqualityValueRange<IsEqual>(state.getRandom(), dstMin, dstMax,
											   a.getMin().asFloat(), a.getMax().asFloat(),
											   b.getMin().asFloat(), b.getMax().asFloat());
		else if (inBaseType == VariableType::TYPE_INT)
			computeEqualityValueRange<IsEqual>(state.getRandom(), dstMin, dstMax,
											   a.getMin().asInt(), a.getMax().asInt(),
											   b.getMin().asInt(), b.getMax().asInt());
		else
		{
			DE_ASSERT(inBaseType == VariableType::TYPE_BOOL);
			computeEqualityValueRange<IsEqual>(state.getRandom(), dstMin, dstMax,
											   a.getMin().asBool(), a.getMax().asBool(),
											   b.getMin().asBool(), b.getMax().asBool());
		}
	}
}

template <bool IsEqual>
float EqualityComparisonOp<IsEqual>::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
{
	if (!state.getProgramParameters().useComparisonOps)
		return 0.0f;

	// \todo [2011-06-13 pyry] Weight down cases that would force constant inputs.

	if (valueRange.getType().isVoid() ||
		(valueRange.getType().getBaseType() == VariableType::TYPE_BOOL && valueRange.getType().getNumElements() == 1))
		return BinaryOp<8, ASSOCIATIVITY_LEFT>::getWeight(state, valueRange);
	else
		return 0.0f;
}

namespace
{

template <bool IsEqual>
struct EqualityCompare
{
	template <typename T>
	static bool compare (T a, T b);
	static bool combine (bool a, bool b);
};

template <>
template <typename T>
inline bool EqualityCompare<true>::compare	(T a, T b)			{ return a == b; }

template <>
inline bool EqualityCompare<true>::combine	(bool a, bool b)	{ return a && b; }

template <>
template <typename T>
inline bool EqualityCompare<false>::compare	(T a, T b)			{ return a != b; }

template <>
inline bool EqualityCompare<false>::combine	(bool a, bool b)	{ return a || b; }

} // anonymous

template <bool IsEqual>
void EqualityComparisonOp<IsEqual>::evaluate (ExecValueAccess dst, ExecConstValueAccess a, ExecConstValueAccess b)
{
	DE_ASSERT(a.getType() == b.getType());


	switch (a.getType().getBaseType())
	{
		case VariableType::TYPE_FLOAT:
			for (int compNdx = 0; compNdx < EXEC_VEC_WIDTH; compNdx++)
			{
				bool result = IsEqual ? true : false;

				for (int elemNdx = 0; elemNdx < a.getType().getNumElements(); elemNdx++)
					result = EqualityCompare<IsEqual>::combine(result, EqualityCompare<IsEqual>::compare(a.component(elemNdx).asFloat(compNdx), b.component(elemNdx).asFloat(compNdx)));

				dst.asBool(compNdx) = result;
			}
			break;

		case VariableType::TYPE_INT:
			for (int compNdx = 0; compNdx < EXEC_VEC_WIDTH; compNdx++)
			{
				bool result = IsEqual ? true : false;

				for (int elemNdx = 0; elemNdx < a.getType().getNumElements(); elemNdx++)
					result = EqualityCompare<IsEqual>::combine(result, EqualityCompare<IsEqual>::compare(a.component(elemNdx).asInt(compNdx), b.component(elemNdx).asInt(compNdx)));

				dst.asBool(compNdx) = result;
			}
			break;

		case VariableType::TYPE_BOOL:
			for (int compNdx = 0; compNdx < EXEC_VEC_WIDTH; compNdx++)
			{
				bool result = IsEqual ? true : false;

				for (int elemNdx = 0; elemNdx < a.getType().getNumElements(); elemNdx++)
					result = EqualityCompare<IsEqual>::combine(result, EqualityCompare<IsEqual>::compare(a.component(elemNdx).asBool(compNdx), b.component(elemNdx).asBool(compNdx)));

				dst.asBool(compNdx) = result;
			}
			break;

		default:
			DE_ASSERT(DE_FALSE);
	}
}

EqualOp::EqualOp (GeneratorState& state, ConstValueRangeAccess valueRange)
	: EqualityComparisonOp<true>(state, valueRange)
{
}

float EqualOp::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
{
	return EqualityComparisonOp<true>::getWeight(state, valueRange);
}

NotEqualOp::NotEqualOp (GeneratorState& state, ConstValueRangeAccess valueRange)
	: EqualityComparisonOp<false>(state, valueRange)
{
}

float NotEqualOp::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
{
	return EqualityComparisonOp<false>::getWeight(state, valueRange);
}

} // rsg
