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