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