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