Fix missing dependency on sparse binds
[platform/upstream/VK-GL-CTS.git] / modules / glshared / glsBuiltinPrecisionTests.cpp
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL (ES) Module
3  * -----------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Precision and range tests for GLSL builtins and types.
22  *
23  *//*--------------------------------------------------------------------*/
24
25 #include "glsBuiltinPrecisionTests.hpp"
26
27 #include "deMath.h"
28 #include "deMemory.h"
29 #include "deDefs.hpp"
30 #include "deRandom.hpp"
31 #include "deSTLUtil.hpp"
32 #include "deStringUtil.hpp"
33 #include "deUniquePtr.hpp"
34 #include "deSharedPtr.hpp"
35 #include "deArrayUtil.hpp"
36
37 #include "tcuCommandLine.hpp"
38 #include "tcuFloatFormat.hpp"
39 #include "tcuInterval.hpp"
40 #include "tcuTestCase.hpp"
41 #include "tcuTestLog.hpp"
42 #include "tcuVector.hpp"
43 #include "tcuMatrix.hpp"
44 #include "tcuResultCollector.hpp"
45
46 #include "gluContextInfo.hpp"
47 #include "gluVarType.hpp"
48 #include "gluRenderContext.hpp"
49 #include "glwDefs.hpp"
50
51 #include "glsShaderExecUtil.hpp"
52
53 #include <cmath>
54 #include <string>
55 #include <sstream>
56 #include <iostream>
57 #include <map>
58 #include <utility>
59 #include <limits>
60
61 // Uncomment this to get evaluation trace dumps to std::cerr
62 // #define GLS_ENABLE_TRACE
63
64 // set this to true to dump even passing results
65 #define GLS_LOG_ALL_RESULTS false
66
67 enum
68 {
69         // Computing reference intervals can take a non-trivial amount of time, especially on
70         // platforms where toggling floating-point rounding mode is slow (emulated arm on x86).
71         // As a workaround watchdog is kept happy by touching it periodically during reference
72         // interval computation.
73         TOUCH_WATCHDOG_VALUE_FREQUENCY  = 4096
74 };
75
76 namespace deqp
77 {
78 namespace gls
79 {
80 namespace BuiltinPrecisionTests
81 {
82
83 using std::string;
84 using std::map;
85 using std::ostream;
86 using std::ostringstream;
87 using std::pair;
88 using std::vector;
89 using std::set;
90
91 using de::MovePtr;
92 using de::Random;
93 using de::SharedPtr;
94 using de::UniquePtr;
95 using tcu::Interval;
96 using tcu::FloatFormat;
97 using tcu::MessageBuilder;
98 using tcu::TestCase;
99 using tcu::TestLog;
100 using tcu::Vector;
101 using tcu::Matrix;
102 namespace matrix = tcu::matrix;
103 using glu::Precision;
104 using glu::RenderContext;
105 using glu::VarType;
106 using glu::DataType;
107 using glu::ShaderType;
108 using glu::ContextInfo;
109 using gls::ShaderExecUtil::Symbol;
110
111 typedef TestCase::IterateResult IterateResult;
112
113 using namespace glw;
114 using namespace tcu;
115
116 /*--------------------------------------------------------------------*//*!
117  * \brief Generic singleton creator.
118  *
119  * instance<T>() returns a reference to a unique default-constructed instance
120  * of T. This is mainly used for our GLSL function implementations: each
121  * function is implemented by an object, and each of the objects has a
122  * distinct class. It would be extremely toilsome to maintain a separate
123  * context object that contained individual instances of the function classes,
124  * so we have to resort to global singleton instances.
125  *
126  *//*--------------------------------------------------------------------*/
127 template <typename T>
128 const T& instance (void)
129 {
130         static const T s_instance = T();
131         return s_instance;
132 }
133
134 /*--------------------------------------------------------------------*//*!
135  * \brief A placeholder type for unused template parameters.
136  *
137  * In the precision tests we are dealing with functions of different arities.
138  * To minimize code duplication, we only define templates with the maximum
139  * number of arguments, currently four. If a function's arity is less than the
140  * maximum, Void us used as the type for unused arguments.
141  *
142  * Although Voids are not used at run-time, they still must be compilable, so
143  * they must support all operations that other types do.
144  *
145  *//*--------------------------------------------------------------------*/
146 struct Void
147 {
148         typedef Void            Element;
149         enum
150         {
151                 SIZE = 0,
152         };
153
154         template <typename T>
155         explicit                        Void                    (const T&)              {}
156                                                 Void                    (void)                  {}
157                                                 operator double (void)  const   { return TCU_NAN; }
158
159         // These are used to make Voids usable as containers in container-generic code.
160         Void&                           operator[]              (int)                   { return *this; }
161         const Void&                     operator[]              (int)   const   { return *this; }
162 };
163
164 ostream& operator<< (ostream& os, Void) { return os << "()"; }
165
166 //! Returns true for all other types except Void
167 template <typename T>   bool isTypeValid                (void)  { return true;  }
168 template <>                             bool isTypeValid<Void>  (void)  { return false; }
169
170 //! Utility function for getting the name of a data type.
171 //! This is used in vector and matrix constructors.
172 template <typename T>
173 const char* dataTypeNameOf (void)
174 {
175         return glu::getDataTypeName(glu::dataTypeOf<T>());
176 }
177
178 template <>
179 const char* dataTypeNameOf<Void> (void)
180 {
181         DE_FATAL("Impossible");
182         return DE_NULL;
183 }
184
185 //! A hack to get Void support for VarType.
186 template <typename T>
187 VarType getVarTypeOf (Precision prec = glu::PRECISION_LAST)
188 {
189         return glu::varTypeOf<T>(prec);
190 }
191
192 template <>
193 VarType getVarTypeOf<Void> (Precision)
194 {
195         DE_FATAL("Impossible");
196         return VarType();
197 }
198
199 /*--------------------------------------------------------------------*//*!
200  * \brief Type traits for generalized interval types.
201  *
202  * We are trying to compute sets of acceptable values not only for
203  * float-valued expressions but also for compound values: vectors and
204  * matrices. We approximate a set of vectors as a vector of intervals and
205  * likewise for matrices.
206  *
207  * We now need generalized operations for each type and its interval
208  * approximation. These are given in the type Traits<T>.
209  *
210  * The type Traits<T>::IVal is the approximation of T: it is `Interval` for
211  * scalar types, and a vector or matrix of intervals for container types.
212  *
213  * To allow template inference to take place, there are function wrappers for
214  * the actual operations in Traits<T>. Hence we can just use:
215  *
216  * makeIVal(someFloat)
217  *
218  * instead of:
219  *
220  * Traits<float>::doMakeIVal(value)
221  *
222  *//*--------------------------------------------------------------------*/
223
224 template <typename T> struct Traits;
225
226 //! Create container from elementwise singleton values.
227 template <typename T>
228 typename Traits<T>::IVal makeIVal (const T& value)
229 {
230         return Traits<T>::doMakeIVal(value);
231 }
232
233 //! Elementwise union of intervals.
234 template <typename T>
235 typename Traits<T>::IVal unionIVal (const typename Traits<T>::IVal& a,
236                                                                         const typename Traits<T>::IVal& b)
237 {
238         return Traits<T>::doUnion(a, b);
239 }
240
241 //! Returns true iff every element of `ival` contains the corresponding element of `value`.
242 template <typename T>
243 bool contains (const typename Traits<T>::IVal& ival, const T& value)
244 {
245         return Traits<T>::doContains(ival, value);
246 }
247
248 //! Returns true iff every element of `ival` contains corresponding element of `value` within the warning interval
249 template <typename T>
250 bool containsWarning(const typename Traits<T>::IVal& ival, const T& value)
251 {
252         return Traits<T>::doContainsWarning(ival, value);
253 }
254
255 //! Print out an interval with the precision of `fmt`.
256 template <typename T>
257 void printIVal (const FloatFormat& fmt, const typename Traits<T>::IVal& ival, ostream& os)
258 {
259         Traits<T>::doPrintIVal(fmt, ival, os);
260 }
261
262 template <typename T>
263 string intervalToString (const FloatFormat& fmt, const typename Traits<T>::IVal& ival)
264 {
265         ostringstream oss;
266         printIVal<T>(fmt, ival, oss);
267         return oss.str();
268 }
269
270 //! Print out a value with the precision of `fmt`.
271 template <typename T>
272 void printValue (const FloatFormat& fmt, const T& value, ostream& os)
273 {
274         Traits<T>::doPrintValue(fmt, value, os);
275 }
276
277 template <typename T>
278 string valueToString (const FloatFormat& fmt, const T& val)
279 {
280         ostringstream oss;
281         printValue(fmt, val, oss);
282         return oss.str();
283 }
284
285 //! Approximate `value` elementwise to the float precision defined in `fmt`.
286 //! The resulting interval might not be a singleton if rounding in both
287 //! directions is allowed.
288 template <typename T>
289 typename Traits<T>::IVal round (const FloatFormat& fmt, const T& value)
290 {
291         return Traits<T>::doRound(fmt, value);
292 }
293
294 template <typename T>
295 typename Traits<T>::IVal convert (const FloatFormat&                            fmt,
296                                                                   const typename Traits<T>::IVal&       value)
297 {
298         return Traits<T>::doConvert(fmt, value);
299 }
300
301 //! Common traits for scalar types.
302 template <typename T>
303 struct ScalarTraits
304 {
305         typedef                         Interval                IVal;
306
307         static Interval         doMakeIVal              (const T& value)
308         {
309                 // Thankfully all scalar types have a well-defined conversion to `double`,
310                 // hence Interval can represent their ranges without problems.
311                 return Interval(double(value));
312         }
313
314         static Interval         doUnion                 (const Interval& a, const Interval& b)
315         {
316                 return a | b;
317         }
318
319         static bool                     doContains              (const Interval& a, T value)
320         {
321                 return a.contains(double(value));
322         }
323
324         static bool                     doContainsWarning(const Interval& a, T value)
325         {
326                 return a.containsWarning(double(value));
327         }
328
329         static Interval         doConvert               (const FloatFormat& fmt, const IVal& ival)
330         {
331                 return fmt.convert(ival);
332         }
333
334         static Interval         doRound                 (const FloatFormat& fmt, T value)
335         {
336                 return fmt.roundOut(double(value), false);
337         }
338 };
339
340 template<>
341 struct Traits<float> : ScalarTraits<float>
342 {
343         static void                     doPrintIVal             (const FloatFormat&     fmt,
344                                                                                  const Interval&        ival,
345                                                                                  ostream&                       os)
346         {
347                 os << fmt.intervalToHex(ival);
348         }
349
350         static void                     doPrintValue    (const FloatFormat&     fmt,
351                                                                                  const float&           value,
352                                                                                  ostream&                       os)
353         {
354                 os << fmt.floatToHex(value);
355         }
356 };
357
358 template<>
359 struct Traits<bool> : ScalarTraits<bool>
360 {
361         static void                     doPrintValue    (const FloatFormat&,
362                                                                                  const float&           value,
363                                                                                  ostream&                       os)
364         {
365                 os << (value != 0.0f ? "true" : "false");
366         }
367
368         static void                     doPrintIVal             (const FloatFormat&,
369                                                                                  const Interval&        ival,
370                                                                                  ostream&                       os)
371         {
372                 os << "{";
373                 if (ival.contains(false))
374                         os << "false";
375                 if (ival.contains(false) && ival.contains(true))
376                         os << ", ";
377                 if (ival.contains(true))
378                         os << "true";
379                 os << "}";
380         }
381 };
382
383 template<>
384 struct Traits<int> : ScalarTraits<int>
385 {
386         static void                     doPrintValue    (const FloatFormat&,
387                                                                                  const int&                     value,
388                                                                                  ostream&                       os)
389         {
390                 os << value;
391         }
392
393         static void                     doPrintIVal             (const FloatFormat&,
394                                                                                  const Interval&        ival,
395                                                                                  ostream&                       os)
396         {
397                 os << "[" << int(ival.lo()) << ", " << int(ival.hi()) << "]";
398         }
399 };
400
401 //! Common traits for containers, i.e. vectors and matrices.
402 //! T is the container type itself, I is the same type with interval elements.
403 template <typename T, typename I>
404 struct ContainerTraits
405 {
406         typedef typename        T::Element              Element;
407         typedef                         I                               IVal;
408
409         static IVal                     doMakeIVal              (const T& value)
410         {
411                 IVal ret;
412
413                 for (int ndx = 0; ndx < T::SIZE; ++ndx)
414                         ret[ndx] = makeIVal(value[ndx]);
415
416                 return ret;
417         }
418
419         static IVal                     doUnion                 (const IVal& a, const IVal& b)
420         {
421                 IVal ret;
422
423                 for (int ndx = 0; ndx < T::SIZE; ++ndx)
424                         ret[ndx] = unionIVal<Element>(a[ndx], b[ndx]);
425
426                 return ret;
427         }
428
429         static bool                     doContains              (const IVal& ival, const T& value)
430         {
431                 for (int ndx = 0; ndx < T::SIZE; ++ndx)
432                         if (!contains(ival[ndx], value[ndx]))
433                                 return false;
434
435                 return true;
436         }
437
438         static bool                     doContainsWarning(const IVal& ival, const T& value)
439         {
440                 for (int ndx = 0; ndx < T::SIZE; ++ndx)
441                         if (!containsWarning(ival[ndx], value[ndx]))
442                                 return false;
443
444                 return true;
445         }
446
447         static void                     doPrintIVal             (const FloatFormat& fmt, const IVal ival, ostream& os)
448         {
449                 os << "(";
450
451                 for (int ndx = 0; ndx < T::SIZE; ++ndx)
452                 {
453                         if (ndx > 0)
454                                 os << ", ";
455
456                         printIVal<Element>(fmt, ival[ndx], os);
457                 }
458
459                 os << ")";
460         }
461
462         static void                     doPrintValue    (const FloatFormat& fmt, const T& value, ostream& os)
463         {
464                 os << dataTypeNameOf<T>() << "(";
465
466                 for (int ndx = 0; ndx < T::SIZE; ++ndx)
467                 {
468                         if (ndx > 0)
469                                 os << ", ";
470
471                         printValue<Element>(fmt, value[ndx], os);
472                 }
473
474                 os << ")";
475         }
476
477         static IVal                     doConvert               (const FloatFormat& fmt, const IVal& value)
478         {
479                 IVal ret;
480
481                 for (int ndx = 0; ndx < T::SIZE; ++ndx)
482                         ret[ndx] = convert<Element>(fmt, value[ndx]);
483
484                 return ret;
485         }
486
487         static IVal                     doRound                 (const FloatFormat& fmt, T value)
488         {
489                 IVal ret;
490
491                 for (int ndx = 0; ndx < T::SIZE; ++ndx)
492                         ret[ndx] = round(fmt, value[ndx]);
493
494                 return ret;
495         }
496 };
497
498 template <typename T, int Size>
499 struct Traits<Vector<T, Size> > :
500         ContainerTraits<Vector<T, Size>, Vector<typename Traits<T>::IVal, Size> >
501 {
502 };
503
504 template <typename T, int Rows, int Cols>
505 struct Traits<Matrix<T, Rows, Cols> > :
506         ContainerTraits<Matrix<T, Rows, Cols>, Matrix<typename Traits<T>::IVal, Rows, Cols> >
507 {
508 };
509
510 //! Void traits. These are just dummies, but technically valid: a Void is a
511 //! unit type with a single possible value.
512 template<>
513 struct Traits<Void>
514 {
515         typedef         Void                    IVal;
516
517         static Void     doMakeIVal                      (const Void& value)                                             { return value; }
518         static Void     doUnion                         (const Void&, const Void&)                              { return Void(); }
519         static bool     doContains                      (const Void&, Void)                                             { return true; }
520         static bool     doContainsWarning       (const Void&, Void)                                             { return true; }
521         static Void     doRound                         (const FloatFormat&, const Void& value) { return value; }
522         static Void     doConvert                       (const FloatFormat&, const Void& value) { return value; }
523
524         static void     doPrintValue    (const FloatFormat&, const Void&, ostream& os)
525         {
526                 os << "()";
527         }
528
529         static void     doPrintIVal             (const FloatFormat&, const Void&, ostream& os)
530         {
531                 os << "()";
532         }
533 };
534
535 //! This is needed for container-generic operations.
536 //! We want a scalar type T to be its own "one-element vector".
537 template <typename T, int Size> struct ContainerOf      { typedef Vector<T, Size>       Container; };
538
539 template <typename T>                   struct ContainerOf<T, 1>                { typedef T             Container; };
540 template <int Size>                             struct ContainerOf<Void, Size>  { typedef Void  Container; };
541
542 // This is a kludge that is only needed to get the ExprP::operator[] syntactic sugar to work.
543 template <typename T>   struct ElementOf                { typedef       typename T::Element     Element; };
544 template <>                             struct ElementOf<float> { typedef       void                            Element; };
545 template <>                             struct ElementOf<bool>  { typedef       void                            Element; };
546 template <>                             struct ElementOf<int>   { typedef       void                            Element; };
547
548 /*--------------------------------------------------------------------*//*!
549  *
550  * \name Abstract syntax for expressions and statements.
551  *
552  * We represent GLSL programs as syntax objects: an Expr<T> represents an
553  * expression whose GLSL type corresponds to the C++ type T, and a Statement
554  * represents a statement.
555  *
556  * To ease memory management, we use shared pointers to refer to expressions
557  * and statements. ExprP<T> is a shared pointer to an Expr<T>, and StatementP
558  * is a shared pointer to a Statement.
559  *
560  * \{
561  *
562  *//*--------------------------------------------------------------------*/
563
564 class ExprBase;
565 class ExpandContext;
566 class Statement;
567 class StatementP;
568 class FuncBase;
569 template <typename T> class ExprP;
570 template <typename T> class Variable;
571 template <typename T> class VariableP;
572 template <typename T> class DefaultSampling;
573
574 typedef set<const FuncBase*> FuncSet;
575
576 template <typename T>
577 VariableP<T>    variable                        (const string& name);
578 StatementP              compoundStatement       (const vector<StatementP>& statements);
579
580 /*--------------------------------------------------------------------*//*!
581  * \brief A variable environment.
582  *
583  * An Environment object maintains the mapping between variables of the
584  * abstract syntax tree and their values.
585  *
586  * \todo [2014-03-28 lauri] At least run-time type safety.
587  *
588  *//*--------------------------------------------------------------------*/
589 class Environment
590 {
591 public:
592         template<typename T>
593         void                                            bind    (const Variable<T>&                                     variable,
594                                                                                  const typename Traits<T>::IVal&        value)
595         {
596                 deUint8* const data = new deUint8[sizeof(value)];
597
598                 deMemcpy(data, &value, sizeof(value));
599                 de::insert(m_map, variable.getName(), SharedPtr<deUint8>(data, de::ArrayDeleter<deUint8>()));
600         }
601
602         template<typename T>
603         typename Traits<T>::IVal&       lookup  (const Variable<T>& variable) const
604         {
605                 deUint8* const data = de::lookup(m_map, variable.getName()).get();
606
607                 return *reinterpret_cast<typename Traits<T>::IVal*>(data);
608         }
609
610 private:
611         map<string, SharedPtr<deUint8> >        m_map;
612 };
613
614 /*--------------------------------------------------------------------*//*!
615  * \brief Evaluation context.
616  *
617  * The evaluation context contains everything that separates one execution of
618  * an expression from the next. Currently this means the desired floating
619  * point precision and the current variable environment.
620  *
621  *//*--------------------------------------------------------------------*/
622 struct EvalContext
623 {
624         EvalContext (const FloatFormat& format_,
625                                  Precision                      floatPrecision_,
626                                  Environment&           env_,
627                                  int                            callDepth_ = 0)
628                 : format                        (format_)
629                 , floatPrecision        (floatPrecision_)
630                 , env                           (env_)
631                 , callDepth                     (callDepth_) {}
632
633         FloatFormat             format;
634         Precision               floatPrecision;
635         Environment&    env;
636         int                             callDepth;
637 };
638
639 /*--------------------------------------------------------------------*//*!
640  * \brief Simple incremental counter.
641  *
642  * This is used to make sure that different ExpandContexts will not produce
643  * overlapping temporary names.
644  *
645  *//*--------------------------------------------------------------------*/
646 class Counter
647 {
648 public:
649                         Counter         (int count = 0) : m_count(count) {}
650         int             operator()      (void) { return m_count++; }
651
652 private:
653         int             m_count;
654 };
655
656 /*--------------------------------------------------------------------*//*!
657  * \brief A statement or declaration.
658  *
659  * Statements have no values. Instead, they are executed for their side
660  * effects only: the execute() method should modify at least one variable in
661  * the environment.
662  *
663  * As a bit of a kludge, a Statement object can also represent a declaration:
664  * when it is evaluated, it can add a variable binding to the environment
665  * instead of modifying a current one.
666  *
667  *//*--------------------------------------------------------------------*/
668 class Statement
669 {
670 public:
671         virtual ~Statement              (void)                                                  {                                                                }
672         //! Execute the statement, modifying the environment of `ctx`
673         void    execute                 (EvalContext&   ctx)    const   { this->doExecute(ctx);                  }
674         void    print                   (ostream&               os)             const   { this->doPrint(os);                     }
675         //! Add the functions used in this statement to `dst`.
676         void    getUsedFuncs    (FuncSet& dst)                  const   { this->doGetUsedFuncs(dst);     }
677
678 protected:
679         virtual void    doPrint                 (ostream& os)                   const   = 0;
680         virtual void    doExecute               (EvalContext& ctx)              const   = 0;
681         virtual void    doGetUsedFuncs  (FuncSet& dst)                  const   = 0;
682 };
683
684 ostream& operator<<(ostream& os, const Statement& stmt)
685 {
686         stmt.print(os);
687         return os;
688 }
689
690 /*--------------------------------------------------------------------*//*!
691  * \brief Smart pointer for statements (and declarations)
692  *
693  *//*--------------------------------------------------------------------*/
694 class StatementP : public SharedPtr<const Statement>
695 {
696 public:
697         typedef         SharedPtr<const Statement>      Super;
698
699                                 StatementP                      (void) {}
700         explicit        StatementP                      (const Statement* ptr)  : Super(ptr) {}
701                                 StatementP                      (const Super& ptr)              : Super(ptr) {}
702 };
703
704 class ExpandContext
705 {
706 public:
707                                                 ExpandContext   (Counter& symCounter) : m_symCounter(symCounter) {}
708                                                 ExpandContext   (const ExpandContext& parent)
709                                                         : m_symCounter(parent.m_symCounter) {}
710
711         template<typename T>
712         VariableP<T>            genSym                  (const string& baseName)
713         {
714                 return variable<T>(baseName + de::toString(m_symCounter()));
715         }
716
717         void                            addStatement    (const StatementP& stmt)
718         {
719                 m_statements.push_back(stmt);
720         }
721
722         vector<StatementP>      getStatements   (void) const
723         {
724                 return m_statements;
725         }
726 private:
727         Counter&                        m_symCounter;
728         vector<StatementP>      m_statements;
729 };
730
731 /*--------------------------------------------------------------------*//*!
732  * \brief
733  *
734  * A statement that modifies a variable or a declaration that binds a variable.
735  *
736  *//*--------------------------------------------------------------------*/
737 template <typename T>
738 class VariableStatement : public Statement
739 {
740 public:
741                                         VariableStatement       (const VariableP<T>& variable, const ExprP<T>& value,
742                                                                                  bool isDeclaration)
743                                                 : m_variable            (variable)
744                                                 , m_value                       (value)
745                                                 , m_isDeclaration       (isDeclaration) {}
746
747 protected:
748         void                    doPrint                         (ostream& os)                                                   const
749         {
750                 if (m_isDeclaration)
751                         os << glu::declare(getVarTypeOf<T>(), m_variable->getName());
752                 else
753                         os << m_variable->getName();
754
755                 os << " = " << *m_value << ";\n";
756         }
757
758         void                    doExecute                       (EvalContext& ctx)                                              const
759         {
760                 if (m_isDeclaration)
761                         ctx.env.bind(*m_variable, m_value->evaluate(ctx));
762                 else
763                         ctx.env.lookup(*m_variable) = m_value->evaluate(ctx);
764         }
765
766         void                    doGetUsedFuncs          (FuncSet& dst)                                                  const
767         {
768                 m_value->getUsedFuncs(dst);
769         }
770
771         VariableP<T>    m_variable;
772         ExprP<T>                m_value;
773         bool                    m_isDeclaration;
774 };
775
776 template <typename T>
777 StatementP variableStatement (const VariableP<T>&       variable,
778                                                           const ExprP<T>&               value,
779                                                           bool                                  isDeclaration)
780 {
781         return StatementP(new VariableStatement<T>(variable, value, isDeclaration));
782 }
783
784 template <typename T>
785 StatementP variableDeclaration (const VariableP<T>& variable, const ExprP<T>& definiens)
786 {
787         return variableStatement(variable, definiens, true);
788 }
789
790 template <typename T>
791 StatementP variableAssignment (const VariableP<T>& variable, const ExprP<T>& value)
792 {
793         return variableStatement(variable, value, false);
794 }
795
796 /*--------------------------------------------------------------------*//*!
797  * \brief A compound statement, i.e. a block.
798  *
799  * A compound statement is executed by executing its constituent statements in
800  * sequence.
801  *
802  *//*--------------------------------------------------------------------*/
803 class CompoundStatement : public Statement
804 {
805 public:
806                                                 CompoundStatement       (const vector<StatementP>& statements)
807                                                         : m_statements  (statements) {}
808
809 protected:
810         void                            doPrint                         (ostream&               os)                                             const
811         {
812                 os << "{\n";
813
814                 for (size_t ndx = 0; ndx < m_statements.size(); ++ndx)
815                         os << *m_statements[ndx];
816
817                 os << "}\n";
818         }
819
820         void                            doExecute                       (EvalContext&   ctx)                                    const
821         {
822                 for (size_t ndx = 0; ndx < m_statements.size(); ++ndx)
823                         m_statements[ndx]->execute(ctx);
824         }
825
826         void                            doGetUsedFuncs          (FuncSet& dst)                                                  const
827         {
828                 for (size_t ndx = 0; ndx < m_statements.size(); ++ndx)
829                         m_statements[ndx]->getUsedFuncs(dst);
830         }
831
832         vector<StatementP>      m_statements;
833 };
834
835 StatementP compoundStatement(const vector<StatementP>& statements)
836 {
837         return StatementP(new CompoundStatement(statements));
838 }
839
840 //! Common base class for all expressions regardless of their type.
841 class ExprBase
842 {
843 public:
844         virtual                         ~ExprBase               (void)                                                                  {}
845         void                            printExpr               (ostream& os) const { this->doPrintExpr(os); }
846
847         //! Output the functions that this expression refers to
848         void                            getUsedFuncs    (FuncSet& dst) const
849         {
850                 this->doGetUsedFuncs(dst);
851         }
852
853 protected:
854         virtual void            doPrintExpr             (ostream&)      const   {}
855         virtual void            doGetUsedFuncs  (FuncSet&)      const   {}
856 };
857
858 //! Type-specific operations for an expression representing type T.
859 template <typename T>
860 class Expr : public ExprBase
861 {
862 public:
863         typedef                         T                               Val;
864         typedef typename        Traits<T>::IVal IVal;
865
866         IVal                            evaluate                (const EvalContext&     ctx) const;
867
868 protected:
869         virtual IVal            doEvaluate              (const EvalContext&     ctx) const = 0;
870 };
871
872 //! Evaluate an expression with the given context, optionally tracing the calls to stderr.
873 template <typename T>
874 typename Traits<T>::IVal Expr<T>::evaluate (const EvalContext& ctx) const
875 {
876 #ifdef GLS_ENABLE_TRACE
877         static const FloatFormat        highpFmt        (-126, 127, 23, true,
878                                                                                          tcu::MAYBE,
879                                                                                          tcu::YES,
880                                                                                          tcu::MAYBE);
881         EvalContext                                     newCtx          (ctx.format, ctx.floatPrecision,
882                                                                                          ctx.env, ctx.callDepth + 1);
883         const IVal                                      ret                     = this->doEvaluate(newCtx);
884
885         if (isTypeValid<T>())
886         {
887                 std::cerr << string(ctx.callDepth, ' ');
888                 this->printExpr(std::cerr);
889                 std::cerr << " -> " << intervalToString<T>(highpFmt, ret) << std::endl;
890         }
891         return ret;
892 #else
893         return this->doEvaluate(ctx);
894 #endif
895 }
896
897 template <typename T>
898 class ExprPBase : public SharedPtr<const Expr<T> >
899 {
900 public:
901 };
902
903 ostream& operator<< (ostream& os, const ExprBase& expr)
904 {
905         expr.printExpr(os);
906         return os;
907 }
908
909 /*--------------------------------------------------------------------*//*!
910  * \brief Shared pointer to an expression of a container type.
911  *
912  * Container types (i.e. vectors and matrices) support the subscription
913  * operator. This class provides a bit of syntactic sugar to allow us to use
914  * the C++ subscription operator to create a subscription expression.
915  *//*--------------------------------------------------------------------*/
916 template <typename T>
917 class ContainerExprPBase : public ExprPBase<T>
918 {
919 public:
920         ExprP<typename T::Element>      operator[]      (int i) const;
921 };
922
923 template <typename T>
924 class ExprP : public ExprPBase<T> {};
925
926 // We treat Voids as containers since the unused parameters in generalized
927 // vector functions are represented as Voids.
928 template <>
929 class ExprP<Void> : public ContainerExprPBase<Void> {};
930
931 template <typename T, int Size>
932 class ExprP<Vector<T, Size> > : public ContainerExprPBase<Vector<T, Size> > {};
933
934 template <typename T, int Rows, int Cols>
935 class ExprP<Matrix<T, Rows, Cols> > : public ContainerExprPBase<Matrix<T, Rows, Cols> > {};
936
937 template <typename T> ExprP<T> exprP (void)
938 {
939         return ExprP<T>();
940 }
941
942 template <typename T>
943 ExprP<T> exprP (const SharedPtr<const Expr<T> >& ptr)
944 {
945         ExprP<T> ret;
946         static_cast<SharedPtr<const Expr<T> >&>(ret) = ptr;
947         return ret;
948 }
949
950 template <typename T>
951 ExprP<T> exprP (const Expr<T>* ptr)
952 {
953         return exprP(SharedPtr<const Expr<T> >(ptr));
954 }
955
956 /*--------------------------------------------------------------------*//*!
957  * \brief A shared pointer to a variable expression.
958  *
959  * This is just a narrowing of ExprP for the operations that require a variable
960  * instead of an arbitrary expression.
961  *
962  *//*--------------------------------------------------------------------*/
963 template <typename T>
964 class VariableP : public SharedPtr<const Variable<T> >
965 {
966 public:
967         typedef         SharedPtr<const Variable<T> >   Super;
968         explicit        VariableP       (const Variable<T>* ptr) : Super(ptr) {}
969                                 VariableP       (void) {}
970                                 VariableP       (const Super& ptr) : Super(ptr) {}
971
972         operator        ExprP<T>        (void) const { return exprP(SharedPtr<const Expr<T> >(*this)); }
973 };
974
975 /*--------------------------------------------------------------------*//*!
976  * \name Syntactic sugar operators for expressions.
977  *
978  * @{
979  *
980  * These operators allow the use of C++ syntax to construct GLSL expressions
981  * containing operators: e.g. "a+b" creates an addition expression with
982  * operands a and b, and so on.
983  *
984  *//*--------------------------------------------------------------------*/
985 ExprP<float>                                            operator-(const ExprP<float>&                                           arg0);
986 ExprP<float>                                            operator+(const ExprP<float>&                                           arg0,
987                                                                                           const ExprP<float>&                                           arg1);
988 ExprP<float>                                            operator-(const ExprP<float>&                                           arg0,
989                                                                                           const ExprP<float>&                                           arg1);
990 ExprP<float>                                            operator*(const ExprP<float>&                                           arg0,
991                                                                                           const ExprP<float>&                                           arg1);
992 ExprP<float>                                            operator/(const ExprP<float>&                                           arg0,
993                                                                                           const ExprP<float>&                                           arg1);
994 template<int Size>
995 ExprP<Vector<float, Size> >                     operator-(const ExprP<Vector<float, Size> >&            arg0);
996 template<int Size>
997 ExprP<Vector<float, Size> >                     operator*(const ExprP<Vector<float, Size> >&            arg0,
998                                                                                           const ExprP<float>&                                           arg1);
999 template<int Size>
1000 ExprP<Vector<float, Size> >                     operator*(const ExprP<Vector<float, Size> >&            arg0,
1001                                                                                           const ExprP<Vector<float, Size> >&            arg1);
1002 template<int Size>
1003 ExprP<Vector<float, Size> >                     operator-(const ExprP<Vector<float, Size> >&            arg0,
1004                                                                                           const ExprP<Vector<float, Size> >&            arg1);
1005 template<int Left, int Mid, int Right>
1006 ExprP<Matrix<float, Left, Right> >      operator* (const ExprP<Matrix<float, Left, Mid> >&      left,
1007                                                                                            const ExprP<Matrix<float, Mid, Right> >&     right);
1008 template<int Rows, int Cols>
1009 ExprP<Vector<float, Rows> >                     operator* (const ExprP<Vector<float, Cols> >&           left,
1010                                                                                            const ExprP<Matrix<float, Rows, Cols> >&     right);
1011 template<int Rows, int Cols>
1012 ExprP<Vector<float, Cols> >                     operator* (const ExprP<Matrix<float, Rows, Cols> >&     left,
1013                                                                                            const ExprP<Vector<float, Rows> >&           right);
1014 template<int Rows, int Cols>
1015 ExprP<Matrix<float, Rows, Cols> >       operator* (const ExprP<Matrix<float, Rows, Cols> >&     left,
1016                                                                                            const ExprP<float>&                                          right);
1017 template<int Rows, int Cols>
1018 ExprP<Matrix<float, Rows, Cols> >       operator+ (const ExprP<Matrix<float, Rows, Cols> >&     left,
1019                                                                                            const ExprP<Matrix<float, Rows, Cols> >&     right);
1020 template<int Rows, int Cols>
1021 ExprP<Matrix<float, Rows, Cols> >       operator- (const ExprP<Matrix<float, Rows, Cols> >&     mat);
1022
1023 //! @}
1024
1025 /*--------------------------------------------------------------------*//*!
1026  * \brief Variable expression.
1027  *
1028  * A variable is evaluated by looking up its range of possible values from an
1029  * environment.
1030  *//*--------------------------------------------------------------------*/
1031 template <typename T>
1032 class Variable : public Expr<T>
1033 {
1034 public:
1035         typedef typename Expr<T>::IVal IVal;
1036
1037                                         Variable        (const string& name) : m_name (name) {}
1038         string                  getName         (void)                                                  const { return m_name; }
1039
1040 protected:
1041         void                    doPrintExpr     (ostream& os)                                   const { os << m_name; }
1042         IVal                    doEvaluate      (const EvalContext& ctx)                const
1043         {
1044                 return ctx.env.lookup<T>(*this);
1045         }
1046
1047 private:
1048         string  m_name;
1049 };
1050
1051 template <typename T>
1052 VariableP<T> variable (const string& name)
1053 {
1054         return VariableP<T>(new Variable<T>(name));
1055 }
1056
1057 template <typename T>
1058 VariableP<T> bindExpression (const string& name, ExpandContext& ctx, const ExprP<T>& expr)
1059 {
1060         VariableP<T> var = ctx.genSym<T>(name);
1061         ctx.addStatement(variableDeclaration(var, expr));
1062         return var;
1063 }
1064
1065 /*--------------------------------------------------------------------*//*!
1066  * \brief Constant expression.
1067  *
1068  * A constant is evaluated by rounding it to a set of possible values allowed
1069  * by the current floating point precision.
1070  *//*--------------------------------------------------------------------*/
1071 template <typename T>
1072 class Constant : public Expr<T>
1073 {
1074 public:
1075         typedef typename Expr<T>::IVal IVal;
1076
1077                         Constant                (const T& value) : m_value(value) {}
1078
1079 protected:
1080         void    doPrintExpr             (ostream& os) const                     { os << m_value; }
1081         IVal    doEvaluate              (const EvalContext&) const      { return makeIVal(m_value); }
1082
1083 private:
1084         T               m_value;
1085 };
1086
1087 template <typename T>
1088 ExprP<T> constant (const T& value)
1089 {
1090         return exprP(new Constant<T>(value));
1091 }
1092
1093 //! Return a reference to a singleton void constant.
1094 const ExprP<Void>& voidP (void)
1095 {
1096         static const ExprP<Void> singleton = constant(Void());
1097
1098         return singleton;
1099 }
1100
1101 /*--------------------------------------------------------------------*//*!
1102  * \brief Four-element tuple.
1103  *
1104  * This is used for various things where we need one thing for each possible
1105  * function parameter. Currently the maximum supported number of parameters is
1106  * four.
1107  *//*--------------------------------------------------------------------*/
1108 template <typename T0 = Void, typename T1 = Void, typename T2 = Void, typename T3 = Void>
1109 struct Tuple4
1110 {
1111         explicit Tuple4 (const T0 e0 = T0(),
1112                                          const T1 e1 = T1(),
1113                                          const T2 e2 = T2(),
1114                                          const T3 e3 = T3())
1115                 : a     (e0)
1116                 , b     (e1)
1117                 , c     (e2)
1118                 , d     (e3)
1119         {
1120         }
1121
1122         T0 a;
1123         T1 b;
1124         T2 c;
1125         T3 d;
1126 };
1127
1128 /*--------------------------------------------------------------------*//*!
1129  * \brief Function signature.
1130  *
1131  * This is a purely compile-time structure used to bundle all types in a
1132  * function signature together. This makes passing the signature around in
1133  * templates easier, since we only need to take and pass a single Sig instead
1134  * of a bunch of parameter types and a return type.
1135  *
1136  *//*--------------------------------------------------------------------*/
1137 template <typename R,
1138                   typename P0 = Void, typename P1 = Void,
1139                   typename P2 = Void, typename P3 = Void>
1140 struct Signature
1141 {
1142         typedef R                                                       Ret;
1143         typedef P0                                                      Arg0;
1144         typedef P1                                                      Arg1;
1145         typedef P2                                                      Arg2;
1146         typedef P3                                                      Arg3;
1147         typedef typename Traits<Ret>::IVal      IRet;
1148         typedef typename Traits<Arg0>::IVal     IArg0;
1149         typedef typename Traits<Arg1>::IVal     IArg1;
1150         typedef typename Traits<Arg2>::IVal     IArg2;
1151         typedef typename Traits<Arg3>::IVal     IArg3;
1152
1153         typedef Tuple4< const Arg0&,    const Arg1&,    const Arg2&,    const Arg3&>    Args;
1154         typedef Tuple4< const IArg0&,   const IArg1&,   const IArg2&,   const IArg3&>   IArgs;
1155         typedef Tuple4< ExprP<Arg0>,    ExprP<Arg1>,    ExprP<Arg2>,    ExprP<Arg3> >   ArgExprs;
1156 };
1157
1158 typedef vector<const ExprBase*> BaseArgExprs;
1159
1160 /*--------------------------------------------------------------------*//*!
1161  * \brief Type-independent operations for function objects.
1162  *
1163  *//*--------------------------------------------------------------------*/
1164 class FuncBase
1165 {
1166 public:
1167         virtual                 ~FuncBase                               (void)                                  {}
1168         virtual string  getName                                 (void)                                  const = 0;
1169         //! Name of extension that this function requires, or empty.
1170         virtual string  getRequiredExtension    (const RenderContext &)                 const { return ""; }
1171         virtual void    print                                   (ostream&,
1172                                                                                          const BaseArgExprs&)   const = 0;
1173         //! Index of output parameter, or -1 if none of the parameters is output.
1174         virtual int             getOutParamIndex                (void)                                  const { return -1; }
1175
1176         void                    printDefinition                 (ostream& os)                   const
1177         {
1178                 doPrintDefinition(os);
1179         }
1180
1181         void                            getUsedFuncs            (FuncSet& dst) const
1182         {
1183                 this->doGetUsedFuncs(dst);
1184         }
1185
1186 protected:
1187         virtual void    doPrintDefinition               (ostream& os)                   const = 0;
1188         virtual void    doGetUsedFuncs                  (FuncSet& dst)                  const = 0;
1189 };
1190
1191 typedef Tuple4<string, string, string, string> ParamNames;
1192
1193 /*--------------------------------------------------------------------*//*!
1194  * \brief Function objects.
1195  *
1196  * Each Func object represents a GLSL function. It can be applied to interval
1197  * arguments, and it returns the an interval that is a conservative
1198  * approximation of the image of the GLSL function over the argument
1199  * intervals. That is, it is given a set of possible arguments and it returns
1200  * the set of possible values.
1201  *
1202  *//*--------------------------------------------------------------------*/
1203 template <typename Sig_>
1204 class Func : public FuncBase
1205 {
1206 public:
1207         typedef Sig_                                                                            Sig;
1208         typedef typename Sig::Ret                                                       Ret;
1209         typedef typename Sig::Arg0                                                      Arg0;
1210         typedef typename Sig::Arg1                                                      Arg1;
1211         typedef typename Sig::Arg2                                                      Arg2;
1212         typedef typename Sig::Arg3                                                      Arg3;
1213         typedef typename Sig::IRet                                                      IRet;
1214         typedef typename Sig::IArg0                                                     IArg0;
1215         typedef typename Sig::IArg1                                                     IArg1;
1216         typedef typename Sig::IArg2                                                     IArg2;
1217         typedef typename Sig::IArg3                                                     IArg3;
1218         typedef typename Sig::Args                                                      Args;
1219         typedef typename Sig::IArgs                                                     IArgs;
1220         typedef typename Sig::ArgExprs                                          ArgExprs;
1221
1222         void                            print                   (ostream&                       os,
1223                                                                                  const BaseArgExprs& args)                              const
1224         {
1225                 this->doPrint(os, args);
1226         }
1227
1228         IRet                            apply                   (const EvalContext&     ctx,
1229                                                                                  const IArg0&           arg0 = IArg0(),
1230                                                                                  const IArg1&           arg1 = IArg1(),
1231                                                                                  const IArg2&           arg2 = IArg2(),
1232                                                                                  const IArg3&           arg3 = IArg3())         const
1233         {
1234                 return this->applyArgs(ctx, IArgs(arg0, arg1, arg2, arg3));
1235         }
1236         IRet                            applyArgs               (const EvalContext&     ctx,
1237                                                                                  const IArgs&           args)                           const
1238         {
1239                 return this->doApply(ctx, args);
1240         }
1241         ExprP<Ret>                      operator()              (const ExprP<Arg0>&             arg0 = voidP(),
1242                                                                                  const ExprP<Arg1>&             arg1 = voidP(),
1243                                                                                  const ExprP<Arg2>&             arg2 = voidP(),
1244                                                                                  const ExprP<Arg3>&             arg3 = voidP())         const;
1245
1246         const ParamNames&       getParamNames   (void)                                                                  const
1247         {
1248                 return this->doGetParamNames();
1249         }
1250
1251 protected:
1252         virtual IRet            doApply                 (const EvalContext&,
1253                                                                                  const IArgs&)                                                  const = 0;
1254         virtual void            doPrint                 (ostream& os, const BaseArgExprs& args) const
1255         {
1256                 os << getName() << "(";
1257
1258                 if (isTypeValid<Arg0>())
1259                         os << *args[0];
1260
1261                 if (isTypeValid<Arg1>())
1262                         os << ", " << *args[1];
1263
1264                 if (isTypeValid<Arg2>())
1265                         os << ", " << *args[2];
1266
1267                 if (isTypeValid<Arg3>())
1268                         os << ", " << *args[3];
1269
1270                 os << ")";
1271         }
1272
1273         virtual const ParamNames&       doGetParamNames (void)                                                  const
1274         {
1275                 static ParamNames       names   ("a", "b", "c", "d");
1276                 return names;
1277         }
1278 };
1279
1280 template <typename Sig>
1281 class Apply : public Expr<typename Sig::Ret>
1282 {
1283 public:
1284         typedef typename Sig::Ret                               Ret;
1285         typedef typename Sig::Arg0                              Arg0;
1286         typedef typename Sig::Arg1                              Arg1;
1287         typedef typename Sig::Arg2                              Arg2;
1288         typedef typename Sig::Arg3                              Arg3;
1289         typedef typename Expr<Ret>::Val                 Val;
1290         typedef typename Expr<Ret>::IVal                IVal;
1291         typedef Func<Sig>                                               ApplyFunc;
1292         typedef typename ApplyFunc::ArgExprs    ArgExprs;
1293
1294                                                 Apply   (const ApplyFunc&               func,
1295                                                                  const ExprP<Arg0>&             arg0 = voidP(),
1296                                                                  const ExprP<Arg1>&             arg1 = voidP(),
1297                                                                  const ExprP<Arg2>&             arg2 = voidP(),
1298                                                                  const ExprP<Arg3>&             arg3 = voidP())
1299                                                         : m_func        (func),
1300                                                           m_args        (arg0, arg1, arg2, arg3) {}
1301
1302                                                 Apply   (const ApplyFunc&       func,
1303                                                                  const ArgExprs&        args)
1304                                                         : m_func        (func),
1305                                                           m_args        (args) {}
1306 protected:
1307         void                            doPrintExpr                     (ostream& os) const
1308         {
1309                 BaseArgExprs    args;
1310                 args.push_back(m_args.a.get());
1311                 args.push_back(m_args.b.get());
1312                 args.push_back(m_args.c.get());
1313                 args.push_back(m_args.d.get());
1314                 m_func.print(os, args);
1315         }
1316
1317         IVal                            doEvaluate              (const EvalContext& ctx) const
1318         {
1319                 return m_func.apply(ctx,
1320                                                         m_args.a->evaluate(ctx), m_args.b->evaluate(ctx),
1321                                                         m_args.c->evaluate(ctx), m_args.d->evaluate(ctx));
1322         }
1323
1324         void                            doGetUsedFuncs  (FuncSet& dst) const
1325         {
1326                 m_func.getUsedFuncs(dst);
1327                 m_args.a->getUsedFuncs(dst);
1328                 m_args.b->getUsedFuncs(dst);
1329                 m_args.c->getUsedFuncs(dst);
1330                 m_args.d->getUsedFuncs(dst);
1331         }
1332
1333         const ApplyFunc&        m_func;
1334         ArgExprs                        m_args;
1335 };
1336
1337 template<typename T>
1338 class Alternatives : public Func<Signature<T, T, T> >
1339 {
1340 public:
1341         typedef typename        Alternatives::Sig               Sig;
1342
1343 protected:
1344         typedef typename        Alternatives::IRet              IRet;
1345         typedef typename        Alternatives::IArgs             IArgs;
1346
1347         virtual string          getName                         (void) const                    { return "alternatives"; }
1348         virtual void            doPrintDefinition       (std::ostream&) const   {}
1349         void                            doGetUsedFuncs          (FuncSet&) const                {}
1350
1351         virtual IRet            doApply                         (const EvalContext&, const IArgs& args) const
1352         {
1353                 return unionIVal<T>(args.a, args.b);
1354         }
1355
1356         virtual void            doPrint                         (ostream& os, const BaseArgExprs& args) const
1357         {
1358                 os << "{" << *args[0] << " | " << *args[1] << "}";
1359         }
1360 };
1361
1362 template <typename Sig>
1363 ExprP<typename Sig::Ret> createApply (const Func<Sig>&                                          func,
1364                                                                           const typename Func<Sig>::ArgExprs&   args)
1365 {
1366         return exprP(new Apply<Sig>(func, args));
1367 }
1368
1369 template <typename Sig>
1370 ExprP<typename Sig::Ret> createApply (
1371         const Func<Sig>&                        func,
1372         const ExprP<typename Sig::Arg0>&        arg0 = voidP(),
1373         const ExprP<typename Sig::Arg1>&        arg1 = voidP(),
1374         const ExprP<typename Sig::Arg2>&        arg2 = voidP(),
1375         const ExprP<typename Sig::Arg3>&        arg3 = voidP())
1376 {
1377         return exprP(new Apply<Sig>(func, arg0, arg1, arg2, arg3));
1378 }
1379
1380 template <typename Sig>
1381 ExprP<typename Sig::Ret> Func<Sig>::operator() (const ExprP<typename Sig::Arg0>& arg0,
1382                                                                                                 const ExprP<typename Sig::Arg1>& arg1,
1383                                                                                                 const ExprP<typename Sig::Arg2>& arg2,
1384                                                                                                 const ExprP<typename Sig::Arg3>& arg3) const
1385 {
1386         return createApply(*this, arg0, arg1, arg2, arg3);
1387 }
1388
1389 template <typename F>
1390 ExprP<typename F::Ret> app (const ExprP<typename F::Arg0>& arg0 = voidP(),
1391                                                         const ExprP<typename F::Arg1>& arg1 = voidP(),
1392                                                         const ExprP<typename F::Arg2>& arg2 = voidP(),
1393                                                         const ExprP<typename F::Arg3>& arg3 = voidP())
1394 {
1395         return createApply(instance<F>(), arg0, arg1, arg2, arg3);
1396 }
1397
1398 template <typename F>
1399 typename F::IRet call (const EvalContext&                       ctx,
1400                                            const typename F::IArg0&             arg0 = Void(),
1401                                            const typename F::IArg1&             arg1 = Void(),
1402                                            const typename F::IArg2&             arg2 = Void(),
1403                                            const typename F::IArg3&             arg3 = Void())
1404 {
1405         return instance<F>().apply(ctx, arg0, arg1, arg2, arg3);
1406 }
1407
1408 template <typename T>
1409 ExprP<T> alternatives (const ExprP<T>& arg0,
1410                                            const ExprP<T>& arg1)
1411 {
1412         return createApply<typename Alternatives<T>::Sig>(instance<Alternatives<T> >(), arg0, arg1);
1413 }
1414
1415 template <typename Sig>
1416 class ApplyVar : public Apply<Sig>
1417 {
1418 public:
1419         typedef typename Sig::Ret                               Ret;
1420         typedef typename Sig::Arg0                              Arg0;
1421         typedef typename Sig::Arg1                              Arg1;
1422         typedef typename Sig::Arg2                              Arg2;
1423         typedef typename Sig::Arg3                              Arg3;
1424         typedef typename Expr<Ret>::Val                 Val;
1425         typedef typename Expr<Ret>::IVal                IVal;
1426         typedef Func<Sig>                                               ApplyFunc;
1427         typedef typename ApplyFunc::ArgExprs    ArgExprs;
1428
1429                                                 ApplyVar        (const ApplyFunc&                       func,
1430                                                                          const VariableP<Arg0>&         arg0,
1431                                                                          const VariableP<Arg1>&         arg1,
1432                                                                          const VariableP<Arg2>&         arg2,
1433                                                                          const VariableP<Arg3>&         arg3)
1434                                                         : Apply<Sig> (func, arg0, arg1, arg2, arg3) {}
1435 protected:
1436         IVal                            doEvaluate              (const EvalContext& ctx) const
1437         {
1438                 const Variable<Arg0>&   var0 = static_cast<const Variable<Arg0>&>(*this->m_args.a);
1439                 const Variable<Arg1>&   var1 = static_cast<const Variable<Arg1>&>(*this->m_args.b);
1440                 const Variable<Arg2>&   var2 = static_cast<const Variable<Arg2>&>(*this->m_args.c);
1441                 const Variable<Arg3>&   var3 = static_cast<const Variable<Arg3>&>(*this->m_args.d);
1442                 return this->m_func.apply(ctx,
1443                                                                   ctx.env.lookup(var0), ctx.env.lookup(var1),
1444                                                                   ctx.env.lookup(var2), ctx.env.lookup(var3));
1445         }
1446 };
1447
1448 template <typename Sig>
1449 ExprP<typename Sig::Ret> applyVar (const Func<Sig>&                                             func,
1450                                                                    const VariableP<typename Sig::Arg0>& arg0,
1451                                                                    const VariableP<typename Sig::Arg1>& arg1,
1452                                                                    const VariableP<typename Sig::Arg2>& arg2,
1453                                                                    const VariableP<typename Sig::Arg3>& arg3)
1454 {
1455         return exprP(new ApplyVar<Sig>(func, arg0, arg1, arg2, arg3));
1456 }
1457
1458 template <typename Sig_>
1459 class DerivedFunc : public Func<Sig_>
1460 {
1461 public:
1462         typedef typename DerivedFunc::ArgExprs          ArgExprs;
1463         typedef typename DerivedFunc::IRet                      IRet;
1464         typedef typename DerivedFunc::IArgs                     IArgs;
1465         typedef typename DerivedFunc::Ret                       Ret;
1466         typedef typename DerivedFunc::Arg0                      Arg0;
1467         typedef typename DerivedFunc::Arg1                      Arg1;
1468         typedef typename DerivedFunc::Arg2                      Arg2;
1469         typedef typename DerivedFunc::Arg3                      Arg3;
1470         typedef typename DerivedFunc::IArg0                     IArg0;
1471         typedef typename DerivedFunc::IArg1                     IArg1;
1472         typedef typename DerivedFunc::IArg2                     IArg2;
1473         typedef typename DerivedFunc::IArg3                     IArg3;
1474
1475 protected:
1476         void                                            doPrintDefinition       (ostream& os) const
1477         {
1478                 const ParamNames&       paramNames      = this->getParamNames();
1479
1480                 initialize();
1481
1482                 os << dataTypeNameOf<Ret>() << " " << this->getName()
1483                         << "(";
1484                 if (isTypeValid<Arg0>())
1485                         os << dataTypeNameOf<Arg0>() << " " << paramNames.a;
1486                 if (isTypeValid<Arg1>())
1487                         os << ", " << dataTypeNameOf<Arg1>() << " " << paramNames.b;
1488                 if (isTypeValid<Arg2>())
1489                         os << ", " << dataTypeNameOf<Arg2>() << " " << paramNames.c;
1490                 if (isTypeValid<Arg3>())
1491                         os << ", " << dataTypeNameOf<Arg3>() << " " << paramNames.d;
1492                 os << ")\n{\n";
1493
1494                 for (size_t ndx = 0; ndx < m_body.size(); ++ndx)
1495                         os << *m_body[ndx];
1496                 os << "return " << *m_ret << ";\n";
1497                 os << "}\n";
1498         }
1499
1500         IRet                                            doApply                 (const EvalContext&     ctx,
1501                                                                                                  const IArgs&           args) const
1502         {
1503                 Environment     funEnv;
1504                 IArgs&          mutArgs         = const_cast<IArgs&>(args);
1505                 IRet            ret;
1506
1507                 initialize();
1508
1509                 funEnv.bind(*m_var0, args.a);
1510                 funEnv.bind(*m_var1, args.b);
1511                 funEnv.bind(*m_var2, args.c);
1512                 funEnv.bind(*m_var3, args.d);
1513
1514                 {
1515                         EvalContext     funCtx(ctx.format, ctx.floatPrecision, funEnv, ctx.callDepth);
1516
1517                         for (size_t ndx = 0; ndx < m_body.size(); ++ndx)
1518                                 m_body[ndx]->execute(funCtx);
1519
1520                         ret = m_ret->evaluate(funCtx);
1521                 }
1522
1523                 // \todo [lauri] Store references instead of values in environment
1524                 const_cast<IArg0&>(mutArgs.a) = funEnv.lookup(*m_var0);
1525                 const_cast<IArg1&>(mutArgs.b) = funEnv.lookup(*m_var1);
1526                 const_cast<IArg2&>(mutArgs.c) = funEnv.lookup(*m_var2);
1527                 const_cast<IArg3&>(mutArgs.d) = funEnv.lookup(*m_var3);
1528
1529                 return ret;
1530         }
1531
1532         void                                            doGetUsedFuncs  (FuncSet& dst) const
1533         {
1534                 initialize();
1535                 if (dst.insert(this).second)
1536                 {
1537                         for (size_t ndx = 0; ndx < m_body.size(); ++ndx)
1538                                 m_body[ndx]->getUsedFuncs(dst);
1539                         m_ret->getUsedFuncs(dst);
1540                 }
1541         }
1542
1543         virtual ExprP<Ret>                      doExpand                (ExpandContext& ctx, const ArgExprs& args_) const = 0;
1544
1545         // These are transparently initialized when first needed. They cannot be
1546         // initialized in the constructor because they depend on the doExpand
1547         // method of the subclass.
1548
1549         mutable VariableP<Arg0>         m_var0;
1550         mutable VariableP<Arg1>         m_var1;
1551         mutable VariableP<Arg2>         m_var2;
1552         mutable VariableP<Arg3>         m_var3;
1553         mutable vector<StatementP>      m_body;
1554         mutable ExprP<Ret>                      m_ret;
1555
1556 private:
1557
1558         void                            initialize              (void)  const
1559         {
1560                 if (!m_ret)
1561                 {
1562                         const ParamNames&       paramNames      = this->getParamNames();
1563                         Counter                         symCounter;
1564                         ExpandContext           ctx                     (symCounter);
1565                         ArgExprs                        args;
1566
1567                         args.a  = m_var0 = variable<Arg0>(paramNames.a);
1568                         args.b  = m_var1 = variable<Arg1>(paramNames.b);
1569                         args.c  = m_var2 = variable<Arg2>(paramNames.c);
1570                         args.d  = m_var3 = variable<Arg3>(paramNames.d);
1571
1572                         m_ret   = this->doExpand(ctx, args);
1573                         m_body  = ctx.getStatements();
1574                 }
1575         }
1576 };
1577
1578 template <typename Sig>
1579 class PrimitiveFunc : public Func<Sig>
1580 {
1581 public:
1582         typedef typename PrimitiveFunc::Ret                     Ret;
1583         typedef typename PrimitiveFunc::ArgExprs        ArgExprs;
1584
1585 protected:
1586         void    doPrintDefinition       (ostream&) const        {}
1587         void    doGetUsedFuncs          (FuncSet&) const        {}
1588 };
1589
1590 template <typename T>
1591 class Cond : public PrimitiveFunc<Signature<T, bool, T, T> >
1592 {
1593 public:
1594         typedef typename Cond::IArgs    IArgs;
1595         typedef typename Cond::IRet             IRet;
1596
1597         string  getName (void) const
1598         {
1599                 return "_cond";
1600         }
1601
1602 protected:
1603
1604         void    doPrint (ostream& os, const BaseArgExprs& args) const
1605         {
1606                 os << "(" << *args[0] << " ? " << *args[1] << " : " << *args[2] << ")";
1607         }
1608
1609         IRet    doApply (const EvalContext&, const IArgs& iargs)const
1610         {
1611                 IRet    ret;
1612
1613                 if (iargs.a.contains(true))
1614                         ret = unionIVal<T>(ret, iargs.b);
1615
1616                 if (iargs.a.contains(false))
1617                         ret = unionIVal<T>(ret, iargs.c);
1618
1619                 return ret;
1620         }
1621 };
1622
1623 template <typename T>
1624 class CompareOperator : public PrimitiveFunc<Signature<bool, T, T> >
1625 {
1626 public:
1627         typedef typename CompareOperator::IArgs IArgs;
1628         typedef typename CompareOperator::IArg0 IArg0;
1629         typedef typename CompareOperator::IArg1 IArg1;
1630         typedef typename CompareOperator::IRet  IRet;
1631
1632 protected:
1633         void                    doPrint (ostream& os, const BaseArgExprs& args) const
1634         {
1635                 os << "(" << *args[0] << getSymbol() << *args[1] << ")";
1636         }
1637
1638         Interval                doApply (const EvalContext&, const IArgs& iargs) const
1639         {
1640                 const IArg0&    arg0 = iargs.a;
1641                 const IArg1&    arg1 = iargs.b;
1642                 IRet    ret;
1643
1644                 if (canSucceed(arg0, arg1))
1645                         ret |= true;
1646                 if (canFail(arg0, arg1))
1647                         ret |= false;
1648
1649                 return ret;
1650         }
1651
1652         virtual string  getSymbol       (void) const = 0;
1653         virtual bool    canSucceed      (const IArg0&, const IArg1&) const = 0;
1654         virtual bool    canFail         (const IArg0&, const IArg1&) const = 0;
1655 };
1656
1657 template <typename T>
1658 class LessThan : public CompareOperator<T>
1659 {
1660 public:
1661         string  getName         (void) const                                                                    { return "lessThan"; }
1662
1663 protected:
1664         string  getSymbol       (void) const                                                                    { return "<";           }
1665
1666         bool    canSucceed      (const Interval& a, const Interval& b) const
1667         {
1668                 return (a.lo() < b.hi());
1669         }
1670
1671         bool    canFail         (const Interval& a, const Interval& b) const
1672         {
1673                 return !(a.hi() < b.lo());
1674         }
1675 };
1676
1677 template <typename T>
1678 ExprP<bool> operator< (const ExprP<T>& a, const ExprP<T>& b)
1679 {
1680         return app<LessThan<T> >(a, b);
1681 }
1682
1683 template <typename T>
1684 ExprP<T> cond (const ExprP<bool>&       test,
1685                            const ExprP<T>&              consequent,
1686                            const ExprP<T>&              alternative)
1687 {
1688         return app<Cond<T> >(test, consequent, alternative);
1689 }
1690
1691 /*--------------------------------------------------------------------*//*!
1692  *
1693  * @}
1694  *
1695  *//*--------------------------------------------------------------------*/
1696
1697 class FloatFunc1 : public PrimitiveFunc<Signature<float, float> >
1698 {
1699 protected:
1700         Interval                        doApply                 (const EvalContext& ctx, const IArgs& iargs) const
1701         {
1702                 return this->applyMonotone(ctx, iargs.a);
1703         }
1704
1705         Interval                        applyMonotone   (const EvalContext& ctx, const Interval& iarg0) const
1706         {
1707                 Interval ret;
1708
1709                 TCU_INTERVAL_APPLY_MONOTONE1(ret, arg0, iarg0, val,
1710                                                                          TCU_SET_INTERVAL(val, point,
1711                                                                                                           point = this->applyPoint(ctx, arg0)));
1712
1713                 ret |= innerExtrema(ctx, iarg0);
1714                 ret &= (this->getCodomain() | TCU_NAN);
1715
1716                 return ctx.format.convert(ret);
1717         }
1718
1719         virtual Interval        innerExtrema    (const EvalContext&, const Interval&) const
1720         {
1721                 return Interval(); // empty interval, i.e. no extrema
1722         }
1723
1724         virtual Interval        applyPoint              (const EvalContext& ctx, double arg0) const
1725         {
1726                 const double    exact   = this->applyExact(arg0);
1727                 const double    prec    = this->precision(ctx, exact, arg0);
1728                 const double    wprec   = this->warningPrecision(ctx, exact, arg0);
1729                 Interval                ioutput = exact + Interval(-prec, prec);
1730                 ioutput.warning(exact - wprec, exact + wprec);
1731                 return ioutput;
1732         }
1733
1734         virtual double          applyExact              (double) const
1735         {
1736                 TCU_THROW(InternalError, "Cannot apply");
1737         }
1738
1739         virtual Interval        getCodomain             (void) const
1740         {
1741                 return Interval::unbounded(true);
1742         }
1743
1744         virtual double          precision               (const EvalContext& ctx, double, double) const = 0;
1745
1746         virtual double  warningPrecision                (const EvalContext& ctx, double exact, double arg0) const
1747         {
1748                 return precision(ctx, exact, arg0);
1749         }
1750
1751 };
1752
1753 class CFloatFunc1 : public FloatFunc1
1754 {
1755 public:
1756                         CFloatFunc1     (const string& name, DoubleFunc1& func)
1757                                 : m_name(name), m_func(func) {}
1758
1759         string                  getName         (void) const            { return m_name; }
1760
1761 protected:
1762         double                  applyExact      (double x) const        { return m_func(x); }
1763
1764         const string    m_name;
1765         DoubleFunc1&    m_func;
1766 };
1767
1768 class FloatFunc2 : public PrimitiveFunc<Signature<float, float, float> >
1769 {
1770 protected:
1771         Interval                        doApply                 (const EvalContext&     ctx, const IArgs& iargs) const
1772         {
1773                 return this->applyMonotone(ctx, iargs.a, iargs.b);
1774         }
1775
1776         Interval                        applyMonotone   (const EvalContext&     ctx,
1777                                                                                  const Interval&        xi,
1778                                                                                  const Interval&        yi) const
1779         {
1780                 Interval reti;
1781
1782                 TCU_INTERVAL_APPLY_MONOTONE2(reti, x, xi, y, yi, ret,
1783                                                                          TCU_SET_INTERVAL(ret, point,
1784                                                                                                           point = this->applyPoint(ctx, x, y)));
1785                 reti |= innerExtrema(ctx, xi, yi);
1786                 reti &= (this->getCodomain() | TCU_NAN);
1787
1788                 return ctx.format.convert(reti);
1789         }
1790
1791         virtual Interval        innerExtrema    (const EvalContext&,
1792                                                                                  const Interval&,
1793                                                                                  const Interval&) const
1794         {
1795                 return Interval(); // empty interval, i.e. no extrema
1796         }
1797
1798         virtual Interval        applyPoint              (const EvalContext&     ctx,
1799                                                                                  double                         x,
1800                                                                                  double                         y) const
1801         {
1802                 const double exact      = this->applyExact(x, y);
1803                 const double prec       = this->precision(ctx, exact, x, y);
1804
1805                 return exact + Interval(-prec, prec);
1806         }
1807
1808         virtual double          applyExact              (double, double) const
1809         {
1810                 TCU_THROW(InternalError, "Cannot apply");
1811         }
1812
1813         virtual Interval        getCodomain             (void) const
1814         {
1815                 return Interval::unbounded(true);
1816         }
1817
1818         virtual double          precision               (const EvalContext&     ctx,
1819                                                                                  double                         ret,
1820                                                                                  double                         x,
1821                                                                                  double                         y) const = 0;
1822 };
1823
1824 class CFloatFunc2 : public FloatFunc2
1825 {
1826 public:
1827                                         CFloatFunc2     (const string&  name,
1828                                                                  DoubleFunc2&   func)
1829                                                 : m_name(name)
1830                                                 , m_func(func)
1831         {
1832         }
1833
1834         string                  getName         (void) const                                            { return m_name; }
1835
1836 protected:
1837         double                  applyExact      (double x, double y) const                      { return m_func(x, y); }
1838
1839         const string    m_name;
1840         DoubleFunc2&    m_func;
1841 };
1842
1843 class InfixOperator : public FloatFunc2
1844 {
1845 protected:
1846         virtual string  getSymbol               (void) const = 0;
1847
1848         void                    doPrint                 (ostream& os, const BaseArgExprs& args) const
1849         {
1850                 os << "(" << *args[0] << " " << getSymbol() << " " << *args[1] << ")";
1851         }
1852
1853         Interval                applyPoint              (const EvalContext&     ctx,
1854                                                                          double                         x,
1855                                                                          double                         y) const
1856         {
1857                 const double exact      = this->applyExact(x, y);
1858
1859                 // Allow either representable number on both sides of the exact value,
1860                 // but require exactly representable values to be preserved.
1861                 return ctx.format.roundOut(exact, !deIsInf(x) && !deIsInf(y));
1862         }
1863
1864         double                  precision               (const EvalContext&, double, double, double) const
1865         {
1866                 return 0.0;
1867         }
1868 };
1869
1870 class FloatFunc3 : public PrimitiveFunc<Signature<float, float, float, float> >
1871 {
1872 protected:
1873         Interval                        doApply                 (const EvalContext&     ctx, const IArgs& iargs) const
1874         {
1875                 return this->applyMonotone(ctx, iargs.a, iargs.b, iargs.c);
1876         }
1877
1878         Interval                        applyMonotone   (const EvalContext&     ctx,
1879                                                                                  const Interval&        xi,
1880                                                                                  const Interval&        yi,
1881                                                                                  const Interval&        zi) const
1882         {
1883                 Interval reti;
1884                 TCU_INTERVAL_APPLY_MONOTONE3(reti, x, xi, y, yi, z, zi, ret,
1885                                                                          TCU_SET_INTERVAL(ret, point,
1886                                                                                                           point = this->applyPoint(ctx, x, y, z)));
1887                 return ctx.format.convert(reti);
1888         }
1889
1890         virtual Interval        applyPoint              (const EvalContext&     ctx,
1891                                                                                  double                         x,
1892                                                                                  double                         y,
1893                                                                                  double                         z) const
1894         {
1895                 const double exact      = this->applyExact(x, y, z);
1896                 const double prec       = this->precision(ctx, exact, x, y, z);
1897                 return exact + Interval(-prec, prec);
1898         }
1899
1900         virtual double          applyExact              (double, double, double) const
1901         {
1902                 TCU_THROW(InternalError, "Cannot apply");
1903         }
1904
1905         virtual double          precision               (const EvalContext&     ctx,
1906                                                                                  double                         result,
1907                                                                                  double                         x,
1908                                                                                  double                         y,
1909                                                                                  double                         z) const = 0;
1910 };
1911
1912 // We define syntactic sugar functions for expression constructors. Since
1913 // these have the same names as ordinary mathematical operations (sin, log
1914 // etc.), it's better to give them a dedicated namespace.
1915 namespace Functions
1916 {
1917
1918 using namespace tcu;
1919
1920 class Add : public InfixOperator
1921 {
1922 public:
1923         string          getName         (void) const                                            { return "add"; }
1924         string          getSymbol       (void) const                                            { return "+"; }
1925
1926         Interval        doApply         (const EvalContext&     ctx,
1927                                                          const IArgs&           iargs) const
1928         {
1929                 // Fast-path for common case
1930                 if (iargs.a.isOrdinary(ctx.format.getMaxValue()) && iargs.b.isOrdinary(ctx.format.getMaxValue()))
1931                 {
1932                         Interval ret;
1933                         TCU_SET_INTERVAL_BOUNDS(ret, sum,
1934                                                                         sum = iargs.a.lo() + iargs.b.lo(),
1935                                                                         sum = iargs.a.hi() + iargs.b.hi());
1936                         return ctx.format.convert(ctx.format.roundOut(ret, true));
1937                 }
1938                 return this->applyMonotone(ctx, iargs.a, iargs.b);
1939         }
1940
1941 protected:
1942         double          applyExact      (double x, double y) const                      { return x + y; }
1943 };
1944
1945 class Mul : public InfixOperator
1946 {
1947 public:
1948         string          getName         (void) const                                                                    { return "mul"; }
1949         string          getSymbol       (void) const                                                                    { return "*"; }
1950
1951         Interval        doApply         (const EvalContext&     ctx, const IArgs& iargs) const
1952         {
1953                 Interval a = iargs.a;
1954                 Interval b = iargs.b;
1955
1956                 // Fast-path for common case
1957                 if (a.isOrdinary(ctx.format.getMaxValue()) && b.isOrdinary(ctx.format.getMaxValue()))
1958                 {
1959                         Interval ret;
1960                         if (a.hi() < 0)
1961                         {
1962                                 a = -a;
1963                                 b = -b;
1964                         }
1965                         if (a.lo() >= 0 && b.lo() >= 0)
1966                         {
1967                                 TCU_SET_INTERVAL_BOUNDS(ret, prod,
1968                                                                                 prod = iargs.a.lo() * iargs.b.lo(),
1969                                                                                 prod = iargs.a.hi() * iargs.b.hi());
1970                                 return ctx.format.convert(ctx.format.roundOut(ret, true));
1971                         }
1972                         if (a.lo() >= 0 && b.hi() <= 0)
1973                         {
1974                                 TCU_SET_INTERVAL_BOUNDS(ret, prod,
1975                                                                                 prod = iargs.a.hi() * iargs.b.lo(),
1976                                                                                 prod = iargs.a.lo() * iargs.b.hi());
1977                                 return ctx.format.convert(ctx.format.roundOut(ret, true));
1978                         }
1979                 }
1980                 return this->applyMonotone(ctx, iargs.a, iargs.b);
1981         }
1982
1983 protected:
1984         double          applyExact      (double x, double y) const                                              { return x * y; }
1985
1986         Interval        innerExtrema(const EvalContext&, const Interval& xi, const Interval& yi) const
1987         {
1988                 if (((xi.contains(-TCU_INFINITY) || xi.contains(TCU_INFINITY)) && yi.contains(0.0)) ||
1989                         ((yi.contains(-TCU_INFINITY) || yi.contains(TCU_INFINITY)) && xi.contains(0.0)))
1990                         return Interval(TCU_NAN);
1991
1992                 return Interval();
1993         }
1994 };
1995
1996 class Sub : public InfixOperator
1997 {
1998 public:
1999         string          getName         (void) const                            { return "sub"; }
2000         string          getSymbol       (void) const                            { return "-"; }
2001
2002         Interval        doApply         (const EvalContext&     ctx, const IArgs& iargs) const
2003         {
2004                 // Fast-path for common case
2005                 if (iargs.a.isOrdinary(ctx.format.getMaxValue()) && iargs.b.isOrdinary(ctx.format.getMaxValue()))
2006                 {
2007                         Interval ret;
2008
2009                         TCU_SET_INTERVAL_BOUNDS(ret, diff,
2010                                                                         diff = iargs.a.lo() - iargs.b.hi(),
2011                                                                         diff = iargs.a.hi() - iargs.b.lo());
2012                         return ctx.format.convert(ctx.format.roundOut(ret, true));
2013
2014                 }
2015                 else
2016                 {
2017                         return this->applyMonotone(ctx, iargs.a, iargs.b);
2018                 }
2019         }
2020
2021 protected:
2022         double          applyExact      (double x, double y) const      { return x - y; }
2023 };
2024
2025 class Negate : public FloatFunc1
2026 {
2027 public:
2028         string  getName         (void) const                                                                    { return "_negate"; }
2029         void    doPrint         (ostream& os, const BaseArgExprs& args) const   { os << "-" << *args[0]; }
2030
2031 protected:
2032         double  precision       (const EvalContext&, double, double) const              { return 0.0; }
2033         double  applyExact      (double x) const                                                                { return -x; }
2034 };
2035
2036 class Div : public InfixOperator
2037 {
2038 public:
2039         string          getName                 (void) const                                            { return "div"; }
2040
2041 protected:
2042         string          getSymbol               (void) const                                            { return "/"; }
2043
2044         Interval        innerExtrema    (const EvalContext&,
2045                                                                  const Interval&                nom,
2046                                                                  const Interval&                den) const
2047         {
2048                 Interval ret;
2049
2050                 if (den.contains(0.0))
2051                 {
2052                         if (nom.contains(0.0))
2053                                 ret |= TCU_NAN;
2054
2055                         if (nom.lo() < 0.0 || nom.hi() > 0.0)
2056                                 ret |= Interval::unbounded();
2057                 }
2058
2059                 return ret;
2060         }
2061
2062         double          applyExact              (double x, double y) const { return x / y; }
2063
2064         Interval        applyPoint              (const EvalContext&     ctx, double x, double y) const
2065         {
2066                 Interval ret = FloatFunc2::applyPoint(ctx, x, y);
2067
2068                 if (!deIsInf(x) && !deIsInf(y) && y != 0.0)
2069                 {
2070                         const Interval dst = ctx.format.convert(ret);
2071                         if (dst.contains(-TCU_INFINITY)) ret |= -ctx.format.getMaxValue();
2072                         if (dst.contains(+TCU_INFINITY)) ret |= +ctx.format.getMaxValue();
2073                 }
2074
2075                 return ret;
2076         }
2077
2078         double          precision               (const EvalContext& ctx, double ret, double, double den) const
2079         {
2080                 const FloatFormat&      fmt             = ctx.format;
2081
2082                 // \todo [2014-03-05 lauri] Check that the limits in GLSL 3.10 are actually correct.
2083                 // For now, we assume that division's precision is 2.5 ULP when the value is within
2084                 // [2^MINEXP, 2^MAXEXP-1]
2085
2086                 if (den == 0.0)
2087                         return 0.0; // Result must be exactly inf
2088                 else if (de::inBounds(deAbs(den),
2089                                                           deLdExp(1.0, fmt.getMinExp()),
2090                                                           deLdExp(1.0, fmt.getMaxExp() - 1)))
2091                         return fmt.ulp(ret, 2.5);
2092                 else
2093                         return TCU_INFINITY; // Can be any number, but must be a number.
2094         }
2095 };
2096
2097 class InverseSqrt : public FloatFunc1
2098 {
2099 public:
2100         string          getName         (void) const                                                    { return "inversesqrt"; }
2101
2102 protected:
2103         double          applyExact      (double x) const                                                { return 1.0 / deSqrt(x); }
2104
2105         double          precision       (const EvalContext& ctx, double ret, double x) const
2106         {
2107                 return x <= 0 ? TCU_NAN : ctx.format.ulp(ret, 2.0);
2108         }
2109
2110         Interval        getCodomain     (void) const
2111         {
2112                 return Interval(0.0, TCU_INFINITY);
2113         }
2114 };
2115
2116 class ExpFunc : public CFloatFunc1
2117 {
2118 public:
2119                                 ExpFunc         (const string& name, DoubleFunc1& func)
2120                                         : CFloatFunc1(name, func) {}
2121 protected:
2122         double          precision       (const EvalContext& ctx, double ret, double x) const
2123         {
2124                 switch (ctx.floatPrecision)
2125                 {
2126                         case glu::PRECISION_HIGHP:
2127                                 return ctx.format.ulp(ret, 3.0 + 2.0 * deAbs(x));
2128                         case glu::PRECISION_MEDIUMP:
2129                                 return ctx.format.ulp(ret, 2.0 + 2.0 * deAbs(x));
2130                         case glu::PRECISION_LOWP:
2131                                 return ctx.format.ulp(ret, 2.0);
2132                         default:
2133                                 DE_FATAL("Impossible");
2134                 }
2135                 return 0;
2136         }
2137
2138         Interval        getCodomain     (void) const
2139         {
2140                 return Interval(0.0, TCU_INFINITY);
2141         }
2142 };
2143
2144 class Exp2      : public ExpFunc        { public: Exp2 (void)   : ExpFunc("exp2", deExp2) {} };
2145 class Exp       : public ExpFunc        { public: Exp (void)    : ExpFunc("exp", deExp) {} };
2146
2147 ExprP<float> exp2       (const ExprP<float>& x) { return app<Exp2>(x); }
2148 ExprP<float> exp        (const ExprP<float>& x) { return app<Exp>(x); }
2149
2150 class LogFunc : public CFloatFunc1
2151 {
2152 public:
2153                                 LogFunc         (const string& name, DoubleFunc1& func)
2154                                         : CFloatFunc1(name, func) {}
2155
2156 protected:
2157         double          precision       (const EvalContext& ctx, double ret, double x) const
2158         {
2159                 if (x <= 0)
2160                         return TCU_NAN;
2161
2162                 switch (ctx.floatPrecision)
2163                 {
2164                         case glu::PRECISION_HIGHP:
2165                                 return (0.5 <= x && x <= 2.0) ? deLdExp(1.0, -21) : ctx.format.ulp(ret, 3.0);
2166                         case glu::PRECISION_MEDIUMP:
2167                                 return (0.5 <= x && x <= 2.0) ? deLdExp(1.0, -7) : ctx.format.ulp(ret, 2.0);
2168                         case glu::PRECISION_LOWP:
2169                                 return ctx.format.ulp(ret, 2.0);
2170                         default:
2171                                 DE_FATAL("Impossible");
2172                 }
2173
2174                 return 0;
2175         }
2176
2177         // OpenGL API Issue #57 "Clarifying the required ULP precision for GLSL built-in log()". Agreed that
2178         // implementations will be allowed 4 ULPs for HIGHP Log/Log2, but CTS should generate a quality warning.
2179         double          warningPrecision(const EvalContext& ctx, double ret, double x) const
2180         {
2181                 if (ctx.floatPrecision == glu::PRECISION_HIGHP && x > 0)
2182                 {
2183                         return (0.5 <= x && x <= 2.0) ? deLdExp(1.0, -21) : ctx.format.ulp(ret, 4.0);
2184                 }
2185                 else
2186                 {
2187                         return precision(ctx, ret, x);
2188                 }
2189         }
2190
2191 };
2192
2193 class Log2      : public LogFunc                { public: Log2  (void) : LogFunc("log2", deLog2) {} };
2194 class Log       : public LogFunc                { public: Log   (void) : LogFunc("log", deLog) {} };
2195
2196 ExprP<float> log2       (const ExprP<float>& x) { return app<Log2>(x); }
2197 ExprP<float> log        (const ExprP<float>& x) { return app<Log>(x); }
2198
2199 #define DEFINE_CONSTRUCTOR1(CLASS, TRET, NAME, T0) \
2200 ExprP<TRET> NAME (const ExprP<T0>& arg0) { return app<CLASS>(arg0); }
2201
2202 #define DEFINE_DERIVED1(CLASS, TRET, NAME, T0, ARG0, EXPANSION)                 \
2203 class CLASS : public DerivedFunc<Signature<TRET, T0> > /* NOLINT(CLASS) */ \
2204 {                                                                                                                                               \
2205 public:                                                                                                                                 \
2206         string                  getName         (void) const            { return #NAME; }       \
2207                                                                                                                                                 \
2208 protected:                                                                                                                              \
2209         ExprP<TRET>             doExpand                (ExpandContext&,                                        \
2210                                                                          const CLASS::ArgExprs& args_) const \
2211         {                                                                                                                                       \
2212                 const ExprP<float>& ARG0 = args_.a;                                                             \
2213                 return EXPANSION;                                                                                               \
2214         }                                                                                                                                       \
2215 };                                                                                                                                              \
2216 DEFINE_CONSTRUCTOR1(CLASS, TRET, NAME, T0)
2217
2218 #define DEFINE_DERIVED_FLOAT1(CLASS, NAME, ARG0, EXPANSION) \
2219         DEFINE_DERIVED1(CLASS, float, NAME, float, ARG0, EXPANSION)
2220
2221 #define DEFINE_CONSTRUCTOR2(CLASS, TRET, NAME, T0, T1)                          \
2222 ExprP<TRET> NAME (const ExprP<T0>& arg0, const ExprP<T1>& arg1)         \
2223 {                                                                                                                                       \
2224         return app<CLASS>(arg0, arg1);                                                                  \
2225 }
2226
2227 #define DEFINE_DERIVED2(CLASS, TRET, NAME, T0, Arg0, T1, Arg1, EXPANSION) \
2228 class CLASS : public DerivedFunc<Signature<TRET, T0, T1> > /* NOLINT(CLASS) */  \
2229 {                                                                                                                                               \
2230 public:                                                                                                                                 \
2231         string                  getName         (void) const            { return #NAME; }       \
2232                                                                                                                                                 \
2233 protected:                                                                                                                              \
2234         ExprP<TRET>             doExpand        (ExpandContext&, const ArgExprs& args_) const \
2235         {                                                                                                                                       \
2236                 const ExprP<T0>& Arg0 = args_.a;                                                                \
2237                 const ExprP<T1>& Arg1 = args_.b;                                                                \
2238                 return EXPANSION;                                                                                               \
2239         }                                                                                                                                       \
2240 };                                                                                                                                              \
2241 DEFINE_CONSTRUCTOR2(CLASS, TRET, NAME, T0, T1)
2242
2243 #define DEFINE_DERIVED_FLOAT2(CLASS, NAME, Arg0, Arg1, EXPANSION)               \
2244         DEFINE_DERIVED2(CLASS, float, NAME, float, Arg0, float, Arg1, EXPANSION)
2245
2246 #define DEFINE_CONSTRUCTOR3(CLASS, TRET, NAME, T0, T1, T2)                              \
2247 ExprP<TRET> NAME (const ExprP<T0>& arg0, const ExprP<T1>& arg1, const ExprP<T2>& arg2) \
2248 {                                                                                                                                               \
2249         return app<CLASS>(arg0, arg1, arg2);                                                            \
2250 }
2251
2252 #define DEFINE_DERIVED3(CLASS, TRET, NAME, T0, ARG0, T1, ARG1, T2, ARG2, EXPANSION) \
2253 class CLASS : public DerivedFunc<Signature<TRET, T0, T1, T2> > /* NOLINT(CLASS) */      \
2254 {                                                                                                                                                               \
2255 public:                                                                                                                                                 \
2256         string                  getName         (void) const    { return #NAME; }                               \
2257                                                                                                                                                                 \
2258 protected:                                                                                                                                              \
2259         ExprP<TRET>             doExpand        (ExpandContext&, const ArgExprs& args_) const   \
2260         {                                                                                                                                                       \
2261                 const ExprP<T0>& ARG0 = args_.a;                                                                                \
2262                 const ExprP<T1>& ARG1 = args_.b;                                                                                \
2263                 const ExprP<T2>& ARG2 = args_.c;                                                                                \
2264                 return EXPANSION;                                                                                                               \
2265         }                                                                                                                                                       \
2266 };                                                                                                                                                              \
2267 DEFINE_CONSTRUCTOR3(CLASS, TRET, NAME, T0, T1, T2)
2268
2269 #define DEFINE_DERIVED_FLOAT3(CLASS, NAME, ARG0, ARG1, ARG2, EXPANSION)                 \
2270         DEFINE_DERIVED3(CLASS, float, NAME, float, ARG0, float, ARG1, float, ARG2, EXPANSION)
2271
2272 #define DEFINE_CONSTRUCTOR4(CLASS, TRET, NAME, T0, T1, T2, T3)                  \
2273 ExprP<TRET> NAME (const ExprP<T0>& arg0, const ExprP<T1>& arg1,                 \
2274                                   const ExprP<T2>& arg2, const ExprP<T3>& arg3)                 \
2275 {                                                                                                                                               \
2276         return app<CLASS>(arg0, arg1, arg2, arg3);                                                      \
2277 }
2278
2279 DEFINE_DERIVED_FLOAT1(Sqrt,             sqrt,           x,              (x == 0.0f ? constant(1.0f) : (constant(1.0f) / app<InverseSqrt>(x))))
2280 DEFINE_DERIVED_FLOAT2(Pow,              pow,            x,      y,      exp2(y * log2(x)))
2281 DEFINE_DERIVED_FLOAT1(Radians,  radians,        d,              (constant(DE_PI) / constant(180.0f)) * d)
2282 DEFINE_DERIVED_FLOAT1(Degrees,  degrees,        r,              (constant(180.0f) / constant(DE_PI)) * r)
2283
2284 class TrigFunc : public CFloatFunc1
2285 {
2286 public:
2287                                         TrigFunc                (const string&          name,
2288                                                                          DoubleFunc1&           func,
2289                                                                          const Interval&        loEx,
2290                                                                          const Interval&        hiEx)
2291                                                 : CFloatFunc1   (name, func)
2292                                                 , m_loExtremum  (loEx)
2293                                                 , m_hiExtremum  (hiEx) {}
2294
2295 protected:
2296         Interval                innerExtrema    (const EvalContext&, const Interval& angle) const
2297         {
2298                 const double            lo              = angle.lo();
2299                 const double            hi              = angle.hi();
2300                 const int                       loSlope = doGetSlope(lo);
2301                 const int                       hiSlope = doGetSlope(hi);
2302
2303                 // Detect the high and low values the function can take between the
2304                 // interval endpoints.
2305                 if (angle.length() >= 2.0 * DE_PI_DOUBLE)
2306                 {
2307                         // The interval is longer than a full cycle, so it must get all possible values.
2308                         return m_hiExtremum | m_loExtremum;
2309                 }
2310                 else if (loSlope == 1 && hiSlope == -1)
2311                 {
2312                         // The slope can change from positive to negative only at the maximum value.
2313                         return m_hiExtremum;
2314                 }
2315                 else if (loSlope == -1 && hiSlope == 1)
2316                 {
2317                         // The slope can change from negative to positive only at the maximum value.
2318                         return m_loExtremum;
2319                 }
2320                 else if (loSlope == hiSlope &&
2321                                  deIntSign(applyExact(hi) - applyExact(lo)) * loSlope == -1)
2322                 {
2323                         // The slope has changed twice between the endpoints, so both extrema are included.
2324                         return m_hiExtremum | m_loExtremum;
2325                 }
2326
2327                 return Interval();
2328         }
2329
2330         Interval        getCodomain                     (void) const
2331         {
2332                 // Ensure that result is always within [-1, 1], or NaN (for +-inf)
2333                 return Interval(-1.0, 1.0) | TCU_NAN;
2334         }
2335
2336         double          precision                       (const EvalContext& ctx, double ret, double arg) const
2337         {
2338                 if (ctx.floatPrecision == glu::PRECISION_HIGHP)
2339                 {
2340                         // Use precision from OpenCL fast relaxed math
2341                         if (-DE_PI_DOUBLE <= arg && arg <= DE_PI_DOUBLE)
2342                         {
2343                                 return deLdExp(1.0, -11);
2344                         }
2345                         else
2346                         {
2347                                 // "larger otherwise", let's pick |x| * 2^-12 , which is slightly over
2348                                 // 2^-11 at x == pi.
2349                                 return deLdExp(deAbs(arg), -12);
2350                         }
2351                 }
2352                 else if (ctx.floatPrecision == glu::PRECISION_MEDIUMP)
2353                 {
2354                         if (-DE_PI_DOUBLE <= arg && arg <= DE_PI_DOUBLE)
2355                         {
2356                                 // from OpenCL half-float extension specification
2357                                 return ctx.format.ulp(ret, 2.0);
2358                         }
2359                         else
2360                         {
2361                                 // |x| * 2^-10, slightly larger than 2 ULP at x == pi
2362                                 return deLdExp(deAbs(arg), -10);
2363                         }
2364                 }
2365                 else
2366                 {
2367                         DE_ASSERT(ctx.floatPrecision == glu::PRECISION_LOWP);
2368
2369                         // from OpenCL half-float extension specification
2370                         return ctx.format.ulp(ret, 2.0);
2371                 }
2372         }
2373
2374         virtual int             doGetSlope              (double angle) const = 0;
2375
2376         Interval                m_loExtremum;
2377         Interval                m_hiExtremum;
2378 };
2379
2380 class Sin : public TrigFunc
2381 {
2382 public:
2383                                 Sin                     (void) : TrigFunc("sin", deSin, -1.0, 1.0) {}
2384
2385 protected:
2386         int                     doGetSlope      (double angle) const { return deIntSign(deCos(angle)); }
2387 };
2388
2389 ExprP<float> sin (const ExprP<float>& x) { return app<Sin>(x); }
2390
2391 class Cos : public TrigFunc
2392 {
2393 public:
2394                                 Cos                     (void) : TrigFunc("cos", deCos, -1.0, 1.0) {}
2395
2396 protected:
2397         int                     doGetSlope      (double angle) const { return -deIntSign(deSin(angle)); }
2398 };
2399
2400 ExprP<float> cos (const ExprP<float>& x) { return app<Cos>(x); }
2401
2402 DEFINE_DERIVED_FLOAT1(Tan, tan, x, sin(x) * (constant(1.0f) / cos(x)))
2403
2404 class ASin : public CFloatFunc1
2405 {
2406 public:
2407                                         ASin            (void) : CFloatFunc1("asin", deAsin) {}
2408
2409 protected:
2410         double                  precision       (const EvalContext& ctx, double, double x) const
2411         {
2412                 if (!de::inBounds(x, -1.0, 1.0))
2413                         return TCU_NAN;
2414
2415                 if (ctx.floatPrecision == glu::PRECISION_HIGHP)
2416                 {
2417                         // Absolute error of 2^-11
2418                         return deLdExp(1.0, -11);
2419                 }
2420                 else
2421                 {
2422                         // Absolute error of 2^-8
2423                         return deLdExp(1.0, -8);
2424                 }
2425
2426         }
2427 };
2428
2429 class ArcTrigFunc : public CFloatFunc1
2430 {
2431 public:
2432                                         ArcTrigFunc     (const string&          name,
2433                                                                  DoubleFunc1&           func,
2434                                                                  double                         precisionULPs,
2435                                                                  const Interval&        domain,
2436                                                                  const Interval&        codomain)
2437                                                 : CFloatFunc1           (name, func)
2438                                                 , m_precision           (precisionULPs)
2439                                                 , m_domain                      (domain)
2440                                                 , m_codomain            (codomain) {}
2441
2442 protected:
2443         double                  precision       (const EvalContext& ctx, double ret, double x) const
2444         {
2445                 if (!m_domain.contains(x))
2446                         return TCU_NAN;
2447
2448                 if (ctx.floatPrecision == glu::PRECISION_HIGHP)
2449                 {
2450                         // Use OpenCL's fast relaxed math precision
2451                         return ctx.format.ulp(ret, m_precision);
2452                 }
2453                 else
2454                 {
2455                         // Use OpenCL half-float spec
2456                         return ctx.format.ulp(ret, 2.0);
2457                 }
2458         }
2459
2460         // We could implement getCodomain with m_codomain, but choose not to,
2461         // because it seems too strict with trascendental constants like pi.
2462
2463         const double    m_precision;
2464         const Interval  m_domain;
2465         const Interval  m_codomain;
2466 };
2467
2468 class ACos : public ArcTrigFunc
2469 {
2470 public:
2471         ACos (void) : ArcTrigFunc("acos", deAcos, 4096.0,
2472                                                           Interval(-1.0, 1.0),
2473                                                           Interval(0.0, DE_PI_DOUBLE)) {}
2474 };
2475
2476 class ATan : public ArcTrigFunc
2477 {
2478 public:
2479         ATan (void) : ArcTrigFunc("atan", deAtanOver, 4096.0,
2480                                                           Interval::unbounded(),
2481                                                           Interval(-DE_PI_DOUBLE * 0.5, DE_PI_DOUBLE * 0.5)) {}
2482 };
2483
2484 class ATan2 : public CFloatFunc2
2485 {
2486 public:
2487                                 ATan2                   (void) : CFloatFunc2 ("atan", deAtan2) {}
2488
2489 protected:
2490         Interval        innerExtrema    (const EvalContext&             ctx,
2491                                                                  const Interval&                yi,
2492                                                                  const Interval&                xi) const
2493         {
2494                 Interval ret;
2495
2496                 if (yi.contains(0.0))
2497                 {
2498                         if (xi.contains(0.0))
2499                                 ret |= TCU_NAN;
2500                         if (xi.intersects(Interval(-TCU_INFINITY, 0.0)))
2501                                 ret |= Interval(-DE_PI_DOUBLE, DE_PI_DOUBLE);
2502                 }
2503
2504                 if (!yi.isFinite(ctx.format.getMaxValue()) || !xi.isFinite(ctx.format.getMaxValue()))
2505                 {
2506                         // Infinities may not be supported, allow anything, including NaN
2507                         ret |= TCU_NAN;
2508                 }
2509
2510                 return ret;
2511         }
2512
2513         double          precision               (const EvalContext& ctx, double ret, double, double) const
2514         {
2515                 if (ctx.floatPrecision == glu::PRECISION_HIGHP)
2516                         return ctx.format.ulp(ret, 4096.0);
2517                 else
2518                         return ctx.format.ulp(ret, 2.0);
2519         }
2520
2521         // Codomain could be [-pi, pi], but that would probably be too strict.
2522 };
2523
2524 DEFINE_DERIVED_FLOAT1(Sinh, sinh, x, (exp(x) - exp(-x)) / constant(2.0f))
2525 DEFINE_DERIVED_FLOAT1(Cosh, cosh, x, (exp(x) + exp(-x)) / constant(2.0f))
2526 DEFINE_DERIVED_FLOAT1(Tanh, tanh, x, sinh(x) / cosh(x))
2527
2528 // These are not defined as derived forms in the GLSL ES spec, but
2529 // that gives us a reasonable precision.
2530 DEFINE_DERIVED_FLOAT1(ASinh, asinh, x, log(x + sqrt(x * x + constant(1.0f))))
2531 DEFINE_DERIVED_FLOAT1(ACosh, acosh, x, log(x + sqrt(alternatives((x + constant(1.0f)) * (x - constant(1.0f)),
2532                                                                                                                                  (x*x - constant(1.0f))))))
2533 DEFINE_DERIVED_FLOAT1(ATanh, atanh, x, constant(0.5f) * log((constant(1.0f) + x) /
2534                                                                                                                         (constant(1.0f) - x)))
2535
2536 template <typename T>
2537 class GetComponent : public PrimitiveFunc<Signature<typename T::Element, T, int> >
2538 {
2539 public:
2540         typedef         typename GetComponent::IRet     IRet;
2541
2542         string          getName         (void) const { return "_getComponent"; }
2543
2544         void            print           (ostream&                               os,
2545                                                          const BaseArgExprs&    args) const
2546         {
2547                 os << *args[0] << "[" << *args[1] << "]";
2548         }
2549
2550 protected:
2551         IRet            doApply         (const EvalContext&,
2552                                                          const typename GetComponent::IArgs& iargs) const
2553         {
2554                 IRet ret;
2555
2556                 for (int compNdx = 0; compNdx < T::SIZE; ++compNdx)
2557                 {
2558                         if (iargs.b.contains(compNdx))
2559                                 ret = unionIVal<typename T::Element>(ret, iargs.a[compNdx]);
2560                 }
2561
2562                 return ret;
2563         }
2564
2565 };
2566
2567 template <typename T>
2568 ExprP<typename T::Element> getComponent (const ExprP<T>& container, int ndx)
2569 {
2570         DE_ASSERT(0 <= ndx && ndx < T::SIZE);
2571         return app<GetComponent<T> >(container, constant(ndx));
2572 }
2573
2574 template <typename T>   string  vecNamePrefix                   (void);
2575 template <>                             string  vecNamePrefix<float>    (void) { return ""; }
2576 template <>                             string  vecNamePrefix<int>              (void) { return "i"; }
2577 template <>                             string  vecNamePrefix<bool>             (void) { return "b"; }
2578
2579 template <typename T, int Size>
2580 string vecName (void) { return vecNamePrefix<T>() + "vec" + de::toString(Size); }
2581
2582 template <typename T, int Size> class GenVec;
2583
2584 template <typename T>
2585 class GenVec<T, 1> : public DerivedFunc<Signature<T, T> >
2586 {
2587 public:
2588         typedef typename GenVec<T, 1>::ArgExprs ArgExprs;
2589
2590         string          getName         (void) const
2591         {
2592                 return "_" + vecName<T, 1>();
2593         }
2594
2595 protected:
2596
2597         ExprP<T>        doExpand        (ExpandContext&, const ArgExprs& args) const { return args.a; }
2598 };
2599
2600 template <typename T>
2601 class GenVec<T, 2> : public PrimitiveFunc<Signature<Vector<T, 2>, T, T> >
2602 {
2603 public:
2604         typedef typename GenVec::IRet   IRet;
2605         typedef typename GenVec::IArgs  IArgs;
2606
2607         string          getName         (void) const
2608         {
2609                 return vecName<T, 2>();
2610         }
2611
2612 protected:
2613         IRet            doApply         (const EvalContext&, const IArgs& iargs) const
2614         {
2615                 return IRet(iargs.a, iargs.b);
2616         }
2617 };
2618
2619 template <typename T>
2620 class GenVec<T, 3> : public PrimitiveFunc<Signature<Vector<T, 3>, T, T, T> >
2621 {
2622 public:
2623         typedef typename GenVec::IRet   IRet;
2624         typedef typename GenVec::IArgs  IArgs;
2625
2626         string  getName         (void) const
2627         {
2628                 return vecName<T, 3>();
2629         }
2630
2631 protected:
2632         IRet    doApply         (const EvalContext&, const IArgs& iargs) const
2633         {
2634                 return IRet(iargs.a, iargs.b, iargs.c);
2635         }
2636 };
2637
2638 template <typename T>
2639 class GenVec<T, 4> : public PrimitiveFunc<Signature<Vector<T, 4>, T, T, T, T> >
2640 {
2641 public:
2642         typedef typename GenVec::IRet   IRet;
2643         typedef typename GenVec::IArgs  IArgs;
2644
2645         string          getName         (void) const { return vecName<T, 4>(); }
2646
2647 protected:
2648         IRet            doApply         (const EvalContext&, const IArgs& iargs) const
2649         {
2650                 return IRet(iargs.a, iargs.b, iargs.c, iargs.d);
2651         }
2652 };
2653
2654
2655
2656 template <typename T, int Rows, int Columns>
2657 class GenMat;
2658
2659 template <typename T, int Rows>
2660 class GenMat<T, Rows, 2> : public PrimitiveFunc<
2661         Signature<Matrix<T, Rows, 2>, Vector<T, Rows>, Vector<T, Rows> > >
2662 {
2663 public:
2664         typedef typename GenMat::Ret    Ret;
2665         typedef typename GenMat::IRet   IRet;
2666         typedef typename GenMat::IArgs  IArgs;
2667
2668         string          getName         (void) const
2669         {
2670                 return dataTypeNameOf<Ret>();
2671         }
2672
2673 protected:
2674
2675         IRet            doApply         (const EvalContext&, const IArgs& iargs) const
2676         {
2677                 IRet    ret;
2678                 ret[0] = iargs.a;
2679                 ret[1] = iargs.b;
2680                 return ret;
2681         }
2682 };
2683
2684 template <typename T, int Rows>
2685 class GenMat<T, Rows, 3> : public PrimitiveFunc<
2686         Signature<Matrix<T, Rows, 3>, Vector<T, Rows>, Vector<T, Rows>, Vector<T, Rows> > >
2687 {
2688 public:
2689         typedef typename GenMat::Ret    Ret;
2690         typedef typename GenMat::IRet   IRet;
2691         typedef typename GenMat::IArgs  IArgs;
2692
2693         string  getName (void) const
2694         {
2695                 return dataTypeNameOf<Ret>();
2696         }
2697
2698 protected:
2699
2700         IRet    doApply (const EvalContext&, const IArgs& iargs) const
2701         {
2702                 IRet    ret;
2703                 ret[0] = iargs.a;
2704                 ret[1] = iargs.b;
2705                 ret[2] = iargs.c;
2706                 return ret;
2707         }
2708 };
2709
2710 template <typename T, int Rows>
2711 class GenMat<T, Rows, 4> : public PrimitiveFunc<
2712         Signature<Matrix<T, Rows, 4>,
2713                           Vector<T, Rows>, Vector<T, Rows>, Vector<T, Rows>, Vector<T, Rows> > >
2714 {
2715 public:
2716         typedef typename GenMat::Ret    Ret;
2717         typedef typename GenMat::IRet   IRet;
2718         typedef typename GenMat::IArgs  IArgs;
2719
2720         string  getName (void) const
2721         {
2722                 return dataTypeNameOf<Ret>();
2723         }
2724
2725 protected:
2726         IRet    doApply (const EvalContext&, const IArgs& iargs) const
2727         {
2728                 IRet    ret;
2729                 ret[0] = iargs.a;
2730                 ret[1] = iargs.b;
2731                 ret[2] = iargs.c;
2732                 ret[3] = iargs.d;
2733                 return ret;
2734         }
2735 };
2736
2737 template <typename T, int Rows>
2738 ExprP<Matrix<T, Rows, 2> > mat2 (const ExprP<Vector<T, Rows> >& arg0,
2739                                                                  const ExprP<Vector<T, Rows> >& arg1)
2740 {
2741         return app<GenMat<T, Rows, 2> >(arg0, arg1);
2742 }
2743
2744 template <typename T, int Rows>
2745 ExprP<Matrix<T, Rows, 3> > mat3 (const ExprP<Vector<T, Rows> >& arg0,
2746                                                                  const ExprP<Vector<T, Rows> >& arg1,
2747                                                                  const ExprP<Vector<T, Rows> >& arg2)
2748 {
2749         return app<GenMat<T, Rows, 3> >(arg0, arg1, arg2);
2750 }
2751
2752 template <typename T, int Rows>
2753 ExprP<Matrix<T, Rows, 4> > mat4 (const ExprP<Vector<T, Rows> >& arg0,
2754                                                                  const ExprP<Vector<T, Rows> >& arg1,
2755                                                                  const ExprP<Vector<T, Rows> >& arg2,
2756                                                                  const ExprP<Vector<T, Rows> >& arg3)
2757 {
2758         return app<GenMat<T, Rows, 4> >(arg0, arg1, arg2, arg3);
2759 }
2760
2761
2762 template <int Rows, int Cols>
2763 class MatNeg : public PrimitiveFunc<Signature<Matrix<float, Rows, Cols>,
2764                                                                                           Matrix<float, Rows, Cols> > >
2765 {
2766 public:
2767         typedef typename MatNeg::IRet           IRet;
2768         typedef typename MatNeg::IArgs          IArgs;
2769
2770         string  getName (void) const
2771         {
2772                 return "_matNeg";
2773         }
2774
2775 protected:
2776         void    doPrint (ostream& os, const BaseArgExprs& args) const
2777         {
2778                 os << "-(" << *args[0] << ")";
2779         }
2780
2781         IRet    doApply (const EvalContext&, const IArgs& iargs)                        const
2782         {
2783                 IRet    ret;
2784
2785                 for (int col = 0; col < Cols; ++col)
2786                 {
2787                         for (int row = 0; row < Rows; ++row)
2788                                 ret[col][row] = -iargs.a[col][row];
2789                 }
2790
2791                 return ret;
2792         }
2793 };
2794
2795 template <typename T, typename Sig>
2796 class CompWiseFunc : public PrimitiveFunc<Sig>
2797 {
2798 public:
2799         typedef Func<Signature<T, T, T> >       ScalarFunc;
2800
2801         string                          getName                 (void)                                                                  const
2802         {
2803                 return doGetScalarFunc().getName();
2804         }
2805 protected:
2806         void                            doPrint                 (ostream&                               os,
2807                                                                                  const BaseArgExprs&    args)                   const
2808         {
2809                 doGetScalarFunc().print(os, args);
2810         }
2811
2812         virtual
2813         const ScalarFunc&       doGetScalarFunc (void)                                                                  const = 0;
2814 };
2815
2816 template <int Rows, int Cols>
2817 class CompMatFuncBase : public CompWiseFunc<float, Signature<Matrix<float, Rows, Cols>,
2818                                                                                                                          Matrix<float, Rows, Cols>,
2819                                                                                                                          Matrix<float, Rows, Cols> > >
2820 {
2821 public:
2822         typedef typename CompMatFuncBase::IRet          IRet;
2823         typedef typename CompMatFuncBase::IArgs         IArgs;
2824
2825 protected:
2826
2827         IRet    doApply (const EvalContext& ctx, const IArgs& iargs) const
2828         {
2829                 IRet                    ret;
2830
2831                 for (int col = 0; col < Cols; ++col)
2832                 {
2833                         for (int row = 0; row < Rows; ++row)
2834                                 ret[col][row] = this->doGetScalarFunc().apply(ctx,
2835                                                                                                                           iargs.a[col][row],
2836                                                                                                                           iargs.b[col][row]);
2837                 }
2838
2839                 return ret;
2840         }
2841 };
2842
2843 template <typename F, int Rows, int Cols>
2844 class CompMatFunc : public CompMatFuncBase<Rows, Cols>
2845 {
2846 protected:
2847         const typename CompMatFunc::ScalarFunc& doGetScalarFunc (void) const
2848         {
2849                 return instance<F>();
2850         }
2851 };
2852
2853 class ScalarMatrixCompMult : public Mul
2854 {
2855 public:
2856         string  getName (void) const
2857         {
2858                 return "matrixCompMult";
2859         }
2860
2861         void    doPrint (ostream& os, const BaseArgExprs& args) const
2862         {
2863                 Func<Sig>::doPrint(os, args);
2864         }
2865 };
2866
2867 template <int Rows, int Cols>
2868 class MatrixCompMult : public CompMatFunc<ScalarMatrixCompMult, Rows, Cols>
2869 {
2870 };
2871
2872 template <int Rows, int Cols>
2873 class ScalarMatFuncBase : public CompWiseFunc<float, Signature<Matrix<float, Rows, Cols>,
2874                                                                                                                            Matrix<float, Rows, Cols>,
2875                                                                                                                            float> >
2876 {
2877 public:
2878         typedef typename ScalarMatFuncBase::IRet        IRet;
2879         typedef typename ScalarMatFuncBase::IArgs       IArgs;
2880
2881 protected:
2882
2883         IRet    doApply (const EvalContext& ctx, const IArgs& iargs) const
2884         {
2885                 IRet    ret;
2886
2887                 for (int col = 0; col < Cols; ++col)
2888                 {
2889                         for (int row = 0; row < Rows; ++row)
2890                                 ret[col][row] = this->doGetScalarFunc().apply(ctx, iargs.a[col][row], iargs.b);
2891                 }
2892
2893                 return ret;
2894         }
2895 };
2896
2897 template <typename F, int Rows, int Cols>
2898 class ScalarMatFunc : public ScalarMatFuncBase<Rows, Cols>
2899 {
2900 protected:
2901         const typename ScalarMatFunc::ScalarFunc&       doGetScalarFunc (void)  const
2902         {
2903                 return instance<F>();
2904         }
2905 };
2906
2907 template<typename T, int Size> struct GenXType;
2908
2909 template<typename T>
2910 struct GenXType<T, 1>
2911 {
2912         static ExprP<T> genXType        (const ExprP<T>& x) { return x; }
2913 };
2914
2915 template<typename T>
2916 struct GenXType<T, 2>
2917 {
2918         static ExprP<Vector<T, 2> >     genXType        (const ExprP<T>& x)
2919         {
2920                 return app<GenVec<T, 2> >(x, x);
2921         }
2922 };
2923
2924 template<typename T>
2925 struct GenXType<T, 3>
2926 {
2927         static ExprP<Vector<T, 3> >     genXType        (const ExprP<T>& x)
2928         {
2929                 return app<GenVec<T, 3> >(x, x, x);
2930         }
2931 };
2932
2933 template<typename T>
2934 struct GenXType<T, 4>
2935 {
2936         static ExprP<Vector<T, 4> >     genXType        (const ExprP<T>& x)
2937         {
2938                 return app<GenVec<T, 4> >(x, x, x, x);
2939         }
2940 };
2941
2942 //! Returns an expression of vector of size `Size` (or scalar if Size == 1),
2943 //! with each element initialized with the expression `x`.
2944 template<typename T, int Size>
2945 ExprP<typename ContainerOf<T, Size>::Container> genXType (const ExprP<T>& x)
2946 {
2947         return GenXType<T, Size>::genXType(x);
2948 }
2949
2950 typedef GenVec<float, 2> FloatVec2;
2951 DEFINE_CONSTRUCTOR2(FloatVec2, Vec2, vec2, float, float)
2952
2953 typedef GenVec<float, 3> FloatVec3;
2954 DEFINE_CONSTRUCTOR3(FloatVec3, Vec3, vec3, float, float, float)
2955
2956 typedef GenVec<float, 4> FloatVec4;
2957 DEFINE_CONSTRUCTOR4(FloatVec4, Vec4, vec4, float, float, float, float)
2958
2959 template <int Size>
2960 class Dot : public DerivedFunc<Signature<float, Vector<float, Size>, Vector<float, Size> > >
2961 {
2962 public:
2963         typedef typename Dot::ArgExprs ArgExprs;
2964
2965         string                  getName         (void) const
2966         {
2967                 return "dot";
2968         }
2969
2970 protected:
2971         ExprP<float>    doExpand        (ExpandContext&, const ArgExprs& args) const
2972         {
2973                 ExprP<float> op[Size];
2974                 // Precompute all products.
2975                 for (int ndx = 0; ndx < Size; ++ndx)
2976                         op[ndx] = args.a[ndx] * args.b[ndx];
2977
2978                 int idx[Size];
2979                 //Prepare an array of indices.
2980                 for (int ndx = 0; ndx < Size; ++ndx)
2981                         idx[ndx] = ndx;
2982
2983                 ExprP<float> res = op[0];
2984                 // Compute the first dot alternative: SUM(a[i]*b[i]), i = 0 .. Size-1
2985                 for (int ndx = 1; ndx < Size; ++ndx)
2986                         res = res + op[ndx];
2987
2988                 // Generate all permutations of indices and
2989                 // using a permutation compute a dot alternative.
2990                 // Generates all possible variants fo summation of products in the dot product expansion expression.
2991                 do {
2992                         ExprP<float> alt = constant(0.0f);
2993                         for (int ndx = 0; ndx < Size; ++ndx)
2994                                 alt = alt + op[idx[ndx]];
2995                         res = alternatives(res, alt);
2996                 } while (std::next_permutation(idx, idx + Size));
2997
2998                 return res;
2999         }
3000 };
3001
3002 template <>
3003 class Dot<1> : public DerivedFunc<Signature<float, float, float> >
3004 {
3005 public:
3006         string                  getName         (void) const
3007         {
3008                 return "dot";
3009         }
3010
3011         ExprP<float>    doExpand        (ExpandContext&, const ArgExprs& args) const
3012         {
3013                 return args.a * args.b;
3014         }
3015 };
3016
3017 template <int Size>
3018 ExprP<float> dot (const ExprP<Vector<float, Size> >& x, const ExprP<Vector<float, Size> >& y)
3019 {
3020         return app<Dot<Size> >(x, y);
3021 }
3022
3023 ExprP<float> dot (const ExprP<float>& x, const ExprP<float>& y)
3024 {
3025         return app<Dot<1> >(x, y);
3026 }
3027
3028 template <int Size>
3029 class Length : public DerivedFunc<
3030         Signature<float, typename ContainerOf<float, Size>::Container> >
3031 {
3032 public:
3033         typedef typename Length::ArgExprs ArgExprs;
3034
3035         string                  getName         (void) const
3036         {
3037                 return "length";
3038         }
3039
3040 protected:
3041         ExprP<float>    doExpand        (ExpandContext&, const ArgExprs& args) const
3042         {
3043                 return sqrt(dot(args.a, args.a));
3044         }
3045 };
3046
3047 template <int Size>
3048 ExprP<float> length (const ExprP<typename ContainerOf<float, Size>::Container>& x)
3049 {
3050         return app<Length<Size> >(x);
3051 }
3052
3053 template <int Size>
3054 class Distance : public DerivedFunc<
3055         Signature<float,
3056                           typename ContainerOf<float, Size>::Container,
3057                           typename ContainerOf<float, Size>::Container> >
3058 {
3059 public:
3060         typedef typename        Distance::Ret           Ret;
3061         typedef typename        Distance::ArgExprs      ArgExprs;
3062
3063         string          getName         (void) const
3064         {
3065                 return "distance";
3066         }
3067
3068 protected:
3069         ExprP<Ret>      doExpand        (ExpandContext&, const ArgExprs& args) const
3070         {
3071                 return length<Size>(args.a - args.b);
3072         }
3073 };
3074
3075 // cross
3076
3077 class Cross : public DerivedFunc<Signature<Vec3, Vec3, Vec3> >
3078 {
3079 public:
3080         string                  getName         (void) const
3081         {
3082                 return "cross";
3083         }
3084
3085 protected:
3086         ExprP<Vec3>             doExpand        (ExpandContext&, const ArgExprs& x) const
3087         {
3088                 return vec3(x.a[1] * x.b[2] - x.b[1] * x.a[2],
3089                                         x.a[2] * x.b[0] - x.b[2] * x.a[0],
3090                                         x.a[0] * x.b[1] - x.b[0] * x.a[1]);
3091         }
3092 };
3093
3094 DEFINE_CONSTRUCTOR2(Cross, Vec3, cross, Vec3, Vec3)
3095
3096 template<int Size>
3097 class Normalize : public DerivedFunc<
3098         Signature<typename ContainerOf<float, Size>::Container,
3099                           typename ContainerOf<float, Size>::Container> >
3100 {
3101 public:
3102         typedef typename        Normalize::Ret          Ret;
3103         typedef typename        Normalize::ArgExprs     ArgExprs;
3104
3105         string          getName         (void) const
3106         {
3107                 return "normalize";
3108         }
3109
3110 protected:
3111         ExprP<Ret>      doExpand        (ExpandContext&, const ArgExprs& args) const
3112         {
3113                 return args.a / length<Size>(args.a);
3114         }
3115 };
3116
3117 template <int Size>
3118 class FaceForward : public DerivedFunc<
3119         Signature<typename ContainerOf<float, Size>::Container,
3120                           typename ContainerOf<float, Size>::Container,
3121                           typename ContainerOf<float, Size>::Container,
3122                           typename ContainerOf<float, Size>::Container> >
3123 {
3124 public:
3125         typedef typename        FaceForward::Ret                Ret;
3126         typedef typename        FaceForward::ArgExprs   ArgExprs;
3127
3128         string          getName         (void) const
3129         {
3130                 return "faceforward";
3131         }
3132
3133 protected:
3134
3135
3136         ExprP<Ret>      doExpand        (ExpandContext&, const ArgExprs& args) const
3137         {
3138                 return cond(dot(args.c, args.b) < constant(0.0f), args.a, -args.a);
3139         }
3140 };
3141
3142 template<int Size, typename Ret, typename Arg0, typename Arg1>
3143 struct ApplyReflect
3144 {
3145         static ExprP<Ret> apply (ExpandContext&         ctx,
3146                                                          const ExprP<Arg0>&     i,
3147                                                          const ExprP<Arg1>&     n)
3148         {
3149                 const ExprP<float>      dotNI   = bindExpression("dotNI", ctx, dot(n, i));
3150
3151                 return i - alternatives((n * dotNI) * constant(2.0f),
3152                                                                 n * (dotNI * constant(2.0f)));
3153         }
3154 };
3155
3156 template<typename Ret, typename Arg0, typename Arg1>
3157 struct ApplyReflect<1, Ret, Arg0, Arg1>
3158 {
3159         static ExprP<Ret> apply (ExpandContext&,
3160                                                          const ExprP<Arg0>&     i,
3161                                                          const ExprP<Arg1>&     n)
3162         {
3163                 return i - alternatives(alternatives((n * (n*i)) * constant(2.0f),
3164                                                                                         n * ((n*i) * constant(2.0f))),
3165                                                                                         (n * n) * (i * constant(2.0f)));
3166         }
3167 };
3168
3169 template <int Size>
3170 class Reflect : public DerivedFunc<
3171         Signature<typename ContainerOf<float, Size>::Container,
3172                           typename ContainerOf<float, Size>::Container,
3173                           typename ContainerOf<float, Size>::Container> >
3174 {
3175 public:
3176         typedef typename        Reflect::Ret            Ret;
3177         typedef typename        Reflect::Arg0           Arg0;
3178         typedef typename        Reflect::Arg1           Arg1;
3179         typedef typename        Reflect::ArgExprs       ArgExprs;
3180
3181         string          getName         (void) const
3182         {
3183                 return "reflect";
3184         }
3185
3186 protected:
3187         ExprP<Ret>      doExpand        (ExpandContext& ctx, const ArgExprs& args) const
3188         {
3189                 const ExprP<Arg0>&      i               = args.a;
3190                 const ExprP<Arg1>&      n               = args.b;
3191
3192                 return ApplyReflect<Size, Ret, Arg0, Arg1>::apply(ctx, i, n);
3193         }
3194 };
3195
3196 template <int Size>
3197 class Refract : public DerivedFunc<
3198         Signature<typename ContainerOf<float, Size>::Container,
3199                           typename ContainerOf<float, Size>::Container,
3200                           typename ContainerOf<float, Size>::Container,
3201                           float> >
3202 {
3203 public:
3204         typedef typename        Refract::Ret            Ret;
3205         typedef typename        Refract::Arg0           Arg0;
3206         typedef typename        Refract::Arg1           Arg1;
3207         typedef typename        Refract::ArgExprs       ArgExprs;
3208
3209         string          getName         (void) const
3210         {
3211                 return "refract";
3212         }
3213
3214 protected:
3215         ExprP<Ret>      doExpand        (ExpandContext& ctx, const ArgExprs& args) const
3216         {
3217                 const ExprP<Arg0>&      i               = args.a;
3218                 const ExprP<Arg1>&      n               = args.b;
3219                 const ExprP<float>&     eta             = args.c;
3220                 const ExprP<float>      dotNI   = bindExpression("dotNI", ctx, dot(n, i));
3221                 const ExprP<float>      k1              = bindExpression("k1", ctx, constant(1.0f) - eta * eta *
3222                                                                                                 (constant(1.0f) - dotNI * dotNI));
3223
3224                 const ExprP<float>      k2              = bindExpression("k2", ctx,
3225                                                                                                 (((dotNI * (-dotNI)) + constant(1.0f)) * eta)
3226                                                                                                 * (-eta) + constant(1.0f));
3227                 const ExprP<float>      k               = bindExpression("k", ctx, alternatives(k1, k2));
3228
3229                 return cond(k < constant(0.0f),
3230                                         genXType<float, Size>(constant(0.0f)),
3231                                         i * eta - n * (eta * dotNI + sqrt(k)));
3232         }
3233 };
3234
3235 class PreciseFunc1 : public CFloatFunc1
3236 {
3237 public:
3238                         PreciseFunc1    (const string& name, DoubleFunc1& func) : CFloatFunc1(name, func) {}
3239 protected:
3240         double  precision               (const EvalContext&, double, double) const      { return 0.0; }
3241 };
3242
3243 class Abs : public PreciseFunc1
3244 {
3245 public:
3246         Abs (void) : PreciseFunc1("abs", deAbs) {}
3247 };
3248
3249 class Sign : public PreciseFunc1
3250 {
3251 public:
3252         Sign (void) : PreciseFunc1("sign", deSign) {}
3253 };
3254
3255 class Floor : public PreciseFunc1
3256 {
3257 public:
3258         Floor (void) : PreciseFunc1("floor", deFloor) {}
3259 };
3260
3261 class Trunc : public PreciseFunc1
3262 {
3263 public:
3264         Trunc (void) : PreciseFunc1("trunc", deTrunc) {}
3265 };
3266
3267 class Round : public FloatFunc1
3268 {
3269 public:
3270         string          getName         (void) const                                                            { return "round"; }
3271
3272 protected:
3273         Interval        applyPoint      (const EvalContext&, double x) const
3274         {
3275                 double                  truncated       = 0.0;
3276                 const double    fract           = deModf(x, &truncated);
3277                 Interval                ret;
3278
3279                 if (fabs(fract) <= 0.5)
3280                         ret |= truncated;
3281                 if (fabs(fract) >= 0.5)
3282                         ret |= truncated + deSign(fract);
3283
3284                 return ret;
3285         }
3286
3287         double          precision       (const EvalContext&, double, double) const      { return 0.0; }
3288 };
3289
3290 class RoundEven : public PreciseFunc1
3291 {
3292 public:
3293         RoundEven (void) : PreciseFunc1("roundEven", deRoundEven) {}
3294 };
3295
3296 class Ceil : public PreciseFunc1
3297 {
3298 public:
3299         Ceil (void) : PreciseFunc1("ceil", deCeil) {}
3300 };
3301
3302 DEFINE_DERIVED_FLOAT1(Fract, fract, x, x - app<Floor>(x))
3303
3304 class PreciseFunc2 : public CFloatFunc2
3305 {
3306 public:
3307                         PreciseFunc2    (const string& name, DoubleFunc2& func) : CFloatFunc2(name, func) {}
3308 protected:
3309         double  precision               (const EvalContext&, double, double, double) const { return 0.0; }
3310 };
3311
3312 DEFINE_DERIVED_FLOAT2(Mod, mod, x, y, x - y * app<Floor>(x / y))
3313
3314 class Modf : public PrimitiveFunc<Signature<float, float, float> >
3315 {
3316 public:
3317         string  getName                         (void) const
3318         {
3319                 return "modf";
3320         }
3321
3322 protected:
3323         IRet    doApply                         (const EvalContext& ctx, const IArgs& iargs) const
3324         {
3325                 Interval        fracIV;
3326                 Interval&       wholeIV         = const_cast<Interval&>(iargs.b);
3327                 double          intPart         = 0;
3328
3329                 TCU_INTERVAL_APPLY_MONOTONE1(fracIV, x, iargs.a, frac, frac = deModf(x, &intPart));
3330                 TCU_INTERVAL_APPLY_MONOTONE1(wholeIV, x, iargs.a, whole,
3331                                                                          deModf(x, &intPart); whole = intPart);
3332
3333                 if (!iargs.a.isFinite(ctx.format.getMaxValue()))
3334                 {
3335                         // Behavior on modf(Inf) not well-defined, allow anything as a fractional part
3336                         // See Khronos bug 13907
3337                         fracIV |= TCU_NAN;
3338                 }
3339
3340                 return fracIV;
3341         }
3342
3343         int             getOutParamIndex        (void) const
3344         {
3345                 return 1;
3346         }
3347 };
3348
3349 int compare(const EvalContext& ctx, double x, double y)
3350 {
3351         if (ctx.format.hasSubnormal() != tcu::YES)
3352         {
3353                 const int               minExp                  = ctx.format.getMinExp();
3354                 const int               fractionBits    = ctx.format.getFractionBits();
3355                 const double    minQuantum              = deLdExp(1.0f, minExp - fractionBits);
3356                 const double    minNormalized   = deLdExp(1.0f, minExp);
3357                 const double    maxSubnormal    = minNormalized - minQuantum;
3358                 const double    minSubnormal    = -maxSubnormal;
3359
3360                 if (minSubnormal <= x && x <= maxSubnormal &&
3361                     minSubnormal <= y && y <= maxSubnormal)
3362                         return 0;
3363         }
3364
3365         if (x < y)
3366                 return -1;
3367         if (y < x)
3368                 return 1;
3369         return 0;
3370 }
3371
3372 class MinMaxFunc : public FloatFunc2
3373 {
3374 public:
3375         MinMaxFunc      (const string&  name,
3376                                  int                    sign)
3377                                 : m_name(name)
3378                                 , m_sign(sign)
3379         {
3380         }
3381
3382         string  getName                         (void) const { return m_name; }
3383
3384 protected:
3385         Interval applyPoint(const EvalContext& ctx, double x, double y) const
3386         {
3387                 const int cmp = compare(ctx, x, y) * m_sign;
3388
3389                 if (cmp > 0)
3390                         return x;
3391                 if (cmp < 0)
3392                         return y;
3393
3394                 // An implementation without subnormals may not be able to distinguish
3395                 // between x and y even when they're not equal in host arithmetic.
3396                 return Interval(x, y);
3397         }
3398
3399         double  precision       (const EvalContext&, double, double, double) const
3400         {
3401                 return 0.0;
3402         }
3403
3404         const string    m_name;
3405         const int               m_sign;
3406 };
3407
3408 class Min : public MinMaxFunc { public: Min (void) : MinMaxFunc("min", -1) {} };
3409 class Max : public MinMaxFunc { public: Max (void) : MinMaxFunc("max", 1) {} };
3410
3411 class Clamp : public FloatFunc3
3412 {
3413 public:
3414         string  getName         (void) const { return "clamp"; }
3415
3416 protected:
3417         Interval applyPoint(const EvalContext& ctx, double x, double minVal, double maxVal) const
3418         {
3419                 if (minVal > maxVal)
3420                         return TCU_NAN;
3421
3422                 const int cmpMin = compare(ctx, x, minVal);
3423                 const int cmpMax = compare(ctx, x, maxVal);
3424                 const int cmpMinMax = compare(ctx, minVal, maxVal);
3425
3426                 if (cmpMin < 0) {
3427                         if (cmpMinMax < 0)
3428                                 return minVal;
3429                         else
3430                                 return Interval(minVal, maxVal);
3431                 }
3432                 if (cmpMax > 0) {
3433                         if (cmpMinMax < 0)
3434                                 return maxVal;
3435                         else
3436                                 return Interval(minVal, maxVal);
3437                 }
3438
3439                 Interval result = x;
3440                 if (cmpMin == 0)
3441                         result |= minVal;
3442                 if (cmpMax == 0)
3443                         result |= maxVal;
3444                 return result;
3445         }
3446
3447         double  precision       (const EvalContext&, double, double, double minVal, double maxVal) const
3448         {
3449                 return minVal > maxVal ? TCU_NAN : 0.0;
3450         }
3451 };
3452
3453 ExprP<float> clamp(const ExprP<float>& x, const ExprP<float>& minVal, const ExprP<float>& maxVal)
3454 {
3455         return app<Clamp>(x, minVal, maxVal);
3456 }
3457
3458 DEFINE_DERIVED_FLOAT3(Mix, mix, x, y, a, alternatives((x * (constant(1.0f) - a)) + y * a,
3459                                                                                                           x + (y - x) * a))
3460
3461 static double step (double edge, double x)
3462 {
3463         return x < edge ? 0.0 : 1.0;
3464 }
3465
3466 class Step : public PreciseFunc2 { public: Step (void) : PreciseFunc2("step", step) {} };
3467
3468 class SmoothStep : public DerivedFunc<Signature<float, float, float, float> >
3469 {
3470 public:
3471         string          getName         (void) const
3472         {
3473                 return "smoothstep";
3474         }
3475
3476 protected:
3477
3478         ExprP<Ret>      doExpand        (ExpandContext& ctx, const ArgExprs& args) const
3479         {
3480                 const ExprP<float>&             edge0   = args.a;
3481                 const ExprP<float>&             edge1   = args.b;
3482                 const ExprP<float>&             x               = args.c;
3483                 const ExprP<float>              tExpr   = clamp((x - edge0) / (edge1 - edge0),
3484                                                                                         constant(0.0f), constant(1.0f));
3485                 const ExprP<float>              t               = bindExpression("t", ctx, tExpr);
3486
3487                 return (t * t * (constant(3.0f) - constant(2.0f) * t));
3488         }
3489 };
3490
3491 class FrExp : public PrimitiveFunc<Signature<float, float, int> >
3492 {
3493 public:
3494         string  getName                 (void) const
3495         {
3496                 return "frexp";
3497         }
3498
3499 protected:
3500         IRet    doApply                 (const EvalContext&, const IArgs& iargs) const
3501         {
3502                 IRet                    ret;
3503                 const IArg0&    x                       = iargs.a;
3504                 IArg1&                  exponent        = const_cast<IArg1&>(iargs.b);
3505
3506                 if (x.hasNaN() || x.contains(TCU_INFINITY) || x.contains(-TCU_INFINITY))
3507                 {
3508                         // GLSL (in contrast to IEEE) says that result of applying frexp
3509                         // to infinity is undefined
3510                         ret = Interval::unbounded() | TCU_NAN;
3511                         exponent = Interval(-deLdExp(1.0, 31), deLdExp(1.0, 31)-1);
3512                 }
3513                 else if (!x.empty())
3514                 {
3515                         int                             loExp   = 0;
3516                         const double    loFrac  = deFrExp(x.lo(), &loExp);
3517                         int                             hiExp   = 0;
3518                         const double    hiFrac  = deFrExp(x.hi(), &hiExp);
3519
3520                         if (deSign(loFrac) != deSign(hiFrac))
3521                         {
3522                                 exponent = Interval(-TCU_INFINITY, de::max(loExp, hiExp));
3523                                 ret = Interval();
3524                                 if (deSign(loFrac) < 0)
3525                                         ret |= Interval(-1.0 + DBL_EPSILON*0.5, 0.0);
3526                                 if (deSign(hiFrac) > 0)
3527                                         ret |= Interval(0.0, 1.0 - DBL_EPSILON*0.5);
3528                         }
3529                         else
3530                         {
3531                                 exponent = Interval(loExp, hiExp);
3532                                 if (loExp == hiExp)
3533                                         ret = Interval(loFrac, hiFrac);
3534                                 else
3535                                         ret = deSign(loFrac) * Interval(0.5, 1.0 - DBL_EPSILON*0.5);
3536                         }
3537                 }
3538
3539                 return ret;
3540         }
3541
3542         int     getOutParamIndex        (void) const
3543         {
3544                 return 1;
3545         }
3546 };
3547
3548 class LdExp : public PrimitiveFunc<Signature<float, float, int> >
3549 {
3550 public:
3551         string          getName                 (void) const
3552         {
3553                 return "ldexp";
3554         }
3555
3556 protected:
3557         Interval        doApply                 (const EvalContext& ctx, const IArgs& iargs) const
3558         {
3559                 Interval        ret = call<Exp2>(ctx, iargs.b);
3560                 // Khronos bug 11180 consensus: if exp2(exponent) cannot be represented,
3561                 // the result is undefined.
3562
3563                 if (ret.contains(TCU_INFINITY) || ret.contains(-TCU_INFINITY))
3564                         ret |= TCU_NAN;
3565
3566                 return call<Mul>(ctx, iargs.a, ret);
3567         }
3568 };
3569
3570 template<int Rows, int Columns>
3571 class Transpose : public PrimitiveFunc<Signature<Matrix<float, Rows, Columns>,
3572                                                                                                  Matrix<float, Columns, Rows> > >
3573 {
3574 public:
3575         typedef typename Transpose::IRet        IRet;
3576         typedef typename Transpose::IArgs       IArgs;
3577
3578         string          getName         (void) const
3579         {
3580                 return "transpose";
3581         }
3582
3583 protected:
3584         IRet            doApply         (const EvalContext&, const IArgs& iargs) const
3585         {
3586                 IRet ret;
3587
3588                 for (int rowNdx = 0; rowNdx < Rows; ++rowNdx)
3589                 {
3590                         for (int colNdx = 0; colNdx < Columns; ++colNdx)
3591                                 ret(rowNdx, colNdx) = iargs.a(colNdx, rowNdx);
3592                 }
3593
3594                 return ret;
3595         }
3596 };
3597
3598 template<typename Ret, typename Arg0, typename Arg1>
3599 class MulFunc : public PrimitiveFunc<Signature<Ret, Arg0, Arg1> >
3600 {
3601 public:
3602         string  getName (void) const                                                                    { return "mul"; }
3603
3604 protected:
3605         void    doPrint (ostream& os, const BaseArgExprs& args) const
3606         {
3607                 os << "(" << *args[0] << " * " << *args[1] << ")";
3608         }
3609 };
3610
3611 template<int LeftRows, int Middle, int RightCols>
3612 class MatMul : public MulFunc<Matrix<float, LeftRows, RightCols>,
3613                                                           Matrix<float, LeftRows, Middle>,
3614                                                           Matrix<float, Middle, RightCols> >
3615 {
3616 protected:
3617         typedef typename MatMul::IRet   IRet;
3618         typedef typename MatMul::IArgs  IArgs;
3619         typedef typename MatMul::IArg0  IArg0;
3620         typedef typename MatMul::IArg1  IArg1;
3621
3622         IRet    doApply (const EvalContext&     ctx, const IArgs& iargs) const
3623         {
3624                 const IArg0&    left    = iargs.a;
3625                 const IArg1&    right   = iargs.b;
3626                 IRet                    ret;
3627
3628                 for (int row = 0; row < LeftRows; ++row)
3629                 {
3630                         for (int col = 0; col < RightCols; ++col)
3631                         {
3632                                 Interval        element (0.0);
3633
3634                                 for (int ndx = 0; ndx < Middle; ++ndx)
3635                                         element = call<Add>(ctx, element,
3636                                                                                 call<Mul>(ctx, left[ndx][row], right[col][ndx]));
3637
3638                                 ret[col][row] = element;
3639                         }
3640                 }
3641
3642                 return ret;
3643         }
3644 };
3645
3646 template<int Rows, int Cols>
3647 class VecMatMul : public MulFunc<Vector<float, Cols>,
3648                                                                  Vector<float, Rows>,
3649                                                                  Matrix<float, Rows, Cols> >
3650 {
3651 public:
3652         typedef typename VecMatMul::IRet        IRet;
3653         typedef typename VecMatMul::IArgs       IArgs;
3654         typedef typename VecMatMul::IArg0       IArg0;
3655         typedef typename VecMatMul::IArg1       IArg1;
3656
3657 protected:
3658         IRet    doApply (const EvalContext& ctx, const IArgs& iargs) const
3659         {
3660                 const IArg0&    left    = iargs.a;
3661                 const IArg1&    right   = iargs.b;
3662                 IRet                    ret;
3663
3664                 for (int col = 0; col < Cols; ++col)
3665                 {
3666                         Interval        element (0.0);
3667
3668                         for (int row = 0; row < Rows; ++row)
3669                                 element = call<Add>(ctx, element, call<Mul>(ctx, left[row], right[col][row]));
3670
3671                         ret[col] = element;
3672                 }
3673
3674                 return ret;
3675         }
3676 };
3677
3678 template<int Rows, int Cols>
3679 class MatVecMul : public MulFunc<Vector<float, Rows>,
3680                                                                  Matrix<float, Rows, Cols>,
3681                                                                  Vector<float, Cols> >
3682 {
3683 public:
3684         typedef typename MatVecMul::IRet        IRet;
3685         typedef typename MatVecMul::IArgs       IArgs;
3686         typedef typename MatVecMul::IArg0       IArg0;
3687         typedef typename MatVecMul::IArg1       IArg1;
3688
3689 protected:
3690         IRet    doApply (const EvalContext& ctx, const IArgs& iargs) const
3691         {
3692                 const IArg0&    left    = iargs.a;
3693                 const IArg1&    right   = iargs.b;
3694
3695                 return call<VecMatMul<Cols, Rows> >(ctx, right,
3696                                                                                         call<Transpose<Rows, Cols> >(ctx, left));
3697         }
3698 };
3699
3700 template<int Rows, int Cols>
3701 class OuterProduct : public PrimitiveFunc<Signature<Matrix<float, Rows, Cols>,
3702                                                                                                         Vector<float, Rows>,
3703                                                                                                         Vector<float, Cols> > >
3704 {
3705 public:
3706         typedef typename OuterProduct::IRet             IRet;
3707         typedef typename OuterProduct::IArgs    IArgs;
3708
3709         string  getName (void) const
3710         {
3711                 return "outerProduct";
3712         }
3713
3714 protected:
3715         IRet    doApply (const EvalContext& ctx, const IArgs& iargs) const
3716         {
3717                 IRet    ret;
3718
3719                 for (int row = 0; row < Rows; ++row)
3720                 {
3721                         for (int col = 0; col < Cols; ++col)
3722                                 ret[col][row] = call<Mul>(ctx, iargs.a[row], iargs.b[col]);
3723                 }
3724
3725                 return ret;
3726         }
3727 };
3728
3729 template<int Rows, int Cols>
3730 ExprP<Matrix<float, Rows, Cols> > outerProduct (const ExprP<Vector<float, Rows> >& left,
3731                                                                                                 const ExprP<Vector<float, Cols> >& right)
3732 {
3733         return app<OuterProduct<Rows, Cols> >(left, right);
3734 }
3735
3736 template<int Size>
3737 class DeterminantBase : public DerivedFunc<Signature<float, Matrix<float, Size, Size> > >
3738 {
3739 public:
3740         string  getName (void) const { return "determinant"; }
3741 };
3742
3743 template<int Size>
3744 class Determinant;
3745
3746 template<int Size>
3747 ExprP<float> determinant (ExprP<Matrix<float, Size, Size> > mat)
3748 {
3749         return app<Determinant<Size> >(mat);
3750 }
3751
3752 template<>
3753 class Determinant<2> : public DeterminantBase<2>
3754 {
3755 protected:
3756         ExprP<Ret>      doExpand (ExpandContext&, const ArgExprs& args) const
3757         {
3758                 ExprP<Mat2>     mat     = args.a;
3759
3760                 return mat[0][0] * mat[1][1] - mat[1][0] * mat[0][1];
3761         }
3762 };
3763
3764 template<>
3765 class Determinant<3> : public DeterminantBase<3>
3766 {
3767 protected:
3768         ExprP<Ret> doExpand (ExpandContext&, const ArgExprs& args) const
3769         {
3770                 ExprP<Mat3>     mat     = args.a;
3771
3772                 return (mat[0][0] * (mat[1][1] * mat[2][2] - mat[1][2] * mat[2][1]) +
3773                                 mat[0][1] * (mat[1][2] * mat[2][0] - mat[1][0] * mat[2][2]) +
3774                                 mat[0][2] * (mat[1][0] * mat[2][1] - mat[1][1] * mat[2][0]));
3775         }
3776 };
3777
3778 template<>
3779 class Determinant<4> : public DeterminantBase<4>
3780 {
3781 protected:
3782          ExprP<Ret>     doExpand        (ExpandContext& ctx, const ArgExprs& args) const
3783         {
3784                 ExprP<Mat4>     mat     = args.a;
3785                 ExprP<Mat3>     minors[4];
3786
3787                 for (int ndx = 0; ndx < 4; ++ndx)
3788                 {
3789                         ExprP<Vec4>             minorColumns[3];
3790                         ExprP<Vec3>             columns[3];
3791
3792                         for (int col = 0; col < 3; ++col)
3793                                 minorColumns[col] = mat[col < ndx ? col : col + 1];
3794
3795                         for (int col = 0; col < 3; ++col)
3796                                 columns[col] = vec3(minorColumns[0][col+1],
3797                                                                         minorColumns[1][col+1],
3798                                                                         minorColumns[2][col+1]);
3799
3800                         minors[ndx] = bindExpression("minor", ctx,
3801                                                                                  mat3(columns[0], columns[1], columns[2]));
3802                 }
3803
3804                 return (mat[0][0] * determinant(minors[0]) -
3805                                 mat[1][0] * determinant(minors[1]) +
3806                                 mat[2][0] * determinant(minors[2]) -
3807                                 mat[3][0] * determinant(minors[3]));
3808         }
3809 };
3810
3811 template<int Size> class Inverse;
3812
3813 template <int Size>
3814 ExprP<Matrix<float, Size, Size> > inverse (ExprP<Matrix<float, Size, Size> > mat)
3815 {
3816         return app<Inverse<Size> >(mat);
3817 }
3818
3819 template<>
3820 class Inverse<2> : public DerivedFunc<Signature<Mat2, Mat2> >
3821 {
3822 public:
3823         string          getName (void) const
3824         {
3825                 return "inverse";
3826         }
3827
3828 protected:
3829         ExprP<Ret>      doExpand (ExpandContext& ctx, const ArgExprs& args) const
3830         {
3831                 ExprP<Mat2>             mat = args.a;
3832                 ExprP<float>    det     = bindExpression("det", ctx, determinant(mat));
3833
3834                 return mat2(vec2(mat[1][1] / det, -mat[0][1] / det),
3835                                         vec2(-mat[1][0] / det, mat[0][0] / det));
3836         }
3837 };
3838
3839 template<>
3840 class Inverse<3> : public DerivedFunc<Signature<Mat3, Mat3> >
3841 {
3842 public:
3843         string          getName         (void) const
3844         {
3845                 return "inverse";
3846         }
3847
3848 protected:
3849         ExprP<Ret>      doExpand        (ExpandContext& ctx, const ArgExprs& args)                      const
3850         {
3851                 ExprP<Mat3>             mat             = args.a;
3852                 ExprP<Mat2>             invA    = bindExpression("invA", ctx,
3853                                                                                                  inverse(mat2(vec2(mat[0][0], mat[0][1]),
3854                                                                                                                           vec2(mat[1][0], mat[1][1]))));
3855
3856                 ExprP<Vec2>             matB    = bindExpression("matB", ctx, vec2(mat[2][0], mat[2][1]));
3857                 ExprP<Vec2>             matC    = bindExpression("matC", ctx, vec2(mat[0][2], mat[1][2]));
3858                 ExprP<float>    matD    = bindExpression("matD", ctx, mat[2][2]);
3859
3860                 ExprP<float>    schur   = bindExpression("schur", ctx,
3861                                                                                                  constant(1.0f) /
3862                                                                                                  (matD - dot(matC * invA, matB)));
3863
3864                 ExprP<Vec2>             t1              = invA * matB;
3865                 ExprP<Vec2>             t2              = t1 * schur;
3866                 ExprP<Mat2>             t3              = outerProduct(t2, matC);
3867                 ExprP<Mat2>             t4              = t3 * invA;
3868                 ExprP<Mat2>             t5              = invA + t4;
3869                 ExprP<Mat2>             blockA  = bindExpression("blockA", ctx, t5);
3870                 ExprP<Vec2>             blockB  = bindExpression("blockB", ctx,
3871                                                                                                  (invA * matB) * -schur);
3872                 ExprP<Vec2>             blockC  = bindExpression("blockC", ctx,
3873                                                                                                  (matC * invA) * -schur);
3874
3875                 return mat3(vec3(blockA[0][0], blockA[0][1], blockC[0]),
3876                                         vec3(blockA[1][0], blockA[1][1], blockC[1]),
3877                                         vec3(blockB[0], blockB[1], schur));
3878         }
3879 };
3880
3881 template<>
3882 class Inverse<4> : public DerivedFunc<Signature<Mat4, Mat4> >
3883 {
3884 public:
3885         string          getName         (void) const { return "inverse"; }
3886
3887 protected:
3888         ExprP<Ret>                      doExpand                        (ExpandContext&         ctx,
3889                                                                                          const ArgExprs&        args)                   const
3890         {
3891                 ExprP<Mat4>     mat             = args.a;
3892                 ExprP<Mat2>     invA    = bindExpression("invA", ctx,
3893                                                                                          inverse(mat2(vec2(mat[0][0], mat[0][1]),
3894                                                                                                                   vec2(mat[1][0], mat[1][1]))));
3895                 ExprP<Mat2>     matB    = bindExpression("matB", ctx,
3896                                                                                          mat2(vec2(mat[2][0], mat[2][1]),
3897                                                                                                   vec2(mat[3][0], mat[3][1])));
3898                 ExprP<Mat2>     matC    = bindExpression("matC", ctx,
3899                                                                                          mat2(vec2(mat[0][2], mat[0][3]),
3900                                                                                                   vec2(mat[1][2], mat[1][3])));
3901                 ExprP<Mat2>     matD    = bindExpression("matD", ctx,
3902                                                                                          mat2(vec2(mat[2][2], mat[2][3]),
3903                                                                                                   vec2(mat[3][2], mat[3][3])));
3904                 ExprP<Mat2>     schur   = bindExpression("schur", ctx,
3905                                                                                          inverse(matD + -(matC * invA * matB)));
3906                 ExprP<Mat2>     blockA  = bindExpression("blockA", ctx,
3907                                                                                          invA + (invA * matB * schur * matC * invA));
3908                 ExprP<Mat2>     blockB  = bindExpression("blockB", ctx,
3909                                                                                          (-invA) * matB * schur);
3910                 ExprP<Mat2>     blockC  = bindExpression("blockC", ctx,
3911                                                                                          (-schur) * matC * invA);
3912
3913                 return mat4(vec4(blockA[0][0], blockA[0][1], blockC[0][0], blockC[0][1]),
3914                                         vec4(blockA[1][0], blockA[1][1], blockC[1][0], blockC[1][1]),
3915                                         vec4(blockB[0][0], blockB[0][1], schur[0][0], schur[0][1]),
3916                                         vec4(blockB[1][0], blockB[1][1], schur[1][0], schur[1][1]));
3917         }
3918 };
3919
3920 class Fma : public DerivedFunc<Signature<float, float, float, float> >
3921 {
3922 public:
3923         string                  getName                                 (void) const
3924         {
3925                 return "fma";
3926         }
3927
3928         string                  getRequiredExtension    (const RenderContext&   context) const
3929         {
3930                 return (glu::contextSupports(context.getType(), glu::ApiType::core(4, 5))) ? "" : "GL_EXT_gpu_shader5";
3931         }
3932
3933 protected:
3934         ExprP<float>    doExpand                                (ExpandContext&, const ArgExprs& x) const
3935         {
3936                 return x.a * x.b + x.c;
3937         }
3938 };
3939
3940 } // Functions
3941
3942 using namespace Functions;
3943
3944 template <typename T>
3945 ExprP<typename T::Element> ContainerExprPBase<T>::operator[] (int i) const
3946 {
3947         return Functions::getComponent(exprP<T>(*this), i);
3948 }
3949
3950 ExprP<float> operator+ (const ExprP<float>& arg0, const ExprP<float>& arg1)
3951 {
3952         return app<Add>(arg0, arg1);
3953 }
3954
3955 ExprP<float> operator- (const ExprP<float>& arg0, const ExprP<float>& arg1)
3956 {
3957         return app<Sub>(arg0, arg1);
3958 }
3959
3960 ExprP<float> operator- (const ExprP<float>& arg0)
3961 {
3962         return app<Negate>(arg0);
3963 }
3964
3965 ExprP<float> operator* (const ExprP<float>& arg0, const ExprP<float>& arg1)
3966 {
3967         return app<Mul>(arg0, arg1);
3968 }
3969
3970 ExprP<float> operator/ (const ExprP<float>& arg0, const ExprP<float>& arg1)
3971 {
3972         return app<Div>(arg0, arg1);
3973 }
3974
3975 template <typename Sig_, int Size>
3976 class GenFunc : public PrimitiveFunc<Signature<
3977         typename ContainerOf<typename Sig_::Ret, Size>::Container,
3978         typename ContainerOf<typename Sig_::Arg0, Size>::Container,
3979         typename ContainerOf<typename Sig_::Arg1, Size>::Container,
3980         typename ContainerOf<typename Sig_::Arg2, Size>::Container,
3981         typename ContainerOf<typename Sig_::Arg3, Size>::Container> >
3982 {
3983 public:
3984         typedef typename GenFunc::IArgs         IArgs;
3985         typedef typename GenFunc::IRet          IRet;
3986
3987                         GenFunc                                 (const Func<Sig_>&      scalarFunc) : m_func (scalarFunc) {}
3988
3989         string  getName                                 (void) const
3990         {
3991                 return m_func.getName();
3992         }
3993
3994         int             getOutParamIndex                (void) const
3995         {
3996                 return m_func.getOutParamIndex();
3997         }
3998
3999         string  getRequiredExtension    (const RenderContext &context) const
4000         {
4001                 return m_func.getRequiredExtension(context);
4002         }
4003
4004 protected:
4005         void    doPrint                                 (ostream& os, const BaseArgExprs& args) const
4006         {
4007                 m_func.print(os, args);
4008         }
4009
4010         IRet    doApply                                 (const EvalContext& ctx, const IArgs& iargs) const
4011         {
4012                 IRet ret;
4013
4014                 for (int ndx = 0; ndx < Size; ++ndx)
4015                 {
4016                         ret[ndx] =
4017                                 m_func.apply(ctx, iargs.a[ndx], iargs.b[ndx], iargs.c[ndx], iargs.d[ndx]);
4018                 }
4019
4020                 return ret;
4021         }
4022
4023         void    doGetUsedFuncs                  (FuncSet& dst) const
4024         {
4025                 m_func.getUsedFuncs(dst);
4026         }
4027
4028         const Func<Sig_>&       m_func;
4029 };
4030
4031 template <typename F, int Size>
4032 class VectorizedFunc : public GenFunc<typename F::Sig, Size>
4033 {
4034 public:
4035         VectorizedFunc  (void) : GenFunc<typename F::Sig, Size>(instance<F>()) {}
4036 };
4037
4038
4039
4040 template <typename Sig_, int Size>
4041 class FixedGenFunc : public PrimitiveFunc <Signature<
4042         typename ContainerOf<typename Sig_::Ret, Size>::Container,
4043         typename ContainerOf<typename Sig_::Arg0, Size>::Container,
4044         typename Sig_::Arg1,
4045         typename ContainerOf<typename Sig_::Arg2, Size>::Container,
4046         typename ContainerOf<typename Sig_::Arg3, Size>::Container> >
4047 {
4048 public:
4049         typedef typename FixedGenFunc::IArgs            IArgs;
4050         typedef typename FixedGenFunc::IRet                     IRet;
4051
4052         string                                          getName                 (void) const
4053         {
4054                 return this->doGetScalarFunc().getName();
4055         }
4056
4057 protected:
4058         void                                            doPrint                 (ostream& os, const BaseArgExprs& args) const
4059         {
4060                 this->doGetScalarFunc().print(os, args);
4061         }
4062
4063         IRet                                            doApply                 (const EvalContext& ctx,
4064                                                                                                  const IArgs&           iargs) const
4065         {
4066                 IRet                            ret;
4067                 const Func<Sig_>&       func    = this->doGetScalarFunc();
4068
4069                 for (int ndx = 0; ndx < Size; ++ndx)
4070                         ret[ndx] = func.apply(ctx, iargs.a[ndx], iargs.b, iargs.c[ndx], iargs.d[ndx]);
4071
4072                 return ret;
4073         }
4074
4075         virtual const Func<Sig_>&       doGetScalarFunc (void) const = 0;
4076 };
4077
4078 template <typename F, int Size>
4079 class FixedVecFunc : public FixedGenFunc<typename F::Sig, Size>
4080 {
4081 protected:
4082         const Func<typename F::Sig>& doGetScalarFunc    (void) const { return instance<F>(); }
4083 };
4084
4085 template<typename Sig>
4086 struct GenFuncs
4087 {
4088         GenFuncs (const Func<Sig>&                      func_,
4089                           const GenFunc<Sig, 2>&        func2_,
4090                           const GenFunc<Sig, 3>&        func3_,
4091                           const GenFunc<Sig, 4>&        func4_)
4092                 : func  (func_)
4093                 , func2 (func2_)
4094                 , func3 (func3_)
4095                 , func4 (func4_)
4096         {}
4097
4098         const Func<Sig>&                func;
4099         const GenFunc<Sig, 2>&  func2;
4100         const GenFunc<Sig, 3>&  func3;
4101         const GenFunc<Sig, 4>&  func4;
4102 };
4103
4104 template<typename F>
4105 GenFuncs<typename F::Sig> makeVectorizedFuncs (void)
4106 {
4107         return GenFuncs<typename F::Sig>(instance<F>(),
4108                                                                          instance<VectorizedFunc<F, 2> >(),
4109                                                                          instance<VectorizedFunc<F, 3> >(),
4110                                                                          instance<VectorizedFunc<F, 4> >());
4111 }
4112
4113 template<int Size>
4114 ExprP<Vector<float, Size> > operator*(const ExprP<Vector<float, Size> >& arg0,
4115                                                                           const ExprP<Vector<float, Size> >& arg1)
4116 {
4117         return app<VectorizedFunc<Mul, Size> >(arg0, arg1);
4118 }
4119
4120 template<int Size>
4121 ExprP<Vector<float, Size> > operator*(const ExprP<Vector<float, Size> >&        arg0,
4122                                                                           const ExprP<float>&                                   arg1)
4123 {
4124         return app<FixedVecFunc<Mul, Size> >(arg0, arg1);
4125 }
4126
4127 template<int Size>
4128 ExprP<Vector<float, Size> > operator/(const ExprP<Vector<float, Size> >&        arg0,
4129                                                                           const ExprP<float>&                                   arg1)
4130 {
4131         return app<FixedVecFunc<Div, Size> >(arg0, arg1);
4132 }
4133
4134 template<int Size>
4135 ExprP<Vector<float, Size> > operator-(const ExprP<Vector<float, Size> >& arg0)
4136 {
4137         return app<VectorizedFunc<Negate, Size> >(arg0);
4138 }
4139
4140 template<int Size>
4141 ExprP<Vector<float, Size> > operator-(const ExprP<Vector<float, Size> >& arg0,
4142                                                                           const ExprP<Vector<float, Size> >& arg1)
4143 {
4144         return app<VectorizedFunc<Sub, Size> >(arg0, arg1);
4145 }
4146
4147 template<int LeftRows, int Middle, int RightCols>
4148 ExprP<Matrix<float, LeftRows, RightCols> >
4149 operator* (const ExprP<Matrix<float, LeftRows, Middle> >&       left,
4150                    const ExprP<Matrix<float, Middle, RightCols> >&      right)
4151 {
4152         return app<MatMul<LeftRows, Middle, RightCols> >(left, right);
4153 }
4154
4155 template<int Rows, int Cols>
4156 ExprP<Vector<float, Rows> > operator* (const ExprP<Vector<float, Cols> >&               left,
4157                                                                            const ExprP<Matrix<float, Rows, Cols> >&     right)
4158 {
4159         return app<VecMatMul<Rows, Cols> >(left, right);
4160 }
4161
4162 template<int Rows, int Cols>
4163 ExprP<Vector<float, Cols> > operator* (const ExprP<Matrix<float, Rows, Cols> >& left,
4164                                                                            const ExprP<Vector<float, Rows> >&           right)
4165 {
4166         return app<MatVecMul<Rows, Cols> >(left, right);
4167 }
4168
4169 template<int Rows, int Cols>
4170 ExprP<Matrix<float, Rows, Cols> > operator* (const ExprP<Matrix<float, Rows, Cols> >&   left,
4171                                                                                          const ExprP<float>&                                            right)
4172 {
4173         return app<ScalarMatFunc<Mul, Rows, Cols> >(left, right);
4174 }
4175
4176 template<int Rows, int Cols>
4177 ExprP<Matrix<float, Rows, Cols> > operator+ (const ExprP<Matrix<float, Rows, Cols> >&   left,
4178                                                                                          const ExprP<Matrix<float, Rows, Cols> >&       right)
4179 {
4180         return app<CompMatFunc<Add, Rows, Cols> >(left, right);
4181 }
4182
4183 template<int Rows, int Cols>
4184 ExprP<Matrix<float, Rows, Cols> > operator- (const ExprP<Matrix<float, Rows, Cols> >&   mat)
4185 {
4186         return app<MatNeg<Rows, Cols> >(mat);
4187 }
4188
4189 template <typename T>
4190 class Sampling
4191 {
4192 public:
4193         virtual void    genFixeds       (const FloatFormat&, vector<T>&)                        const {}
4194         virtual T               genRandom       (const FloatFormat&, Precision, Random&)        const { return T(); }
4195         virtual double  getWeight       (void)                                                                          const { return 0.0; }
4196 };
4197
4198 template <>
4199 class DefaultSampling<Void> : public Sampling<Void>
4200 {
4201 public:
4202         void    genFixeds       (const FloatFormat&, vector<Void>& dst) const { dst.push_back(Void()); }
4203 };
4204
4205 template <>
4206 class DefaultSampling<bool> : public Sampling<bool>
4207 {
4208 public:
4209         void    genFixeds       (const FloatFormat&, vector<bool>& dst) const
4210         {
4211                 dst.push_back(true);
4212                 dst.push_back(false);
4213         }
4214 };
4215
4216 template <>
4217 class DefaultSampling<int> : public Sampling<int>
4218 {
4219 public:
4220         int             genRandom       (const FloatFormat&, Precision prec, Random& rnd) const
4221         {
4222                 const int       exp             = rnd.getInt(0, getNumBits(prec)-2);
4223                 const int       sign    = rnd.getBool() ? -1 : 1;
4224
4225                 return sign * rnd.getInt(0, (deInt32)1 << exp);
4226         }
4227
4228         void    genFixeds       (const FloatFormat&, vector<int>& dst) const
4229         {
4230                 dst.push_back(0);
4231                 dst.push_back(-1);
4232                 dst.push_back(1);
4233         }
4234         double  getWeight       (void) const { return 1.0; }
4235
4236 private:
4237         static inline int getNumBits (Precision prec)
4238         {
4239                 switch (prec)
4240                 {
4241                         case glu::PRECISION_LOWP:               return 8;
4242                         case glu::PRECISION_MEDIUMP:    return 16;
4243                         case glu::PRECISION_HIGHP:              return 32;
4244                         default:
4245                                 DE_ASSERT(false);
4246                                 return 0;
4247                 }
4248         }
4249 };
4250
4251 template <>
4252 class DefaultSampling<float> : public Sampling<float>
4253 {
4254 public:
4255         float   genRandom       (const FloatFormat& format, Precision prec, Random& rnd) const;
4256         void    genFixeds       (const FloatFormat& format, vector<float>& dst) const;
4257         double  getWeight       (void) const { return 1.0; }
4258 };
4259
4260 //! Generate a random float from a reasonable general-purpose distribution.
4261 float DefaultSampling<float>::genRandom (const FloatFormat& format,
4262                                                                                  Precision,
4263                                                                                  Random&                        rnd) const
4264 {
4265         const int               minExp                  = format.getMinExp();
4266         const int               maxExp                  = format.getMaxExp();
4267         const bool              haveSubnormal   = format.hasSubnormal() != tcu::NO;
4268
4269         // Choose exponent so that the cumulative distribution is cubic.
4270         // This makes the probability distribution quadratic, with the peak centered on zero.
4271         const double    minRoot                 = deCbrt(minExp - 0.5 - (haveSubnormal ? 1.0 : 0.0));
4272         const double    maxRoot                 = deCbrt(maxExp + 0.5);
4273         const int               fractionBits    = format.getFractionBits();
4274         const int               exp                             = int(deRoundEven(dePow(rnd.getDouble(minRoot, maxRoot),
4275                                                                                                                         3.0)));
4276         float                   base                    = 0.0f; // integral power of two
4277         float                   quantum                 = 0.0f; // smallest representable difference in the binade
4278         float                   significand             = 0.0f; // Significand.
4279
4280         DE_ASSERT(fractionBits < std::numeric_limits<float>::digits);
4281
4282         // Generate some occasional special numbers
4283         switch (rnd.getInt(0, 64))
4284         {
4285                 case 0:         return 0;
4286                 case 1:         return TCU_INFINITY;
4287                 case 2:         return -TCU_INFINITY;
4288                 case 3:         return TCU_NAN;
4289                 default:        break;
4290         }
4291
4292         if (exp >= minExp)
4293         {
4294                 // Normal number
4295                 base = deFloatLdExp(1.0f, exp);
4296                 quantum = deFloatLdExp(1.0f, exp - fractionBits);
4297         }
4298         else
4299         {
4300                 // Subnormal
4301                 base = 0.0f;
4302                 quantum = deFloatLdExp(1.0f, minExp - fractionBits);
4303         }
4304
4305         switch (rnd.getInt(0, 16))
4306         {
4307                 case 0: // The highest number in this binade, significand is all bits one.
4308                         significand = base - quantum;
4309                         break;
4310                 case 1: // Significand is one.
4311                         significand = quantum;
4312                         break;
4313                 case 2: // Significand is zero.
4314                         significand = 0.0;
4315                         break;
4316                 default: // Random (evenly distributed) significand.
4317                 {
4318                         deUint64 intFraction = rnd.getUint64() & ((1ull << fractionBits) - 1);
4319                         significand = float(intFraction) * quantum;
4320                 }
4321         }
4322
4323         // Produce positive numbers more often than negative.
4324         return (rnd.getInt(0,3) == 0 ? -1.0f : 1.0f) * (base + significand);
4325 }
4326
4327 //! Generate a standard set of floats that should always be tested.
4328 void DefaultSampling<float>::genFixeds (const FloatFormat& format, vector<float>& dst) const
4329 {
4330         const int                       minExp                  = format.getMinExp();
4331         const int                       maxExp                  = format.getMaxExp();
4332         const int                       fractionBits    = format.getFractionBits();
4333         const float                     minQuantum              = deFloatLdExp(1.0f, minExp - fractionBits);
4334         const float                     minNormalized   = deFloatLdExp(1.0f, minExp);
4335         const float                     maxQuantum              = deFloatLdExp(1.0f, maxExp - fractionBits);
4336
4337         // NaN
4338         dst.push_back(TCU_NAN);
4339         // Zero
4340         dst.push_back(0.0f);
4341
4342         for (int sign = -1; sign <= 1; sign += 2)
4343         {
4344                 // Smallest subnormal
4345                 dst.push_back((float)sign * minQuantum);
4346
4347                 // Largest subnormal
4348                 dst.push_back((float)sign * (minNormalized - minQuantum));
4349
4350                 // Smallest normalized
4351                 dst.push_back((float)sign * minNormalized);
4352
4353                 // Next smallest normalized
4354                 dst.push_back((float)sign * (minNormalized + minQuantum));
4355
4356                 dst.push_back((float)sign * 0.5f);
4357                 dst.push_back((float)sign * 1.0f);
4358                 dst.push_back((float)sign * 2.0f);
4359
4360                 // Largest number
4361                 dst.push_back((float)sign * (deFloatLdExp(1.0f, maxExp) +
4362                                                                         (deFloatLdExp(1.0f, maxExp) - maxQuantum)));
4363
4364                 dst.push_back((float)sign * TCU_INFINITY);
4365         }
4366 }
4367
4368 template <typename T, int Size>
4369 class DefaultSampling<Vector<T, Size> > : public Sampling<Vector<T, Size> >
4370 {
4371 public:
4372         typedef Vector<T, Size>         Value;
4373
4374         Value   genRandom       (const FloatFormat& fmt, Precision prec, Random& rnd) const
4375         {
4376                 Value ret;
4377
4378                 for (int ndx = 0; ndx < Size; ++ndx)
4379                         ret[ndx] = instance<DefaultSampling<T> >().genRandom(fmt, prec, rnd);
4380
4381                 return ret;
4382         }
4383
4384         void    genFixeds       (const FloatFormat& fmt, vector<Value>& dst) const
4385         {
4386                 vector<T> scalars;
4387
4388                 instance<DefaultSampling<T> >().genFixeds(fmt, scalars);
4389
4390                 for (size_t scalarNdx = 0; scalarNdx < scalars.size(); ++scalarNdx)
4391                         dst.push_back(Value(scalars[scalarNdx]));
4392         }
4393
4394         double  getWeight       (void) const
4395         {
4396                 return dePow(instance<DefaultSampling<T> >().getWeight(), Size);
4397         }
4398 };
4399
4400 template <typename T, int Rows, int Columns>
4401 class DefaultSampling<Matrix<T, Rows, Columns> > : public Sampling<Matrix<T, Rows, Columns> >
4402 {
4403 public:
4404         typedef Matrix<T, Rows, Columns>                Value;
4405
4406         Value   genRandom       (const FloatFormat& fmt, Precision prec, Random& rnd) const
4407         {
4408                 Value ret;
4409
4410                 for (int rowNdx = 0; rowNdx < Rows; ++rowNdx)
4411                         for (int colNdx = 0; colNdx < Columns; ++colNdx)
4412                                 ret(rowNdx, colNdx) = instance<DefaultSampling<T> >().genRandom(fmt, prec, rnd);
4413
4414                 return ret;
4415         }
4416
4417         void    genFixeds       (const FloatFormat& fmt, vector<Value>& dst) const
4418         {
4419                 vector<T> scalars;
4420
4421                 instance<DefaultSampling<T> >().genFixeds(fmt, scalars);
4422
4423                 for (size_t scalarNdx = 0; scalarNdx < scalars.size(); ++scalarNdx)
4424                         dst.push_back(Value(scalars[scalarNdx]));
4425
4426                 if (Columns == Rows)
4427                 {
4428                         Value   mat     (0.0);
4429                         T               x       = T(1.0f);
4430                         mat[0][0] = x;
4431                         for (int ndx = 0; ndx < Columns; ++ndx)
4432                         {
4433                                 mat[Columns-1-ndx][ndx] = x;
4434                                 x *= T(2.0f);
4435                         }
4436                         dst.push_back(mat);
4437                 }
4438         }
4439
4440         double  getWeight       (void) const
4441         {
4442                 return dePow(instance<DefaultSampling<T> >().getWeight(), Rows * Columns);
4443         }
4444 };
4445
4446 struct Context
4447 {
4448         Context         (const string&          name_,
4449                                  TestContext&           testContext_,
4450                                  RenderContext&         renderContext_,
4451                                  const FloatFormat&     floatFormat_,
4452                                  const FloatFormat&     highpFormat_,
4453                                  Precision                      precision_,
4454                                  ShaderType                     shaderType_,
4455                                  size_t                         numRandoms_)
4456                 : name                          (name_)
4457                 , testContext           (testContext_)
4458                 , renderContext         (renderContext_)
4459                 , floatFormat           (floatFormat_)
4460                 , highpFormat           (highpFormat_)
4461                 , precision                     (precision_)
4462                 , shaderType            (shaderType_)
4463                 , numRandoms            (numRandoms_) {}
4464
4465         string                          name;
4466         TestContext&            testContext;
4467         RenderContext&          renderContext;
4468         FloatFormat                     floatFormat;
4469         FloatFormat                     highpFormat;
4470         Precision                       precision;
4471         ShaderType                      shaderType;
4472         size_t                          numRandoms;
4473 };
4474
4475 template<typename In0_ = Void, typename In1_ = Void, typename In2_ = Void, typename In3_ = Void>
4476 struct InTypes
4477 {
4478         typedef In0_    In0;
4479         typedef In1_    In1;
4480         typedef In2_    In2;
4481         typedef In3_    In3;
4482 };
4483
4484 template <typename In>
4485 int numInputs (void)
4486 {
4487         return (!isTypeValid<typename In::In0>() ? 0 :
4488                         !isTypeValid<typename In::In1>() ? 1 :
4489                         !isTypeValid<typename In::In2>() ? 2 :
4490                         !isTypeValid<typename In::In3>() ? 3 :
4491                         4);
4492 }
4493
4494 template<typename Out0_, typename Out1_ = Void>
4495 struct OutTypes
4496 {
4497         typedef Out0_   Out0;
4498         typedef Out1_   Out1;
4499 };
4500
4501 template <typename Out>
4502 int numOutputs (void)
4503 {
4504         return (!isTypeValid<typename Out::Out0>() ? 0 :
4505                         !isTypeValid<typename Out::Out1>() ? 1 :
4506                         2);
4507 }
4508
4509 template<typename In>
4510 struct Inputs
4511 {
4512         vector<typename In::In0>        in0;
4513         vector<typename In::In1>        in1;
4514         vector<typename In::In2>        in2;
4515         vector<typename In::In3>        in3;
4516 };
4517
4518 template<typename Out>
4519 struct Outputs
4520 {
4521         Outputs (size_t size) : out0(size), out1(size) {}
4522
4523         vector<typename Out::Out0>      out0;
4524         vector<typename Out::Out1>      out1;
4525 };
4526
4527 template<typename In, typename Out>
4528 struct Variables
4529 {
4530         VariableP<typename In::In0>             in0;
4531         VariableP<typename In::In1>             in1;
4532         VariableP<typename In::In2>             in2;
4533         VariableP<typename In::In3>             in3;
4534         VariableP<typename Out::Out0>   out0;
4535         VariableP<typename Out::Out1>   out1;
4536 };
4537
4538 template<typename In>
4539 struct Samplings
4540 {
4541         Samplings       (const Sampling<typename In::In0>&      in0_,
4542                                  const Sampling<typename In::In1>&      in1_,
4543                                  const Sampling<typename In::In2>&      in2_,
4544                                  const Sampling<typename In::In3>&      in3_)
4545                 : in0 (in0_), in1 (in1_), in2 (in2_), in3 (in3_) {}
4546
4547         const Sampling<typename In::In0>&       in0;
4548         const Sampling<typename In::In1>&       in1;
4549         const Sampling<typename In::In2>&       in2;
4550         const Sampling<typename In::In3>&       in3;
4551 };
4552
4553 template<typename In>
4554 struct DefaultSamplings : Samplings<In>
4555 {
4556         DefaultSamplings        (void)
4557                 : Samplings<In>(instance<DefaultSampling<typename In::In0> >(),
4558                                                 instance<DefaultSampling<typename In::In1> >(),
4559                                                 instance<DefaultSampling<typename In::In2> >(),
4560                                                 instance<DefaultSampling<typename In::In3> >()) {}
4561 };
4562
4563 class PrecisionCase : public TestCase
4564 {
4565 public:
4566         IterateResult           iterate                 (void);
4567
4568 protected:
4569                                                 PrecisionCase   (const Context&         context,
4570                                                                                  const string&          name,
4571                                                                                  const string&          extension       = "")
4572                                                         : TestCase              (context.testContext,
4573                                                                                          name.c_str(),
4574                                                                                          name.c_str())
4575                                                         , m_ctx                 (context)
4576                                                         , m_status              ()
4577                                                         , m_rnd                 (0xdeadbeefu +
4578                                                                                          context.testContext.getCommandLine().getBaseSeed())
4579                                                         , m_extension   (extension)
4580         {
4581         }
4582
4583         RenderContext&          getRenderContext(void) const                    { return m_ctx.renderContext; }
4584
4585         const FloatFormat&      getFormat               (void) const                    { return m_ctx.floatFormat; }
4586
4587         TestLog&                        log                             (void) const                    { return m_testCtx.getLog(); }
4588
4589         virtual void            runTest                 (void) = 0;
4590
4591         template <typename In, typename Out>
4592         void                            testStatement   (const Variables<In, Out>&      variables,
4593                                                                                  const Inputs<In>&                      inputs,
4594                                                                                  const Statement&                       stmt);
4595
4596         template<typename T>
4597         Symbol                          makeSymbol              (const Variable<T>& variable)
4598         {
4599                 return Symbol(variable.getName(), getVarTypeOf<T>(m_ctx.precision));
4600         }
4601
4602         Context                         m_ctx;
4603         ResultCollector         m_status;
4604         Random                          m_rnd;
4605         const string            m_extension;
4606 };
4607
4608 IterateResult PrecisionCase::iterate (void)
4609 {
4610         runTest();
4611         m_status.setTestContextResult(m_testCtx);
4612         return STOP;
4613 }
4614
4615 template <typename In, typename Out>
4616 void PrecisionCase::testStatement (const Variables<In, Out>&    variables,
4617                                                                    const Inputs<In>&                    inputs,
4618                                                                    const Statement&                             stmt)
4619 {
4620         using namespace ShaderExecUtil;
4621
4622         typedef typename        In::In0         In0;
4623         typedef typename        In::In1         In1;
4624         typedef typename        In::In2         In2;
4625         typedef typename        In::In3         In3;
4626         typedef typename        Out::Out0       Out0;
4627         typedef typename        Out::Out1       Out1;
4628
4629         const FloatFormat&      fmt                     = getFormat();
4630         const int                       inCount         = numInputs<In>();
4631         const int                       outCount        = numOutputs<Out>();
4632         const size_t            numValues       = (inCount > 0) ? inputs.in0.size() : 1;
4633         Outputs<Out>            outputs         (numValues);
4634         ShaderSpec                      spec;
4635         const FloatFormat       highpFmt        = m_ctx.highpFormat;
4636         const int                       maxMsgs         = 100;
4637         int                                     numErrors       = 0;
4638         Environment                     env;            // Hoisted out of the inner loop for optimization.
4639
4640         switch (inCount)
4641         {
4642                 case 4:
4643                         DE_ASSERT(inputs.in3.size() == numValues);
4644                 // Fallthrough
4645                 case 3:
4646                         DE_ASSERT(inputs.in2.size() == numValues);
4647                 // Fallthrough
4648                 case 2:
4649                         DE_ASSERT(inputs.in1.size() == numValues);
4650                 // Fallthrough
4651                 case 1:
4652                         DE_ASSERT(inputs.in0.size() == numValues);
4653                 // Fallthrough
4654                 default:
4655                         break;
4656         }
4657
4658         // Print out the statement and its definitions
4659         log() << TestLog::Message << "Statement: " << stmt << TestLog::EndMessage;
4660         {
4661                 ostringstream   oss;
4662                 FuncSet                 funcs;
4663
4664                 stmt.getUsedFuncs(funcs);
4665                 for (FuncSet::const_iterator it = funcs.begin(); it != funcs.end(); ++it)
4666                 {
4667                         (*it)->printDefinition(oss);
4668                 }
4669                 if (!funcs.empty())
4670                         log() << TestLog::Message << "Reference definitions:\n" << oss.str()
4671                                   << TestLog::EndMessage;
4672         }
4673
4674         // Initialize ShaderSpec from precision, variables and statement.
4675         {
4676                 ostringstream os;
4677                 os << "precision " << glu::getPrecisionName(m_ctx.precision) << " float;\n";
4678                 spec.globalDeclarations = os.str();
4679         }
4680
4681         spec.version = getContextTypeGLSLVersion(getRenderContext().getType());
4682
4683         if (!m_extension.empty())
4684                 spec.globalDeclarations = "#extension " + m_extension + " : require\n";
4685
4686         spec.inputs.resize(inCount);
4687
4688         switch (inCount)
4689         {
4690                 case 4:
4691                         spec.inputs[3] = makeSymbol(*variables.in3);
4692                 // Fallthrough
4693                 case 3:
4694                         spec.inputs[2] = makeSymbol(*variables.in2);
4695                 // Fallthrough
4696                 case 2:
4697                         spec.inputs[1] = makeSymbol(*variables.in1);
4698                 // Fallthrough
4699                 case 1:
4700                         spec.inputs[0] = makeSymbol(*variables.in0);
4701                 // Fallthrough
4702                 default:
4703                         break;
4704         }
4705
4706         spec.outputs.resize(outCount);
4707
4708         switch (outCount)
4709         {
4710                 case 2: spec.outputs[1] = makeSymbol(*variables.out1);  // Fallthrough
4711                 case 1: spec.outputs[0] = makeSymbol(*variables.out0);
4712                 default: break;
4713         }
4714
4715         spec.source = de::toString(stmt);
4716
4717         // Run the shader with inputs.
4718         {
4719                 UniquePtr<ShaderExecutor>       executor                (createExecutor(getRenderContext(),
4720                                                                                                                                         m_ctx.shaderType,
4721                                                                                                                                         spec));
4722                 const void*                                     inputArr[]              =
4723                 {
4724                         &inputs.in0.front(), &inputs.in1.front(), &inputs.in2.front(), &inputs.in3.front(),
4725                 };
4726                 void*                                           outputArr[]             =
4727                 {
4728                         &outputs.out0.front(), &outputs.out1.front(),
4729                 };
4730
4731                 executor->log(log());
4732                 if (!executor->isOk())
4733                         TCU_FAIL("Shader compilation failed");
4734
4735                 executor->useProgram();
4736                 executor->execute(int(numValues), inputArr, outputArr);
4737         }
4738
4739         // Initialize environment with unused values so we don't need to bind in inner loop.
4740         {
4741                 const typename Traits<In0>::IVal                in0;
4742                 const typename Traits<In1>::IVal                in1;
4743                 const typename Traits<In2>::IVal                in2;
4744                 const typename Traits<In3>::IVal                in3;
4745                 const typename Traits<Out0>::IVal               reference0;
4746                 const typename Traits<Out1>::IVal               reference1;
4747
4748                 env.bind(*variables.in0, in0);
4749                 env.bind(*variables.in1, in1);
4750                 env.bind(*variables.in2, in2);
4751                 env.bind(*variables.in3, in3);
4752                 env.bind(*variables.out0, reference0);
4753                 env.bind(*variables.out1, reference1);
4754         }
4755
4756         // For each input tuple, compute output reference interval and compare
4757         // shader output to the reference.
4758         for (size_t valueNdx = 0; valueNdx < numValues; valueNdx++)
4759         {
4760                 bool                                            result = true;
4761                 bool                                            inExpectedRange;
4762                 bool                                            inWarningRange;
4763                 const char*                                     failStr = "Fail";
4764                 typename Traits<Out0>::IVal     reference0;
4765                 typename Traits<Out1>::IVal     reference1;
4766
4767                 if (valueNdx % (size_t)TOUCH_WATCHDOG_VALUE_FREQUENCY == 0)
4768                         m_testCtx.touchWatchdog();
4769
4770                 env.lookup(*variables.in0) = convert<In0>(fmt, round(fmt, inputs.in0[valueNdx]));
4771                 env.lookup(*variables.in1) = convert<In1>(fmt, round(fmt, inputs.in1[valueNdx]));
4772                 env.lookup(*variables.in2) = convert<In2>(fmt, round(fmt, inputs.in2[valueNdx]));
4773                 env.lookup(*variables.in3) = convert<In3>(fmt, round(fmt, inputs.in3[valueNdx]));
4774
4775                 {
4776                         EvalContext     ctx (fmt, m_ctx.precision, env);
4777                         stmt.execute(ctx);
4778                 }
4779
4780                 switch (outCount)
4781                 {
4782                         case 2:
4783                                 reference1      = convert<Out1>(highpFmt, env.lookup(*variables.out1));
4784                                 inExpectedRange = contains(reference1, outputs.out1[valueNdx]);
4785                                 inWarningRange  = containsWarning(reference1, outputs.out1[valueNdx]);
4786                                 if (!inExpectedRange && inWarningRange)
4787                                 {
4788                                         m_status.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Shader output 1 has low-quality shader precision");
4789                                         failStr = "QualityWarning";
4790                                         result = false;
4791                                 }
4792                                 else if (!inExpectedRange)
4793                                 {
4794                                         m_status.addResult(QP_TEST_RESULT_FAIL, "Shader output 1 is outside acceptable range");
4795                                         failStr = "Fail";
4796                                         result = false;
4797                                 }
4798                         // Fallthrough
4799
4800                         case 1:
4801                                 reference0      = convert<Out0>(highpFmt, env.lookup(*variables.out0));
4802                                 inExpectedRange = contains(reference0, outputs.out0[valueNdx]);
4803                                 inWarningRange  = containsWarning(reference0, outputs.out0[valueNdx]);
4804                                 if (!inExpectedRange && inWarningRange)
4805                                 {
4806                                         m_status.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Shader output 0 has low-quality shader precision");
4807                                         failStr = "QualityWarning";
4808                                         result = false;
4809                                 }
4810                                 else if (!inExpectedRange)
4811                                 {
4812                                         m_status.addResult(QP_TEST_RESULT_FAIL, "Shader output 0 is outside acceptable range");
4813                                         failStr = "Fail";
4814                                         result = false;
4815                                 }
4816
4817                         default: break;
4818                 }
4819
4820                 if (!result)
4821                         ++numErrors;
4822
4823                 if ((!result && numErrors <= maxMsgs) || GLS_LOG_ALL_RESULTS)
4824                 {
4825                         MessageBuilder  builder = log().message();
4826
4827                         builder << (result ? "Passed" : failStr) << " sample:\n";
4828
4829                         if (inCount > 0)
4830                         {
4831                                 builder << "\t" << variables.in0->getName() << " = "
4832                                                 << valueToString(highpFmt, inputs.in0[valueNdx]) << "\n";
4833                         }
4834
4835                         if (inCount > 1)
4836                         {
4837                                 builder << "\t" << variables.in1->getName() << " = "
4838                                                 << valueToString(highpFmt, inputs.in1[valueNdx]) << "\n";
4839                         }
4840
4841                         if (inCount > 2)
4842                         {
4843                                 builder << "\t" << variables.in2->getName() << " = "
4844                                                 << valueToString(highpFmt, inputs.in2[valueNdx]) << "\n";
4845                         }
4846
4847                         if (inCount > 3)
4848                         {
4849                                 builder << "\t" << variables.in3->getName() << " = "
4850                                                 << valueToString(highpFmt, inputs.in3[valueNdx]) << "\n";
4851                         }
4852
4853                         if (outCount > 0)
4854                         {
4855                                 builder << "\t" << variables.out0->getName() << " = "
4856                                                 << valueToString(highpFmt, outputs.out0[valueNdx]) << "\n"
4857                                                 << "\tExpected range: "
4858                                                 << intervalToString<typename Out::Out0>(highpFmt, reference0) << "\n";
4859                         }
4860
4861                         if (outCount > 1)
4862                         {
4863                                 builder << "\t" << variables.out1->getName() << " = "
4864                                                 << valueToString(highpFmt, outputs.out1[valueNdx]) << "\n"
4865                                                 << "\tExpected range: "
4866                                                 << intervalToString<typename Out::Out1>(highpFmt, reference1) << "\n";
4867                         }
4868
4869                         builder << TestLog::EndMessage;
4870                 }
4871         }
4872
4873         if (numErrors > maxMsgs)
4874         {
4875                 log() << TestLog::Message << "(Skipped " << (numErrors - maxMsgs) << " messages.)"
4876                           << TestLog::EndMessage;
4877         }
4878
4879         if (numErrors == 0)
4880         {
4881                 log() << TestLog::Message << "All " << numValues << " inputs passed."
4882                           << TestLog::EndMessage;
4883         }
4884         else
4885         {
4886                 log() << TestLog::Message << numErrors << "/" << numValues << " inputs failed or had quality warnings."
4887                           << TestLog::EndMessage;
4888         }
4889 }
4890
4891
4892
4893 template <typename T>
4894 struct InputLess
4895 {
4896         bool operator() (const T& val1, const T& val2) const
4897         {
4898                 return val1 < val2;
4899         }
4900 };
4901
4902 template <typename T>
4903 bool inputLess (const T& val1, const T& val2)
4904 {
4905         return InputLess<T>()(val1, val2);
4906 }
4907
4908 template <>
4909 struct InputLess<float>
4910 {
4911         bool operator() (const float& val1, const float& val2) const
4912         {
4913                 if (deIsNaN(val1))
4914                         return false;
4915                 if (deIsNaN(val2))
4916                         return true;
4917                 return val1 < val2;
4918         }
4919 };
4920
4921 template <typename T, int Size>
4922 struct InputLess<Vector<T, Size> >
4923 {
4924         bool operator() (const Vector<T, Size>& vec1, const Vector<T, Size>& vec2) const
4925         {
4926                 for (int ndx = 0; ndx < Size; ++ndx)
4927                 {
4928                         if (inputLess(vec1[ndx], vec2[ndx]))
4929                                 return true;
4930                         if (inputLess(vec2[ndx], vec1[ndx]))
4931                                 return false;
4932                 }
4933
4934                 return false;
4935         }
4936 };
4937
4938 template <typename T, int Rows, int Cols>
4939 struct InputLess<Matrix<T, Rows, Cols> >
4940 {
4941         bool operator() (const Matrix<T, Rows, Cols>& mat1,
4942                                          const Matrix<T, Rows, Cols>& mat2) const
4943         {
4944                 for (int col = 0; col < Cols; ++col)
4945                 {
4946                         if (inputLess(mat1[col], mat2[col]))
4947                                 return true;
4948                         if (inputLess(mat2[col], mat1[col]))
4949                                 return false;
4950                 }
4951
4952                 return false;
4953         }
4954 };
4955
4956 template <typename In>
4957 struct InTuple :
4958         public Tuple4<typename In::In0, typename In::In1, typename In::In2, typename In::In3>
4959 {
4960         InTuple (const typename In::In0& in0,
4961                          const typename In::In1& in1,
4962                          const typename In::In2& in2,
4963                          const typename In::In3& in3)
4964                 : Tuple4<typename In::In0, typename In::In1, typename In::In2, typename In::In3>
4965                   (in0, in1, in2, in3) {}
4966 };
4967
4968 template <typename In>
4969 struct InputLess<InTuple<In> >
4970 {
4971         bool operator() (const InTuple<In>& in1, const InTuple<In>& in2) const
4972         {
4973                 if (inputLess(in1.a, in2.a))
4974                         return true;
4975                 if (inputLess(in2.a, in1.a))
4976                         return false;
4977                 if (inputLess(in1.b, in2.b))
4978                         return true;
4979                 if (inputLess(in2.b, in1.b))
4980                         return false;
4981                 if (inputLess(in1.c, in2.c))
4982                         return true;
4983                 if (inputLess(in2.c, in1.c))
4984                         return false;
4985                 if (inputLess(in1.d, in2.d))
4986                         return true;
4987                 return false;
4988         }
4989 };
4990
4991 template<typename In>
4992 Inputs<In> generateInputs (const Samplings<In>& samplings,
4993                                                    const FloatFormat&   floatFormat,
4994                                                    Precision                    intPrecision,
4995                                                    size_t                               numSamples,
4996                                                    Random&                              rnd)
4997 {
4998         Inputs<In>                                                                      ret;
4999         Inputs<In>                                                                      fixedInputs;
5000         set<InTuple<In>, InputLess<InTuple<In> > >      seenInputs;
5001
5002         samplings.in0.genFixeds(floatFormat, fixedInputs.in0);
5003         samplings.in1.genFixeds(floatFormat, fixedInputs.in1);
5004         samplings.in2.genFixeds(floatFormat, fixedInputs.in2);
5005         samplings.in3.genFixeds(floatFormat, fixedInputs.in3);
5006
5007         for (size_t ndx0 = 0; ndx0 < fixedInputs.in0.size(); ++ndx0)
5008         {
5009                 for (size_t ndx1 = 0; ndx1 < fixedInputs.in1.size(); ++ndx1)
5010                 {
5011                         for (size_t ndx2 = 0; ndx2 < fixedInputs.in2.size(); ++ndx2)
5012                         {
5013                                 for (size_t ndx3 = 0; ndx3 < fixedInputs.in3.size(); ++ndx3)
5014                                 {
5015                                         const InTuple<In>       tuple   (fixedInputs.in0[ndx0],
5016                                                                                                  fixedInputs.in1[ndx1],
5017                                                                                                  fixedInputs.in2[ndx2],
5018                                                                                                  fixedInputs.in3[ndx3]);
5019
5020                                         seenInputs.insert(tuple);
5021                                         ret.in0.push_back(tuple.a);
5022                                         ret.in1.push_back(tuple.b);
5023                                         ret.in2.push_back(tuple.c);
5024                                         ret.in3.push_back(tuple.d);
5025                                 }
5026                         }
5027                 }
5028         }
5029
5030         for (size_t ndx = 0; ndx < numSamples; ++ndx)
5031         {
5032                 const typename In::In0  in0             = samplings.in0.genRandom(floatFormat, intPrecision, rnd);
5033                 const typename In::In1  in1             = samplings.in1.genRandom(floatFormat, intPrecision, rnd);
5034                 const typename In::In2  in2             = samplings.in2.genRandom(floatFormat, intPrecision, rnd);
5035                 const typename In::In3  in3             = samplings.in3.genRandom(floatFormat, intPrecision, rnd);
5036                 const InTuple<In>               tuple   (in0, in1, in2, in3);
5037
5038                 if (de::contains(seenInputs, tuple))
5039                         continue;
5040
5041                 seenInputs.insert(tuple);
5042                 ret.in0.push_back(in0);
5043                 ret.in1.push_back(in1);
5044                 ret.in2.push_back(in2);
5045                 ret.in3.push_back(in3);
5046         }
5047
5048         return ret;
5049 }
5050
5051 class FuncCaseBase : public PrecisionCase
5052 {
5053 public:
5054         IterateResult   iterate                 (void);
5055
5056 protected:
5057                                         FuncCaseBase    (const Context&         context,
5058                                                                          const string&          name,
5059                                                                          const FuncBase&        func)
5060                                                 : PrecisionCase (context, name, func.getRequiredExtension(context.renderContext)) {}
5061 };
5062
5063 IterateResult FuncCaseBase::iterate (void)
5064 {
5065         MovePtr<ContextInfo>    info    (ContextInfo::create(getRenderContext()));
5066
5067         if (!m_extension.empty() && !info->isExtensionSupported(m_extension.c_str()) &&
5068                 !glu::contextSupports(getRenderContext().getType(), glu::ApiType::core(4, 5)))
5069                 throw NotSupportedError("Unsupported extension: " + m_extension);
5070
5071         runTest();
5072
5073         m_status.setTestContextResult(m_testCtx);
5074         return STOP;
5075 }
5076
5077 template <typename Sig>
5078 class FuncCase : public FuncCaseBase
5079 {
5080 public:
5081         typedef Func<Sig>                                               CaseFunc;
5082         typedef typename Sig::Ret                               Ret;
5083         typedef typename Sig::Arg0                              Arg0;
5084         typedef typename Sig::Arg1                              Arg1;
5085         typedef typename Sig::Arg2                              Arg2;
5086         typedef typename Sig::Arg3                              Arg3;
5087         typedef InTypes<Arg0, Arg1, Arg2, Arg3> In;
5088         typedef OutTypes<Ret>                                   Out;
5089
5090                                         FuncCase        (const Context&         context,
5091                                                                  const string&          name,
5092                                                                  const CaseFunc&        func)
5093                                                 : FuncCaseBase  (context, name, func)
5094                                                 , m_func                (func) {}
5095
5096 protected:
5097         void                            runTest         (void);
5098
5099         virtual const Samplings<In>&    getSamplings    (void)
5100         {
5101                 return instance<DefaultSamplings<In> >();
5102         }
5103
5104 private:
5105         const CaseFunc&                 m_func;
5106 };
5107
5108 template <typename Sig>
5109 void FuncCase<Sig>::runTest (void)
5110 {
5111         const Inputs<In>        inputs  (generateInputs(getSamplings(),
5112                                                                                                 m_ctx.floatFormat,
5113                                                                                                 m_ctx.precision,
5114                                                                                                 m_ctx.numRandoms,
5115                                                                                                 m_rnd));
5116         Variables<In, Out>      variables;
5117
5118         variables.out0  = variable<Ret>("out0");
5119         variables.out1  = variable<Void>("out1");
5120         variables.in0   = variable<Arg0>("in0");
5121         variables.in1   = variable<Arg1>("in1");
5122         variables.in2   = variable<Arg2>("in2");
5123         variables.in3   = variable<Arg3>("in3");
5124
5125         {
5126                 ExprP<Ret>      expr    = applyVar(m_func,
5127                                                                            variables.in0, variables.in1,
5128                                                                            variables.in2, variables.in3);
5129                 StatementP      stmt    = variableAssignment(variables.out0, expr);
5130
5131                 this->testStatement(variables, inputs, *stmt);
5132         }
5133 }
5134
5135 template <typename Sig>
5136 class InOutFuncCase : public FuncCaseBase
5137 {
5138 public:
5139         typedef Func<Sig>                                               CaseFunc;
5140         typedef typename Sig::Ret                               Ret;
5141         typedef typename Sig::Arg0                              Arg0;
5142         typedef typename Sig::Arg1                              Arg1;
5143         typedef typename Sig::Arg2                              Arg2;
5144         typedef typename Sig::Arg3                              Arg3;
5145         typedef InTypes<Arg0, Arg2, Arg3>               In;
5146         typedef OutTypes<Ret, Arg1>                             Out;
5147
5148                                         InOutFuncCase   (const Context&         context,
5149                                                                          const string&          name,
5150                                                                          const CaseFunc&        func)
5151                                                 : FuncCaseBase  (context, name, func)
5152                                                 , m_func                (func) {}
5153
5154 protected:
5155         void                            runTest         (void);
5156
5157         virtual const Samplings<In>&    getSamplings    (void)
5158         {
5159                 return instance<DefaultSamplings<In> >();
5160         }
5161
5162 private:
5163         const CaseFunc&                 m_func;
5164 };
5165
5166 template <typename Sig>
5167 void InOutFuncCase<Sig>::runTest (void)
5168 {
5169         const Inputs<In>        inputs  (generateInputs(getSamplings(),
5170                                                                                                 m_ctx.floatFormat,
5171                                                                                                 m_ctx.precision,
5172                                                                                                 m_ctx.numRandoms,
5173                                                                                                 m_rnd));
5174         Variables<In, Out>      variables;
5175
5176         variables.out0  = variable<Ret>("out0");
5177         variables.out1  = variable<Arg1>("out1");
5178         variables.in0   = variable<Arg0>("in0");
5179         variables.in1   = variable<Arg2>("in1");
5180         variables.in2   = variable<Arg3>("in2");
5181         variables.in3   = variable<Void>("in3");
5182
5183         {
5184                 ExprP<Ret>      expr    = applyVar(m_func,
5185                                                                            variables.in0, variables.out1,
5186                                                                            variables.in1, variables.in2);
5187                 StatementP      stmt    = variableAssignment(variables.out0, expr);
5188
5189                 this->testStatement(variables, inputs, *stmt);
5190         }
5191 }
5192
5193 template <typename Sig>
5194 PrecisionCase* createFuncCase (const Context&   context,
5195                                                            const string&        name,
5196                                                            const Func<Sig>&     func)
5197 {
5198         switch (func.getOutParamIndex())
5199         {
5200                 case -1:
5201                         return new FuncCase<Sig>(context, name, func);
5202                 case 1:
5203                         return new InOutFuncCase<Sig>(context, name, func);
5204                 default:
5205                         DE_FATAL("Impossible");
5206         }
5207         return DE_NULL;
5208 }
5209
5210 class CaseFactory
5211 {
5212 public:
5213         virtual                                         ~CaseFactory    (void) {}
5214         virtual MovePtr<TestNode>       createCase              (const Context& ctx) const = 0;
5215         virtual string                          getName                 (void) const = 0;
5216         virtual string                          getDesc                 (void) const = 0;
5217 };
5218
5219 class FuncCaseFactory : public CaseFactory
5220 {
5221 public:
5222         virtual const FuncBase& getFunc         (void) const = 0;
5223
5224         string                                  getName         (void) const
5225         {
5226                 return de::toLower(getFunc().getName());
5227         }
5228
5229         string                                  getDesc         (void) const
5230         {
5231                 return "Function '" + getFunc().getName() + "'";
5232         }
5233 };
5234
5235 template <typename Sig>
5236 class GenFuncCaseFactory : public CaseFactory
5237 {
5238 public:
5239
5240                                                 GenFuncCaseFactory      (const GenFuncs<Sig>&   funcs,
5241                                                                                          const string&                  name)
5242                                                         : m_funcs       (funcs)
5243                                                         , m_name        (de::toLower(name)) {}
5244
5245         MovePtr<TestNode>       createCase                      (const Context& ctx) const
5246         {
5247                 TestCaseGroup*  group = new TestCaseGroup(ctx.testContext,
5248                                                                                                   ctx.name.c_str(), ctx.name.c_str());
5249
5250                 group->addChild(createFuncCase(ctx, "scalar", m_funcs.func));
5251                 group->addChild(createFuncCase(ctx, "vec2", m_funcs.func2));
5252                 group->addChild(createFuncCase(ctx, "vec3", m_funcs.func3));
5253                 group->addChild(createFuncCase(ctx, "vec4", m_funcs.func4));
5254
5255                 return MovePtr<TestNode>(group);
5256         }
5257
5258         string                          getName                         (void) const
5259         {
5260                 return m_name;
5261         }
5262
5263         string                          getDesc                         (void) const
5264         {
5265                 return "Function '" + m_funcs.func.getName() + "'";
5266         }
5267
5268 private:
5269         const GenFuncs<Sig>     m_funcs;
5270         string                          m_name;
5271 };
5272
5273 template <template <int> class GenF>
5274 class TemplateFuncCaseFactory : public FuncCaseFactory
5275 {
5276 public:
5277         MovePtr<TestNode>       createCase              (const Context& ctx) const
5278         {
5279                 TestCaseGroup*  group = new TestCaseGroup(ctx.testContext,
5280                                                           ctx.name.c_str(), ctx.name.c_str());
5281                 group->addChild(createFuncCase(ctx, "scalar", instance<GenF<1> >()));
5282                 group->addChild(createFuncCase(ctx, "vec2", instance<GenF<2> >()));
5283                 group->addChild(createFuncCase(ctx, "vec3", instance<GenF<3> >()));
5284                 group->addChild(createFuncCase(ctx, "vec4", instance<GenF<4> >()));
5285
5286                 return MovePtr<TestNode>(group);
5287         }
5288
5289         const FuncBase&         getFunc                 (void) const { return instance<GenF<1> >(); }
5290 };
5291
5292 template <template <int> class GenF>
5293 class SquareMatrixFuncCaseFactory : public FuncCaseFactory
5294 {
5295 public:
5296         MovePtr<TestNode>       createCase              (const Context& ctx) const
5297         {
5298                 TestCaseGroup*  group = new TestCaseGroup(ctx.testContext,
5299                                                           ctx.name.c_str(), ctx.name.c_str());
5300                 group->addChild(createFuncCase(ctx, "mat2", instance<GenF<2> >()));
5301 #if 0
5302                 // disabled until we get reasonable results
5303                 group->addChild(createFuncCase(ctx, "mat3", instance<GenF<3> >()));
5304                 group->addChild(createFuncCase(ctx, "mat4", instance<GenF<4> >()));
5305 #endif
5306
5307                 return MovePtr<TestNode>(group);
5308         }
5309
5310         const FuncBase&         getFunc                 (void) const { return instance<GenF<2> >(); }
5311 };
5312
5313 template <template <int, int> class GenF>
5314 class MatrixFuncCaseFactory : public FuncCaseFactory
5315 {
5316 public:
5317         MovePtr<TestNode>       createCase              (const Context& ctx) const
5318         {
5319                 TestCaseGroup*  const group = new TestCaseGroup(ctx.testContext,
5320                                                                                                                 ctx.name.c_str(), ctx.name.c_str());
5321
5322                 this->addCase<2, 2>(ctx, group);
5323                 this->addCase<3, 2>(ctx, group);
5324                 this->addCase<4, 2>(ctx, group);
5325                 this->addCase<2, 3>(ctx, group);
5326                 this->addCase<3, 3>(ctx, group);
5327                 this->addCase<4, 3>(ctx, group);
5328                 this->addCase<2, 4>(ctx, group);
5329                 this->addCase<3, 4>(ctx, group);
5330                 this->addCase<4, 4>(ctx, group);
5331
5332                 return MovePtr<TestNode>(group);
5333         }
5334
5335         const FuncBase&         getFunc                 (void) const { return instance<GenF<2,2> >(); }
5336
5337 private:
5338         template <int Rows, int Cols>
5339         void                            addCase                 (const Context& ctx, TestCaseGroup* group) const
5340         {
5341                 const char*     const name = dataTypeNameOf<Matrix<float, Rows, Cols> >();
5342
5343                 group->addChild(createFuncCase(ctx, name, instance<GenF<Rows, Cols> >()));
5344         }
5345 };
5346
5347 template <typename Sig>
5348 class SimpleFuncCaseFactory : public CaseFactory
5349 {
5350 public:
5351                                                 SimpleFuncCaseFactory   (const Func<Sig>& func) : m_func(func) {}
5352
5353         MovePtr<TestNode>       createCase              (const Context& ctx) const
5354         {
5355                 return MovePtr<TestNode>(createFuncCase(ctx, ctx.name.c_str(), m_func));
5356         }
5357
5358         string                          getName                                 (void) const
5359         {
5360                 return de::toLower(m_func.getName());
5361         }
5362
5363         string                          getDesc                                 (void) const
5364         {
5365                 return "Function '" + getName() + "'";
5366         }
5367
5368 private:
5369         const Func<Sig>&        m_func;
5370 };
5371
5372 template <typename F>
5373 SharedPtr<SimpleFuncCaseFactory<typename F::Sig> > createSimpleFuncCaseFactory (void)
5374 {
5375         return SharedPtr<SimpleFuncCaseFactory<typename F::Sig> >(
5376                 new SimpleFuncCaseFactory<typename F::Sig>(instance<F>()));
5377 }
5378
5379 class BuiltinFuncs : public CaseFactories
5380 {
5381 public:
5382         const vector<const CaseFactory*>        getFactories    (void) const
5383         {
5384                 vector<const CaseFactory*> ret;
5385
5386                 for (size_t ndx = 0; ndx < m_factories.size(); ++ndx)
5387                         ret.push_back(m_factories[ndx].get());
5388
5389                 return ret;
5390         }
5391
5392         void                                                            addFactory              (SharedPtr<const CaseFactory> fact)
5393         {
5394                 m_factories.push_back(fact);
5395         }
5396
5397 private:
5398         vector<SharedPtr<const CaseFactory> >                   m_factories;
5399 };
5400
5401 template <typename F>
5402 void addScalarFactory(BuiltinFuncs& funcs, string name = "")
5403 {
5404         if (name.empty())
5405                 name = instance<F>().getName();
5406
5407         funcs.addFactory(SharedPtr<const CaseFactory>(new GenFuncCaseFactory<typename F::Sig>(
5408                                                                                                           makeVectorizedFuncs<F>(), name)));
5409 }
5410
5411 MovePtr<const CaseFactories> createES3BuiltinCases (void)
5412 {
5413         MovePtr<BuiltinFuncs>   funcs   (new BuiltinFuncs());
5414
5415         addScalarFactory<Add>(*funcs);
5416         addScalarFactory<Sub>(*funcs);
5417         addScalarFactory<Mul>(*funcs);
5418         addScalarFactory<Div>(*funcs);
5419
5420         addScalarFactory<Radians>(*funcs);
5421         addScalarFactory<Degrees>(*funcs);
5422         addScalarFactory<Sin>(*funcs);
5423         addScalarFactory<Cos>(*funcs);
5424         addScalarFactory<Tan>(*funcs);
5425         addScalarFactory<ASin>(*funcs);
5426         addScalarFactory<ACos>(*funcs);
5427         addScalarFactory<ATan2>(*funcs, "atan2");
5428         addScalarFactory<ATan>(*funcs);
5429         addScalarFactory<Sinh>(*funcs);
5430         addScalarFactory<Cosh>(*funcs);
5431         addScalarFactory<Tanh>(*funcs);
5432         addScalarFactory<ASinh>(*funcs);
5433         addScalarFactory<ACosh>(*funcs);
5434         addScalarFactory<ATanh>(*funcs);
5435
5436         addScalarFactory<Pow>(*funcs);
5437         addScalarFactory<Exp>(*funcs);
5438         addScalarFactory<Log>(*funcs);
5439         addScalarFactory<Exp2>(*funcs);
5440         addScalarFactory<Log2>(*funcs);
5441         addScalarFactory<Sqrt>(*funcs);
5442         addScalarFactory<InverseSqrt>(*funcs);
5443
5444         addScalarFactory<Abs>(*funcs);
5445         addScalarFactory<Sign>(*funcs);
5446         addScalarFactory<Floor>(*funcs);
5447         addScalarFactory<Trunc>(*funcs);
5448         addScalarFactory<Round>(*funcs);
5449         addScalarFactory<RoundEven>(*funcs);
5450         addScalarFactory<Ceil>(*funcs);
5451         addScalarFactory<Fract>(*funcs);
5452         addScalarFactory<Mod>(*funcs);
5453         funcs->addFactory(createSimpleFuncCaseFactory<Modf>());
5454         addScalarFactory<Min>(*funcs);
5455         addScalarFactory<Max>(*funcs);
5456         addScalarFactory<Clamp>(*funcs);
5457         addScalarFactory<Mix>(*funcs);
5458         addScalarFactory<Step>(*funcs);
5459         addScalarFactory<SmoothStep>(*funcs);
5460
5461         funcs->addFactory(SharedPtr<const CaseFactory>(new TemplateFuncCaseFactory<Length>()));
5462         funcs->addFactory(SharedPtr<const CaseFactory>(new TemplateFuncCaseFactory<Distance>()));
5463         funcs->addFactory(SharedPtr<const CaseFactory>(new TemplateFuncCaseFactory<Dot>()));
5464         funcs->addFactory(createSimpleFuncCaseFactory<Cross>());
5465         funcs->addFactory(SharedPtr<const CaseFactory>(new TemplateFuncCaseFactory<Normalize>()));
5466         funcs->addFactory(SharedPtr<const CaseFactory>(new TemplateFuncCaseFactory<FaceForward>()));
5467         funcs->addFactory(SharedPtr<const CaseFactory>(new TemplateFuncCaseFactory<Reflect>()));
5468         funcs->addFactory(SharedPtr<const CaseFactory>(new TemplateFuncCaseFactory<Refract>()));
5469
5470
5471         funcs->addFactory(SharedPtr<const CaseFactory>(new MatrixFuncCaseFactory<MatrixCompMult>()));
5472         funcs->addFactory(SharedPtr<const CaseFactory>(new MatrixFuncCaseFactory<OuterProduct>()));
5473         funcs->addFactory(SharedPtr<const CaseFactory>(new MatrixFuncCaseFactory<Transpose>()));
5474         funcs->addFactory(SharedPtr<const CaseFactory>(new SquareMatrixFuncCaseFactory<Determinant>()));
5475         funcs->addFactory(SharedPtr<const CaseFactory>(new SquareMatrixFuncCaseFactory<Inverse>()));
5476
5477         return MovePtr<const CaseFactories>(funcs.release());
5478 }
5479
5480 MovePtr<const CaseFactories> createES31BuiltinCases (void)
5481 {
5482         MovePtr<BuiltinFuncs>   funcs   (new BuiltinFuncs());
5483
5484         addScalarFactory<FrExp>(*funcs);
5485         addScalarFactory<LdExp>(*funcs);
5486         addScalarFactory<Fma>(*funcs);
5487
5488         return MovePtr<const CaseFactories>(funcs.release());
5489 }
5490
5491 struct PrecisionTestContext
5492 {
5493         PrecisionTestContext    (TestContext&                           testCtx_,
5494                                                          RenderContext&                         renderCtx_,
5495                                                          const FloatFormat&                     highp_,
5496                                                          const FloatFormat&                     mediump_,
5497                                                          const FloatFormat&                     lowp_,
5498                                                          const vector<ShaderType>&      shaderTypes_,
5499                                                          int                                            numRandoms_)
5500                 : testCtx               (testCtx_)
5501                 , renderCtx             (renderCtx_)
5502                 , shaderTypes   (shaderTypes_)
5503                 , numRandoms    (numRandoms_)
5504         {
5505                 formats[glu::PRECISION_HIGHP]   = &highp_;
5506                 formats[glu::PRECISION_MEDIUMP] = &mediump_;
5507                 formats[glu::PRECISION_LOWP]    = &lowp_;
5508         }
5509
5510         TestContext&                    testCtx;
5511         RenderContext&                  renderCtx;
5512         const FloatFormat*              formats[glu::PRECISION_LAST];
5513         vector<ShaderType>              shaderTypes;
5514         int                                             numRandoms;
5515 };
5516
5517 TestCaseGroup* createFuncGroup (const PrecisionTestContext&     ctx,
5518                                                                 const CaseFactory&                      factory)
5519 {
5520         TestCaseGroup* const    group   = new TestCaseGroup(ctx.testCtx,
5521                                                                                                                 factory.getName().c_str(),
5522                                                                                                                 factory.getDesc().c_str());
5523
5524         for (int precNdx = 0; precNdx < glu::PRECISION_LAST; ++precNdx)
5525         {
5526                 const Precision         precision       = Precision(precNdx);
5527                 const string            precName        (glu::getPrecisionName(precision));
5528                 const FloatFormat&      fmt                     = *de::getSizedArrayElement<glu::PRECISION_LAST>(ctx.formats, precNdx);
5529                 const FloatFormat&      highpFmt        = *de::getSizedArrayElement<glu::PRECISION_LAST>(ctx.formats,
5530                                                                                                                                                                                  glu::PRECISION_HIGHP);
5531
5532                 for (size_t shaderNdx = 0; shaderNdx < ctx.shaderTypes.size(); ++shaderNdx)
5533                 {
5534                         const ShaderType        shaderType      = ctx.shaderTypes[shaderNdx];
5535                         const string            shaderName      (glu::getShaderTypeName(shaderType));
5536                         const string            name            = precName + "_" + shaderName;
5537                         const Context           caseCtx         (name, ctx.testCtx, ctx.renderCtx, fmt, highpFmt,
5538                                                                                          precision, shaderType, ctx.numRandoms);
5539
5540                         group->addChild(factory.createCase(caseCtx).release());
5541                 }
5542         }
5543
5544         return group;
5545 }
5546
5547 void addBuiltinPrecisionTests (TestContext&                                     testCtx,
5548                                                            RenderContext&                               renderCtx,
5549                                                            const CaseFactories&                 cases,
5550                                                            const vector<ShaderType>&    shaderTypes,
5551                                                            TestCaseGroup&                               dstGroup)
5552 {
5553         const int                                               userRandoms     = testCtx.getCommandLine().getTestIterationCount();
5554         const int                                               defRandoms      = 16384;
5555         const int                                               numRandoms      = userRandoms > 0 ? userRandoms : defRandoms;
5556         const FloatFormat                               highp           (-126, 127, 23, true,
5557                                                                                                  tcu::MAYBE,    // subnormals
5558                                                                                                  tcu::YES,              // infinities
5559                                                                                                  tcu::MAYBE);   // NaN
5560         // \todo [2014-04-01 lauri] Check these once Khronos bug 11840 is resolved.
5561         const FloatFormat                               mediump         (-13, 13, 9, false);
5562         // A fixed-point format is just a floating point format with a fixed
5563         // exponent and support for subnormals.
5564         const FloatFormat                               lowp            (0, 0, 7, false, tcu::YES);
5565         const PrecisionTestContext              ctx                     (testCtx, renderCtx, highp, mediump, lowp,
5566                                                                                                  shaderTypes, numRandoms);
5567
5568         for (size_t ndx = 0; ndx < cases.getFactories().size(); ++ndx)
5569                 dstGroup.addChild(createFuncGroup(ctx, *cases.getFactories()[ndx]));
5570 }
5571
5572 } // BuiltinPrecisionTests
5573 } // gls
5574 } // deqp