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