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