xref: /aosp_15_r20/external/deqp/modules/gles2/scripts/genutil.py (revision 35238bce31c2a825756842865a792f8cf7f89930)
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
23import re
24import math
25import random
26
27PREAMBLE = """
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
32class CaseGroup:
33    def __init__(self, name, description, children):
34        self.name = name
35        self.description = description
36        self.children = children
37
38class ShaderCase:
39    def __init__(self):
40        pass
41
42g_processedCases = {}
43
44def 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
51def 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
65def 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
78def 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
86def 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
105def shuffled(lst):
106    tmp = lst[:]
107    random.shuffle(tmp)
108    return tmp
109
110def 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
115def toFloat(lst): return [Scalar(float(v.x)) for v in lst]
116def toInt(lst): return [Scalar(int(v.x)) for v in lst]
117def toBool(lst): return [Scalar(bool(v.x)) for v in lst]
118def toVec4(lst): return [v.toFloat().toVec4() for v in lst]
119def toVec3(lst): return [v.toFloat().toVec3() for v in lst]
120def toVec2(lst): return [v.toFloat().toVec2() for v in lst]
121def toIVec4(lst): return [v.toInt().toVec4() for v in lst]
122def toIVec3(lst): return [v.toInt().toVec3() for v in lst]
123def toIVec2(lst): return [v.toInt().toVec2() for v in lst]
124def toBVec4(lst): return [v.toBool().toVec4() for v in lst]
125def toBVec3(lst): return [v.toBool().toVec3() for v in lst]
126def toBVec2(lst): return [v.toBool().toVec2() for v in lst]
127def toMat2(lst): return [v.toMat2() for v in lst]
128def toMat3(lst): return [v.toMat3() for v in lst]
129def toMat4(lst): return [v.toMat4() for v in lst]
130
131# Random value generation.
132
133class 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
154def glslSign(a): return 0.0 if (a == 0) else +1.0 if (a > 0.0) else -1.0
155def glslMod(x, y): return x - y*math.floor(x/y)
156def glslClamp(x, mn, mx): return mn if (x < mn) else mx if (x > mx) else x
157
158class 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
215class 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
304class 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
331class 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
416class 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
507class 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.
595class 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
657class Mat2(Mat):
658    def __init__(self, m00, m01, m10, m11):
659        Mat.__init__(self, 2, 2, [m00, m10, m01, m11])
660
661class 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
667class 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])
673