Add new framebuffer fetch extension tests am: 2a609fb223
[platform/upstream/VK-GL-CTS.git] / modules / gles2 / 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:
33         def __init__(self, name, description, children):
34                 self.name                       = name
35                 self.description        = description
36                 self.children           = children
37
38 class ShaderCase:
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 "\t%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 toBool(lst):        return [Scalar(bool(v.x)) for v in lst]
118 def toVec4(lst):        return [v.toFloat().toVec4() for v in lst]
119 def toVec3(lst):        return [v.toFloat().toVec3() for v in lst]
120 def toVec2(lst):        return [v.toFloat().toVec2() for v in lst]
121 def toIVec4(lst):       return [v.toInt().toVec4() for v in lst]
122 def toIVec3(lst):       return [v.toInt().toVec3() for v in lst]
123 def toIVec2(lst):       return [v.toInt().toVec2() for v in lst]
124 def toBVec4(lst):       return [v.toBool().toVec4() for v in lst]
125 def toBVec3(lst):       return [v.toBool().toVec3() for v in lst]
126 def toBVec2(lst):       return [v.toBool().toVec2() for v in lst]
127 def toMat2(lst):        return [v.toMat2() for v in lst]
128 def toMat3(lst):        return [v.toMat3() for v in lst]
129 def toMat4(lst):        return [v.toMat4() for v in lst]
130
131 # Random value generation.
132
133 class GenRandom:
134         def __init__(self):
135                 pass
136
137         def uniformVec4(self, count, mn, mx):
138                 ret = [Vec4(random.uniform(mn, mx), random.uniform(mn, mx), random.uniform(mn, mx), random.uniform(mn, mx)) for x in xrange(count)]
139                 ret[0].x = mn
140                 ret[1].x = mx
141                 ret[2].x = (mn + mx) * 0.5
142                 return ret
143
144         def uniformBVec4(self, count):
145                 ret = [Vec4(random.random() >= 0.5, random.random() >= 0.5, random.random() >= 0.5, random.random() >= 0.5) for x in xrange(count)]
146                 ret[0].x = True
147                 ret[1].x = False
148                 return ret
149
150 #       def uniform(self,
151
152 # Math operating on Scalar/Vector types.
153
154 def glslSign(a):                        return 0.0 if (a == 0) else +1.0 if (a > 0.0) else -1.0
155 def glslMod(x, y):                      return x - y*math.floor(x/y)
156 def glslClamp(x, mn, mx):       return mn if (x < mn) else mx if (x > mx) else x
157
158 class GenMath:
159         @staticmethod
160         def unary(func):        return lambda val: val.applyUnary(func)
161
162         @staticmethod
163         def binary(func):       return lambda a, b: (b.expandVec(a)).applyBinary(func, a.expandVec(b))
164
165         @staticmethod
166         def frac(val):          return val.applyUnary(lambda x: x - math.floor(x))
167
168         @staticmethod
169         def exp2(val):          return val.applyUnary(lambda x: math.pow(2.0, x))
170
171         @staticmethod
172         def log2(val):          return val.applyUnary(lambda x: math.log(x, 2.0))
173
174         @staticmethod
175         def rsq(val):           return val.applyUnary(lambda x: 1.0 / math.sqrt(x))
176
177         @staticmethod
178         def sign(val):          return val.applyUnary(glslSign)
179
180         @staticmethod
181         def isEqual(a, b):      return Scalar(a.isEqual(b))
182
183         @staticmethod
184         def isNotEqual(a, b):   return Scalar(not a.isEqual(b))
185
186         @staticmethod
187         def step(a, b):         return (b.expandVec(a)).applyBinary(lambda edge, x: [1.0, 0.0][x < edge], a.expandVec(b))
188
189         @staticmethod
190         def length(a):          return a.length()
191
192         @staticmethod
193         def distance(a, b):     return a.distance(b)
194
195         @staticmethod
196         def dot(a, b):          return a.dot(b)
197
198         @staticmethod
199         def cross(a, b):        return a.cross(b)
200
201         @staticmethod
202         def normalize(a):       return a.normalize()
203
204         @staticmethod
205         def boolAny(a):         return a.boolAny()
206
207         @staticmethod
208         def boolAll(a):         return a.boolAll()
209
210         @staticmethod
211         def boolNot(a):         return a.boolNot()
212
213 # ..
214
215 class Scalar:
216         def __init__(self, x):
217                 self.x = x
218
219         def applyUnary(self, func):                     return Scalar(func(self.x))
220         def applyBinary(self, func, other):     return Scalar(func(self.x, other.x))
221
222         def isEqual(self, other):       assert isinstance(other, Scalar); return (self.x == other.x)
223
224         def expandVec(self, val):       return val
225         def toScalar(self):                     return Scalar(self.x)
226         def toVec2(self):                       return Vec2(self.x, self.x)
227         def toVec3(self):                       return Vec3(self.x, self.x, self.x)
228         def toVec4(self):                       return Vec4(self.x, self.x, self.x, self.x)
229         def toMat2(self):                       return self.toVec2().toMat2()
230         def toMat3(self):                       return self.toVec3().toMat3()
231         def toMat4(self):                       return self.toVec4().toMat4()
232
233         def toFloat(self):                      return Scalar(float(self.x))
234         def toInt(self):                        return Scalar(int(self.x))
235         def toBool(self):                       return Scalar(bool(self.x))
236
237         def getNumScalars(self):        return 1
238         def getScalars(self):           return [self.x]
239
240         def typeString(self):
241                 if isinstance(self.x, bool):
242                         return "bool"
243                 elif isinstance(self.x, int):
244                         return "int"
245                 elif isinstance(self.x, float):
246                         return "float"
247                 else:
248                         assert False
249
250         def vec4Swizzle(self):
251                 return ""
252
253         def __str__(self):
254                 return "%s" % self.x
255
256         def length(self):
257                 return Scalar(abs(self.x))
258
259         def distance(self, v):
260                 assert isinstance(v, Scalar)
261                 return Scalar(abs(self.x - v.x))
262
263         def dot(self, v):
264                 assert isinstance(v, Scalar)
265                 return Scalar(self.x * v.x)
266
267         def normalize(self):
268                 return Scalar(glslSign(self.x))
269
270         def __neg__(self):
271                 return Scalar(-self.x)
272
273         def __add__(self, val):
274                 assert isinstance(val, Scalar)
275                 return Scalar(self.x + val.x)
276
277         def __sub__(self, val):
278                 return self + (-val)
279
280         def __mul__(self, val):
281                 if isinstance(val, Scalar):
282                         return Scalar(self.x * val.x)
283                 elif isinstance(val, Vec2):
284                         return Vec2(self.x * val.x, self.x * val.y)
285                 elif isinstance(val, Vec3):
286                         return Vec3(self.x * val.x, self.x * val.y, self.x * val.z)
287                 elif isinstance(val, Vec4):
288                         return Vec4(self.x * val.x, self.x * val.y, self.x * val.z, self.x * val.w)
289                 else:
290                         assert False
291
292         def __div__(self, val):
293                 if isinstance(val, Scalar):
294                         return Scalar(self.x / val.x)
295                 elif isinstance(val, Vec2):
296                         return Vec2(self.x / val.x, self.x / val.y)
297                 elif isinstance(val, Vec3):
298                         return Vec3(self.x / val.x, self.x / val.y, self.x / val.z)
299                 elif isinstance(val, Vec4):
300                         return Vec4(self.x / val.x, self.x / val.y, self.x / val.z, self.x / val.w)
301                 else:
302                         assert False
303
304 class Vec:
305         @staticmethod
306         def fromScalarList(lst):
307                 assert (len(lst) >= 1 and len(lst) <= 4)
308                 if (len(lst) == 1):             return Scalar(lst[0])
309                 elif (len(lst) == 2):   return Vec2(lst[0], lst[1])
310                 elif (len(lst) == 3):   return Vec3(lst[0], lst[1], lst[2])
311                 else:                                   return Vec4(lst[0], lst[1], lst[2], lst[3])
312
313         def isEqual(self, other):
314                 assert isinstance(other, Vec);
315                 return (self.getScalars() == other.getScalars())
316
317         def length(self):
318                 return Scalar(math.sqrt(self.dot(self).x))
319
320         def normalize(self):
321                 return self * Scalar(1.0 / self.length().x)
322
323         def swizzle(self, indexList):
324                 inScalars = self.getScalars()
325                 outScalars = map(lambda ndx: inScalars[ndx], indexList)
326                 return Vec.fromScalarList(outScalars)
327
328         def __init__(self):
329                 pass
330
331 class Vec2(Vec):
332         def __init__(self, x, y):
333                 assert(x.__class__ == y.__class__)
334                 self.x = x
335                 self.y = y
336
337         def applyUnary(self, func):                     return Vec2(func(self.x), func(self.y))
338         def applyBinary(self, func, other):     return Vec2(func(self.x, other.x), func(self.y, other.y))
339
340         def expandVec(self, val):       return val.toVec2()
341         def toScalar(self):                     return Scalar(self.x)
342         def toVec2(self):                       return Vec2(self.x, self.y)
343         def toVec3(self):                       return Vec3(self.x, self.y, 0.0)
344         def toVec4(self):                       return Vec4(self.x, self.y, 0.0, 0.0)
345         def toMat2(self):                       return Mat2(float(self.x), 0.0, 0.0, float(self.y));
346
347         def toFloat(self):                      return Vec2(float(self.x), float(self.y))
348         def toInt(self):                        return Vec2(int(self.x), int(self.y))
349         def toBool(self):                       return Vec2(bool(self.x), bool(self.y))
350
351         def getNumScalars(self):        return 2
352         def getScalars(self):           return [self.x, self.y]
353
354         def typeString(self):
355                 if isinstance(self.x, bool):
356                         return "bvec2"
357                 elif isinstance(self.x, int):
358                         return "ivec2"
359                 elif isinstance(self.x, float):
360                         return "vec2"
361                 else:
362                         assert False
363
364         def vec4Swizzle(self):
365                 return ".xyxy"
366
367         def __str__(self):
368                 if isinstance(self.x, bool):
369                         return "bvec2(%s, %s)" % (str(self.x).lower(), str(self.y).lower())
370                 elif isinstance(self.x, int):
371                         return "ivec2(%i, %i)" % (self.x, self.y)
372                 elif isinstance(self.x, float):
373                         return "vec2(%s, %s)" % (self.x, self.y)
374                 else:
375                         assert False
376
377         def distance(self, v):
378                 assert isinstance(v, Vec2)
379                 return (self - v).length()
380
381         def dot(self, v):
382                 assert isinstance(v, Vec2)
383                 return Scalar(self.x*v.x + self.y*v.y)
384
385         def __neg__(self):
386                 return Vec2(-self.x, -self.y)
387
388         def __add__(self, val):
389                 if isinstance(val, Scalar):
390                         return Vec2(self.x + val, self.y + val)
391                 elif isinstance(val, Vec2):
392                         return Vec2(self.x + val.x, self.y + val.y)
393                 else:
394                         assert False
395
396         def __sub__(self, val):
397                 return self + (-val)
398
399         def __mul__(self, val):
400                 if isinstance(val, Scalar):
401                         val = val.toVec2()
402                 assert isinstance(val, Vec2)
403                 return Vec2(self.x * val.x, self.y * val.y)
404
405         def __div__(self, val):
406                 if isinstance(val, Scalar):
407                         return Vec2(self.x / val.x, self.y / val.x)
408                 else:
409                         assert isinstance(val, Vec2)
410                         return Vec2(self.x / val.x, self.y / val.y)
411
412         def boolAny(self):      return Scalar(self.x or self.y)
413         def boolAll(self):      return Scalar(self.x and self.y)
414         def boolNot(self):      return Vec2(not self.x, not self.y)
415
416 class Vec3(Vec):
417         def __init__(self, x, y, z):
418                 assert((x.__class__ == y.__class__) and (x.__class__ == z.__class__))
419                 self.x = x
420                 self.y = y
421                 self.z = z
422
423         def applyUnary(self, func):                     return Vec3(func(self.x), func(self.y), func(self.z))
424         def applyBinary(self, func, other):     return Vec3(func(self.x, other.x), func(self.y, other.y), func(self.z, other.z))
425
426         def expandVec(self, val):       return val.toVec3()
427         def toScalar(self):                     return Scalar(self.x)
428         def toVec2(self):                       return Vec2(self.x, self.y)
429         def toVec3(self):                       return Vec3(self.x, self.y, self.z)
430         def toVec4(self):                       return Vec4(self.x, self.y, self.z, 0.0)
431         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));
432
433         def toFloat(self):                      return Vec3(float(self.x), float(self.y), float(self.z))
434         def toInt(self):                        return Vec3(int(self.x), int(self.y), int(self.z))
435         def toBool(self):                       return Vec3(bool(self.x), bool(self.y), bool(self.z))
436
437         def getNumScalars(self):        return 3
438         def getScalars(self):           return [self.x, self.y, self.z]
439
440         def typeString(self):
441                 if isinstance(self.x, bool):
442                         return "bvec3"
443                 elif isinstance(self.x, int):
444                         return "ivec3"
445                 elif isinstance(self.x, float):
446                         return "vec3"
447                 else:
448                         assert False
449
450         def vec4Swizzle(self):
451                 return ".xyzx"
452
453         def __str__(self):
454                 if isinstance(self.x, bool):
455                         return "bvec3(%s, %s, %s)" % (str(self.x).lower(), str(self.y).lower(), str(self.z).lower())
456                 elif isinstance(self.x, int):
457                         return "ivec3(%i, %i, %i)" % (self.x, self.y, self.z)
458                 elif isinstance(self.x, float):
459                         return "vec3(%s, %s, %s)" % (self.x, self.y, self.z)
460                 else:
461                         assert False
462
463         def distance(self, v):
464                 assert isinstance(v, Vec3)
465                 return (self - v).length()
466
467         def dot(self, v):
468                 assert isinstance(v, Vec3)
469                 return Scalar(self.x*v.x + self.y*v.y + self.z*v.z)
470
471         def cross(self, v):
472                 assert isinstance(v, Vec3)
473                 return Vec3(self.y*v.z - v.y*self.z,
474                                         self.z*v.x - v.z*self.x,
475                                         self.x*v.y - v.x*self.y)
476
477         def __neg__(self):
478                 return Vec3(-self.x, -self.y, -self.z)
479
480         def __add__(self, val):
481                 if isinstance(val, Scalar):
482                         return Vec3(self.x + val, self.y + val)
483                 elif isinstance(val, Vec3):
484                         return Vec3(self.x + val.x, self.y + val.y, self.z + val.z)
485                 else:
486                         assert False
487
488         def __sub__(self, val):
489                 return self + (-val)
490
491         def __mul__(self, val):
492                 if isinstance(val, Scalar):
493                         val = val.toVec3()
494                 assert isinstance(val, Vec3)
495                 return Vec3(self.x * val.x, self.y * val.y, self.z * val.z)
496
497         def __div__(self, val):
498                 if isinstance(val, Scalar):
499                         return Vec3(self.x / val.x, self.y / val.x, self.z / val.x)
500                 else:
501                         assert False
502
503         def boolAny(self):      return Scalar(self.x or self.y or self.z)
504         def boolAll(self):      return Scalar(self.x and self.y and self.z)
505         def boolNot(self):      return Vec3(not self.x, not self.y, not self.z)
506
507 class Vec4(Vec):
508         def __init__(self, x, y, z, w):
509                 assert((x.__class__ == y.__class__) and (x.__class__ == z.__class__) and (x.__class__ == w.__class__))
510                 self.x = x
511                 self.y = y
512                 self.z = z
513                 self.w = w
514
515         def applyUnary(self, func):                     return Vec4(func(self.x), func(self.y), func(self.z), func(self.w))
516         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))
517
518         def expandVec(self, val):       return val.toVec4()
519         def toScalar(self):                     return Scalar(self.x)
520         def toVec2(self):                       return Vec2(self.x, self.y)
521         def toVec3(self):                       return Vec3(self.x, self.y, self.z)
522         def toVec4(self):                       return Vec4(self.x, self.y, self.z, self.w)
523         def toMat2(self):                       return Mat2(float(self.x), float(self.y), float(self.z), float(self.w))
524         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));
525
526         def toFloat(self):                      return Vec4(float(self.x), float(self.y), float(self.z), float(self.w))
527         def toInt(self):                        return Vec4(int(self.x), int(self.y), int(self.z), int(self.w))
528         def toBool(self):                       return Vec4(bool(self.x), bool(self.y), bool(self.z), bool(self.w))
529
530         def getNumScalars(self):        return 4
531         def getScalars(self):           return [self.x, self.y, self.z, self.w]
532
533         def typeString(self):
534                 if isinstance(self.x, bool):
535                         return "bvec4"
536                 elif isinstance(self.x, int):
537                         return "ivec4"
538                 elif isinstance(self.x, float):
539                         return "vec4"
540                 else:
541                         assert False
542
543         def vec4Swizzle(self):
544                 return ""
545
546         def __str__(self):
547                 if isinstance(self.x, bool):
548                         return "bvec4(%s, %s, %s, %s)" % (str(self.x).lower(), str(self.y).lower(), str(self.z).lower(), str(self.w).lower())
549                 elif isinstance(self.x, int):
550                         return "ivec4(%i, %i, %i, %i)" % (self.x, self.y, self.z, self.w)
551                 elif isinstance(self.x, float):
552                         return "vec4(%s, %s, %s, %s)" % (self.x, self.y, self.z, self.w)
553                 else:
554                         assert False
555
556         def distance(self, v):
557                 assert isinstance(v, Vec4)
558                 return (self - v).length()
559
560         def dot(self, v):
561                 assert isinstance(v, Vec4)
562                 return Scalar(self.x*v.x + self.y*v.y + self.z*v.z + self.w*v.w)
563
564         def __neg__(self):
565                 return Vec4(-self.x, -self.y, -self.z, -self.w)
566
567         def __add__(self, val):
568                 if isinstance(val, Scalar):
569                         return Vec3(self.x + val, self.y + val)
570                 elif isinstance(val, Vec4):
571                         return Vec4(self.x + val.x, self.y + val.y, self.z + val.z, self.w + val.w)
572                 else:
573                         assert False
574
575         def __sub__(self, val):
576                 return self + (-val)
577
578         def __mul__(self, val):
579                 if isinstance(val, Scalar):
580                         val = val.toVec4()
581                 assert isinstance(val, Vec4)
582                 return Vec4(self.x * val.x, self.y * val.y, self.z * val.z, self.w * val.w)
583
584         def __div__(self, val):
585                 if isinstance(val, Scalar):
586                         return Vec4(self.x / val.x, self.y / val.x, self.z / val.x, self.w / val.x)
587                 else:
588                         assert False
589
590         def boolAny(self):      return Scalar(self.x or self.y or self.z or self.w)
591         def boolAll(self):      return Scalar(self.x and self.y and self.z and self.w)
592         def boolNot(self):      return Vec4(not self.x, not self.y, not self.z, not self.w)
593
594 # \note Column-major storage.
595 class Mat:
596         def __init__ (self, numCols, numRows, scalars):
597                 assert len(scalars) == numRows*numCols
598                 self.numCols    = numCols
599                 self.numRows    = numRows
600                 self.scalars    = scalars
601
602         @staticmethod
603         def identity (numCols, numRows):
604                 scalars = []
605                 for col in range(0, numCols):
606                         for row in range(0, numRows):
607                                 scalars.append(1.0 if col == row else 0.0)
608                 return Mat(numCols, numRows, scalars)
609
610         def get (self, colNdx, rowNdx):
611                 assert 0 <= colNdx and colNdx < self.numCols
612                 assert 0 <= rowNdx and rowNdx < self.numRows
613                 return self.scalars[colNdx*self.numRows + rowNdx]
614
615         def set (self, colNdx, rowNdx, scalar):
616                 assert 0 <= colNdx and colNdx < self.numCols
617                 assert 0 <= rowNdx and rowNdx < self.numRows
618                 self.scalars[colNdx*self.numRows + rowNdx] = scalar
619
620         def toMatrix (self, numCols, numRows):
621                 res = Mat.identity(numCols, numRows)
622                 for col in range(0, min(self.numCols, numCols)):
623                         for row in range(0, min(self.numRows, numRows)):
624                                 res.set(col, row, self.get(col, row))
625                 return res
626
627         def toMat2 (self):              return self.toMatrix(2, 2)
628         def toMat2x3 (self):    return self.toMatrix(2, 3)
629         def toMat2x4 (self):    return self.toMatrix(2, 4)
630         def toMat3x2 (self):    return self.toMatrix(3, 2)
631         def toMat3 (self):              return self.toMatrix(3, 3)
632         def toMat3x4 (self):    return self.toMatrix(3, 4)
633         def toMat4x2 (self):    return self.toMatrix(4, 2)
634         def toMat4x3 (self):    return self.toMatrix(4, 3)
635         def toMat4 (self):              return self.toMatrix(4, 4)
636
637         def typeString(self):
638                 if self.numRows == self.numCols:
639                         return "mat%d" % self.numRows
640                 else:
641                         return "mat%dx%d" % (self.numCols, self.numRows)
642
643         def __str__(self):
644                 return "%s(%s)" % (self.typeString(), ", ".join([str(s) for s in self.scalars]))
645
646         def isTypeEqual (self, other):
647                 return isinstance(other, Mat) and self.numRows == other.numRows and self.numCols == other.numCols
648
649         def isEqual(self, other):
650                 assert self.isTypeEqual(other)
651                 return (self.scalars == other.scalars)
652
653         def compMul(self, val):
654                 assert self.isTypeEqual(val)
655                 return Mat(self.numRows, self.numCols, [self.scalars(i) * val.scalars(i) for i in range(self.numRows*self.numCols)])
656
657 class Mat2(Mat):
658         def __init__(self, m00, m01, m10, m11):
659                 Mat.__init__(self, 2, 2, [m00, m10, m01, m11])
660
661 class Mat3(Mat):
662         def __init__(self, m00, m01, m02, m10, m11, m12, m20, m21, m22):
663                 Mat.__init__(self, 3, 3, [m00, m10, m20,
664                                                                   m01, m11, m21,
665                                                                   m02, m12, m22])
666
667 class Mat4(Mat):
668         def __init__(self, m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33):
669                 Mat.__init__(self, 4, 4, [m00, m10, m20, m30,
670                                                                   m01, m11, m21, m31,
671                                                                   m02, m12, m22, m32,
672                                                                   m03, m13, m23, m33])