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