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