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