You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
620 lines
18 KiB
620 lines
18 KiB
#ifndef _RSGBUILTINFUNCTIONS_HPP
|
|
#define _RSGBUILTINFUNCTIONS_HPP
|
|
/*-------------------------------------------------------------------------
|
|
* 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 Built-in Functions.
|
|
*//*--------------------------------------------------------------------*/
|
|
|
|
#include "rsgDefs.hpp"
|
|
#include "rsgExpression.hpp"
|
|
#include "rsgUtils.hpp"
|
|
#include "deMath.h"
|
|
|
|
namespace rsg
|
|
{
|
|
|
|
// Template for built-in functions with form "GenType func(GenType val)".
|
|
template <class GetValueRangeWeight, class ComputeValueRange, class Evaluate>
|
|
class UnaryBuiltinVecFunc : public Expression
|
|
{
|
|
public:
|
|
UnaryBuiltinVecFunc (GeneratorState& state, const char* function, ConstValueRangeAccess valueRange);
|
|
virtual ~UnaryBuiltinVecFunc (void);
|
|
|
|
Expression* createNextChild (GeneratorState& state);
|
|
void tokenize (GeneratorState& state, TokenStream& str) const;
|
|
|
|
void evaluate (ExecutionContext& execCtx);
|
|
ExecConstValueAccess getValue (void) const { return m_value.getValue(m_inValueRange.getType()); }
|
|
|
|
static float getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange);
|
|
|
|
private:
|
|
std::string m_function;
|
|
ValueRange m_inValueRange;
|
|
ExecValueStorage m_value;
|
|
Expression* m_child;
|
|
};
|
|
|
|
template <class GetValueRangeWeight, class ComputeValueRange, class Evaluate>
|
|
UnaryBuiltinVecFunc<GetValueRangeWeight, ComputeValueRange, Evaluate>::UnaryBuiltinVecFunc (GeneratorState& state, const char* function, ConstValueRangeAccess valueRange)
|
|
: m_function (function)
|
|
, m_inValueRange (valueRange.getType())
|
|
, m_child (DE_NULL)
|
|
{
|
|
DE_UNREF(state);
|
|
DE_ASSERT(valueRange.getType().isFloatOrVec());
|
|
|
|
m_value.setStorage(valueRange.getType());
|
|
|
|
// Compute input value range
|
|
for (int ndx = 0; ndx < m_inValueRange.getType().getNumElements(); ndx++)
|
|
{
|
|
ConstValueRangeAccess outRange = valueRange.component(ndx);
|
|
ValueRangeAccess inRange = m_inValueRange.asAccess().component(ndx);
|
|
|
|
ComputeValueRange()(outRange.getMin().asFloat(), outRange.getMax().asFloat(), inRange.getMin().asFloat(), inRange.getMax().asFloat());
|
|
}
|
|
}
|
|
|
|
template <class GetValueRangeWeight, class ComputeValueRange, class Evaluate>
|
|
UnaryBuiltinVecFunc<GetValueRangeWeight, ComputeValueRange, Evaluate>::~UnaryBuiltinVecFunc (void)
|
|
{
|
|
delete m_child;
|
|
}
|
|
|
|
template <class GetValueRangeWeight, class ComputeValueRange, class Evaluate>
|
|
Expression* UnaryBuiltinVecFunc<GetValueRangeWeight, ComputeValueRange, Evaluate>::createNextChild (GeneratorState& state)
|
|
{
|
|
if (m_child)
|
|
return DE_NULL;
|
|
|
|
m_child = Expression::createRandom(state, m_inValueRange.asAccess());
|
|
return m_child;
|
|
}
|
|
|
|
template <class GetValueRangeWeight, class ComputeValueRange, class Evaluate>
|
|
void UnaryBuiltinVecFunc<GetValueRangeWeight, ComputeValueRange, Evaluate>::tokenize (GeneratorState& state, TokenStream& str) const
|
|
{
|
|
str << Token(m_function.c_str()) << Token::LEFT_PAREN;
|
|
m_child->tokenize(state, str);
|
|
str << Token::RIGHT_PAREN;
|
|
}
|
|
|
|
template <class GetValueRangeWeight, class ComputeValueRange, class Evaluate>
|
|
void UnaryBuiltinVecFunc<GetValueRangeWeight, ComputeValueRange, Evaluate>::evaluate (ExecutionContext& execCtx)
|
|
{
|
|
m_child->evaluate(execCtx);
|
|
|
|
ExecConstValueAccess srcValue = m_child->getValue();
|
|
ExecValueAccess dstValue = m_value.getValue(m_inValueRange.getType());
|
|
|
|
for (int elemNdx = 0; elemNdx < m_inValueRange.getType().getNumElements(); elemNdx++)
|
|
{
|
|
ExecConstValueAccess srcComp = srcValue.component(elemNdx);
|
|
ExecValueAccess dstComp = dstValue.component(elemNdx);
|
|
|
|
for (int compNdx = 0; compNdx < EXEC_VEC_WIDTH; compNdx++)
|
|
dstComp.asFloat(compNdx) = Evaluate()(srcComp.asFloat(compNdx));
|
|
}
|
|
}
|
|
|
|
template <class GetValueRangeWeight, class ComputeValueRange, class Evaluate>
|
|
float UnaryBuiltinVecFunc<GetValueRangeWeight, ComputeValueRange, Evaluate>::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
|
|
{
|
|
// \todo [2011-06-14 pyry] Void support?
|
|
if (!valueRange.getType().isFloatOrVec())
|
|
return 0.0f;
|
|
|
|
int availableLevels = state.getShaderParameters().maxExpressionDepth - state.getExpressionDepth();
|
|
|
|
if (availableLevels < getConservativeValueExprDepth(state, valueRange) + 1)
|
|
return 0.0f;
|
|
|
|
// Compute value range weight
|
|
float combinedWeight = 1.0f;
|
|
for (int elemNdx = 0; elemNdx < valueRange.getType().getNumElements(); elemNdx++)
|
|
{
|
|
float elemWeight = GetValueRangeWeight()(valueRange.component(elemNdx).getMin().asFloat(), valueRange.component(elemNdx).getMax().asFloat());
|
|
combinedWeight *= elemWeight;
|
|
}
|
|
|
|
return combinedWeight;
|
|
}
|
|
|
|
// Proxy template.
|
|
template <class C>
|
|
struct GetUnaryBuiltinVecWeight
|
|
{
|
|
inline float operator() (float outMin, float outMax) const { return C::getCompWeight(outMin, outMax); }
|
|
};
|
|
|
|
template <class C>
|
|
struct ComputeUnaryBuiltinVecRange
|
|
{
|
|
inline void operator() (float outMin, float outMax, float& inMin, float& inMax) const { C::computeValueRange(outMin, outMax, inMin, inMax); }
|
|
};
|
|
|
|
template <class C>
|
|
struct EvaluateUnaryBuiltinVec
|
|
{
|
|
inline float operator() (float inVal) const { return C::evaluateComp(inVal); }
|
|
};
|
|
|
|
template <class C>
|
|
class UnaryBuiltinVecTemplateProxy : public UnaryBuiltinVecFunc<GetUnaryBuiltinVecWeight<C>, ComputeUnaryBuiltinVecRange<C>, EvaluateUnaryBuiltinVec<C> >
|
|
{
|
|
public:
|
|
UnaryBuiltinVecTemplateProxy (GeneratorState& state, const char* function, ConstValueRangeAccess valueRange)
|
|
: UnaryBuiltinVecFunc<GetUnaryBuiltinVecWeight<C>, ComputeUnaryBuiltinVecRange<C>, EvaluateUnaryBuiltinVec<C> >(state, function, valueRange)
|
|
{
|
|
}
|
|
};
|
|
|
|
// Template for trigonometric function group.
|
|
template <class C>
|
|
class UnaryTrigonometricFunc : public UnaryBuiltinVecTemplateProxy<C>
|
|
{
|
|
public:
|
|
UnaryTrigonometricFunc (GeneratorState& state, const char* function, ConstValueRangeAccess valueRange)
|
|
: UnaryBuiltinVecTemplateProxy<C>(state, function, valueRange)
|
|
{
|
|
}
|
|
|
|
static inline float getCompWeight (float outMin, float outMax)
|
|
{
|
|
if (Scalar::min<float>() == outMin || Scalar::max<float>() == outMax)
|
|
return 1.0f; // Infinite value range, anything goes
|
|
|
|
// Transform range
|
|
float inMin, inMax;
|
|
if (!C::transformValueRange(outMin, outMax, inMin, inMax))
|
|
return 0.0f; // Not possible to transform value range (out of range perhaps)
|
|
|
|
// Quantize
|
|
if (!quantizeFloatRange(inMin, inMax))
|
|
return 0.0f; // Not possible to quantize - would cause accuracy issues
|
|
|
|
if (outMin == outMax)
|
|
return 1.0f; // Constant value and passed quantization
|
|
|
|
// Evaluate new intersection
|
|
float intersectionLen = C::evaluateComp(inMax) - C::evaluateComp(inMin);
|
|
float valRangeLen = outMax - outMin;
|
|
|
|
return deFloatMax(0.1f, intersectionLen/valRangeLen);
|
|
}
|
|
|
|
static inline void computeValueRange (float outMin, float outMax, float& inMin, float& inMax)
|
|
{
|
|
DE_VERIFY(C::transformValueRange(outMin, outMax, inMin, inMax));
|
|
DE_VERIFY(quantizeFloatRange(inMin, inMax));
|
|
DE_ASSERT(inMin <= inMax);
|
|
}
|
|
|
|
static float getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
|
|
{
|
|
if (state.getProgramParameters().trigonometricBaseWeight <= 0.0f)
|
|
return 0.0f;
|
|
|
|
return UnaryBuiltinVecTemplateProxy<C>::getWeight(state, valueRange) * state.getProgramParameters().trigonometricBaseWeight;
|
|
}
|
|
};
|
|
|
|
class SinOp : public UnaryTrigonometricFunc<SinOp>
|
|
{
|
|
public:
|
|
SinOp (GeneratorState& state, ConstValueRangeAccess valueRange)
|
|
: UnaryTrigonometricFunc<SinOp>(state, "sin", valueRange)
|
|
{
|
|
}
|
|
|
|
static inline bool transformValueRange (float outMin, float outMax, float& inMin, float& inMax)
|
|
{
|
|
if (outMax < -1.0f || outMin > 1.0f)
|
|
return false;
|
|
|
|
inMin = (outMin >= -1.0f) ? deFloatAsin(outMin) : -0.5f*DE_PI;
|
|
inMax = (outMax <= +1.0f) ? deFloatAsin(outMax) : +0.5f*DE_PI;
|
|
|
|
return true;
|
|
}
|
|
|
|
static inline float evaluateComp (float inVal)
|
|
{
|
|
return deFloatSin(inVal);
|
|
}
|
|
};
|
|
|
|
class CosOp : public UnaryTrigonometricFunc<CosOp>
|
|
{
|
|
public:
|
|
CosOp (GeneratorState& state, ConstValueRangeAccess valueRange)
|
|
: UnaryTrigonometricFunc<CosOp>(state, "cos", valueRange)
|
|
{
|
|
}
|
|
|
|
static inline bool transformValueRange (float outMin, float outMax, float& inMin, float& inMax)
|
|
{
|
|
if (outMax < -1.0f || outMin > 1.0f)
|
|
return false;
|
|
|
|
inMax = (outMin >= -1.0f) ? deFloatAcos(outMin) : +DE_PI;
|
|
inMin = (outMax <= +1.0f) ? deFloatAcos(outMax) : -DE_PI;
|
|
|
|
return true;
|
|
}
|
|
|
|
static inline float evaluateComp (float inVal)
|
|
{
|
|
return deFloatCos(inVal);
|
|
}
|
|
};
|
|
|
|
class TanOp : public UnaryTrigonometricFunc<TanOp>
|
|
{
|
|
public:
|
|
TanOp (GeneratorState& state, ConstValueRangeAccess valueRange)
|
|
: UnaryTrigonometricFunc<TanOp>(state, "tan", valueRange)
|
|
{
|
|
}
|
|
|
|
static inline bool transformValueRange (float outMin, float outMax, float& inMin, float& inMax)
|
|
{
|
|
// \note Currently tan() is limited to -4..4 range. Otherwise we will run into accuracy issues
|
|
const float rangeMin = -4.0f;
|
|
const float rangeMax = +4.0f;
|
|
|
|
if (outMax < rangeMin || outMin > rangeMax)
|
|
return false;
|
|
|
|
inMin = deFloatAtanOver(deFloatMax(outMin, rangeMin));
|
|
inMax = deFloatAtanOver(deFloatMin(outMax, rangeMax));
|
|
|
|
return true;
|
|
}
|
|
|
|
static inline float evaluateComp (float inVal)
|
|
{
|
|
return deFloatTan(inVal);
|
|
}
|
|
};
|
|
|
|
class AsinOp : public UnaryTrigonometricFunc<AsinOp>
|
|
{
|
|
public:
|
|
AsinOp (GeneratorState& state, ConstValueRangeAccess valueRange)
|
|
: UnaryTrigonometricFunc<AsinOp>(state, "asin", valueRange)
|
|
{
|
|
}
|
|
|
|
static inline bool transformValueRange (float outMin, float outMax, float& inMin, float& inMax)
|
|
{
|
|
const float rangeMin = -DE_PI/2.0f;
|
|
const float rangeMax = +DE_PI/2.0f;
|
|
|
|
if (outMax < rangeMin || outMin > rangeMax)
|
|
return false; // Out of range
|
|
|
|
inMin = deFloatSin(deFloatMax(outMin, rangeMin));
|
|
inMax = deFloatSin(deFloatMin(outMax, rangeMax));
|
|
|
|
return true;
|
|
}
|
|
|
|
static inline float evaluateComp (float inVal)
|
|
{
|
|
return deFloatAsin(inVal);
|
|
}
|
|
};
|
|
|
|
class AcosOp : public UnaryTrigonometricFunc<AcosOp>
|
|
{
|
|
public:
|
|
AcosOp (GeneratorState& state, ConstValueRangeAccess valueRange)
|
|
: UnaryTrigonometricFunc<AcosOp>(state, "acos", valueRange)
|
|
{
|
|
}
|
|
|
|
static inline bool transformValueRange (float outMin, float outMax, float& inMin, float& inMax)
|
|
{
|
|
const float rangeMin = 0.0f;
|
|
const float rangeMax = DE_PI;
|
|
|
|
if (outMax < rangeMin || outMin > rangeMax)
|
|
return false; // Out of range
|
|
|
|
inMax = deFloatCos(deFloatMax(outMin, rangeMin));
|
|
inMin = deFloatCos(deFloatMin(outMax, rangeMax));
|
|
|
|
return true;
|
|
}
|
|
|
|
static inline float evaluateComp (float inVal)
|
|
{
|
|
return deFloatAcos(inVal);
|
|
}
|
|
};
|
|
|
|
class AtanOp : public UnaryTrigonometricFunc<AtanOp>
|
|
{
|
|
public:
|
|
AtanOp (GeneratorState& state, ConstValueRangeAccess valueRange)
|
|
: UnaryTrigonometricFunc<AtanOp>(state, "atan", valueRange)
|
|
{
|
|
}
|
|
|
|
static inline bool transformValueRange (float outMin, float outMax, float& inMin, float& inMax)
|
|
{
|
|
// \note For accuracy reasons output range is limited to -1..1
|
|
const float rangeMin = -1.0f;
|
|
const float rangeMax = +1.0f;
|
|
|
|
if (outMax < rangeMin || outMin > rangeMax)
|
|
return false; // Out of range
|
|
|
|
inMin = deFloatTan(deFloatMax(outMin, rangeMin));
|
|
inMax = deFloatTan(deFloatMin(outMax, rangeMax));
|
|
|
|
return true;
|
|
}
|
|
|
|
static inline float evaluateComp (float inVal)
|
|
{
|
|
return deFloatAtanOver(inVal);
|
|
}
|
|
};
|
|
|
|
// Template for exponential function group.
|
|
// \todo [2011-07-07 pyry] Shares most of the code with Trigonometric variant..
|
|
template <class C>
|
|
class UnaryExponentialFunc : public UnaryBuiltinVecTemplateProxy<C>
|
|
{
|
|
public:
|
|
UnaryExponentialFunc (GeneratorState& state, const char* function, ConstValueRangeAccess valueRange)
|
|
: UnaryBuiltinVecTemplateProxy<C>(state, function, valueRange)
|
|
{
|
|
}
|
|
|
|
static inline float getCompWeight (float outMin, float outMax)
|
|
{
|
|
if (Scalar::min<float>() == outMin || Scalar::max<float>() == outMax)
|
|
return 1.0f; // Infinite value range, anything goes
|
|
|
|
// Transform range
|
|
float inMin, inMax;
|
|
if (!C::transformValueRange(outMin, outMax, inMin, inMax))
|
|
return 0.0f; // Not possible to transform value range (out of range perhaps)
|
|
|
|
// Quantize
|
|
if (!quantizeFloatRange(inMin, inMax))
|
|
return 0.0f; // Not possible to quantize - would cause accuracy issues
|
|
|
|
if (outMin == outMax)
|
|
return 1.0f; // Constant value and passed quantization
|
|
|
|
// Evaluate new intersection
|
|
float intersectionLen = C::evaluateComp(inMax) - C::evaluateComp(inMin);
|
|
float valRangeLen = outMax - outMin;
|
|
|
|
return deFloatMax(0.1f, intersectionLen/valRangeLen);
|
|
}
|
|
|
|
static inline void computeValueRange (float outMin, float outMax, float& inMin, float& inMax)
|
|
{
|
|
DE_VERIFY(C::transformValueRange(outMin, outMax, inMin, inMax));
|
|
DE_VERIFY(quantizeFloatRange(inMin, inMax));
|
|
DE_ASSERT(inMin <= inMax);
|
|
}
|
|
|
|
static float getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
|
|
{
|
|
if (state.getProgramParameters().exponentialBaseWeight <= 0.0f)
|
|
return 0.0f;
|
|
|
|
return UnaryBuiltinVecTemplateProxy<C>::getWeight(state, valueRange) * state.getProgramParameters().exponentialBaseWeight;
|
|
}
|
|
};
|
|
|
|
class ExpOp : public UnaryExponentialFunc<ExpOp>
|
|
{
|
|
public:
|
|
ExpOp (GeneratorState& state, ConstValueRangeAccess valueRange)
|
|
: UnaryExponentialFunc<ExpOp>(state, "exp", valueRange)
|
|
{
|
|
}
|
|
|
|
static inline bool transformValueRange (float outMin, float outMax, float& inMin, float& inMax)
|
|
{
|
|
// Limited due to accuracy reasons, should be 0..+inf
|
|
const float rangeMin = 0.1f;
|
|
const float rangeMax = 10.0f;
|
|
|
|
if (outMax < rangeMin || outMin > rangeMax)
|
|
return false; // Out of range
|
|
|
|
inMin = deFloatLog(deFloatMax(outMin, rangeMin));
|
|
inMax = deFloatLog(deFloatMin(outMax, rangeMax));
|
|
|
|
return true;
|
|
}
|
|
|
|
static inline float evaluateComp (float inVal)
|
|
{
|
|
return deFloatExp(inVal);
|
|
}
|
|
};
|
|
|
|
class LogOp : public UnaryExponentialFunc<LogOp>
|
|
{
|
|
public:
|
|
LogOp (GeneratorState& state, ConstValueRangeAccess valueRange)
|
|
: UnaryExponentialFunc<LogOp>(state, "log", valueRange)
|
|
{
|
|
}
|
|
|
|
static inline bool transformValueRange (float outMin, float outMax, float& inMin, float& inMax)
|
|
{
|
|
// Limited due to accuracy reasons, should be -inf..+inf
|
|
const float rangeMin = 0.1f;
|
|
const float rangeMax = 6.0f;
|
|
|
|
if (outMax < rangeMin || outMin > rangeMax)
|
|
return false; // Out of range
|
|
|
|
inMin = deFloatExp(deFloatMax(outMin, rangeMin));
|
|
inMax = deFloatExp(deFloatMin(outMax, rangeMax));
|
|
|
|
return true;
|
|
}
|
|
|
|
static inline float evaluateComp (float inVal)
|
|
{
|
|
return deFloatLog(inVal);
|
|
}
|
|
};
|
|
|
|
class Exp2Op : public UnaryExponentialFunc<Exp2Op>
|
|
{
|
|
public:
|
|
Exp2Op (GeneratorState& state, ConstValueRangeAccess valueRange)
|
|
: UnaryExponentialFunc<Exp2Op>(state, "exp2", valueRange)
|
|
{
|
|
}
|
|
|
|
static inline bool transformValueRange (float outMin, float outMax, float& inMin, float& inMax)
|
|
{
|
|
// Limited due to accuracy reasons, should be 0..+inf
|
|
const float rangeMin = 0.1f;
|
|
const float rangeMax = 10.0f;
|
|
|
|
if (outMax < rangeMin || outMin > rangeMax)
|
|
return false; // Out of range
|
|
|
|
inMin = deFloatLog2(deFloatMax(outMin, rangeMin));
|
|
inMax = deFloatLog2(deFloatMin(outMax, rangeMax));
|
|
|
|
return true;
|
|
}
|
|
|
|
static inline float evaluateComp (float inVal)
|
|
{
|
|
return deFloatExp2(inVal);
|
|
}
|
|
};
|
|
|
|
class Log2Op : public UnaryExponentialFunc<Log2Op>
|
|
{
|
|
public:
|
|
Log2Op (GeneratorState& state, ConstValueRangeAccess valueRange)
|
|
: UnaryExponentialFunc<Log2Op>(state, "log2", valueRange)
|
|
{
|
|
}
|
|
|
|
static inline bool transformValueRange (float outMin, float outMax, float& inMin, float& inMax)
|
|
{
|
|
// Limited due to accuracy reasons, should be -inf..+inf
|
|
const float rangeMin = 0.1f;
|
|
const float rangeMax = 6.0f;
|
|
|
|
if (outMax < rangeMin || outMin > rangeMax)
|
|
return false; // Out of range
|
|
|
|
inMin = deFloatExp2(deFloatMax(outMin, rangeMin));
|
|
inMax = deFloatExp2(deFloatMin(outMax, rangeMax));
|
|
|
|
return true;
|
|
}
|
|
|
|
static inline float evaluateComp (float inVal)
|
|
{
|
|
return deFloatLog2(inVal);
|
|
}
|
|
};
|
|
|
|
class SqrtOp : public UnaryExponentialFunc<SqrtOp>
|
|
{
|
|
public:
|
|
SqrtOp (GeneratorState& state, ConstValueRangeAccess valueRange)
|
|
: UnaryExponentialFunc<SqrtOp>(state, "sqrt", valueRange)
|
|
{
|
|
}
|
|
|
|
static inline bool transformValueRange (float outMin, float outMax, float& inMin, float& inMax)
|
|
{
|
|
// Limited due to accuracy reasons, should be 0..+inf
|
|
const float rangeMin = 0.0f;
|
|
const float rangeMax = 4.0f;
|
|
|
|
if (outMax < rangeMin || outMin > rangeMax)
|
|
return false; // Out of range
|
|
|
|
inMin = deFloatMax(outMin, rangeMin);
|
|
inMax = deFloatMin(outMax, rangeMax);
|
|
|
|
inMin *= inMin;
|
|
inMax *= inMax;
|
|
|
|
return true;
|
|
}
|
|
|
|
static inline float evaluateComp (float inVal)
|
|
{
|
|
return deFloatSqrt(inVal);
|
|
}
|
|
};
|
|
|
|
class InvSqrtOp : public UnaryExponentialFunc<InvSqrtOp>
|
|
{
|
|
public:
|
|
InvSqrtOp (GeneratorState& state, ConstValueRangeAccess valueRange)
|
|
: UnaryExponentialFunc<InvSqrtOp>(state, "inversesqrt", valueRange)
|
|
{
|
|
}
|
|
|
|
static inline bool transformValueRange (float outMin, float outMax, float& inMin, float& inMax)
|
|
{
|
|
// Limited due to accuracy reasons
|
|
const float rangeMin = 0.4f;
|
|
const float rangeMax = 3.0f;
|
|
|
|
if (outMax < rangeMin || outMin > rangeMax)
|
|
return false; // Out of range
|
|
|
|
inMax = 1.0f/deFloatMax(outMin, rangeMin);
|
|
inMin = 1.0f/deFloatMin(outMax, rangeMax);
|
|
|
|
inMin *= inMin;
|
|
inMax *= inMax;
|
|
|
|
return true;
|
|
}
|
|
|
|
static inline float evaluateComp (float inVal)
|
|
{
|
|
return 1.0f/deFloatSqrt(inVal);
|
|
}
|
|
};
|
|
|
|
} // rsg
|
|
|
|
#endif // _RSGBUILTINFUNCTIONS_HPP
|