1 #ifndef _RSGBUILTINFUNCTIONS_HPP
2 #define _RSGBUILTINFUNCTIONS_HPP
3 /*-------------------------------------------------------------------------
4  * drawElements Quality Program Random Shader Generator
5  * ----------------------------------------------------
6  *
7  * Copyright 2014 The Android Open Source Project
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Built-in Functions.
24  *//*--------------------------------------------------------------------*/
25 
26 #include "rsgDefs.hpp"
27 #include "rsgExpression.hpp"
28 #include "rsgUtils.hpp"
29 #include "deMath.h"
30 
31 namespace rsg
32 {
33 
34 // Template for built-in functions with form "GenType func(GenType val)".
35 template <class GetValueRangeWeight, class ComputeValueRange, class Evaluate>
36 class UnaryBuiltinVecFunc : public Expression
37 {
38 public:
39 								UnaryBuiltinVecFunc		(GeneratorState& state, const char* function, ConstValueRangeAccess valueRange);
40 	virtual						~UnaryBuiltinVecFunc	(void);
41 
42 	Expression*					createNextChild			(GeneratorState& state);
43 	void						tokenize				(GeneratorState& state, TokenStream& str) const;
44 
45 	void						evaluate				(ExecutionContext& execCtx);
getValue(void) const46 	ExecConstValueAccess		getValue				(void) const { return m_value.getValue(m_inValueRange.getType()); }
47 
48 	static float				getWeight				(const GeneratorState& state, ConstValueRangeAccess valueRange);
49 
50 private:
51 	std::string					m_function;
52 	ValueRange					m_inValueRange;
53 	ExecValueStorage			m_value;
54 	Expression*					m_child;
55 };
56 
57 template <class GetValueRangeWeight, class ComputeValueRange, class Evaluate>
UnaryBuiltinVecFunc(GeneratorState & state,const char * function,ConstValueRangeAccess valueRange)58 UnaryBuiltinVecFunc<GetValueRangeWeight, ComputeValueRange, Evaluate>::UnaryBuiltinVecFunc (GeneratorState& state, const char* function, ConstValueRangeAccess valueRange)
59 	: m_function		(function)
60 	, m_inValueRange	(valueRange.getType())
61 	, m_child			(DE_NULL)
62 {
63 	DE_UNREF(state);
64 	DE_ASSERT(valueRange.getType().isFloatOrVec());
65 
66 	m_value.setStorage(valueRange.getType());
67 
68 	// Compute input value range
69 	for (int ndx = 0; ndx < m_inValueRange.getType().getNumElements(); ndx++)
70 	{
71 		ConstValueRangeAccess	outRange	= valueRange.component(ndx);
72 		ValueRangeAccess		inRange		= m_inValueRange.asAccess().component(ndx);
73 
74 		ComputeValueRange()(outRange.getMin().asFloat(), outRange.getMax().asFloat(), inRange.getMin().asFloat(), inRange.getMax().asFloat());
75 	}
76 }
77 
78 template <class GetValueRangeWeight, class ComputeValueRange, class Evaluate>
~UnaryBuiltinVecFunc(void)79 UnaryBuiltinVecFunc<GetValueRangeWeight, ComputeValueRange, Evaluate>::~UnaryBuiltinVecFunc (void)
80 {
81 	delete m_child;
82 }
83 
84 template <class GetValueRangeWeight, class ComputeValueRange, class Evaluate>
createNextChild(GeneratorState & state)85 Expression* UnaryBuiltinVecFunc<GetValueRangeWeight, ComputeValueRange, Evaluate>::createNextChild (GeneratorState& state)
86 {
87 	if (m_child)
88 		return DE_NULL;
89 
90 	m_child = Expression::createRandom(state, m_inValueRange);
91 	return m_child;
92 }
93 
94 template <class GetValueRangeWeight, class ComputeValueRange, class Evaluate>
tokenize(GeneratorState & state,TokenStream & str) const95 void UnaryBuiltinVecFunc<GetValueRangeWeight, ComputeValueRange, Evaluate>::tokenize (GeneratorState& state, TokenStream& str) const
96 {
97 	str << Token(m_function.c_str()) << Token::LEFT_PAREN;
98 	m_child->tokenize(state, str);
99 	str << Token::RIGHT_PAREN;
100 }
101 
102 template <class GetValueRangeWeight, class ComputeValueRange, class Evaluate>
evaluate(ExecutionContext & execCtx)103 void UnaryBuiltinVecFunc<GetValueRangeWeight, ComputeValueRange, Evaluate>::evaluate (ExecutionContext& execCtx)
104 {
105 	m_child->evaluate(execCtx);
106 
107 	ExecConstValueAccess	srcValue	= m_child->getValue();
108 	ExecValueAccess			dstValue	= m_value.getValue(m_inValueRange.getType());
109 
110 	for (int elemNdx = 0; elemNdx < m_inValueRange.getType().getNumElements(); elemNdx++)
111 	{
112 		ExecConstValueAccess	srcComp		= srcValue.component(elemNdx);
113 		ExecValueAccess			dstComp		= dstValue.component(elemNdx);
114 
115 		for (int compNdx = 0; compNdx < EXEC_VEC_WIDTH; compNdx++)
116 			dstComp.asFloat(compNdx) = Evaluate()(srcComp.asFloat(compNdx));
117 	}
118 }
119 
120 template <class GetValueRangeWeight, class ComputeValueRange, class Evaluate>
getWeight(const GeneratorState & state,ConstValueRangeAccess valueRange)121 float UnaryBuiltinVecFunc<GetValueRangeWeight, ComputeValueRange, Evaluate>::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
122 {
123 	// \todo [2011-06-14 pyry] Void support?
124 	if (!valueRange.getType().isFloatOrVec())
125 		return 0.0f;
126 
127 	int availableLevels = state.getShaderParameters().maxExpressionDepth - state.getExpressionDepth();
128 
129 	if (availableLevels < getConservativeValueExprDepth(state, valueRange) + 1)
130 		return 0.0f;
131 
132 	// Compute value range weight
133 	float combinedWeight = 1.0f;
134 	for (int elemNdx = 0; elemNdx < valueRange.getType().getNumElements(); elemNdx++)
135 	{
136 		float elemWeight = GetValueRangeWeight()(valueRange.component(elemNdx).getMin().asFloat(), valueRange.component(elemNdx).getMax().asFloat());
137 		combinedWeight *= elemWeight;
138 	}
139 
140 	return combinedWeight;
141 }
142 
143 // Proxy template.
144 template <class C>
145 struct GetUnaryBuiltinVecWeight
146 {
operator ()rsg::GetUnaryBuiltinVecWeight147 	inline float operator() (float outMin, float outMax) const { return C::getCompWeight(outMin, outMax); }
148 };
149 
150 template <class C>
151 struct ComputeUnaryBuiltinVecRange
152 {
operator ()rsg::ComputeUnaryBuiltinVecRange153 	inline void operator() (float outMin, float outMax, float& inMin, float& inMax) const { C::computeValueRange(outMin, outMax, inMin, inMax); }
154 };
155 
156 template <class C>
157 struct EvaluateUnaryBuiltinVec
158 {
operator ()rsg::EvaluateUnaryBuiltinVec159 	inline float operator() (float inVal) const { return C::evaluateComp(inVal); }
160 };
161 
162 template <class C>
163 class UnaryBuiltinVecTemplateProxy : public UnaryBuiltinVecFunc<GetUnaryBuiltinVecWeight<C>, ComputeUnaryBuiltinVecRange<C>, EvaluateUnaryBuiltinVec<C> >
164 {
165 public:
UnaryBuiltinVecTemplateProxy(GeneratorState & state,const char * function,ConstValueRangeAccess valueRange)166 	UnaryBuiltinVecTemplateProxy (GeneratorState& state, const char* function, ConstValueRangeAccess valueRange)
167 		: UnaryBuiltinVecFunc<GetUnaryBuiltinVecWeight<C>, ComputeUnaryBuiltinVecRange<C>, EvaluateUnaryBuiltinVec<C> >(state, function, valueRange)
168 	{
169 	}
170 };
171 
172 // Template for trigonometric function group.
173 template <class C>
174 class UnaryTrigonometricFunc : public UnaryBuiltinVecTemplateProxy<C>
175 {
176 public:
UnaryTrigonometricFunc(GeneratorState & state,const char * function,ConstValueRangeAccess valueRange)177 	UnaryTrigonometricFunc (GeneratorState& state, const char* function, ConstValueRangeAccess valueRange)
178 		: UnaryBuiltinVecTemplateProxy<C>(state, function, valueRange)
179 	{
180 	}
181 
getCompWeight(float outMin,float outMax)182 	static inline float getCompWeight (float outMin, float outMax)
183 	{
184 		if (Scalar::min<float>() == outMin || Scalar::max<float>() == outMax)
185 			return 1.0f; // Infinite value range, anything goes
186 
187 		// Transform range
188 		float inMin, inMax;
189 		if (!C::transformValueRange(outMin, outMax, inMin, inMax))
190 			return 0.0f; // Not possible to transform value range (out of range perhaps)
191 
192 		// Quantize
193 		if (!quantizeFloatRange(inMin, inMax))
194 			return 0.0f; // Not possible to quantize - would cause accuracy issues
195 
196 		if (outMin == outMax)
197 			return 1.0f; // Constant value and passed quantization
198 
199 		// Evaluate new intersection
200 		float intersectionLen	= C::evaluateComp(inMax) - C::evaluateComp(inMin);
201 		float valRangeLen		= outMax - outMin;
202 
203 		return deFloatMax(0.1f, intersectionLen/valRangeLen);
204 	}
205 
computeValueRange(float outMin,float outMax,float & inMin,float & inMax)206 	static inline void computeValueRange (float outMin, float outMax, float& inMin, float& inMax)
207 	{
208 		DE_VERIFY(C::transformValueRange(outMin, outMax, inMin, inMax));
209 		DE_VERIFY(quantizeFloatRange(inMin, inMax));
210 		DE_ASSERT(inMin <= inMax);
211 	}
212 
getWeight(const GeneratorState & state,ConstValueRangeAccess valueRange)213 	static float getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
214 	{
215 		if (state.getProgramParameters().trigonometricBaseWeight <= 0.0f)
216 			return 0.0f;
217 
218 		return UnaryBuiltinVecTemplateProxy<C>::getWeight(state, valueRange) * state.getProgramParameters().trigonometricBaseWeight;
219 	}
220 };
221 
222 class SinOp : public UnaryTrigonometricFunc<SinOp>
223 {
224 public:
SinOp(GeneratorState & state,ConstValueRangeAccess valueRange)225 	SinOp (GeneratorState& state, ConstValueRangeAccess valueRange)
226 		: UnaryTrigonometricFunc<SinOp>(state, "sin", valueRange)
227 	{
228 	}
229 
transformValueRange(float outMin,float outMax,float & inMin,float & inMax)230 	static inline bool transformValueRange (float outMin, float outMax, float& inMin, float& inMax)
231 	{
232 		if (outMax < -1.0f || outMin > 1.0f)
233 			return false;
234 
235 		inMin = (outMin >= -1.0f) ? deFloatAsin(outMin) : -0.5f*DE_PI;
236 		inMax = (outMax <= +1.0f) ? deFloatAsin(outMax) : +0.5f*DE_PI;
237 
238 		return true;
239 	}
240 
evaluateComp(float inVal)241 	static inline float evaluateComp (float inVal)
242 	{
243 		return deFloatSin(inVal);
244 	}
245 };
246 
247 class CosOp : public UnaryTrigonometricFunc<CosOp>
248 {
249 public:
CosOp(GeneratorState & state,ConstValueRangeAccess valueRange)250 	CosOp (GeneratorState& state, ConstValueRangeAccess valueRange)
251 		: UnaryTrigonometricFunc<CosOp>(state, "cos", valueRange)
252 	{
253 	}
254 
transformValueRange(float outMin,float outMax,float & inMin,float & inMax)255 	static inline bool transformValueRange (float outMin, float outMax, float& inMin, float& inMax)
256 	{
257 		if (outMax < -1.0f || outMin > 1.0f)
258 			return false;
259 
260 		inMax = (outMin >= -1.0f) ? deFloatAcos(outMin) : +DE_PI;
261 		inMin = (outMax <= +1.0f) ? deFloatAcos(outMax) : -DE_PI;
262 
263 		return true;
264 	}
265 
evaluateComp(float inVal)266 	static inline float evaluateComp (float inVal)
267 	{
268 		return deFloatCos(inVal);
269 	}
270 };
271 
272 class TanOp : public UnaryTrigonometricFunc<TanOp>
273 {
274 public:
TanOp(GeneratorState & state,ConstValueRangeAccess valueRange)275 	TanOp (GeneratorState& state, ConstValueRangeAccess valueRange)
276 		: UnaryTrigonometricFunc<TanOp>(state, "tan", valueRange)
277 	{
278 	}
279 
transformValueRange(float outMin,float outMax,float & inMin,float & inMax)280 	static inline bool transformValueRange (float outMin, float outMax, float& inMin, float& inMax)
281 	{
282 		// \note Currently tan() is limited to -4..4 range. Otherwise we will run into accuracy issues
283 		const float rangeMin = -4.0f;
284 		const float rangeMax = +4.0f;
285 
286 		if (outMax < rangeMin || outMin > rangeMax)
287 			return false;
288 
289 		inMin = deFloatAtanOver(deFloatMax(outMin, rangeMin));
290 		inMax = deFloatAtanOver(deFloatMin(outMax, rangeMax));
291 
292 		return true;
293 	}
294 
evaluateComp(float inVal)295 	static inline float evaluateComp (float inVal)
296 	{
297 		return deFloatTan(inVal);
298 	}
299 };
300 
301 class AsinOp : public UnaryTrigonometricFunc<AsinOp>
302 {
303 public:
AsinOp(GeneratorState & state,ConstValueRangeAccess valueRange)304 	AsinOp (GeneratorState& state, ConstValueRangeAccess valueRange)
305 		: UnaryTrigonometricFunc<AsinOp>(state, "asin", valueRange)
306 	{
307 	}
308 
transformValueRange(float outMin,float outMax,float & inMin,float & inMax)309 	static inline bool transformValueRange (float outMin, float outMax, float& inMin, float& inMax)
310 	{
311 		const float rangeMin = -DE_PI/2.0f;
312 		const float rangeMax = +DE_PI/2.0f;
313 
314 		if (outMax < rangeMin || outMin > rangeMax)
315 			return false; // Out of range
316 
317 		inMin = deFloatSin(deFloatMax(outMin, rangeMin));
318 		inMax = deFloatSin(deFloatMin(outMax, rangeMax));
319 
320 		return true;
321 	}
322 
evaluateComp(float inVal)323 	static inline float evaluateComp (float inVal)
324 	{
325 		return deFloatAsin(inVal);
326 	}
327 };
328 
329 class AcosOp : public UnaryTrigonometricFunc<AcosOp>
330 {
331 public:
AcosOp(GeneratorState & state,ConstValueRangeAccess valueRange)332 	AcosOp (GeneratorState& state, ConstValueRangeAccess valueRange)
333 		: UnaryTrigonometricFunc<AcosOp>(state, "acos", valueRange)
334 	{
335 	}
336 
transformValueRange(float outMin,float outMax,float & inMin,float & inMax)337 	static inline bool transformValueRange (float outMin, float outMax, float& inMin, float& inMax)
338 	{
339 		const float rangeMin = 0.0f;
340 		const float rangeMax = DE_PI;
341 
342 		if (outMax < rangeMin || outMin > rangeMax)
343 			return false; // Out of range
344 
345 		inMax = deFloatCos(deFloatMax(outMin, rangeMin));
346 		inMin = deFloatCos(deFloatMin(outMax, rangeMax));
347 
348 		return true;
349 	}
350 
evaluateComp(float inVal)351 	static inline float evaluateComp (float inVal)
352 	{
353 		return deFloatAcos(inVal);
354 	}
355 };
356 
357 class AtanOp : public UnaryTrigonometricFunc<AtanOp>
358 {
359 public:
AtanOp(GeneratorState & state,ConstValueRangeAccess valueRange)360 	AtanOp (GeneratorState& state, ConstValueRangeAccess valueRange)
361 		: UnaryTrigonometricFunc<AtanOp>(state, "atan", valueRange)
362 	{
363 	}
364 
transformValueRange(float outMin,float outMax,float & inMin,float & inMax)365 	static inline bool transformValueRange (float outMin, float outMax, float& inMin, float& inMax)
366 	{
367 		// \note For accuracy reasons output range is limited to -1..1
368 		const float rangeMin = -1.0f;
369 		const float rangeMax = +1.0f;
370 
371 		if (outMax < rangeMin || outMin > rangeMax)
372 			return false; // Out of range
373 
374 		inMin = deFloatTan(deFloatMax(outMin, rangeMin));
375 		inMax = deFloatTan(deFloatMin(outMax, rangeMax));
376 
377 		return true;
378 	}
379 
evaluateComp(float inVal)380 	static inline float evaluateComp (float inVal)
381 	{
382 		return deFloatAtanOver(inVal);
383 	}
384 };
385 
386 // Template for exponential function group.
387 // \todo [2011-07-07 pyry] Shares most of the code with Trigonometric variant..
388 template <class C>
389 class UnaryExponentialFunc : public UnaryBuiltinVecTemplateProxy<C>
390 {
391 public:
UnaryExponentialFunc(GeneratorState & state,const char * function,ConstValueRangeAccess valueRange)392 	UnaryExponentialFunc (GeneratorState& state, const char* function, ConstValueRangeAccess valueRange)
393 		: UnaryBuiltinVecTemplateProxy<C>(state, function, valueRange)
394 	{
395 	}
396 
getCompWeight(float outMin,float outMax)397 	static inline float getCompWeight (float outMin, float outMax)
398 	{
399 		if (Scalar::min<float>() == outMin || Scalar::max<float>() == outMax)
400 			return 1.0f; // Infinite value range, anything goes
401 
402 		// Transform range
403 		float inMin, inMax;
404 		if (!C::transformValueRange(outMin, outMax, inMin, inMax))
405 			return 0.0f; // Not possible to transform value range (out of range perhaps)
406 
407 		// Quantize
408 		if (!quantizeFloatRange(inMin, inMax))
409 			return 0.0f; // Not possible to quantize - would cause accuracy issues
410 
411 		if (outMin == outMax)
412 			return 1.0f; // Constant value and passed quantization
413 
414 		// Evaluate new intersection
415 		float intersectionLen	= C::evaluateComp(inMax) - C::evaluateComp(inMin);
416 		float valRangeLen		= outMax - outMin;
417 
418 		return deFloatMax(0.1f, intersectionLen/valRangeLen);
419 	}
420 
computeValueRange(float outMin,float outMax,float & inMin,float & inMax)421 	static inline void computeValueRange (float outMin, float outMax, float& inMin, float& inMax)
422 	{
423 		DE_VERIFY(C::transformValueRange(outMin, outMax, inMin, inMax));
424 		DE_VERIFY(quantizeFloatRange(inMin, inMax));
425 		DE_ASSERT(inMin <= inMax);
426 	}
427 
getWeight(const GeneratorState & state,ConstValueRangeAccess valueRange)428 	static float getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
429 	{
430 		if (state.getProgramParameters().exponentialBaseWeight <= 0.0f)
431 			return 0.0f;
432 
433 		return UnaryBuiltinVecTemplateProxy<C>::getWeight(state, valueRange) * state.getProgramParameters().exponentialBaseWeight;
434 	}
435 };
436 
437 class ExpOp : public UnaryExponentialFunc<ExpOp>
438 {
439 public:
ExpOp(GeneratorState & state,ConstValueRangeAccess valueRange)440 	ExpOp (GeneratorState& state, ConstValueRangeAccess valueRange)
441 		: UnaryExponentialFunc<ExpOp>(state, "exp", valueRange)
442 	{
443 	}
444 
transformValueRange(float outMin,float outMax,float & inMin,float & inMax)445 	static inline bool transformValueRange (float outMin, float outMax, float& inMin, float& inMax)
446 	{
447 		// Limited due to accuracy reasons, should be 0..+inf
448 		const float rangeMin = 0.1f;
449 		const float rangeMax = 10.0f;
450 
451 		if (outMax < rangeMin || outMin > rangeMax)
452 			return false; // Out of range
453 
454 		inMin = deFloatLog(deFloatMax(outMin, rangeMin));
455 		inMax = deFloatLog(deFloatMin(outMax, rangeMax));
456 
457 		return true;
458 	}
459 
evaluateComp(float inVal)460 	static inline float evaluateComp (float inVal)
461 	{
462 		return deFloatExp(inVal);
463 	}
464 };
465 
466 class LogOp : public UnaryExponentialFunc<LogOp>
467 {
468 public:
LogOp(GeneratorState & state,ConstValueRangeAccess valueRange)469 	LogOp (GeneratorState& state, ConstValueRangeAccess valueRange)
470 		: UnaryExponentialFunc<LogOp>(state, "log", valueRange)
471 	{
472 	}
473 
transformValueRange(float outMin,float outMax,float & inMin,float & inMax)474 	static inline bool transformValueRange (float outMin, float outMax, float& inMin, float& inMax)
475 	{
476 		// Limited due to accuracy reasons, should be -inf..+inf
477 		const float rangeMin = 0.1f;
478 		const float rangeMax = 6.0f;
479 
480 		if (outMax < rangeMin || outMin > rangeMax)
481 			return false; // Out of range
482 
483 		inMin = deFloatExp(deFloatMax(outMin, rangeMin));
484 		inMax = deFloatExp(deFloatMin(outMax, rangeMax));
485 
486 		return true;
487 	}
488 
evaluateComp(float inVal)489 	static inline float evaluateComp (float inVal)
490 	{
491 		return deFloatLog(inVal);
492 	}
493 };
494 
495 class Exp2Op : public UnaryExponentialFunc<Exp2Op>
496 {
497 public:
Exp2Op(GeneratorState & state,ConstValueRangeAccess valueRange)498 	Exp2Op (GeneratorState& state, ConstValueRangeAccess valueRange)
499 		: UnaryExponentialFunc<Exp2Op>(state, "exp2", valueRange)
500 	{
501 	}
502 
transformValueRange(float outMin,float outMax,float & inMin,float & inMax)503 	static inline bool transformValueRange (float outMin, float outMax, float& inMin, float& inMax)
504 	{
505 		// Limited due to accuracy reasons, should be 0..+inf
506 		const float rangeMin = 0.1f;
507 		const float rangeMax = 10.0f;
508 
509 		if (outMax < rangeMin || outMin > rangeMax)
510 			return false; // Out of range
511 
512 		inMin = deFloatLog2(deFloatMax(outMin, rangeMin));
513 		inMax = deFloatLog2(deFloatMin(outMax, rangeMax));
514 
515 		return true;
516 	}
517 
evaluateComp(float inVal)518 	static inline float evaluateComp (float inVal)
519 	{
520 		return deFloatExp2(inVal);
521 	}
522 };
523 
524 class Log2Op : public UnaryExponentialFunc<Log2Op>
525 {
526 public:
Log2Op(GeneratorState & state,ConstValueRangeAccess valueRange)527 	Log2Op (GeneratorState& state, ConstValueRangeAccess valueRange)
528 		: UnaryExponentialFunc<Log2Op>(state, "log2", valueRange)
529 	{
530 	}
531 
transformValueRange(float outMin,float outMax,float & inMin,float & inMax)532 	static inline bool transformValueRange (float outMin, float outMax, float& inMin, float& inMax)
533 	{
534 		// Limited due to accuracy reasons, should be -inf..+inf
535 		const float rangeMin = 0.1f;
536 		const float rangeMax = 6.0f;
537 
538 		if (outMax < rangeMin || outMin > rangeMax)
539 			return false; // Out of range
540 
541 		inMin = deFloatExp2(deFloatMax(outMin, rangeMin));
542 		inMax = deFloatExp2(deFloatMin(outMax, rangeMax));
543 
544 		return true;
545 	}
546 
evaluateComp(float inVal)547 	static inline float evaluateComp (float inVal)
548 	{
549 		return deFloatLog2(inVal);
550 	}
551 };
552 
553 class SqrtOp : public UnaryExponentialFunc<SqrtOp>
554 {
555 public:
SqrtOp(GeneratorState & state,ConstValueRangeAccess valueRange)556 	SqrtOp (GeneratorState& state, ConstValueRangeAccess valueRange)
557 		: UnaryExponentialFunc<SqrtOp>(state, "sqrt", valueRange)
558 	{
559 	}
560 
transformValueRange(float outMin,float outMax,float & inMin,float & inMax)561 	static inline bool transformValueRange (float outMin, float outMax, float& inMin, float& inMax)
562 	{
563 		// Limited due to accuracy reasons, should be 0..+inf
564 		const float rangeMin = 0.0f;
565 		const float rangeMax = 4.0f;
566 
567 		if (outMax < rangeMin || outMin > rangeMax)
568 			return false; // Out of range
569 
570 		inMin = deFloatMax(outMin, rangeMin);
571 		inMax = deFloatMin(outMax, rangeMax);
572 
573 		inMin *= inMin;
574 		inMax *= inMax;
575 
576 		return true;
577 	}
578 
evaluateComp(float inVal)579 	static inline float evaluateComp (float inVal)
580 	{
581 		return deFloatSqrt(inVal);
582 	}
583 };
584 
585 class InvSqrtOp : public UnaryExponentialFunc<InvSqrtOp>
586 {
587 public:
InvSqrtOp(GeneratorState & state,ConstValueRangeAccess valueRange)588 	InvSqrtOp (GeneratorState& state, ConstValueRangeAccess valueRange)
589 		: UnaryExponentialFunc<InvSqrtOp>(state, "inversesqrt", valueRange)
590 	{
591 	}
592 
transformValueRange(float outMin,float outMax,float & inMin,float & inMax)593 	static inline bool transformValueRange (float outMin, float outMax, float& inMin, float& inMax)
594 	{
595 		// Limited due to accuracy reasons
596 		const float rangeMin = 0.4f;
597 		const float rangeMax = 3.0f;
598 
599 		if (outMax < rangeMin || outMin > rangeMax)
600 			return false; // Out of range
601 
602 		inMax = 1.0f/deFloatMax(outMin, rangeMin);
603 		inMin = 1.0f/deFloatMin(outMax, rangeMax);
604 
605 		inMin *= inMin;
606 		inMax *= inMax;
607 
608 		return true;
609 	}
610 
evaluateComp(float inVal)611 	static inline float evaluateComp (float inVal)
612 	{
613 		return 1.0f/deFloatSqrt(inVal);
614 	}
615 };
616 
617 } // rsg
618 
619 #endif // _RSGBUILTINFUNCTIONS_HPP
620