1import re
2import math
3import random
4
5PREAMBLE = """
6# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
7# modify the generating script file. Otherwise changes will be lost!
8"""[1:]
9
10class CaseGroup:
11	def __init__(self, name, description, children):
12		self.name			= name
13		self.description	= description
14		self.children		= children
15
16class ShaderCase:
17	def __init__(self):
18		pass
19
20g_processedCases = {}
21
22def indentTextBlock(text, indent):
23	indentStr = indent * "\t"
24	lines = text.split("\n")
25	lines = [indentStr + line for line in lines]
26	lines = [ ["", line][line.strip() != ""] for line in lines]
27	return "\n".join(lines)
28
29def writeCase(f, case, indent, prefix):
30	print "\t%s" % (prefix + case.name)
31	if isinstance(case, CaseGroup):
32		f.write(indentTextBlock('group %s "%s"\n\n' % (case.name, case.description), indent))
33		for child in case.children:
34			writeCase(f, child, indent + 1, prefix + case.name + ".")
35		f.write(indentTextBlock("\nend # %s\n" % case.name, indent))
36	else:
37		# \todo [petri] Fix hack.
38		fullPath = prefix + case.name
39		assert (fullPath not in g_processedCases)
40		g_processedCases[fullPath] = None
41		f.write(indentTextBlock(str(case) + "\n", indent))
42
43def writeAllCases(fileName, caseList):
44	# Write all cases to file.
45	print "  %s.." % fileName
46	f = file(fileName, "wb")
47	f.write(PREAMBLE + "\n")
48	for case in caseList:
49		writeCase(f, case, 0, "")
50	f.close()
51
52	print "done! (%d cases written)" % len(g_processedCases)
53
54# Template operations.
55
56def genValues(inputs, outputs):
57	res = []
58	for (name, values) in inputs:
59		res.append("input %s = [ %s ];" % (name, " | ".join([str(v) for v in values]).lower()))
60	for (name, values) in outputs:
61		res.append("output %s = [ %s ];" % (name, " | ".join([str(v) for v in values]).lower()))
62	return ("\n".join(res))
63
64def fillTemplate(template, params):
65	s = template
66
67	for (key, value) in params.items():
68		m = re.search(r"^(\s*)\$\{\{%s\}\}$" % key, s, re.M)
69		if m is not None:
70			start = m.start(0)
71			end = m.end(0)
72			ws = m.group(1)
73			if value is not None:
74				repl = "\n".join(["%s%s" % (ws, line) for line in value.split("\n")])
75				s = s[:start] + repl + s[end:]
76			else:
77				s = s[:start] + s[end+1:] # drop the whole line
78		else:
79			s = s.replace("${{%s}}" % key, value)
80	return s
81
82# Return shuffled version of list
83def shuffled(lst):
84	tmp = lst[:]
85	random.shuffle(tmp)
86	return tmp
87
88def repeatToLength(lst, toLength):
89	return (toLength / len(lst)) * lst + lst[: toLength % len(lst)]
90
91# Helpers to convert a list of Scalar/Vec values into another type.
92
93def toFloat(lst):	return [Scalar(float(v.x)) for v in lst]
94def toInt(lst):		return [Scalar(int(v.x)) for v in lst]
95def toBool(lst):	return [Scalar(bool(v.x)) for v in lst]
96def toVec4(lst):	return [v.toFloat().toVec4() for v in lst]
97def toVec3(lst):	return [v.toFloat().toVec3() for v in lst]
98def toVec2(lst):	return [v.toFloat().toVec2() for v in lst]
99def toIVec4(lst):	return [v.toInt().toVec4() for v in lst]
100def toIVec3(lst):	return [v.toInt().toVec3() for v in lst]
101def toIVec2(lst):	return [v.toInt().toVec2() for v in lst]
102def toBVec4(lst):	return [v.toBool().toVec4() for v in lst]
103def toBVec3(lst):	return [v.toBool().toVec3() for v in lst]
104def toBVec2(lst):	return [v.toBool().toVec2() for v in lst]
105def toMat2(lst):	return [v.toMat2() for v in lst]
106def toMat3(lst):	return [v.toMat3() for v in lst]
107def toMat4(lst):	return [v.toMat4() for v in lst]
108
109# Random value generation.
110
111class GenRandom:
112	def __init__(self):
113		pass
114
115	def uniformVec4(self, count, mn, mx):
116		ret = [Vec4(random.uniform(mn, mx), random.uniform(mn, mx), random.uniform(mn, mx), random.uniform(mn, mx)) for x in xrange(count)]
117		ret[0].x = mn
118		ret[1].x = mx
119		ret[2].x = (mn + mx) * 0.5
120		return ret
121
122	def uniformBVec4(self, count):
123		ret = [Vec4(random.random() >= 0.5, random.random() >= 0.5, random.random() >= 0.5, random.random() >= 0.5) for x in xrange(count)]
124		ret[0].x = True
125		ret[1].x = False
126		return ret
127
128#	def uniform(self,
129
130# Math operating on Scalar/Vector types.
131
132def glslSign(a):			return 0.0 if (a == 0) else +1.0 if (a > 0.0) else -1.0
133def glslMod(x, y):			return x - y*math.floor(x/y)
134def glslClamp(x, mn, mx):	return mn if (x < mn) else mx if (x > mx) else x
135
136class GenMath:
137	@staticmethod
138	def unary(func):	return lambda val: val.applyUnary(func)
139
140	@staticmethod
141	def binary(func):	return lambda a, b: (b.expandVec(a)).applyBinary(func, a.expandVec(b))
142
143	@staticmethod
144	def frac(val):		return val.applyUnary(lambda x: x - math.floor(x))
145
146	@staticmethod
147	def exp2(val):		return val.applyUnary(lambda x: math.pow(2.0, x))
148
149	@staticmethod
150	def log2(val):		return val.applyUnary(lambda x: math.log(x, 2.0))
151
152	@staticmethod
153	def rsq(val):		return val.applyUnary(lambda x: 1.0 / math.sqrt(x))
154
155	@staticmethod
156	def sign(val):		return val.applyUnary(glslSign)
157
158	@staticmethod
159	def isEqual(a, b):	return Scalar(a.isEqual(b))
160
161	@staticmethod
162	def isNotEqual(a, b):	return Scalar(not a.isEqual(b))
163
164	@staticmethod
165	def step(a, b):		return (b.expandVec(a)).applyBinary(lambda edge, x: [1.0, 0.0][x < edge], a.expandVec(b))
166
167	@staticmethod
168	def length(a):		return a.length()
169
170	@staticmethod
171	def distance(a, b):	return a.distance(b)
172
173	@staticmethod
174	def dot(a, b):		return a.dot(b)
175
176	@staticmethod
177	def cross(a, b):	return a.cross(b)
178
179	@staticmethod
180	def normalize(a):	return a.normalize()
181
182	@staticmethod
183	def boolAny(a):		return a.boolAny()
184
185	@staticmethod
186	def boolAll(a):		return a.boolAll()
187
188	@staticmethod
189	def boolNot(a):		return a.boolNot()
190
191# ..
192
193class Scalar:
194	def __init__(self, x):
195		self.x = x
196
197	def applyUnary(self, func):			return Scalar(func(self.x))
198	def applyBinary(self, func, other):	return Scalar(func(self.x, other.x))
199
200	def isEqual(self, other):	assert isinstance(other, Scalar); return (self.x == other.x)
201
202	def expandVec(self, val):	return val
203	def toScalar(self):			return Scalar(self.x)
204	def toVec2(self):			return Vec2(self.x, self.x)
205	def toVec3(self):			return Vec3(self.x, self.x, self.x)
206	def toVec4(self):			return Vec4(self.x, self.x, self.x, self.x)
207	def toMat2(self):			return self.toVec2().toMat2()
208	def toMat3(self):			return self.toVec3().toMat3()
209	def toMat4(self):			return self.toVec4().toMat4()
210
211	def toFloat(self):			return Scalar(float(self.x))
212	def toInt(self):			return Scalar(int(self.x))
213	def toBool(self):			return Scalar(bool(self.x))
214
215	def getNumScalars(self):	return 1
216	def getScalars(self):		return [self.x]
217
218	def typeString(self):
219		if isinstance(self.x, bool):
220			return "bool"
221		elif isinstance(self.x, int):
222			return "int"
223		elif isinstance(self.x, float):
224			return "float"
225		else:
226			assert False
227
228	def vec4Swizzle(self):
229		return ""
230
231	def __str__(self):
232		return "%s" % self.x
233
234	def length(self):
235		return Scalar(abs(self.x))
236
237	def distance(self, v):
238		assert isinstance(v, Scalar)
239		return Scalar(abs(self.x - v.x))
240
241	def dot(self, v):
242		assert isinstance(v, Scalar)
243		return Scalar(self.x * v.x)
244
245	def normalize(self):
246		return Scalar(glslSign(self.x))
247
248	def __neg__(self):
249		return Scalar(-self.x)
250
251	def __add__(self, val):
252		assert isinstance(val, Scalar)
253		return Scalar(self.x + val.x)
254
255	def __sub__(self, val):
256		return self + (-val)
257
258	def __mul__(self, val):
259		if isinstance(val, Scalar):
260			return Scalar(self.x * val.x)
261		elif isinstance(val, Vec2):
262			return Vec2(self.x * val.x, self.x * val.y)
263		elif isinstance(val, Vec3):
264			return Vec3(self.x * val.x, self.x * val.y, self.x * val.z)
265		elif isinstance(val, Vec4):
266			return Vec4(self.x * val.x, self.x * val.y, self.x * val.z, self.x * val.w)
267		else:
268			assert False
269
270	def __div__(self, val):
271		if isinstance(val, Scalar):
272			return Scalar(self.x / val.x)
273		elif isinstance(val, Vec2):
274			return Vec2(self.x / val.x, self.x / val.y)
275		elif isinstance(val, Vec3):
276			return Vec3(self.x / val.x, self.x / val.y, self.x / val.z)
277		elif isinstance(val, Vec4):
278			return Vec4(self.x / val.x, self.x / val.y, self.x / val.z, self.x / val.w)
279		else:
280			assert False
281
282class Vec:
283	@staticmethod
284	def fromScalarList(lst):
285		assert (len(lst) >= 1 and len(lst) <= 4)
286		if (len(lst) == 1):		return Scalar(lst[0])
287		elif (len(lst) == 2):	return Vec2(lst[0], lst[1])
288		elif (len(lst) == 3):	return Vec3(lst[0], lst[1], lst[2])
289		else:					return Vec4(lst[0], lst[1], lst[2], lst[3])
290
291	def isEqual(self, other):
292		assert isinstance(other, Vec);
293		return (self.getScalars() == other.getScalars())
294
295	def length(self):
296		return Scalar(math.sqrt(self.dot(self).x))
297
298	def normalize(self):
299		return self * Scalar(1.0 / self.length().x)
300
301	def swizzle(self, indexList):
302		inScalars = self.getScalars()
303		outScalars = map(lambda ndx: inScalars[ndx], indexList)
304		return Vec.fromScalarList(outScalars)
305
306	def __init__(self):
307		pass
308
309class Vec2(Vec):
310	def __init__(self, x, y):
311		assert(x.__class__ == y.__class__)
312		self.x = x
313		self.y = y
314
315	def applyUnary(self, func):			return Vec2(func(self.x), func(self.y))
316	def applyBinary(self, func, other):	return Vec2(func(self.x, other.x), func(self.y, other.y))
317
318	def expandVec(self, val):	return val.toVec2()
319	def toScalar(self):			return Scalar(self.x)
320	def toVec2(self):			return Vec2(self.x, self.y)
321	def toVec3(self):			return Vec3(self.x, self.y, 0.0)
322	def toVec4(self):			return Vec4(self.x, self.y, 0.0, 0.0)
323	def toMat2(self):			return Mat2(float(self.x), 0.0, 0.0, float(self.y));
324
325	def toFloat(self):			return Vec2(float(self.x), float(self.y))
326	def toInt(self):			return Vec2(int(self.x), int(self.y))
327	def toBool(self):			return Vec2(bool(self.x), bool(self.y))
328
329	def getNumScalars(self):	return 2
330	def getScalars(self):		return [self.x, self.y]
331
332	def typeString(self):
333		if isinstance(self.x, bool):
334			return "bvec2"
335		elif isinstance(self.x, int):
336			return "ivec2"
337		elif isinstance(self.x, float):
338			return "vec2"
339		else:
340			assert False
341
342	def vec4Swizzle(self):
343		return ".xyxy"
344
345	def __str__(self):
346		if isinstance(self.x, bool):
347			return "bvec2(%s, %s)" % (str(self.x).lower(), str(self.y).lower())
348		elif isinstance(self.x, int):
349			return "ivec2(%i, %i)" % (self.x, self.y)
350		elif isinstance(self.x, float):
351			return "vec2(%s, %s)" % (self.x, self.y)
352		else:
353			assert False
354
355	def distance(self, v):
356		assert isinstance(v, Vec2)
357		return (self - v).length()
358
359	def dot(self, v):
360		assert isinstance(v, Vec2)
361		return Scalar(self.x*v.x + self.y*v.y)
362
363	def __neg__(self):
364		return Vec2(-self.x, -self.y)
365
366	def __add__(self, val):
367		if isinstance(val, Scalar):
368			return Vec2(self.x + val, self.y + val)
369		elif isinstance(val, Vec2):
370			return Vec2(self.x + val.x, self.y + val.y)
371		else:
372			assert False
373
374	def __sub__(self, val):
375		return self + (-val)
376
377	def __mul__(self, val):
378		if isinstance(val, Scalar):
379			val = val.toVec2()
380		assert isinstance(val, Vec2)
381		return Vec2(self.x * val.x, self.y * val.y)
382
383	def __div__(self, val):
384		if isinstance(val, Scalar):
385			return Vec2(self.x / val.x, self.y / val.x)
386		else:
387			assert isinstance(val, Vec2)
388			return Vec2(self.x / val.x, self.y / val.y)
389
390	def boolAny(self):	return Scalar(self.x or self.y)
391	def boolAll(self):	return Scalar(self.x and self.y)
392	def boolNot(self):	return Vec2(not self.x, not self.y)
393
394class Vec3(Vec):
395	def __init__(self, x, y, z):
396		assert((x.__class__ == y.__class__) and (x.__class__ == z.__class__))
397		self.x = x
398		self.y = y
399		self.z = z
400
401	def applyUnary(self, func):			return Vec3(func(self.x), func(self.y), func(self.z))
402	def applyBinary(self, func, other):	return Vec3(func(self.x, other.x), func(self.y, other.y), func(self.z, other.z))
403
404	def expandVec(self, val):	return val.toVec3()
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, self.z)
408	def toVec4(self):			return Vec4(self.x, self.y, self.z, 0.0)
409	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));
410
411	def toFloat(self):			return Vec3(float(self.x), float(self.y), float(self.z))
412	def toInt(self):			return Vec3(int(self.x), int(self.y), int(self.z))
413	def toBool(self):			return Vec3(bool(self.x), bool(self.y), bool(self.z))
414
415	def getNumScalars(self):	return 3
416	def getScalars(self):		return [self.x, self.y, self.z]
417
418	def typeString(self):
419		if isinstance(self.x, bool):
420			return "bvec3"
421		elif isinstance(self.x, int):
422			return "ivec3"
423		elif isinstance(self.x, float):
424			return "vec3"
425		else:
426			assert False
427
428	def vec4Swizzle(self):
429		return ".xyzx"
430
431	def __str__(self):
432		if isinstance(self.x, bool):
433			return "bvec3(%s, %s, %s)" % (str(self.x).lower(), str(self.y).lower(), str(self.z).lower())
434		elif isinstance(self.x, int):
435			return "ivec3(%i, %i, %i)" % (self.x, self.y, self.z)
436		elif isinstance(self.x, float):
437			return "vec3(%s, %s, %s)" % (self.x, self.y, self.z)
438		else:
439			assert False
440
441	def distance(self, v):
442		assert isinstance(v, Vec3)
443		return (self - v).length()
444
445	def dot(self, v):
446		assert isinstance(v, Vec3)
447		return Scalar(self.x*v.x + self.y*v.y + self.z*v.z)
448
449	def cross(self, v):
450		assert isinstance(v, Vec3)
451		return Vec3(self.y*v.z - v.y*self.z,
452					self.z*v.x - v.z*self.x,
453					self.x*v.y - v.x*self.y)
454
455	def __neg__(self):
456		return Vec3(-self.x, -self.y, -self.z)
457
458	def __add__(self, val):
459		if isinstance(val, Scalar):
460			return Vec3(self.x + val, self.y + val)
461		elif isinstance(val, Vec3):
462			return Vec3(self.x + val.x, self.y + val.y, self.z + val.z)
463		else:
464			assert False
465
466	def __sub__(self, val):
467		return self + (-val)
468
469	def __mul__(self, val):
470		if isinstance(val, Scalar):
471			val = val.toVec3()
472		assert isinstance(val, Vec3)
473		return Vec3(self.x * val.x, self.y * val.y, self.z * val.z)
474
475	def __div__(self, val):
476		if isinstance(val, Scalar):
477			return Vec3(self.x / val.x, self.y / val.x, self.z / val.x)
478		else:
479			assert False
480
481	def boolAny(self):	return Scalar(self.x or self.y or self.z)
482	def boolAll(self):	return Scalar(self.x and self.y and self.z)
483	def boolNot(self):	return Vec3(not self.x, not self.y, not self.z)
484
485class Vec4(Vec):
486	def __init__(self, x, y, z, w):
487		assert((x.__class__ == y.__class__) and (x.__class__ == z.__class__) and (x.__class__ == w.__class__))
488		self.x = x
489		self.y = y
490		self.z = z
491		self.w = w
492
493	def applyUnary(self, func):			return Vec4(func(self.x), func(self.y), func(self.z), func(self.w))
494	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))
495
496	def expandVec(self, val):	return val.toVec4()
497	def toScalar(self):			return Scalar(self.x)
498	def toVec2(self):			return Vec2(self.x, self.y)
499	def toVec3(self):			return Vec3(self.x, self.y, self.z)
500	def toVec4(self):			return Vec4(self.x, self.y, self.z, self.w)
501	def toMat2(self):			return Mat2(float(self.x), float(self.y), float(self.z), float(self.w))
502	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));
503
504	def toFloat(self):			return Vec4(float(self.x), float(self.y), float(self.z), float(self.w))
505	def toInt(self):			return Vec4(int(self.x), int(self.y), int(self.z), int(self.w))
506	def toBool(self):			return Vec4(bool(self.x), bool(self.y), bool(self.z), bool(self.w))
507
508	def getNumScalars(self):	return 4
509	def getScalars(self):		return [self.x, self.y, self.z, self.w]
510
511	def typeString(self):
512		if isinstance(self.x, bool):
513			return "bvec4"
514		elif isinstance(self.x, int):
515			return "ivec4"
516		elif isinstance(self.x, float):
517			return "vec4"
518		else:
519			assert False
520
521	def vec4Swizzle(self):
522		return ""
523
524	def __str__(self):
525		if isinstance(self.x, bool):
526			return "bvec4(%s, %s, %s, %s)" % (str(self.x).lower(), str(self.y).lower(), str(self.z).lower(), str(self.w).lower())
527		elif isinstance(self.x, int):
528			return "ivec4(%i, %i, %i, %i)" % (self.x, self.y, self.z, self.w)
529		elif isinstance(self.x, float):
530			return "vec4(%s, %s, %s, %s)" % (self.x, self.y, self.z, self.w)
531		else:
532			assert False
533
534	def distance(self, v):
535		assert isinstance(v, Vec4)
536		return (self - v).length()
537
538	def dot(self, v):
539		assert isinstance(v, Vec4)
540		return Scalar(self.x*v.x + self.y*v.y + self.z*v.z + self.w*v.w)
541
542	def __neg__(self):
543		return Vec4(-self.x, -self.y, -self.z, -self.w)
544
545	def __add__(self, val):
546		if isinstance(val, Scalar):
547			return Vec3(self.x + val, self.y + val)
548		elif isinstance(val, Vec4):
549			return Vec4(self.x + val.x, self.y + val.y, self.z + val.z, self.w + val.w)
550		else:
551			assert False
552
553	def __sub__(self, val):
554		return self + (-val)
555
556	def __mul__(self, val):
557		if isinstance(val, Scalar):
558			val = val.toVec4()
559		assert isinstance(val, Vec4)
560		return Vec4(self.x * val.x, self.y * val.y, self.z * val.z, self.w * val.w)
561
562	def __div__(self, val):
563		if isinstance(val, Scalar):
564			return Vec4(self.x / val.x, self.y / val.x, self.z / val.x, self.w / val.x)
565		else:
566			assert False
567
568	def boolAny(self):	return Scalar(self.x or self.y or self.z or self.w)
569	def boolAll(self):	return Scalar(self.x and self.y and self.z and self.w)
570	def boolNot(self):	return Vec4(not self.x, not self.y, not self.z, not self.w)
571
572# \note Column-major storage.
573class Mat:
574	def __init__ (self, numCols, numRows, scalars):
575		assert len(scalars) == numRows*numCols
576		self.numCols	= numCols
577		self.numRows	= numRows
578		self.scalars	= scalars
579
580	@staticmethod
581	def identity (numCols, numRows):
582		scalars = []
583		for col in range(0, numCols):
584			for row in range(0, numRows):
585				scalars.append(1.0 if col == row else 0.0)
586		return Mat(numCols, numRows, scalars)
587
588	def get (self, colNdx, rowNdx):
589		assert 0 <= colNdx and colNdx < self.numCols
590		assert 0 <= rowNdx and rowNdx < self.numRows
591		return self.scalars[colNdx*self.numRows + rowNdx]
592
593	def set (self, colNdx, rowNdx, scalar):
594		assert 0 <= colNdx and colNdx < self.numCols
595		assert 0 <= rowNdx and rowNdx < self.numRows
596		self.scalars[colNdx*self.numRows + rowNdx] = scalar
597
598	def toMatrix (self, numCols, numRows):
599		res = Mat.identity(numCols, numRows)
600		for col in range(0, min(self.numCols, numCols)):
601			for row in range(0, min(self.numRows, numRows)):
602				res.set(col, row, self.get(col, row))
603		return res
604
605	def toMat2 (self):		return self.toMatrix(2, 2)
606	def toMat2x3 (self):	return self.toMatrix(2, 3)
607	def toMat2x4 (self):	return self.toMatrix(2, 4)
608	def toMat3x2 (self):	return self.toMatrix(3, 2)
609	def toMat3 (self):		return self.toMatrix(3, 3)
610	def toMat3x4 (self):	return self.toMatrix(3, 4)
611	def toMat4x2 (self):	return self.toMatrix(4, 2)
612	def toMat4x3 (self):	return self.toMatrix(4, 3)
613	def toMat4 (self):		return self.toMatrix(4, 4)
614
615	def typeString(self):
616		if self.numRows == self.numCols:
617			return "mat%d" % self.numRows
618		else:
619			return "mat%dx%d" % (self.numCols, self.numRows)
620
621	def __str__(self):
622		return "%s(%s)" % (self.typeString(), ", ".join([str(s) for s in self.scalars]))
623
624	def isTypeEqual (self, other):
625		return isinstance(other, Mat) and self.numRows == other.numRows and self.numCols == other.numCols
626
627	def isEqual(self, other):
628		assert self.isTypeEqual(other)
629		return (self.scalars == other.scalars)
630
631	def compMul(self, val):
632		assert self.isTypeEqual(val)
633		return Mat(self.numRows, self.numCols, [self.scalars(i) * val.scalars(i) for i in range(self.numRows*self.numCols)])
634
635class Mat2(Mat):
636	def __init__(self, m00, m01, m10, m11):
637		Mat.__init__(self, 2, 2, [m00, m10, m01, m11])
638
639class Mat3(Mat):
640	def __init__(self, m00, m01, m02, m10, m11, m12, m20, m21, m22):
641		Mat.__init__(self, 3, 3, [m00, m10, m20,
642								  m01, m11, m21,
643								  m02, m12, m22])
644
645class Mat4(Mat):
646	def __init__(self, m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33):
647		Mat.__init__(self, 4, 4, [m00, m10, m20, m30,
648								  m01, m11, m21, m31,
649								  m02, m12, m22, m32,
650								  m03, m13, m23, m33])
651