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