Merge changes I5f7e56e3,I7f88e1da into oreo-cts-dev am: 67694b5635 am: aa425927d0...
[platform/upstream/VK-GL-CTS.git] / modules / gles3 / scripts / genutil.py
1 # -*- coding: utf-8 -*-
2
3 #-------------------------------------------------------------------------
4 # drawElements Quality Program utilities
5 # --------------------------------------
6 #
7 # Copyright 2016 The Android Open Source Project
8 #
9 # Licensed under the Apache License, Version 2.0 (the "License");
10 # you may not use this file except in compliance with the License.
11 # You may obtain a copy of the License at
12 #
13 #      http://www.apache.org/licenses/LICENSE-2.0
14 #
15 # Unless required by applicable law or agreed to in writing, software
16 # distributed under the License is distributed on an "AS IS" BASIS,
17 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 # See the License for the specific language governing permissions and
19 # limitations under the License.
20 #
21 #-------------------------------------------------------------------------
22
23 import re
24 import math
25 import random
26
27 PREAMBLE = """
28 # WARNING: This file is auto-generated. Do NOT modify it manually, but rather
29 # modify the generating script file. Otherwise changes will be lost!
30 """[1:]
31
32 class CaseGroup(object):
33         def __init__(self, name, description, children):
34                 self.name                       = name
35                 self.description        = description
36                 self.children           = children
37
38 class ShaderCase(object):
39         def __init__(self):
40                 pass
41
42 g_processedCases = {}
43
44 def indentTextBlock(text, indent):
45         indentStr = indent * "\t"
46         lines = text.split("\n")
47         lines = [indentStr + line for line in lines]
48         lines = [ ["", line][line.strip() != ""] for line in lines]
49         return "\n".join(lines)
50
51 def writeCase(f, case, indent, prefix):
52         print "    %s" % (prefix + case.name)
53         if isinstance(case, CaseGroup):
54                 f.write(indentTextBlock('group %s "%s"\n\n' % (case.name, case.description), indent))
55                 for child in case.children:
56                         writeCase(f, child, indent + 1, prefix + case.name + ".")
57                 f.write(indentTextBlock("\nend # %s\n" % case.name, indent))
58         else:
59                 # \todo [petri] Fix hack.
60                 fullPath = prefix + case.name
61                 assert (fullPath not in g_processedCases)
62                 g_processedCases[fullPath] = None
63                 f.write(indentTextBlock(str(case) + "\n", indent))
64
65 def writeAllCases(fileName, caseList):
66         # Write all cases to file.
67         print "  %s.." % fileName
68         f = file(fileName, "wb")
69         f.write(PREAMBLE + "\n")
70         for case in caseList:
71                 writeCase(f, case, 0, "")
72         f.close()
73
74         print "done! (%d cases written)" % len(g_processedCases)
75
76 # Template operations.
77
78 def genValues(inputs, outputs):
79         res = []
80         for (name, values) in inputs:
81                 res.append("input %s = [ %s ];" % (name, " | ".join([str(v) for v in values]).lower()))
82         for (name, values) in outputs:
83                 res.append("output %s = [ %s ];" % (name, " | ".join([str(v) for v in values]).lower()))
84         return ("\n".join(res))
85
86 def fillTemplate(template, params):
87         s = template
88
89         for (key, value) in params.items():
90                 m = re.search(r"^(\s*)\$\{\{%s\}\}$" % key, s, re.M)
91                 if m is not None:
92                         start = m.start(0)
93                         end = m.end(0)
94                         ws = m.group(1)
95                         if value is not None:
96                                 repl = "\n".join(["%s%s" % (ws, line) for line in value.split("\n")])
97                                 s = s[:start] + repl + s[end:]
98                         else:
99                                 s = s[:start] + s[end+1:] # drop the whole line
100                 else:
101                         s = s.replace("${{%s}}" % key, value)
102         return s
103
104 # Return shuffled version of list
105 def shuffled(lst):
106         tmp = lst[:]
107         random.shuffle(tmp)
108         return tmp
109
110 def repeatToLength(lst, toLength):
111         return (toLength / len(lst)) * lst + lst[: toLength % len(lst)]
112
113 # Helpers to convert a list of Scalar/Vec values into another type.
114
115 def toFloat(lst):       return [Scalar(float(v.x)) for v in lst]
116 def toInt(lst):         return [Scalar(int(v.x)) for v in lst]
117 def toUint(lst):        return [Uint(int(v.x)) for v in lst]
118 def toBool(lst):        return [Scalar(bool(v.x)) for v in lst]
119 def toVec4(lst):        return [v.toFloat().toVec4() for v in lst]
120 def toVec3(lst):        return [v.toFloat().toVec3() for v in lst]
121 def toVec2(lst):        return [v.toFloat().toVec2() for v in lst]
122 def toIVec4(lst):       return [v.toInt().toVec4() for v in lst]
123 def toIVec3(lst):       return [v.toInt().toVec3() for v in lst]
124 def toIVec2(lst):       return [v.toInt().toVec2() for v in lst]
125 def toBVec4(lst):       return [v.toBool().toVec4() for v in lst]
126 def toBVec3(lst):       return [v.toBool().toVec3() for v in lst]
127 def toBVec2(lst):       return [v.toBool().toVec2() for v in lst]
128 def toUVec4(lst):       return [v.toUint().toUVec4() for v in lst]
129 def toUVec3(lst):       return [v.toUint().toUVec3() for v in lst]
130 def toUVec2(lst):       return [v.toUint().toUVec2() for v in lst]
131 def toMat2(lst):        return [v.toMat2() for v in lst]
132 def toMat2x3(lst):      return [v.toMat2x3() for v in lst]
133 def toMat2x4(lst):      return [v.toMat2x4() for v in lst]
134 def toMat3x2(lst):      return [v.toMat3x2() for v in lst]
135 def toMat3(lst):        return [v.toMat3() for v in lst]
136 def toMat3x4(lst):      return [v.toMat3x4() for v in lst]
137 def toMat4x2(lst):      return [v.toMat4x2() for v in lst]
138 def toMat4x3(lst):      return [v.toMat4x3() for v in lst]
139 def toMat4(lst):        return [v.toMat4() for v in lst]
140
141 # Random value generation.
142
143 class GenRandom(object):
144         def __init__(self):
145                 pass
146
147         def uniformVec4(self, count, mn, mx):
148                 ret = [Vec4(random.uniform(mn, mx), random.uniform(mn, mx), random.uniform(mn, mx), random.uniform(mn, mx)) for x in xrange(count)]
149                 ret[0].x = mn
150                 ret[1].x = mx
151                 ret[2].x = (mn + mx) * 0.5
152                 return ret
153
154         def uniformBVec4(self, count):
155                 ret = [Vec4(random.random() >= 0.5, random.random() >= 0.5, random.random() >= 0.5, random.random() >= 0.5) for x in xrange(count)]
156                 ret[0].x = True
157                 ret[1].x = False
158                 return ret
159
160 #       def uniform(self,
161
162 # Math operating on Scalar/Vector types.
163
164 def glslSign(a):                        return 0.0 if (a == 0) else +1.0 if (a > 0.0) else -1.0
165 def glslMod(x, y):                      return x - y*math.floor(x/y)
166 def glslClamp(x, mn, mx):       return mn if (x < mn) else mx if (x > mx) else x
167
168 class GenMath(object):
169         @staticmethod
170         def unary(func):        return lambda val: val.applyUnary(func)
171
172         @staticmethod
173         def binary(func):       return lambda a, b: (b.expandVec(a)).applyBinary(func, a.expandVec(b))
174
175         @staticmethod
176         def frac(val):          return val.applyUnary(lambda x: x - math.floor(x))
177
178         @staticmethod
179         def exp2(val):          return val.applyUnary(lambda x: math.pow(2.0, x))
180
181         @staticmethod
182         def log2(val):          return val.applyUnary(lambda x: math.log(x, 2.0))
183
184         @staticmethod
185         def rsq(val):           return val.applyUnary(lambda x: 1.0 / math.sqrt(x))
186
187         @staticmethod
188         def sign(val):          return val.applyUnary(glslSign)
189
190         @staticmethod
191         def isEqual(a, b):      return Scalar(a.isEqual(b))
192
193         @staticmethod
194         def isNotEqual(a, b):   return Scalar(not a.isEqual(b))
195
196         @staticmethod
197         def step(a, b):         return (b.expandVec(a)).applyBinary(lambda edge, x: [1.0, 0.0][x < edge], a.expandVec(b))
198
199         @staticmethod
200         def length(a):          return a.length()
201
202         @staticmethod
203         def distance(a, b):     return a.distance(b)
204
205         @staticmethod
206         def dot(a, b):          return a.dot(b)
207
208         @staticmethod
209         def cross(a, b):        return a.cross(b)
210
211         @staticmethod
212         def normalize(a):       return a.normalize()
213
214         @staticmethod
215         def boolAny(a):         return a.boolAny()
216
217         @staticmethod
218         def boolAll(a):         return a.boolAll()
219
220         @staticmethod
221         def boolNot(a):         return a.boolNot()
222
223         @staticmethod
224         def abs(a):                     return a.abs()
225
226 # ..
227
228 class Scalar(object):
229         def __init__(self, x):
230                 self.x = x
231
232         def applyUnary(self, func):                     return Scalar(func(self.x))
233         def applyBinary(self, func, other):     return Scalar(func(self.x, other.x))
234
235         def isEqual(self, other):       assert isinstance(other, Scalar); return (self.x == other.x)
236
237         def expandVec(self, val):       return val
238         def toScalar(self):                     return Scalar(self.x)
239         def toVec2(self):                       return Vec2(self.x, self.x)
240         def toVec3(self):                       return Vec3(self.x, self.x, self.x)
241         def toVec4(self):                       return Vec4(self.x, self.x, self.x, self.x)
242         def toUVec2(self):                      return UVec2(self.x, self.x)
243         def toUVec3(self):                      return UVec3(self.x, self.x, self.x)
244         def toUVec4(self):                      return UVec4(self.x, self.x, self.x, self.x)
245         def toMat2(self):                       return Mat.fromScalar(2, 2, float(self.x))
246         def toMat2x3(self):                     return Mat.fromScalar(2, 3, float(self.x))
247         def toMat2x4(self):                     return Mat.fromScalar(2, 4, float(self.x))
248         def toMat3x2(self):                     return Mat.fromScalar(3, 2, float(self.x))
249         def toMat3(self):                       return Mat.fromScalar(3, 3, float(self.x))
250         def toMat3x4(self):                     return Mat.fromScalar(3, 4, float(self.x))
251         def toMat4x2(self):                     return Mat.fromScalar(4, 2, float(self.x))
252         def toMat4x3(self):                     return Mat.fromScalar(4, 3, float(self.x))
253         def toMat4(self):                       return Mat.fromScalar(4, 4, float(self.x))
254
255         def toFloat(self):                      return Scalar(float(self.x))
256         def toInt(self):                        return Scalar(int(self.x))
257         def toUint(self):                       return Uint(int(self.x))
258         def toBool(self):                       return Scalar(bool(self.x))
259
260         def getNumScalars(self):        return 1
261         def getScalars(self):           return [self.x]
262
263         def typeString(self):
264                 if isinstance(self.x, bool):
265                         return "bool"
266                 elif isinstance(self.x, int):
267                         return "int"
268                 elif isinstance(self.x, float):
269                         return "float"
270                 else:
271                         assert False
272
273         def vec4Swizzle(self):
274                 return ""
275
276         def __str__(self):
277                 return str(self.x).lower()
278
279         def __float__(self):
280                 return float(self.x)
281
282         def length(self):
283                 return Scalar(abs(self.x))
284
285         def distance(self, v):
286                 assert isinstance(v, Scalar)
287                 return Scalar(abs(self.x - v.x))
288
289         def dot(self, v):
290                 assert isinstance(v, Scalar)
291                 return Scalar(self.x * v.x)
292
293         def normalize(self):
294                 return Scalar(glslSign(self.x))
295
296         def abs(self):
297                 if isinstance(self.x, bool):
298                         return Scalar(self.x)
299                 else:
300                         return Scalar(abs(self.x))
301
302         def __neg__(self):
303                 return Scalar(-self.x)
304
305         def __add__(self, val):
306                 assert isinstance(val, Scalar)
307                 return Scalar(self.x + val.x)
308
309         def __sub__(self, val):
310                 return self + (-val)
311
312         def __mul__(self, val):
313                 if isinstance(val, Scalar):
314                         return Scalar(self.x * val.x)
315                 elif isinstance(val, Vec2):
316                         return Vec2(self.x * val.x, self.x * val.y)
317                 elif isinstance(val, Vec3):
318                         return Vec3(self.x * val.x, self.x * val.y, self.x * val.z)
319                 elif isinstance(val, Vec4):
320                         return Vec4(self.x * val.x, self.x * val.y, self.x * val.z, self.x * val.w)
321                 else:
322                         assert False
323
324         def __div__(self, val):
325                 if isinstance(val, Scalar):
326                         return Scalar(self.x / val.x)
327                 elif isinstance(val, Vec2):
328                         return Vec2(self.x / val.x, self.x / val.y)
329                 elif isinstance(val, Vec3):
330                         return Vec3(self.x / val.x, self.x / val.y, self.x / val.z)
331                 elif isinstance(val, Vec4):
332                         return Vec4(self.x / val.x, self.x / val.y, self.x / val.z, self.x / val.w)
333                 else:
334                         assert False
335
336 class Uint(Scalar):
337         def __init__(self, x):
338                 assert x >= 0
339                 self.x = x
340
341         def typeString(self):
342                 return "uint"
343
344         def abs(self):
345                 return Scalar.abs(self).toUint()
346
347         def __neg__(self):
348                 return Scalar.__neg__(self).toUint()
349
350         def __add__(self, val):
351                 return Scalar.__add__(self, val).toUint()
352
353         def __sub__(self, val):
354                 return self + (-val)
355
356         def __mul__(self, val):
357                 return Scalar.__mul__(self, val).toUint()
358
359         def __div__(self, val):
360                 return Scalar.__div__(self, val).toUint()
361
362 class Vec(object):
363         @staticmethod
364         def fromScalarList(lst):
365                 assert (len(lst) >= 1 and len(lst) <= 4)
366                 if (len(lst) == 1):             return Scalar(lst[0])
367                 elif (len(lst) == 2):   return Vec2(lst[0], lst[1])
368                 elif (len(lst) == 3):   return Vec3(lst[0], lst[1], lst[2])
369                 else:                                   return Vec4(lst[0], lst[1], lst[2], lst[3])
370
371         def isEqual(self, other):
372                 assert isinstance(other, Vec);
373                 return (self.getScalars() == other.getScalars())
374
375         def length(self):
376                 return Scalar(math.sqrt(self.dot(self).x))
377
378         def normalize(self):
379                 return self * Scalar(1.0 / self.length().x)
380
381         def swizzle(self, indexList):
382                 inScalars = self.getScalars()
383                 outScalars = map(lambda ndx: inScalars[ndx], indexList)
384                 return Vec.fromScalarList(outScalars)
385
386         def __init__(self):
387                 pass
388
389         def __eq__(self, other):
390                 return self.isEqual(other)
391
392         def __ne__(self, other):
393                 return not self.isEqual(other)
394
395 class Vec2(Vec):
396         def __init__(self, x, y):
397                 assert(x.__class__ == y.__class__)
398                 self.x = x
399                 self.y = y
400
401         def applyUnary(self, func):                     return Vec2(func(self.x), func(self.y))
402         def applyBinary(self, func, other):     return Vec2(func(self.x, other.x), func(self.y, other.y))
403
404         def expandVec(self, val):       return val.toVec2()
405         def toScalar(self):                     return Scalar(self.x)
406         def toVec2(self):                       return Vec2(self.x, self.y)
407         def toVec3(self):                       return Vec3(self.x, self.y, 0.0)
408         def toVec4(self):                       return Vec4(self.x, self.y, 0.0, 0.0)
409         def toUVec2(self):                      return UVec2(self.x, self.y)
410         def toUVec3(self):                      return UVec3(self.x, self.y, 0.0)
411         def toUVec4(self):                      return UVec4(self.x, self.y, 0.0, 0.0)
412         def toMat2(self):                       return Mat2(float(self.x), 0.0, 0.0, float(self.y));
413
414         def toFloat(self):                      return Vec2(float(self.x), float(self.y))
415         def toInt(self):                        return Vec2(int(self.x), int(self.y))
416         def toUint(self):                       return UVec2(int(self.x), int(self.y))
417         def toBool(self):                       return Vec2(bool(self.x), bool(self.y))
418
419         def getNumScalars(self):        return 2
420         def getScalars(self):           return [self.x, self.y]
421
422         def typeString(self):
423                 if isinstance(self.x, bool):
424                         return "bvec2"
425                 elif isinstance(self.x, int):
426                         return "ivec2"
427                 elif isinstance(self.x, float):
428                         return "vec2"
429                 else:
430                         assert False
431
432         def vec4Swizzle(self):
433                 return ".xyxy"
434
435         def __str__(self):
436                 if isinstance(self.x, bool):
437                         return "bvec2(%s, %s)" % (str(self.x).lower(), str(self.y).lower())
438                 elif isinstance(self.x, int):
439                         return "ivec2(%i, %i)" % (self.x, self.y)
440                 elif isinstance(self.x, float):
441                         return "vec2(%s, %s)" % (self.x, self.y)
442                 else:
443                         assert False
444
445         def distance(self, v):
446                 assert isinstance(v, Vec2)
447                 return (self - v).length()
448
449         def dot(self, v):
450                 assert isinstance(v, Vec2)
451                 return Scalar(self.x*v.x + self.y*v.y)
452
453         def abs(self):
454                 if isinstance(self.x, bool):
455                         return Vec2(self.x, self.y)
456                 else:
457                         return Vec2(abs(self.x), abs(self.y))
458
459         def __neg__(self):
460                 return Vec2(-self.x, -self.y)
461
462         def __add__(self, val):
463                 if isinstance(val, Scalar):
464                         return Vec2(self.x + val, self.y + val)
465                 elif isinstance(val, Vec2):
466                         return Vec2(self.x + val.x, self.y + val.y)
467                 else:
468                         assert False
469
470         def __sub__(self, val):
471                 return self + (-val)
472
473         def __mul__(self, val):
474                 if isinstance(val, Scalar):
475                         val = val.toVec2()
476                 assert isinstance(val, Vec2)
477                 return Vec2(self.x * val.x, self.y * val.y)
478
479         def __div__(self, val):
480                 if isinstance(val, Scalar):
481                         return Vec2(self.x / val.x, self.y / val.x)
482                 else:
483                         assert isinstance(val, Vec2)
484                         return Vec2(self.x / val.x, self.y / val.y)
485
486         def boolAny(self):      return Scalar(self.x or self.y)
487         def boolAll(self):      return Scalar(self.x and self.y)
488         def boolNot(self):      return Vec2(not self.x, not self.y)
489
490 class UVec2(Vec2):
491         def __init__(self, x, y):
492                 assert isinstance(x, int) and isinstance(y, int)
493                 assert x >= 0 and y >= 0
494                 Vec2.__init__(self, x, y)
495
496         def typeString(self):
497                 return "uvec2"
498
499         def __str__(self):
500                 return "uvec2(%i, %i)" % (self.x, self.y)
501
502         def abs(self):
503                 return Vec2.abs(self).toUint()
504
505 class Vec3(Vec):
506         def __init__(self, x, y, z):
507                 assert((x.__class__ == y.__class__) and (x.__class__ == z.__class__))
508                 self.x = x
509                 self.y = y
510                 self.z = z
511
512         def applyUnary(self, func):                     return Vec3(func(self.x), func(self.y), func(self.z))
513         def applyBinary(self, func, other):     return Vec3(func(self.x, other.x), func(self.y, other.y), func(self.z, other.z))
514
515         def expandVec(self, val):       return val.toVec3()
516         def toScalar(self):                     return Scalar(self.x)
517         def toVec2(self):                       return Vec2(self.x, self.y)
518         def toVec3(self):                       return Vec3(self.x, self.y, self.z)
519         def toVec4(self):                       return Vec4(self.x, self.y, self.z, 0.0)
520         def toUVec2(self):                      return UVec2(self.x, self.y)
521         def toUVec3(self):                      return UVec3(self.x, self.y, self.z)
522         def toUVec4(self):                      return UVec4(self.x, self.y, self.z, 0.0)
523         def toMat3(self):                       return Mat3(float(self.x), 0.0, 0.0,  0.0, float(self.y), 0.0,  0.0, 0.0, float(self.z));
524
525         def toFloat(self):                      return Vec3(float(self.x), float(self.y), float(self.z))
526         def toInt(self):                        return Vec3(int(self.x), int(self.y), int(self.z))
527         def toUint(self):                       return UVec3(int(self.x), int(self.y), int(self.z))
528         def toBool(self):                       return Vec3(bool(self.x), bool(self.y), bool(self.z))
529
530         def getNumScalars(self):        return 3
531         def getScalars(self):           return [self.x, self.y, self.z]
532
533         def typeString(self):
534                 if isinstance(self.x, bool):
535                         return "bvec3"
536                 elif isinstance(self.x, int):
537                         return "ivec3"
538                 elif isinstance(self.x, float):
539                         return "vec3"
540                 else:
541                         assert False
542
543         def vec4Swizzle(self):
544                 return ".xyzx"
545
546         def __str__(self):
547                 if isinstance(self.x, bool):
548                         return "bvec3(%s, %s, %s)" % (str(self.x).lower(), str(self.y).lower(), str(self.z).lower())
549                 elif isinstance(self.x, int):
550                         return "ivec3(%i, %i, %i)" % (self.x, self.y, self.z)
551                 elif isinstance(self.x, float):
552                         return "vec3(%s, %s, %s)" % (self.x, self.y, self.z)
553                 else:
554                         assert False
555
556         def distance(self, v):
557                 assert isinstance(v, Vec3)
558                 return (self - v).length()
559
560         def dot(self, v):
561                 assert isinstance(v, Vec3)
562                 return Scalar(self.x*v.x + self.y*v.y + self.z*v.z)
563
564         def cross(self, v):
565                 assert isinstance(v, Vec3)
566                 return Vec3(self.y*v.z - v.y*self.z,
567                                         self.z*v.x - v.z*self.x,
568                                         self.x*v.y - v.x*self.y)
569
570         def abs(self):
571                 if isinstance(self.x, bool):
572                         return Vec3(self.x, self.y, self.z)
573                 else:
574                         return Vec3(abs(self.x), abs(self.y), abs(self.z))
575
576         def __neg__(self):
577                 return Vec3(-self.x, -self.y, -self.z)
578
579         def __add__(self, val):
580                 if isinstance(val, Scalar):
581                         return Vec3(self.x + val, self.y + val)
582                 elif isinstance(val, Vec3):
583                         return Vec3(self.x + val.x, self.y + val.y, self.z + val.z)
584                 else:
585                         assert False
586
587         def __sub__(self, val):
588                 return self + (-val)
589
590         def __mul__(self, val):
591                 if isinstance(val, Scalar):
592                         val = val.toVec3()
593                 assert isinstance(val, Vec3)
594                 return Vec3(self.x * val.x, self.y * val.y, self.z * val.z)
595
596         def __div__(self, val):
597                 if isinstance(val, Scalar):
598                         return Vec3(self.x / val.x, self.y / val.x, self.z / val.x)
599                 elif isinstance(val, Vec3):
600                         return Vec3(self.x / val.x, self.y / val.y, self.z / val.z)
601                 else:
602                         assert False
603
604         def boolAny(self):      return Scalar(self.x or self.y or self.z)
605         def boolAll(self):      return Scalar(self.x and self.y and self.z)
606         def boolNot(self):      return Vec3(not self.x, not self.y, not self.z)
607
608 class UVec3(Vec3):
609         def __init__(self, x, y, z):
610                 assert isinstance(x, int) and isinstance(y, int) and isinstance(z, int)
611                 assert x >= 0 and y >= 0 and z >= 0
612                 Vec3.__init__(self, x, y, z)
613
614         def typeString(self):
615                 return "uvec3"
616
617         def __str__(self):
618                 return "uvec3(%i, %i, %i)" % (self.x, self.y, self.z)
619
620         def abs(self):
621                 return Vec3.abs(self).toUint()
622
623 class Vec4(Vec):
624         def __init__(self, x, y, z, w):
625                 assert((x.__class__ == y.__class__) and (x.__class__ == z.__class__) and (x.__class__ == w.__class__))
626                 self.x = x
627                 self.y = y
628                 self.z = z
629                 self.w = w
630
631         def applyUnary(self, func):                     return Vec4(func(self.x), func(self.y), func(self.z), func(self.w))
632         def applyBinary(self, func, other):     return Vec4(func(self.x, other.x), func(self.y, other.y), func(self.z, other.z), func(self.w, other.w))
633
634         def expandVec(self, val):       return val.toVec4()
635         def toScalar(self):                     return Scalar(self.x)
636         def toVec2(self):                       return Vec2(self.x, self.y)
637         def toVec3(self):                       return Vec3(self.x, self.y, self.z)
638         def toVec4(self):                       return Vec4(self.x, self.y, self.z, self.w)
639         def toUVec2(self):                      return UVec2(self.x, self.y)
640         def toUVec3(self):                      return UVec3(self.x, self.y, self.z)
641         def toUVec4(self):                      return UVec4(self.x, self.y, self.z, self.w)
642         def toMat2(self):                       return Mat2(float(self.x), float(self.y), float(self.z), float(self.w))
643         def toMat4(self):                       return Mat4(float(self.x), 0.0, 0.0, 0.0,  0.0, float(self.y), 0.0, 0.0,  0.0, 0.0, float(self.z), 0.0,  0.0, 0.0, 0.0, float(self.w));
644
645         def toFloat(self):                      return Vec4(float(self.x), float(self.y), float(self.z), float(self.w))
646         def toInt(self):                        return Vec4(int(self.x), int(self.y), int(self.z), int(self.w))
647         def toUint(self):                       return UVec4(int(self.x), int(self.y), int(self.z), int(self.w))
648         def toBool(self):                       return Vec4(bool(self.x), bool(self.y), bool(self.z), bool(self.w))
649
650         def getNumScalars(self):        return 4
651         def getScalars(self):           return [self.x, self.y, self.z, self.w]
652
653         def typeString(self):
654                 if isinstance(self.x, bool):
655                         return "bvec4"
656                 elif isinstance(self.x, int):
657                         return "ivec4"
658                 elif isinstance(self.x, float):
659                         return "vec4"
660                 else:
661                         assert False
662
663         def vec4Swizzle(self):
664                 return ""
665
666         def __str__(self):
667                 if isinstance(self.x, bool):
668                         return "bvec4(%s, %s, %s, %s)" % (str(self.x).lower(), str(self.y).lower(), str(self.z).lower(), str(self.w).lower())
669                 elif isinstance(self.x, int):
670                         return "ivec4(%i, %i, %i, %i)" % (self.x, self.y, self.z, self.w)
671                 elif isinstance(self.x, float):
672                         return "vec4(%s, %s, %s, %s)" % (self.x, self.y, self.z, self.w)
673                 else:
674                         assert False
675
676         def distance(self, v):
677                 assert isinstance(v, Vec4)
678                 return (self - v).length()
679
680         def dot(self, v):
681                 assert isinstance(v, Vec4)
682                 return Scalar(self.x*v.x + self.y*v.y + self.z*v.z + self.w*v.w)
683
684         def abs(self):
685                 if isinstance(self.x, bool):
686                         return Vec4(self.x, self.y, self.z, self.w)
687                 else:
688                         return Vec4(abs(self.x), abs(self.y), abs(self.z), abs(self.w))
689
690         def __neg__(self):
691                 return Vec4(-self.x, -self.y, -self.z, -self.w)
692
693         def __add__(self, val):
694                 if isinstance(val, Scalar):
695                         return Vec3(self.x + val, self.y + val)
696                 elif isinstance(val, Vec4):
697                         return Vec4(self.x + val.x, self.y + val.y, self.z + val.z, self.w + val.w)
698                 else:
699                         assert False
700
701         def __sub__(self, val):
702                 return self + (-val)
703
704         def __mul__(self, val):
705                 if isinstance(val, Scalar):
706                         val = val.toVec4()
707                 assert isinstance(val, Vec4)
708                 return Vec4(self.x * val.x, self.y * val.y, self.z * val.z, self.w * val.w)
709
710         def __div__(self, val):
711                 if isinstance(val, Scalar):
712                         return Vec4(self.x / val.x, self.y / val.x, self.z / val.x, self.w / val.x)
713                 elif isinstance(val, Vec4):
714                         return Vec4(self.x / val.x, self.y / val.y, self.z / val.z, self.w / val.w)
715                 else:
716                         assert False
717
718         def boolAny(self):      return Scalar(self.x or self.y or self.z or self.w)
719         def boolAll(self):      return Scalar(self.x and self.y and self.z and self.w)
720         def boolNot(self):      return Vec4(not self.x, not self.y, not self.z, not self.w)
721
722 class UVec4(Vec4):
723         def __init__(self, x, y, z, w):
724                 assert isinstance(x, int) and isinstance(y, int) and isinstance(z, int) and isinstance(w, int)
725                 assert x >= 0 and y >= 0 and z >= 0 and w >= 0
726                 Vec4.__init__(self, x, y, z, w)
727
728         def typeString(self):
729                 return "uvec4"
730
731         def __str__(self):
732                 return "uvec4(%i, %i, %i, %i)" % (self.x, self.y, self.z, self.w)
733
734         def abs(self):
735                 return Vec4.abs(self).toUint()
736
737 # \note Column-major storage.
738 class Mat(object):
739         def __init__ (self, numCols, numRows, scalars):
740                 assert len(scalars) == numRows*numCols
741                 self.numCols    = numCols
742                 self.numRows    = numRows
743                 self.scalars    = scalars
744
745         @staticmethod
746         def fromScalar (numCols, numRows, scalar):
747                 scalars = []
748                 for col in range(0, numCols):
749                         for row in range(0, numRows):
750                                 scalars.append(scalar if col == row else 0.0)
751                 return Mat(numCols, numRows, scalars)
752
753         @staticmethod
754         def identity (numCols, numRows):
755                 return Mat.fromScalar(numCols, numRows, 1.0)
756
757         def get (self, colNdx, rowNdx):
758                 assert 0 <= colNdx and colNdx < self.numCols
759                 assert 0 <= rowNdx and rowNdx < self.numRows
760                 return self.scalars[colNdx*self.numRows + rowNdx]
761
762         def set (self, colNdx, rowNdx, scalar):
763                 assert 0 <= colNdx and colNdx < self.numCols
764                 assert 0 <= rowNdx and rowNdx < self.numRows
765                 self.scalars[colNdx*self.numRows + rowNdx] = scalar
766
767         def toMatrix (self, numCols, numRows):
768                 res = Mat.identity(numCols, numRows)
769                 for col in range(0, min(self.numCols, numCols)):
770                         for row in range(0, min(self.numRows, numRows)):
771                                 res.set(col, row, self.get(col, row))
772                 return res
773
774         def toMat2 (self):              return self.toMatrix(2, 2)
775         def toMat2x3 (self):    return self.toMatrix(2, 3)
776         def toMat2x4 (self):    return self.toMatrix(2, 4)
777         def toMat3x2 (self):    return self.toMatrix(3, 2)
778         def toMat3 (self):              return self.toMatrix(3, 3)
779         def toMat3x4 (self):    return self.toMatrix(3, 4)
780         def toMat4x2 (self):    return self.toMatrix(4, 2)
781         def toMat4x3 (self):    return self.toMatrix(4, 3)
782         def toMat4 (self):              return self.toMatrix(4, 4)
783
784         def typeString(self):
785                 if self.numRows == self.numCols:
786                         return "mat%d" % self.numRows
787                 else:
788                         return "mat%dx%d" % (self.numCols, self.numRows)
789
790         def __str__(self):
791                 return "%s(%s)" % (self.typeString(), ", ".join(["%s" % s for s in self.scalars]))
792
793         def isTypeEqual (self, other):
794                 return isinstance(other, Mat) and self.numRows == other.numRows and self.numCols == other.numCols
795
796         def isEqual(self, other):
797                 assert self.isTypeEqual(other)
798                 return (self.scalars == other.scalars)
799
800         def compMul(self, val):
801                 assert self.isTypeEqual(val)
802                 return Mat(self.numRows, self.numCols, [self.scalars(i) * val.scalars(i) for i in range(self.numRows*self.numCols)])
803
804 class Mat2(Mat):
805         def __init__(self, m00, m01, m10, m11):
806                 Mat.__init__(self, 2, 2, [m00, m10, m01, m11])
807
808 class Mat3(Mat):
809         def __init__(self, m00, m01, m02, m10, m11, m12, m20, m21, m22):
810                 Mat.__init__(self, 3, 3, [m00, m10, m20,
811                                                                   m01, m11, m21,
812                                                                   m02, m12, m22])
813
814 class Mat4(Mat):
815         def __init__(self, m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33):
816                 Mat.__init__(self, 4, 4, [m00, m10, m20, m30,
817                                                                   m01, m11, m21, m31,
818                                                                   m02, m12, m22, m32,
819                                                                   m03, m13, m23, m33])