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