xref: /aosp_15_r20/external/deqp/framework/randomshaders/rsgBuiltinFunctions.hpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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