glsl: test loop unroll with uint overflow
[piglit.git] / generated_tests / builtin_function.py
blobc438371dbc43aee928ad54f858ebbae942a250c9
1 # coding=utf-8
3 # Copyright © 2011 Intel Corporation
5 # Permission is hereby granted, free of charge, to any person obtaining a
6 # copy of this software and associated documentation files (the "Software"),
7 # to deal in the Software without restriction, including without limitation
8 # the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 # and/or sell copies of the Software, and to permit persons to whom the
10 # Software is furnished to do so, subject to the following conditions:
12 # The above copyright notice and this permission notice (including the next
13 # paragraph) shall be included in all copies or substantial portions of the
14 # Software.
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 # DEALINGS IN THE SOFTWARE.
24 # This source file defines a set of test vectors that can be used to
25 # test GLSL's built-in functions and operators. It is intended to be
26 # used by Python code that generates Piglit tests.
28 # The key export is the dictionary test_suite. It contains an entry
29 # for each possible overload of every pure built-in function and
30 # operator. By iterating through this dictionary you can find a set
31 # of test vectors for testing nearly every built-in GLSL function.
33 # The following functions are not included, since they are not pure,
34 # so they can't be tested using simple vectors:
35 # - dFdx()
36 # - dFdy()
37 # - fwidth()
38 # - ftransform()
39 # - Increment and decrement operators
41 # The following functions are not included, since they need to be
42 # tested in specialized ways:
43 # - modf(): not tested because it has an out parameter
44 # - isnan() and isinf(): not tested because special effort is required
45 # to create values that cause these functions to return true.
47 # Also not tested are array subscripting, field/method selection,
48 # swizzling, the function call operator, assignment, and the sequence
49 # operator.
51 import collections
52 import itertools
53 import functools
54 import warnings
56 import numpy as np
59 # Floating point types used by Python and numpy
60 FLOATING_TYPES = (float, np.float64, np.float32)
62 # Due to a bug in the Windows implementation of numpy, there are
63 # multiple int32 types (and multiple uint32 types). So we have to
64 # find them all when doing isinstance checks. The following code will
65 # create two-element tuples on numpy implementations that have the
66 # bug, and one-element tuples on numpy implementations that don't.
67 INT32_TYPES = tuple(set([np.int32, type(np.abs(np.int32(1)))]))
68 UINT32_TYPES = tuple(set([np.uint32,
69 type(np.dot(np.uint32(0), np.uint32(0)))]))
70 INT64_TYPES = tuple(set([np.int64, type(np.abs(np.int64(1)))]))
71 UINT64_TYPES = tuple(set([np.uint64,
72 type(np.dot(np.uint64(0), np.uint64(0)))]))
75 @functools.total_ordering
76 class GlslBuiltinType(object):
77 """Class representing a GLSL built-in type."""
78 def __init__(self, name, base_type, num_cols, num_rows,
79 version_introduced):
80 self.__name = name
81 if base_type is not None:
82 self.__base_type = base_type
83 else:
84 self.__base_type = self
85 self.__num_cols = num_cols
86 self.__num_rows = num_rows
87 self.__version_introduced = version_introduced
89 @property
90 def name(self):
91 """The name of the type, as a string."""
92 return self.__name
94 @property
95 def base_type(self):
96 """For vectors and matrices, the type of data stored in each
97 element. For scalars, equal to self.
98 """
99 return self.__base_type
101 @property
102 def num_cols(self):
103 """For matrices, the number of columns. For vectors and
104 scalars, 1.
106 return self.__num_cols
108 @property
109 def num_rows(self):
110 """For vectors and matrices, the number of rows. For scalars,
113 return self.__num_rows
115 @property
116 def is_scalar(self):
117 return self.__num_cols == 1 and self.__num_rows == 1
119 @property
120 def is_vector(self):
121 return self.__num_cols == 1 and self.__num_rows != 1
123 @property
124 def is_matrix(self):
125 return self.__num_cols != 1
127 @property
128 def version_introduced(self):
129 """The earliest version of GLSL that this type appears in (as
130 a string, e.g. 110).
132 return self.__version_introduced
134 def __eq__(self, other):
135 if isinstance(other, GlslBuiltinType):
136 return self.name == other.name
138 return NotImplemented
140 def __lt__(self, other):
141 if isinstance(other, GlslBuiltinType):
142 return self.name < other.name
144 return NotImplemented
146 def __hash__(self):
147 return hash('__GLslBuiltinType_{}__'.format(self.name))
149 def __str__(self):
150 return self.__name
152 def __repr__(self):
153 return 'glsl_{0}'.format(self.__name)
156 # Concrete declarations of GlslBuiltinType
157 glsl_bool = GlslBuiltinType('bool', None, 1, 1, 110)
158 glsl_int = GlslBuiltinType('int', None, 1, 1, 110)
159 glsl_uint = GlslBuiltinType('uint', None, 1, 1, 130)
160 glsl_float = GlslBuiltinType('float', None, 1, 1, 110)
161 glsl_vec2 = GlslBuiltinType('vec2', glsl_float, 1, 2, 110)
162 glsl_vec3 = GlslBuiltinType('vec3', glsl_float, 1, 3, 110)
163 glsl_vec4 = GlslBuiltinType('vec4', glsl_float, 1, 4, 110)
164 glsl_bvec2 = GlslBuiltinType('bvec2', glsl_bool, 1, 2, 110)
165 glsl_bvec3 = GlslBuiltinType('bvec3', glsl_bool, 1, 3, 110)
166 glsl_bvec4 = GlslBuiltinType('bvec4', glsl_bool, 1, 4, 110)
167 glsl_ivec2 = GlslBuiltinType('ivec2', glsl_int, 1, 2, 110)
168 glsl_ivec3 = GlslBuiltinType('ivec3', glsl_int, 1, 3, 110)
169 glsl_ivec4 = GlslBuiltinType('ivec4', glsl_int, 1, 4, 110)
170 glsl_uvec2 = GlslBuiltinType('uvec2', glsl_uint, 1, 2, 130)
171 glsl_uvec3 = GlslBuiltinType('uvec3', glsl_uint, 1, 3, 130)
172 glsl_uvec4 = GlslBuiltinType('uvec4', glsl_uint, 1, 4, 130)
173 glsl_mat2 = GlslBuiltinType('mat2', glsl_float, 2, 2, 110)
174 glsl_mat3 = GlslBuiltinType('mat3', glsl_float, 3, 3, 110)
175 glsl_mat4 = GlslBuiltinType('mat4', glsl_float, 4, 4, 110)
176 glsl_mat2x2 = glsl_mat2
177 glsl_mat3x2 = GlslBuiltinType('mat3x2', glsl_float, 3, 2, 120)
178 glsl_mat4x2 = GlslBuiltinType('mat4x2', glsl_float, 4, 2, 120)
179 glsl_mat2x3 = GlslBuiltinType('mat2x3', glsl_float, 2, 3, 120)
180 glsl_mat3x3 = glsl_mat3
181 glsl_mat4x3 = GlslBuiltinType('mat4x3', glsl_float, 4, 3, 120)
182 glsl_mat2x4 = GlslBuiltinType('mat2x4', glsl_float, 2, 4, 120)
183 glsl_mat3x4 = GlslBuiltinType('mat3x4', glsl_float, 3, 4, 120)
184 glsl_mat4x4 = glsl_mat4
185 glsl_int64_t = GlslBuiltinType('int64_t', None, 1, 1, 400)
186 glsl_i64vec2 = GlslBuiltinType('i64vec2', glsl_int64_t, 1, 2, 400)
187 glsl_i64vec3 = GlslBuiltinType('i64vec3', glsl_int64_t, 1, 3, 400)
188 glsl_i64vec4 = GlslBuiltinType('i64vec4', glsl_int64_t, 1, 4, 400)
189 glsl_uint64_t = GlslBuiltinType('uint64_t', None, 1, 1, 400)
190 glsl_u64vec2 = GlslBuiltinType('u64vec2', glsl_uint64_t, 1, 2, 400)
191 glsl_u64vec3 = GlslBuiltinType('u64vec3', glsl_uint64_t, 1, 3, 400)
192 glsl_u64vec4 = GlslBuiltinType('u64vec4', glsl_uint64_t, 1, 4, 400)
194 # Named tuple representing the signature of a single overload of a
195 # built-in GLSL function or operator:
196 # - name is a name suitable for use in test filenames. For functions,
197 # this is the name of the function. For operators, it is a short
198 # description of the operator, beginning with "op", e.g. "op-plus".
199 # - template is a Python format string that can be used to construct
200 # GLSL code that invokes the function or operator.
201 # - version_introduced earliest version of GLSL the test applies to
202 # (as a string, e.g. 110).
203 # - rettype is the return type of the function or operator (as a
204 # GlslBuiltinType).
205 # - argtypes is a tuple containing the types of each parameter (as
206 # GlslBuiltinTypes).
208 # For example, the function
210 # vec3 step(float edge, vec3 x)
212 # has a signature of
214 # Signature(name='step', template='step({0}, {1})',
215 # version_introduced=110, rettype='vec3',
216 # argtypes=('float', 'vec3'))
217 Signature = collections.namedtuple(
218 'Signature',
219 ('name', 'template', 'version_introduced', 'extension', 'rettype', 'argtypes'))
222 # Named tuple representing a single piece of test data for testing a
223 # built-in GLSL function:
224 # - arguments is a tuple containing the arguments to apply to the
225 # function. Each argument is of a type native to numpy (e.g.
226 # numpy.float32 or numpy.ndarray)
227 # - result is the value the function is expected to return. It is
228 # also of a type native to numpy.
229 # - tolerance is a float32 representing how much deviation from the
230 # result we expect, considering the floating point precision
231 # requirements of GLSL and OpenGL. The value may be zero for test
232 # vectors involving booleans and integers. If result is a vector or
233 # matrix, tolerance should be interpreted as the maximum permissible
234 # RMS error (as would be computed by the distance() function).
235 TestVector = collections.namedtuple(
236 'TestVector', ('arguments', 'result', 'tolerance'))
239 def glsl_type_of(value):
240 """Return the GLSL type corresponding to the given native numpy
241 value, as a GlslBuiltinType.
243 if isinstance(value, FLOATING_TYPES):
244 return glsl_float
245 elif isinstance(value, (bool, np.bool_)):
246 return glsl_bool
247 elif isinstance(value, INT32_TYPES):
248 return glsl_int
249 elif isinstance(value, UINT32_TYPES):
250 return glsl_uint
251 elif isinstance(value, np.int64):
252 return glsl_int64_t
253 elif isinstance(value, np.uint64):
254 return glsl_uint64_t
255 else:
256 assert isinstance(value, np.ndarray)
257 if len(value.shape) == 1:
258 # Vector
259 vector_length = value.shape[0]
260 assert 2 <= vector_length <= 4
261 if value.dtype in FLOATING_TYPES:
262 return (glsl_vec2, glsl_vec3, glsl_vec4)[vector_length - 2]
263 elif value.dtype == np.int64:
264 return (glsl_i64vec2, glsl_i64vec3, glsl_i64vec4)[vector_length - 2]
265 elif value.dtype == np.uint64:
266 return (glsl_u64vec2, glsl_u64vec3, glsl_u64vec4)[vector_length - 2]
267 elif value.dtype == bool:
268 return (glsl_bvec2, glsl_bvec3, glsl_bvec4)[vector_length - 2]
269 elif value.dtype in INT32_TYPES:
270 return (glsl_ivec2, glsl_ivec3, glsl_ivec4)[vector_length - 2]
271 elif value.dtype in UINT32_TYPES:
272 return (glsl_uvec2, glsl_uvec3, glsl_uvec4)[vector_length - 2]
273 else:
274 raise Exception(
275 'Unexpected vector base type {0}'.format(value.dtype))
276 else:
277 # Matrix
278 assert value.dtype in FLOATING_TYPES
279 assert len(value.shape) == 2
280 matrix_rows = value.shape[0]
281 assert 2 <= matrix_rows <= 4
282 matrix_columns = value.shape[1]
283 assert 2 <= matrix_columns <= 4
284 matrix_types = ((glsl_mat2x2, glsl_mat2x3, glsl_mat2x4),
285 (glsl_mat3x2, glsl_mat3x3, glsl_mat3x4),
286 (glsl_mat4x2, glsl_mat4x3, glsl_mat4x4))
287 return matrix_types[matrix_columns - 2][matrix_rows - 2]
290 def column_major_values(value):
291 """Given a native numpy value, return a list of the scalar values
292 comprising it, in column-major order."""
293 if isinstance(value, np.ndarray):
294 return list(np.reshape(value, newshape=-1, order='F'))
295 else:
296 return [value]
299 def glsl_constant(value):
300 """Given a native numpy value, return GLSL code that constructs
301 it."""
302 column_major = np.reshape(np.array(value), newshape=-1, order='F')
303 if column_major.dtype == bool:
304 values = ['true' if x else 'false' for x in column_major]
305 elif column_major.dtype == np.int64:
306 values = [repr(x) + 'l' for x in column_major]
307 elif column_major.dtype == np.uint64:
308 values = [repr(x) + 'ul' for x in column_major]
309 elif column_major.dtype in UINT32_TYPES:
310 values = [repr(x) + 'u' for x in column_major]
311 else:
312 values = [repr(x) for x in column_major]
313 if len(column_major) == 1:
314 return values[0]
315 else:
316 return '{0}({1})'.format(glsl_type_of(value), ', '.join(values))
319 def round_to_32_bits(value):
320 """If value is a floating point type, round it down to 32 bits.
321 Otherwise return it unchanged.
323 if isinstance(value, float):
324 return np.float32(value)
325 elif isinstance(value, np.ndarray) and value.dtype == np.float64:
326 return np.array(value, dtype=np.float32)
327 else:
328 return value
331 def extend_to_64_bits(value):
332 """If value is a floating point type, extend it to 64 bits.
333 Otherwise return it unchanged.
335 if isinstance(value, np.float32):
336 return np.float64(value)
337 elif isinstance(value, np.ndarray) and value.dtype == np.float32:
338 return np.array(value, dtype=np.float64)
339 else:
340 return value
343 # Dictionary containing the test vectors. Each entry in the
344 # dictionary represents a single overload of a single built-in
345 # function. Its key is a Signature tuple, and its value is a list of
346 # TestVector tuples.
348 # Note: the dictionary is initialized to {} here, but it is filled
349 # with test vectors by code later in this file.
350 test_suite = {}
353 # Implementation
354 # ==============
356 # The functions below shouldn't be necessary to call from outside this
357 # file. They exist solely to populate test_suite with test vectors.
359 # Functions that simulate GLSL built-in functions (in the cases where
360 # the GLSL built-in functions have no python or numpy equivalent, or
361 # in cases where there is a behavioral difference). These functions
362 # return None if the behavior of the GLSL built-in is undefined for
363 # the given set of inputs.
364 def _multiply(x, y):
365 x_type = glsl_type_of(x)
366 y_type = glsl_type_of(y)
368 if x_type.is_vector and y_type.is_vector:
369 # vector * vector is done componentwise.
370 return x * y
371 else:
372 # All other cases are standard linear algebraic
373 # multiplication, which numpy calls "dot".
374 return np.dot(x, y)
377 def _divide(x, y):
378 if any(y_element == 0 for y_element in column_major_values(y)):
379 # Division by zero is undefined.
380 return None
381 if glsl_type_of(x).base_type == glsl_int or glsl_type_of(x).base_type == glsl_int64_t:
382 # The GLSL spec does not make it clear what the rounding rules
383 # are when performing integer division. C99 requires
384 # round-toward-zero, so in the absence of any other
385 # information, assume that's the correct behavior for GLSL.
387 # Python and numpy's rounding rules are inconsistent, so to
388 # make sure we get round-toward-zero behavior, divide the
389 # absolute values of x and y, and then fix the sign.
390 return (np.abs(x) // np.abs(y)) * (np.sign(x) * np.sign(y))
391 elif glsl_type_of(x).base_type == glsl_uint or glsl_type_of(x).base_type == glsl_uint64_t:
392 return x // y
393 else:
394 return x / y
397 def _modulus(x, y):
398 if any(x_element < 0 for x_element in column_major_values(x)):
399 # Modulus operation with a negative first operand is
400 # undefined.
401 return None
402 if any(y_element <= 0 for y_element in column_major_values(y)):
403 # Modulus operation with a negative or zero second operand is
404 # undefined.
405 return None
406 return x % y
409 def _lshift(x, y):
410 base = glsl_type_of(x).base_type
411 if base in (glsl_int64_t, glsl_uint64_t):
412 bits = 64
413 else:
414 bits = 32
415 if not all(0 <= y_element < bits for y_element in column_major_values(y)):
416 # Shifts by less than 0 or more than the number of bits in the
417 # type being shifted are undefined.
418 return None
420 # Once we're sure that y is non-negative and small enough to fit
421 # any integer type, we can convert it to the same type as x, so
422 # the result will always be of the same type.
423 result = x << _change_int_base_type(y, x.dtype)
425 # Shifting should always produce a result with the same base type
426 # as the left argument.
427 assert glsl_type_of(result).base_type == glsl_type_of(x).base_type
429 return result
432 def _rshift(x, y):
433 base = glsl_type_of(x).base_type
434 if base in (glsl_int64_t, glsl_uint64_t):
435 bits = 64
436 shift_type = glsl_int if base == glsl_int64_t else glsl_uint
437 else:
438 bits = 32
439 shift_type = base
440 if not all(0 <= y_element < bits for y_element in column_major_values(y)):
441 # Shifts by less than 0 or more than the number of bits in the
442 # type being shifted are undefined.
443 return None
445 # Once we're sure that y is non-negative and small enough to fit
446 # any integer type, we can convert it to the same type as x, so
447 # the result will always be of the same type.
448 result = x >> _change_int_base_type(y, x.dtype)
450 # Shifting should always produce a result with the same base type
451 # as the left argument.
452 assert glsl_type_of(result).base_type == glsl_type_of(x).base_type
454 return result
457 def _equal(x, y):
458 return all(column_major_values(x == y))
461 def _not_equal(x, y):
462 return not _equal(x, y)
465 def _arctan2(y, x):
466 if x == y == 0.0:
467 return None
468 return np.arctan2(y, x)
471 def _pow(x, y):
472 if x < 0.0:
473 return None
474 if x == 0.0 and y <= 0.0:
475 return None
476 return np.power(x, y)
479 def _exp2(x):
480 # exp2() is not available in versions of numpy < 1.3.0 so we
481 # emulate it with power().
482 return np.power(2, x)
485 def _trunc(x):
486 # trunc() rounds toward zero. It is not available in version
487 # 1.2.1 of numpy so we emulate it with floor(), sign(), and abs().
488 return np.sign(x) * np.floor(np.abs(x))
491 def _clamp(x, minVal, maxVal):
492 if minVal > maxVal:
493 return None
494 return min(max(x, minVal), maxVal)
497 # Inefficient, but obvious
498 def _mid3(x, y, z):
499 return np.sort([x, y, z])[1]
501 def _smoothstep(edge0, edge1, x):
502 if edge0 >= edge1:
503 return None
504 t = _clamp((x-edge0)/(edge1-edge0), 0.0, 1.0)
505 return t*t*(3.0-2.0*t)
508 def _normalize(x):
509 return x/np.linalg.norm(x)
512 def _faceforward(N, I, Nref):
513 if np.dot(Nref, I) < 0.0:
514 return N
515 else:
516 return -N
519 def _reflect(I, N):
520 return I-2*np.dot(N, I)*N
523 def _refract(I, N, eta):
524 k = 1.0-eta*eta*(1.0-np.dot(N, I)*np.dot(N, I))
525 if k < 0.0:
526 return I*0.0
527 else:
528 return eta*I-(eta*np.dot(N, I)+np.sqrt(k))*N
531 def _change_int_base_type(x, new_type):
532 """Change base type of integer scalar or vector
533 to the given one.
535 if isinstance(x, np.ndarray):
536 return np.array(x, dtype=new_type)
537 else:
538 return x.astype(new_type)
541 def _argument_types_match(arguments, argument_indices_to_match):
542 """Return True if all of the arguments indexed by
543 argument_indices_to_match have the same GLSL type.
545 types = [glsl_type_of(arguments[i]) for i in argument_indices_to_match]
546 return all(x == types[0] for x in types)
549 def _strict_tolerance(arguments, result):
550 """Compute tolerance using a strict interpretation of the GLSL and
551 OpenGL standards.
553 From the GLSL 1.20 spec (4.1.4 "Floats"):
555 "As an input value to one of the processing units, a
556 floating-point variable is expected to match the IEEE single
557 precision floating-point definition for precision and dynamic
558 range. It is not required that the precision of internal
559 processing match the IEEE floating-point specification for
560 floating-point operations, but the guidelines for precision
561 established by the OpenGL 1.4 specification must be met."
563 From the OpenGL 1.4 spec (2.1.1 "Floating-Point Computation"):
565 "We require simply that numbers' floating-point parts contain
566 enough bits ... so that individual results of floating-point
567 operations are accurate to about 1 part in 10^5."
569 A harsh interpretation of the above is that (a) no precision is
570 lost in moving numbers into or out of the GPU, and (b) any
571 built-in function constitutes a single operation, so therefore the
572 error in applying any built-in function should be off by no more
573 than 1e-5 times its theoretically correct value.
575 This is not the only possible interpretation, however. Certain
576 built-in functions, such as the cross product, are computed by a
577 formula consisting of many elementary multiplications and
578 additions, in which a large amount of cancellation sometimes
579 occurs. It's possible that these rules are meant to apply to
580 those elementary multiplications and additions, and not the full
581 built-in function. Other built-in functions, such as the trig
582 functions, are typically implemented by a series approximation, in
583 which 1 part in 10^5 accuracy seems like overkill. See below for
584 the tolerance computation we use on these other functions.
586 return 1e-5 * np.linalg.norm(result)
589 def _trig_tolerance(arguments, result):
590 """Compute a more lenient tolerance bound for trig functions.
592 The GLSL and OpenGL specs don't provide any guidance as to the
593 required accuracy of trig functions (other than the "1 part in
594 10^5" general accuracy requirement, which seems like overkill for
595 trig functions.
597 So the tolerance here is rather arbitrarily chosen to be either 1
598 part in 10^3 or 10^-4, whichever is larger.
600 return max(1e-4, 1e-3 * np.linalg.norm(result))
603 def _cross_product_tolerance(arguments, result):
604 """Compute a more lenient tolerance bound for cross product.
606 Since the computation of a cross product may involve a large
607 amount of cancellation, an error tolerance of 1 part in 10^5
608 (referred to the magnitude of the result vector) is overly tight.
610 So instead we allow the error to be 1 part in 10^5 referred to the
611 product of the magnitudes of the arguments.
613 assert len(arguments) == 2
614 return 1e-5 * np.linalg.norm(arguments[0]) * np.linalg.norm(arguments[1])
617 def _simulate_function(test_inputs, python_equivalent, tolerance_function):
618 """Construct test vectors by simulating a GLSL function on a list
619 of possible inputs, and return a list of test vectors.
621 test_inputs is a list of possible input sequences, each of which
622 represents a set of arguments that should be applied to the
623 function.
625 python_equivalent is the function to simulate--it should return
626 None if the GLSL function returns undefined results for the given
627 set of inputs, otherwise it should return the expected result.
628 Input sequences for which python_equivalent returns None are
629 ignored.
631 tolerance_function is the function to call to compute the
632 tolerance. It should take the set of arguments and the expected
633 result as its parameters. It is only used for functions that
634 return floating point values.
636 python_equivalent and tolerance_function are simulated using 64
637 bit floats for maximum possible accuracy. The vector, however, is
638 built with rounded to 32 bits values since that is the data type
639 that we expect to get back from OpenGL.
641 test_vectors = []
642 for inputs in test_inputs:
643 expected_output = python_equivalent(
644 *[extend_to_64_bits(x) for x in inputs])
645 if expected_output is not None:
646 if glsl_type_of(expected_output).base_type != glsl_float:
647 tolerance = 0.0
648 else:
649 tolerance = tolerance_function(inputs, expected_output)
650 test_vectors.append(TestVector(inputs,
651 round_to_32_bits(expected_output),
652 round_to_32_bits(tolerance)))
653 return test_vectors
656 def _vectorize_test_vectors(test_vectors, scalar_arg_indices, vector_length):
657 """Build a new set of test vectors by combining elements of
658 test_vectors into vectors of length vector_length. For example,
659 vectorizing the test vectors
661 [TestVector((10, 20), 30, tolerance), TestVector((11, 20), 31, tolerance)]
663 into vectors of length 2 would produce the result:
665 [TestVector((vec2(10, 11), vec2(20, 20)), vec2(30, 31), new_tolerance)].
667 Tolerances are combined in root-sum-square fashion.
669 scalar_arg_indices is a sequence of argument indices which should
670 not be vectorized. So, if scalar_arg_indices is [1] in the above
671 example, the result would be:
673 [TestVector((vec2(10, 11), 20), vec2(30, 31), new_tolerance)].
675 def make_groups(test_vectors):
676 """Group test vectors according to the values passed to the
677 arguments that should not be vectorized.
679 groups = {}
680 for tv in test_vectors:
681 key = tuple(tv.arguments[i] for i in scalar_arg_indices)
682 if key not in groups:
683 groups[key] = []
684 groups[key].append(tv)
685 return groups
687 def partition_vectors(test_vectors, partition_size):
688 """Partition test_vectors into lists of length partition_size.
689 If partition_size does not evenly divide the number of test
690 vectors, wrap around as necessary to ensure that every input
691 test vector is included.
693 for i in range(0, len(test_vectors), partition_size):
694 partition = []
695 for j in range(partition_size):
696 partition.append(test_vectors[(i + j) % len(test_vectors)])
697 yield partition
699 def merge_vectors(test_vectors):
700 """Merge the given set of test vectors (whose arguments and
701 result are scalars) into a single test vector whose arguments
702 and result are vectors. For argument indices in
703 scalar_arg_indices, leave the argument as a scalar.
705 arity = len(test_vectors[0].arguments)
706 arguments = []
707 for j in range(arity):
708 if j in scalar_arg_indices:
709 arguments.append(test_vectors[0].arguments[j])
710 else:
711 arguments.append(
712 np.array([tv.arguments[j] for tv in test_vectors]))
713 result = np.array([tv.result for tv in test_vectors])
714 tolerance = np.linalg.norm(
715 [tv.tolerance for tv in test_vectors])
716 return TestVector(arguments, result, tolerance)
718 vectorized_test_vectors = []
719 groups = make_groups(test_vectors)
720 for key in sorted(groups.keys()):
721 test_vectors = groups[key]
722 vectorized_test_vectors.extend(
723 merge_vectors(partition)
724 for partition in partition_vectors(test_vectors, vector_length))
725 return vectorized_test_vectors
728 def _store_test_vector(test_suite_dict, name, glsl_version, extension, test_vector,
729 template=None):
730 """Store a test vector in the appropriate place in
731 test_suite_dict. The dictionary key (which is a Signature tuple)
732 is generated by consulting the argument and return types of the
733 test vector, and combining them with name and glsl_version.
735 glsl_version is adjusted if necessary to reflect when the argument
736 and return types were introduced into GLSL.
738 If template is supplied, it is used instead as the template for the
739 Signature objects generated.
741 if template is None:
742 arg_indices = range(len(test_vector.arguments))
743 template = '{0}({1})'.format(
744 name, ', '.join('{{{0}}}'.format(i) for i in arg_indices))
745 rettype = glsl_type_of(test_vector.result)
746 argtypes = tuple(glsl_type_of(arg) for arg in test_vector.arguments)
747 adjusted_glsl_version = max(
748 glsl_version, rettype.version_introduced,
749 *[t.version_introduced for t in argtypes])
750 signature = Signature(
751 name, template, adjusted_glsl_version, extension, rettype, argtypes)
752 if signature not in test_suite_dict:
753 test_suite_dict[signature] = []
754 test_suite_dict[signature].append(test_vector)
757 def _store_test_vectors(test_suite_dict, name, glsl_version, extension,
758 test_vectors, template=None):
759 """Store multiple test vectors in the appropriate places in
760 test_suite_dict.
762 If template is supplied, it is used instead as the template for the
763 Signature objects generated.
765 for test_vector in test_vectors:
766 _store_test_vector(test_suite_dict, name, glsl_version, extension,
767 test_vector, template=template)
770 def make_arguments(input_generators):
771 """Construct a list of tuples of input arguments to test.
773 input_generators is a list, the ith element of which is a sequence
774 of values that are suitable for use as the ith argument of the
775 function under test.
777 Output is a list, each element of which is a tuple of arguments to
778 be passed to the function under test. These values are produced
779 by taking the cartesian product of the input sequences.
781 In addition, this function rounds floating point inputs to 32
782 bits, so that there will be no rounding errors when the input
783 values are passed into OpenGL.
785 input_generators = [
786 [round_to_32_bits(x) for x in seq] for seq in input_generators]
787 return list(itertools.product(*input_generators))
790 def _make_componentwise_test_vectors(test_suite_dict):
791 """Add test vectors to test_suite_dict for GLSL built-in
792 functions that operate on vectors in componentwise fashion.
793 Examples include sin(), cos(), min(), max(), and clamp().
795 # Make sure atan(x) and atan(x,y) don't misbehave for very large
796 # or very small input values.
797 atan_inputs = [0.0]
798 for exponent in (-10, -1, 0, 1, 10):
799 atan_inputs.append(pow(10.0, exponent))
800 atan_inputs.append(-pow(10.0, exponent))
801 # Make a similar set of inputs for acosh(), except don't use any
802 # values < 1, since acosh() is only defined for x >= 1.
803 acosh_inputs = [1.0 + x for x in atan_inputs if x >= 0]
804 ints = [np.int32(x) for x in [-5, -2, -1, 0, 1, 2, 5]]
805 uints = [np.uint32(x) for x in [0, 1, 2, 5, 34]]
806 bools = [True, False]
808 def f(name, arity, glsl_version, python_equivalent,
809 alternate_scalar_arg_indices, test_inputs,
810 tolerance_function=_strict_tolerance,
811 extension=None):
812 """Create test vectors for the function with the given name
813 and arity, which was introduced in the given glsl_version.
815 python_equivalent is a Python function which operates on scalars,
816 and simulates the GLSL function. This function should return None
817 in any case where the output of the GLSL function is undefined.
819 If alternate_scalar_arg_indices is not None, also create test
820 vectors for an alternate vectorized version of the function,
821 in which some arguments are scalars.
822 alternate_scalar_arg_indices is a sequence of the indices of
823 the arguments which are scalars.
825 test_inputs is a list, the ith element of which is a list of
826 values that are suitable for use as the ith argument of the
827 function.
829 If tolerance_function is supplied, it is a function which
830 should be used to compute the tolerance for the test vectors.
831 Otherwise, _strict_tolerance is used.
833 scalar_test_vectors = _simulate_function(
834 make_arguments(test_inputs), python_equivalent, tolerance_function)
835 _store_test_vectors(
836 test_suite_dict, name, glsl_version, extension, scalar_test_vectors)
837 if alternate_scalar_arg_indices is None:
838 scalar_arg_indices_list = [()]
839 else:
840 scalar_arg_indices_list = [(), alternate_scalar_arg_indices]
841 for scalar_arg_indices in scalar_arg_indices_list:
842 for vector_length in (2, 3, 4):
843 _store_test_vectors(
844 test_suite_dict, name, glsl_version, extension,
845 _vectorize_test_vectors(
846 scalar_test_vectors, scalar_arg_indices,
847 vector_length))
849 f('radians', 1, 110, np.radians, None, [np.linspace(-180.0, 180.0, 4)])
850 f('degrees', 1, 110, np.degrees, None, [np.linspace(-np.pi, np.pi, 4)])
851 f('sin', 1, 110, np.sin, None, [np.linspace(-np.pi, np.pi, 4)],
852 _trig_tolerance)
853 f('cos', 1, 110, np.cos, None, [np.linspace(-np.pi, np.pi, 4)],
854 _trig_tolerance)
855 f('tan', 1, 110, np.tan, None, [np.linspace(-np.pi, np.pi, 4)],
856 _trig_tolerance)
857 f('asin', 1, 110, np.arcsin, None, [np.linspace(-1.0, 1.0, 4)],
858 _trig_tolerance)
859 f('acos', 1, 110, np.arccos, None, [np.linspace(-1.0, 1.0, 4)],
860 _trig_tolerance)
861 f('atan', 1, 110, np.arctan, None, [atan_inputs], _trig_tolerance)
862 f('atan', 2, 110, _arctan2, None, [atan_inputs, atan_inputs],
863 _trig_tolerance)
864 f('sinh', 1, 130, np.sinh, None, [np.linspace(-2.0, 2.0, 4)],
865 _trig_tolerance)
866 f('cosh', 1, 130, np.cosh, None, [np.linspace(-2.0, 2.0, 4)],
867 _trig_tolerance)
868 f('tanh', 1, 130, np.tanh, None, [np.linspace(-2.0, 2.0, 4)],
869 _trig_tolerance)
870 f('asinh', 1, 130, np.arcsinh, None, [atan_inputs], _trig_tolerance)
871 f('acosh', 1, 130, np.arccosh, None, [acosh_inputs], _trig_tolerance)
872 f('atanh', 1, 130, np.arctanh, None, [np.linspace(-0.99, 0.99, 4)],
873 _trig_tolerance)
874 f('pow', 2, 110, _pow, None, [np.linspace(0.0, 2.0, 4),
875 np.linspace(-2.0, 2.0, 4)])
876 f('exp', 1, 110, np.exp, None, [np.linspace(-2.0, 2.0, 4)])
877 f('log', 1, 110, np.log, None, [np.linspace(0.01, 2.0, 4)])
878 f('exp2', 1, 110, _exp2, None, [np.linspace(-2.0, 2.0, 4)])
879 f('log2', 1, 110, np.log2, None, [np.linspace(0.01, 2.0, 4)])
880 f('sqrt', 1, 110, np.sqrt, None, [np.linspace(0.0, 2.0, 4)])
881 f('inversesqrt', 1, 110, lambda x: 1.0/np.sqrt(x), None,
882 [np.linspace(0.1, 2.0, 4)])
883 f('abs', 1, 110, np.abs, None, [np.linspace(-1.5, 1.5, 5)])
884 f('abs', 1, 130, np.abs, None, [ints])
885 f('sign', 1, 110, np.sign, None, [np.linspace(-1.5, 1.5, 5)])
886 f('sign', 1, 130, np.sign, None, [ints])
887 f('floor', 1, 110, np.floor, None, [np.linspace(-2.0, 2.0, 4)])
889 # Note: with trunc we want to test values in which the floating
890 # point exponent is < 0, > 23 or in the middle. Hence, we append
891 # some numbers to cover all possible scenarios. In addition, we
892 # want to check bitsize barriers (> 32, > 64, etc.) in case the
893 # conversion is done with a cast to and from another int based
894 # type.
895 f('trunc', 1, 130, _trunc, None,
896 [np.append(np.linspace(-2.0, 2.0, 8),
897 [0.0, 45027112.0, -45027112.0,
898 1.9584199e10, -1.9584199e10,
899 4.5027112e19, -4.5027112e19])])
901 # Note: the direction of rounding used by round() is not specified
902 # for half-integer values, so we test it over a range that doesn't
903 # include exact half-integer values. roundEven() is required to
904 # round half-integer values to the nearest even integer, so we
905 # test it over a range that does include exact half-integer
906 # values. In both cases, we can use numpy's round() function,
907 # because it rounds half-integer values to even, and all other
908 # values to nearest.
909 f('round', 1, 130, np.round, None, [np.linspace(-2.0, 2.0, 8)])
910 f('roundEven', 1, 130, np.round, None, [np.linspace(-2.0, 2.0, 25)])
912 f('ceil', 1, 110, np.ceil, None, [np.linspace(-2.0, 2.0, 4)])
913 f('fract', 1, 110, lambda x: x-np.floor(x), None,
914 [np.linspace(-2.0, 2.0, 4)])
915 f('mod', 2, 110, lambda x, y: x-y*np.floor(x/y), [1],
916 [np.linspace(-1.9, 1.9, 4), np.linspace(-2.0, 2.0, 4)])
917 f('min', 2, 110, min, [1],
918 [np.linspace(-2.0, 2.0, 4), np.linspace(-2.0, 2.0, 4)])
919 f('min', 2, 130, min, [1], [ints, ints])
920 f('min', 2, 130, min, [1], [uints, uints])
921 f('max', 2, 110, max, [1],
922 [np.linspace(-2.0, 2.0, 4), np.linspace(-2.0, 2.0, 4)])
923 f('max', 2, 130, max, [1], [ints, ints])
924 f('max', 2, 130, max, [1], [uints, uints])
925 f('min3', 2, 110, min, None,
926 [np.linspace(-2.0, 2.0, 4), np.linspace(-2.0, 2.0, 4),
927 np.linspace(-2.0, 2.0, 4)],
928 extension="AMD_shader_trinary_minmax")
929 f('min3', 2, 130, min, None, [ints, ints, ints],
930 extension="AMD_shader_trinary_minmax")
931 f('min3', 2, 130, min, None, [uints, uints, uints],
932 extension="AMD_shader_trinary_minmax")
933 f('max3', 2, 110, max, None,
934 [np.linspace(-2.0, 2.0, 4), np.linspace(-2.0, 2.0, 4),
935 np.linspace(-2.0, 2.0, 4)],
936 extension="AMD_shader_trinary_minmax")
937 f('max3', 2, 130, max, None, [ints, ints, ints],
938 extension="AMD_shader_trinary_minmax")
939 f('max3', 2, 130, max, None, [uints, uints, uints],
940 extension="AMD_shader_trinary_minmax")
941 f('mid3', 2, 110, _mid3, None,
942 [np.linspace(-2.0, 2.0, 4), np.linspace(-2.0, 2.0, 4),
943 np.linspace(-2.0, 2.0, 4)],
944 extension="AMD_shader_trinary_minmax")
945 f('mid3', 2, 130, _mid3, None, [ints, ints, ints],
946 extension="AMD_shader_trinary_minmax")
947 f('mid3', 2, 130, _mid3, None, [uints, uints, uints],
948 extension="AMD_shader_trinary_minmax")
949 f('clamp', 3, 110, _clamp, [1, 2], [np.linspace(-2.0, 2.0, 4),
950 np.linspace(-1.5, 1.5, 3), np.linspace(-1.5, 1.5, 3)])
951 f('clamp', 3, 130, _clamp, [1, 2], [ints, ints, ints])
952 f('clamp', 3, 130, _clamp, [1, 2], [uints, uints, uints])
953 f('mix', 3, 110, lambda x, y, a: x*(1-a)+y*a, [2],
954 [np.linspace(-2.0, 2.0, 2), np.linspace(-3.0, 3.0, 2),
955 np.linspace(0.0, 1.0, 4)])
956 f('mix', 3, 130, lambda x, y, a: y if a else x, None,
957 [np.linspace(-2.0, 2.0, 2), np.linspace(-3.0, 3.0, 2), bools])
958 f('step', 2, 110, lambda edge, x: 0.0 if x < edge else 1.0, [0],
959 [np.linspace(-2.0, 2.0, 4), np.linspace(-2.0, 2.0, 4)])
960 f('smoothstep', 3, 110, _smoothstep, [0, 1],
961 [np.linspace(-1.9, 1.9, 4), np.linspace(-1.9, 1.9, 4),
962 np.linspace(-2.0, 2.0, 4)])
964 f('abs', 1, 150, np.abs, None, [np.linspace(-10, 15, 54).astype(np.int64)],
965 extension="ARB_gpu_shader_int64")
966 f('sign', 1, 150, np.sign, None, [np.linspace(-15, 15, 5).astype(np.int64)],
967 extension="ARB_gpu_shader_int64")
968 f('min', 2, 150, min, [1],
969 [np.linspace(-20, 20, 4).astype(np.int64), np.linspace(-20, 20, 4).astype(np.int64)],
970 extension="ARB_gpu_shader_int64")
971 f('min', 2, 150, min, [1],
972 [np.linspace(20, 90, 4).astype(np.uint64), np.linspace(20, 90, 4).astype(np.uint64)],
973 extension="ARB_gpu_shader_int64")
974 f('max', 2, 150, max, [1],
975 [np.linspace(-20, 20, 4).astype(np.int64), np.linspace(-20, 20, 4).astype(np.int64)],
976 extension="ARB_gpu_shader_int64")
977 f('max', 2, 150, max, [1],
978 [np.linspace(20, 90, 4).astype(np.uint64), np.linspace(20, 90, 4).astype(np.uint64)],
979 extension="ARB_gpu_shader_int64")
980 f('clamp', 3, 150, _clamp, [1, 2], [np.linspace(-20, 20, 4).astype(np.int64),
981 np.linspace(-15, 15, 3).astype(np.int64),
982 np.linspace(-15, 15, 3).astype(np.int64)],
983 extension="ARB_gpu_shader_int64")
984 f('mix', 3, 150, lambda x, y, a: y if a else x, None,
985 [np.linspace(-20, 20, 2).astype(np.int64), np.linspace(-30, 30, 2).astype(np.int64), bools],
986 extension="ARB_gpu_shader_int64")
987 _make_componentwise_test_vectors(test_suite)
990 def _make_vector_relational_test_vectors(test_suite_dict):
991 """Add test vectors to test_suite_dict for GLSL built-in functions
992 that operate on vectors of floats, ints, or bools, but not on
993 single floats, ints, or bools. Examples include lessThan(),
994 equal(), and not().
996 _default_inputs = {
997 'v': np.linspace(-1.5, 1.5, 4),
998 'i': np.array([-5, -2, -1, 0, 1, 2, 5], dtype=np.int32),
999 'u': np.array([0, 1, 2, 5, 34], dtype=np.uint32),
1000 'b': np.array([False, True])
1003 def f(name, arity, glsl_version, python_equivalent, arg_types,
1004 tolerance_function=_strict_tolerance,
1005 extension=None):
1006 """Make test vectors for the function with the given name and
1007 arity, which was introduced in the given glsl_version.
1009 python_equivalent is a Python function which operates on scalars,
1010 and simulates the GLSL function.
1012 arg_types is a string containing 'v' if the function supports
1013 standard "vec" inputs, 'i' if it supports "ivec" inputs, and 'b'
1014 if it supports "bvec" inputs. The output type of the function is
1015 assumed to be the same as its input type.
1017 If tolerance_function is supplied, it is a function which
1018 should be used to compute the tolerance for the test vectors.
1019 Otherwise, _strict_tolerance is used.
1021 for arg_type in arg_types:
1022 test_inputs = [_default_inputs[arg_type]]*arity
1023 scalar_test_vectors = _simulate_function(
1024 make_arguments(test_inputs), python_equivalent,
1025 tolerance_function)
1026 for vector_length in (2, 3, 4):
1027 _store_test_vectors(
1028 test_suite_dict, name, glsl_version, extension,
1029 _vectorize_test_vectors(
1030 scalar_test_vectors, (), vector_length))
1032 f('lessThan', 2, 110, lambda x, y: x < y, 'viu')
1033 f('lessThanEqual', 2, 110, lambda x, y: x <= y, 'viu')
1034 f('greaterThan', 2, 110, lambda x, y: x > y, 'viu')
1035 f('greaterThanEqual', 2, 110, lambda x, y: x >= y, 'viu')
1036 f('equal', 2, 110, lambda x, y: x == y, 'viub')
1037 f('notEqual', 2, 110, lambda x, y: x != y, 'viub')
1038 f('not', 1, 110, lambda x: not x, 'b')
1039 _make_vector_relational_test_vectors(test_suite)
1042 def _make_vector_or_matrix_test_vectors(test_suite_dict):
1043 """Add test vectors to test_suite_dict for GLSL built-in functions
1044 that operate on vectors/matrices as a whole. Examples include
1045 length(), dot(), cross(), normalize(), and refract().
1047 def match_args(*indices):
1048 """Return a function that determines whether the type of the
1049 arguments at the given indices match.
1051 For example:
1053 match(1, 3)
1055 is equivalent to:
1057 lambda a, b, c, d: glsl_type_of(b) == glsl_type_of(d)
1059 return lambda *args: _argument_types_match(args, indices)
1061 def match_simple_binop(x, y):
1062 """Determine whether the type of the arguments is compatible
1063 for a simple binary operator (such as '+').
1065 Arguments are compatible if one is a scalar and the other is a
1066 vector/matrix with the same base type, or if they are the same
1067 type.
1069 x_type = glsl_type_of(x)
1070 y_type = glsl_type_of(y)
1071 if x_type.base_type != y_type.base_type:
1072 return False
1073 if x_type.is_scalar or y_type.is_scalar:
1074 return True
1075 return x_type == y_type
1077 def match_multiply(x, y):
1078 """Determine whether the type of the arguments is compatible
1079 for multiply.
1081 Arguments are compatible if they are scalars, vectors, or
1082 matrices with the same base type, and the vector/matrix sizes
1083 are properly matched.
1085 x_type = glsl_type_of(x)
1086 y_type = glsl_type_of(y)
1087 if x_type.base_type != y_type.base_type:
1088 return False
1089 if x_type.is_scalar or y_type.is_scalar:
1090 return True
1091 if x_type.is_vector and y_type.is_matrix:
1092 # When multiplying vector * matrix, the vector is
1093 # transposed to a row vector. So its row count must match
1094 # the row count of the matrix.
1095 return x_type.num_rows == y_type.num_rows
1096 elif x_type.is_vector:
1097 assert y_type.is_vector
1098 # When multiplying vector * vector, the multiplication is
1099 # done componentwise, so the types must match exactly.
1100 return x_type == y_type
1101 else:
1102 assert x_type.is_matrix
1103 # When multiplying matrix * matrix or matrix * vector, a
1104 # standard linear algebraic multiply is used, so x's
1105 # column count must match y's row count.
1106 return x_type.num_cols == y_type.num_rows
1108 def match_shift(x, y):
1109 """Determine whether the type of the arguments is compatible
1110 for shift operations.
1112 Arguments are compatible if they are the same length or the
1113 first one is a vector and the second is a scalar. Their base
1114 types need not be the same, but they both must be integral.
1116 x_type = glsl_type_of(x)
1117 y_type = glsl_type_of(y)
1118 if x_type.base_type not in (glsl_int, glsl_uint, glsl_int64_t, glsl_uint64_t):
1119 return False
1120 if y_type.base_type not in (glsl_int, glsl_uint, glsl_int64_t, glsl_uint64_t):
1121 return False
1122 if y_type.is_scalar:
1123 return True
1124 assert not x_type.is_matrix
1125 assert not y_type.is_matrix
1126 return x_type.num_rows == y_type.num_rows
1128 def match_assignment_operators(x, y):
1129 """ Determine when scalar and matrix arithmetic works
1131 A matrix and a scalar can be combined, but only when being assigned
1132 into a large enough type.
1135 x_type = glsl_type_of(x)
1136 y_type = glsl_type_of(y)
1137 if x_type.base_type != y_type.base_type:
1138 return False
1139 if y_type.is_scalar:
1140 return True
1141 return x_type == y_type
1143 def match_assignment_multiply(x, y):
1144 """Determine whether the type of the arguments is compatible
1145 for multiply.
1147 Arguments are compatible if they are scalars, vectors, or
1148 matrices with the same base type, and the vector/matrix sizes
1149 are properly matched, and that y is scalar
1151 x_type = glsl_type_of(x)
1152 y_type = glsl_type_of(y)
1153 if x_type.base_type != y_type.base_type:
1154 return False
1155 if y_type.is_scalar:
1156 return True
1157 if x_type.is_scalar:
1158 return False
1159 if x_type.is_vector and y_type.is_matrix:
1160 # When multiplying vector * matrix, the vector is
1161 # transposed to a row vector. So its row count must match
1162 # the row count of the matrix.
1163 return x_type.num_rows == y_type.num_rows == y_type.num_cols
1164 elif x_type.is_vector:
1165 assert y_type.is_vector
1166 # When multiplying vector * vector, the multiplication is
1167 # done componentwise, so the types must match exactly.
1168 return x_type == y_type
1169 else:
1170 assert x_type.is_matrix
1171 # When multiplying matrix * matrix or matrix * vector, a
1172 # standard linear algebraic multiply is used, so x's
1173 # column count must match y's row count.
1174 return (x_type.num_cols == y_type.num_rows and
1175 x_type.num_cols == y_type.num_cols)
1177 bools = [False, True]
1178 bvecs = [np.array(bs) for bs in itertools.product(bools, bools)] + \
1179 [np.array(bs) for bs in itertools.product(bools, bools, bools)] + \
1180 [np.array(bs) for bs in itertools.product(bools, bools, bools, bools)]
1181 ints = [np.int32(x) for x in [12, -6, 76, -32, 0]]
1182 small_ints = \
1183 [np.int32(x) for x in [-31, -25, -5, -2, -1, 0, 1, 2, 5, 25, 31]]
1184 ivecs = [
1185 np.array([38, 35], dtype=np.int32),
1186 np.array([64, -9], dtype=np.int32),
1187 np.array([64, 9], dtype=np.int32),
1188 np.array([-36, 32, -88], dtype=np.int32),
1189 np.array([36, 32, 88], dtype=np.int32),
1190 np.array([59, 77, 68], dtype=np.int32),
1191 np.array([-64, 72, 88, -76], dtype=np.int32),
1192 np.array([64, 72, 88, 76], dtype=np.int32),
1193 np.array([-24, 40, -23, 64], dtype=np.int32),
1194 np.array([24, 40, 23, 64], dtype=np.int32),
1196 small_ivecs = [
1197 np.array([13, 26], dtype=np.int32),
1198 np.array([-2, 26], dtype=np.int32),
1199 np.array([2, 26], dtype=np.int32),
1200 np.array([22, -23, 4], dtype=np.int32),
1201 np.array([22, 23, 4], dtype=np.int32),
1202 np.array([-19, 1, -13], dtype=np.int32),
1203 np.array([19, 1, 13], dtype=np.int32),
1204 np.array([16, 24, -23, -25], dtype=np.int32),
1205 np.array([16, 24, 23, 25], dtype=np.int32),
1206 np.array([-23, -12, 14, 19], dtype=np.int32),
1207 np.array([23, 12, 14, 19], dtype=np.int32),
1209 uints = [np.uint32(x) for x in [0, 6, 12, 32, 74]]
1210 small_uints = [np.uint32(x) for x in [0, 1, 2, 5, 25, 31]]
1211 large_uints = [np.uint32(x) for x in [0xdeadbeef, 0xaffeaffe, 0xbadbad]]
1212 uvecs = [
1213 np.array([38, 35], dtype=np.uint32),
1214 np.array([64, 9], dtype=np.uint32),
1215 np.array([36, 32, 88], dtype=np.uint32),
1216 np.array([59, 77, 68], dtype=np.uint32),
1217 np.array([66, 72, 87, 75], dtype=np.uint32),
1218 np.array([24, 40, 23, 74], dtype=np.uint32)
1220 small_uvecs = [
1221 np.array([13, 26], dtype=np.uint32),
1222 np.array([2, 26], dtype=np.uint32),
1223 np.array([22, 23, 4], dtype=np.uint32),
1224 np.array([19, 1, 13], dtype=np.uint32),
1225 np.array([16, 24, 23, 25], dtype=np.uint32),
1226 np.array([23, 12, 14, 19], dtype=np.uint32),
1228 nz_floats = [-1.33, 0.85]
1229 floats = [0.0] + nz_floats
1230 vecs = [
1231 np.array([-0.10, -1.20]),
1232 np.array([-0.42, 0.48]),
1233 np.array([-0.03, -0.85, -0.94]),
1234 np.array([1.67, 0.66, 1.87]),
1235 np.array([-1.65, 1.33, 1.93, 0.76]),
1236 np.array([0.80, -0.15, -0.51, 0.0])
1238 nz_floats_vecs = nz_floats + vecs
1239 vec3s = [
1240 np.array([-0.03, -0.85, -0.94]),
1241 np.array([1.67, 0.66, 1.87]),
1243 norm_floats_vecs = [_normalize(x) for x in nz_floats_vecs]
1244 squaremats = [
1245 np.array([[ 1.60, 0.76],
1246 [ 1.53, -1.00]]), # mat2
1247 np.array([[-0.13, -0.87],
1248 [-1.40, 1.40]]), # mat2
1249 np.array([[-1.11, 1.67, -0.41],
1250 [ 0.13, 1.09, -0.02],
1251 [ 0.56, 0.95, 0.24]]), # mat3
1252 np.array([[-1.69, -0.46, -0.18],
1253 [-1.09, 1.75, 2.00],
1254 [-1.53, -0.70, -1.47]]), # mat3
1255 np.array([[-1.00, -0.55, -1.08, 1.79],
1256 [ 1.77, 0.62, 0.48, -1.35],
1257 [ 0.09, -0.71, -1.39, -1.21],
1258 [-0.91, -1.82, -1.43, 0.72]]), # mat4
1259 np.array([[ 0.06, 1.31, 1.52, -1.96],
1260 [ 1.60, -0.32, 0.51, -1.84],
1261 [ 1.25, 0.45, 1.90, -0.72],
1262 [-0.16, 0.45, -0.88, 0.39]]), # mat4
1264 mats = squaremats + [
1265 np.array([[ 0.09, 1.30, 1.25],
1266 [-1.19, 0.08, 1.08]]), # mat3x2
1267 np.array([[-0.36, -1.08, -0.60],
1268 [-0.53, 0.88, -1.79]]), # mat3x2
1269 np.array([[-0.46, 1.94],
1270 [-0.45, -0.75],
1271 [ 1.03, -0.50]]), # mat2x3
1272 np.array([[ 1.38, -1.08],
1273 [-1.27, 1.83],
1274 [ 1.00, -0.74]]), # mat2x3
1275 np.array([[ 1.81, -0.87, 0.81, 0.65],
1276 [-1.16, -1.52, 0.25, -1.51]]), # mat4x2
1277 np.array([[ 1.93, -1.63, 0.29, 1.60],
1278 [ 0.49, 0.27, 0.14, 0.94]]), # mat4x2
1279 np.array([[ 0.16, -1.69],
1280 [-0.80, 0.59],
1281 [-1.74, -1.43],
1282 [-0.02, -1.21]]), # mat2x4
1283 np.array([[-1.02, 0.74],
1284 [-1.64, -0.13],
1285 [-1.59, 0.47],
1286 [ 0.30, 1.13]]), # mat2x4
1287 np.array([[-0.27, -1.38, -1.41, -0.12],
1288 [-0.17, -0.56, 1.47, 1.86],
1289 [-1.85, -1.29, 1.77, 0.01]]), # mat4x3
1290 np.array([[-0.47, -0.15, 1.97, -1.05],
1291 [-0.20, 0.53, -1.82, -1.41],
1292 [-1.39, -0.19, 1.62, 1.58]]), # mat4x3
1293 np.array([[ 1.42, -0.86, 0.27],
1294 [ 1.80, -1.74, 0.04],
1295 [-1.88, -0.37, 0.43],
1296 [ 1.37, 1.90, 0.71]]), # mat3x4
1297 np.array([[-1.72, 0.09, 0.45],
1298 [-0.31, -1.58, 1.92],
1299 [ 0.14, 0.18, -0.56],
1300 [ 0.40, -0.77, 1.76]]), # mat3x4
1303 int64s = [np.int64(x) for x in [
1306 -1192,
1307 1048576,
1308 4251475,
1309 29852643761,
1310 -4398046511104,
1311 -3948976685146,
1312 -135763469567146206]]
1313 uint64s = [np.uint64(x) for x in [
1316 1192,
1317 1048576,
1318 4251475,
1319 29852643761,
1320 4398046511104,
1321 3948976685146,
1322 135763469567146206,
1323 11654173250180970009]]
1324 small_uint64s = [np.uint64(x) for x in [0, 1, 2, 5, 25, 31, 32, 47, 63]]
1325 small_ivec64s = [
1326 np.array([13, 63], dtype=np.int64),
1327 np.array([-52, 50], dtype=np.int64),
1328 np.array([46, -50, 0], dtype=np.int64),
1329 np.array([52, 23, -5], dtype=np.int64),
1330 np.array([2, -5, 45, -63], dtype=np.int64),
1331 np.array([34, 4, -24, 62], dtype=np.int64),
1333 small_uvec64s = [
1334 np.array([13, 63], dtype=np.uint64),
1335 np.array([52, 50], dtype=np.uint64),
1336 np.array([24, 61], dtype=np.uint64),
1337 np.array([46, 50, 0], dtype=np.uint64),
1338 np.array([52, 23, 5], dtype=np.uint64),
1339 np.array([2, 5, 45, 63], dtype=np.uint64),
1340 np.array([34, 4, 24, 62], dtype=np.uint64),
1343 int64vecs = [
1344 np.array([-10, -12], dtype=np.int64),
1345 np.array([-42, 48], dtype=np.int64),
1346 np.array([-1333333333333333259, 85, 94], dtype=np.int64),
1347 np.array([167, 66, 187], dtype=np.int64),
1348 np.array([165, 133, 193, 76], dtype=np.int64),
1349 np.array([80, -15, -51, 0], dtype=np.int64)
1351 int64_i64vecs = int64s + int64vecs
1352 i64vec3s = [
1353 np.array([-3, -85, -94], dtype=np.int64),
1354 np.array([ 1333333333333333259, 66, 87], dtype=np.int64),
1357 uint64vecs = [
1358 np.array([10, 12], dtype=np.uint64),
1359 np.array([42, 48], dtype=np.uint64),
1360 np.array([1333333333333333259, 85, 94], dtype=np.uint64),
1361 np.array([167, 66, 187], dtype=np.uint64),
1362 np.array([165, 133, 193, 76], dtype=np.uint64),
1363 np.array([80, 15, 51, 0], dtype=np.uint64)
1365 uint64_u64vecs = uint64s + uint64vecs
1366 u64vec3s = [
1367 np.array([3, 85, 94], dtype=np.uint64),
1368 np.array([ 1333333333333333259, 66, 87], dtype=np.uint64),
1371 def f(name, arity, glsl_version, python_equivalent,
1372 filter, test_inputs, tolerance_function=_strict_tolerance,
1373 template=None,
1374 extension=None):
1375 """Make test vectors for the function with the given name and
1376 arity, which was introduced in the given glsl_version.
1378 python_equivalent is a Python function which simulates the GLSL
1379 function. This function should return None in any case where the
1380 output of the GLSL function is undefined. However, it need not
1381 check that the lengths of the input vectors are all the same.
1383 If filter is not None, it will be called with each set of
1384 arguments, and test cases will only be generated if the filter
1385 returns True.
1387 test_inputs is a list, the ith element of which is a list of
1388 vectors and/or scalars that are suitable for use as the ith
1389 argument of the function.
1391 If tolerance_function is supplied, it is a function which
1392 should be used to compute the tolerance for the test vectors.
1393 Otherwise, _strict_tolerance is used.
1395 If template is supplied, it is used instead as the template for
1396 the Signature objects generated.
1398 test_inputs = make_arguments(test_inputs)
1399 if filter is not None:
1400 test_inputs = \
1401 [arguments for arguments in test_inputs if filter(*arguments)]
1402 _store_test_vectors(
1403 test_suite_dict, name, glsl_version, extension,
1404 _simulate_function(
1405 test_inputs, python_equivalent, tolerance_function),
1406 template=template)
1408 f('op-assign-add', 2, 110, lambda x, y: x + y, match_assignment_operators,
1409 [floats+vecs+mats+ints+ivecs+uints+uvecs,
1410 floats+vecs+mats+ints+ivecs+uints+uvecs],
1411 template='{0};\n result += {1}')
1412 # This can generate an overflow warning, this is expected
1413 with warnings.catch_warnings():
1414 warnings.simplefilter('ignore', RuntimeWarning)
1415 f('op-assign-sub', 2, 110,
1416 lambda x, y: x - y, match_assignment_operators,
1417 [floats+vecs+mats+ints+ivecs+uints+uvecs,
1418 floats+vecs+mats+ints+ivecs+uints+uvecs],
1419 template='{0};\n result -= {1}')
1420 f('op-assign-mult', 2, 110, _multiply, match_assignment_multiply,
1421 [floats+vecs+mats+ints+ivecs+uints+uvecs,
1422 floats+vecs+mats+ints+ivecs+uints+uvecs],
1423 template='{0};\n result *= {1}')
1424 f('op-assign-div', 2, 110, _divide, match_assignment_operators,
1425 [floats+vecs+mats+ints+ivecs+uints+uvecs,
1426 floats+vecs+mats+ints+ivecs+uints+uvecs],
1427 template='{0};\n result /= {1}')
1428 f('op-assign-div-large', 2, 130, _divide, match_assignment_operators,
1429 [large_uints, large_uints+small_uints],
1430 template='{0};\n result /= {1}')
1431 f('op-assign-mod', 2, 130, _modulus, match_assignment_operators,
1432 [ints+ivecs+uints+uvecs, ints+ivecs+uints+uvecs],
1433 template='{0};\n result %= {1}')
1434 f('op-assign-bitand', 2, 130, lambda x, y: x & y,
1435 match_assignment_operators,
1436 [ints+ivecs+uints+uvecs, ints+ivecs+uints+uvecs],
1437 template='{0}; result &= {1}')
1438 f('op-assign-bitor', 2, 130, lambda x, y: x | y,
1439 match_assignment_operators,
1440 [ints+ivecs+uints+uvecs, ints+ivecs+uints+uvecs],
1441 template='{0};\n result |= {1}')
1442 f('op-assign-bitxor', 2, 130, lambda x, y: x ^ y,
1443 match_assignment_operators,
1444 [ints+ivecs+uints+uvecs, ints+ivecs+uints+uvecs],
1445 template='{0};\n result ^= {1}')
1446 f('op-assign-lshift', 2, 130, _lshift, match_shift,
1447 [small_ints+small_ivecs+small_uints+small_uvecs,
1448 small_ints+small_ivecs+small_uints+small_uvecs],
1449 template='{0}; result <<= {1}')
1450 f('op-assign-rshift', 2, 130, _rshift, match_shift,
1451 [small_ints+small_ivecs+small_uints+small_uvecs,
1452 small_ints+small_ivecs+small_uints+small_uvecs],
1453 template='{0}; result >>= {1}')
1454 f('op-add', 2, 110, lambda x, y: x + y, match_simple_binop,
1455 [floats+vecs+mats+ints+ivecs+uints+uvecs,
1456 floats+vecs+mats+ints+ivecs+uints+uvecs],
1457 template='({0} + {1})')
1458 # This can generate an overflow warning, this is expected
1459 with warnings.catch_warnings():
1460 warnings.simplefilter('ignore', RuntimeWarning)
1461 f('op-sub', 2, 110, lambda x, y: x - y, match_simple_binop,
1462 [floats+vecs+mats+ints+ivecs+uints+uvecs,
1463 floats+vecs+mats+ints+ivecs+uints+uvecs],
1464 template='({0} - {1})')
1465 f('op-mult', 2, 110, _multiply, match_multiply,
1466 [floats+vecs+mats+ints+ivecs+uints+uvecs,
1467 floats+vecs+mats+ints+ivecs+uints+uvecs],
1468 template='({0} * {1})')
1469 f('op-div', 2, 110, _divide, match_simple_binop,
1470 [floats+vecs+mats+ints+ivecs+uints+uvecs,
1471 floats+vecs+mats+ints+ivecs+uints+uvecs],
1472 template='({0} / {1})')
1473 f('op-div-large', 2, 130, _divide, match_simple_binop,
1474 [large_uints, large_uints+small_uints], template='({0} / {1})')
1475 f('op-mod', 2, 130, _modulus, match_simple_binop,
1476 [ints+ivecs+uints+uvecs, ints+ivecs+uints+uvecs], template='({0} % {1})')
1477 f('op-uplus', 1, 110, lambda x: +x, None,
1478 [floats+vecs+mats+ints+ivecs+uints+uvecs], template='(+ {0})')
1479 f('op-neg', 1, 110, lambda x: -x, None,
1480 [floats+vecs+mats+ints+ivecs+uints+uvecs], template='(- {0})')
1481 f('op-gt', 2, 110, lambda x, y: x > y, match_args(0, 1),
1482 [ints+uints+floats, ints+uints+floats], template='({0} > {1})')
1483 f('op-lt', 2, 110, lambda x, y: x < y, match_args(0, 1),
1484 [ints+uints+floats, ints+uints+floats], template='({0} < {1})')
1485 f('op-ge', 2, 110, lambda x, y: x >= y, match_args(0, 1),
1486 [ints+uints+floats, ints+uints+floats], template='({0} >= {1})')
1487 f('op-le', 2, 110, lambda x, y: x <= y, match_args(0, 1),
1488 [ints+uints+floats, ints+uints+floats], template='({0} <= {1})')
1489 f('op-eq', 2, 110, _equal, match_args(0, 1),
1490 [floats+vecs+mats+ints+ivecs+uints+uvecs+bools+bvecs,
1491 floats+vecs+mats+ints+ivecs+uints+uvecs+bools+bvecs],
1492 template='({0} == {1})')
1493 f('op-ne', 2, 110, _not_equal, match_args(0, 1),
1494 [floats+vecs+mats+ints+ivecs+uints+uvecs+bools+bvecs,
1495 floats+vecs+mats+ints+ivecs+uints+uvecs+bools+bvecs],
1496 template='({0} != {1})')
1497 f('op-and', 2, 110, lambda x, y: x and y, None, [bools, bools],
1498 template='({0} && {1})')
1499 f('op-or', 2, 110, lambda x, y: x or y, None, [bools, bools],
1500 template='({0} || {1})')
1501 f('op-xor', 2, 110, lambda x, y: x != y, None, [bools, bools],
1502 template='({0} ^^ {1})')
1503 f('op-not', 1, 110, lambda x: not x, None, [bools], template='(! {0})')
1504 f('op-selection', 3, 110, lambda x, y, z: y if x else z, match_args(1, 2),
1505 [bools, floats+vecs+mats+ints+ivecs+uints+uvecs+bools+bvecs,
1506 floats+vecs+mats+ints+ivecs+uints+uvecs+bools+bvecs],
1507 template='({0} ? {1} : {2})')
1508 f('op-complement', 1, 130, lambda x: ~x, None, [ints+ivecs+uints+uvecs],
1509 template='(~ {0})')
1510 f('op-lshift', 2, 130, _lshift, match_shift,
1511 [small_ints+small_ivecs+small_uints+small_uvecs,
1512 small_ints+small_ivecs+small_uints+small_uvecs],
1513 template='({0} << {1})')
1514 f('op-rshift', 2, 130, _rshift, match_shift,
1515 [small_ints+small_ivecs+small_uints+small_uvecs,
1516 small_ints+small_ivecs+small_uints+small_uvecs],
1517 template='({0} >> {1})')
1518 f('op-bitand', 2, 130, lambda x, y: x & y, match_simple_binop,
1519 [ints+ivecs+uints+uvecs, ints+ivecs+uints+uvecs],
1520 template='({0} & {1})')
1521 f('op-bitor', 2, 130, lambda x, y: x | y, match_simple_binop,
1522 [ints+ivecs+uints+uvecs, ints+ivecs+uints+uvecs],
1523 template='({0} | {1})')
1524 f('op-bitxor', 2, 130, lambda x, y: x ^ y, match_simple_binop,
1525 [ints+ivecs+uints+uvecs, ints+ivecs+uints+uvecs],
1526 template='({0} ^ {1})')
1527 f('op-bitand-neg', 2, 130, lambda x, y: x & (-y), match_simple_binop,
1528 [ints+ivecs+uints+uvecs, ints+ivecs+uints+uvecs],
1529 template='({0} & (- {1}))')
1530 f('op-bitand-not', 2, 130, lambda x, y: x & (~y), match_simple_binop,
1531 [ints+ivecs+uints+uvecs, ints+ivecs+uints+uvecs],
1532 template='({0} & (~ {1}))')
1533 f('op-bitor-neg', 2, 130, lambda x, y: x | (-y), match_simple_binop,
1534 [ints+ivecs+uints+uvecs, ints+ivecs+uints+uvecs],
1535 template='({0} | (- {1}))')
1536 f('op-bitor-not', 2, 130, lambda x, y: x | (~y), match_simple_binop,
1537 [ints+ivecs+uints+uvecs, ints+ivecs+uints+uvecs],
1538 template='({0} | (~ {1}))')
1539 f('op-bitxor-neg', 2, 130, lambda x, y: x ^ (-y), match_simple_binop,
1540 [ints+ivecs+uints+uvecs, ints+ivecs+uints+uvecs],
1541 template='({0} ^ (- {1}))')
1542 f('op-bitxor-not', 2, 130, lambda x, y: x ^ (~y), match_simple_binop,
1543 [ints+ivecs+uints+uvecs, ints+ivecs+uints+uvecs],
1544 template='({0} ^ (~ {1}))')
1545 f('op-bitand-neg-abs', 2, 130, lambda x, y: x & (-abs(y)), match_simple_binop,
1546 [ints+ivecs, ints+ivecs],
1547 template='({0} & (- abs({1})))')
1548 f('op-bitand-not-abs', 2, 130, lambda x, y: x & (~abs(y)), match_simple_binop,
1549 [ints+ivecs, ints+ivecs],
1550 template='({0} & (~ abs({1})))')
1551 f('op-bitor-neg-abs', 2, 130, lambda x, y: x | (-abs(y)), match_simple_binop,
1552 [ints+ivecs, ints+ivecs],
1553 template='({0} | (- abs({1})))')
1554 f('op-bitor-not-abs', 2, 130, lambda x, y: x | (~abs(y)), match_simple_binop,
1555 [ints+ivecs, ints+ivecs],
1556 template='({0} | (~ abs({1})))')
1557 f('op-bitxor-neg-abs', 2, 130, lambda x, y: x ^ (-abs(y)), match_simple_binop,
1558 [ints+ivecs, ints+ivecs],
1559 template='({0} ^ (- abs({1})))')
1560 f('op-bitxor-not-abs', 2, 130, lambda x, y: x ^ (~abs(y)), match_simple_binop,
1561 [ints+ivecs, ints+ivecs],
1562 template='({0} ^ (~ abs({1})))')
1563 f('op-bitand-abs-neg', 2, 130, lambda x, y: x & abs(-y), match_simple_binop,
1564 [ints+ivecs, ints+ivecs],
1565 template='({0} & abs(- {1}))')
1566 f('op-bitand-abs-not', 2, 130, lambda x, y: x & abs(~y), match_simple_binop,
1567 [ints+ivecs, ints+ivecs],
1568 template='({0} & abs(~ {1}))')
1569 f('op-bitor-abs-neg', 2, 130, lambda x, y: x | abs(-y), match_simple_binop,
1570 [ints+ivecs, ints+ivecs],
1571 template='({0} | abs(- {1}))')
1572 f('op-bitor-abs-not', 2, 130, lambda x, y: x | abs(~y), match_simple_binop,
1573 [ints+ivecs, ints+ivecs],
1574 template='({0} | abs(~ {1}))')
1575 f('op-bitxor-abs-neg', 2, 130, lambda x, y: x ^ abs(-y), match_simple_binop,
1576 [ints+ivecs, ints+ivecs],
1577 template='({0} ^ abs(- {1}))')
1578 f('op-bitxor-abs-not', 2, 130, lambda x, y: x ^ abs(~y), match_simple_binop,
1579 [ints+ivecs, ints+ivecs],
1580 template='({0} ^ abs(~ {1}))')
1581 f('length', 1, 110, np.linalg.norm, None, [floats+vecs])
1582 f('distance', 2, 110, lambda x, y: np.linalg.norm(x-y), match_args(0, 1),
1583 [floats+vecs, floats+vecs])
1584 f('dot', 2, 110, np.dot, match_args(0, 1), [floats+vecs, floats+vecs])
1585 f('cross', 2, 110, np.cross, match_args(0, 1), [vec3s, vec3s],
1586 _cross_product_tolerance)
1587 f('normalize', 1, 110, _normalize, None, [nz_floats_vecs])
1588 f('faceforward', 3, 110, _faceforward, match_args(0, 1, 2),
1589 [floats+vecs, floats+vecs, floats+vecs])
1590 f('reflect', 2, 110, _reflect, match_args(0, 1),
1591 [floats+vecs, norm_floats_vecs])
1592 f('refract', 3, 110, _refract, match_args(0, 1),
1593 [norm_floats_vecs, norm_floats_vecs, [0.5, 2.0]])
1595 # Note: technically matrixCompMult operates componentwise.
1596 # However, since it is the only componentwise function to operate
1597 # on matrices, it is easier to generate test cases for it here
1598 # than to add matrix support to _make_componentwise_test_vectors.
1599 f('matrixCompMult', 2, 110, lambda x, y: x*y, match_args(0, 1),
1600 [mats, mats])
1602 f('outerProduct', 2, 120, np.outer, None, [vecs, vecs])
1603 f('transpose', 1, 120, np.transpose, None, [mats])
1604 f('any', 1, 110, any, None, [bvecs])
1605 f('all', 1, 110, all, None, [bvecs])
1607 f('inverse', 1, 140, np.linalg.inv, None, [squaremats])
1609 f('determinant', 1, 150, np.linalg.det, None, [squaremats])
1611 with warnings.catch_warnings():
1612 warnings.simplefilter('ignore', RuntimeWarning)
1613 f('op-add', 2, 150, lambda x, y: x + y, match_simple_binop,
1614 [int64s+int64vecs+uint64s+uint64vecs,
1615 int64s+int64vecs+uint64s+uint64vecs],
1616 template='({0} + {1})',
1617 extension="ARB_gpu_shader_int64")
1618 with warnings.catch_warnings():
1619 warnings.simplefilter('ignore', RuntimeWarning)
1620 f('op-sub', 2, 150, lambda x, y: x - y, match_simple_binop,
1621 [int64s+int64vecs+uint64s+uint64vecs,
1622 int64s+int64vecs+uint64s+uint64vecs],
1623 template='({0} - {1})',
1624 extension="ARB_gpu_shader_int64")
1625 f('op-mult', 2, 150, _multiply, match_multiply,
1626 [int64s+int64vecs+uint64s+uint64vecs,
1627 int64s+int64vecs+uint64s+uint64vecs],
1628 template='({0} * {1})',
1629 extension="ARB_gpu_shader_int64")
1630 f('op-div', 2, 150, _divide, match_simple_binop,
1631 [int64s+int64vecs+uint64s+uint64vecs,
1632 int64s+int64vecs+uint64s+uint64vecs],
1633 template='({0} / {1})',
1634 extension="ARB_gpu_shader_int64")
1635 f('op-mod', 2, 150, _modulus, match_simple_binop,
1636 [int64s+int64vecs+uint64s+uint64vecs,
1637 int64s+int64vecs+uint64s+uint64vecs],
1638 template='({0} % {1})',
1639 extension="ARB_gpu_shader_int64")
1640 f('op-gt', 2, 150, lambda x, y: x > y, match_args(0, 1),
1641 [int64s+uint64s,
1642 int64s+uint64s],
1643 template = '({0} > {1})',
1644 extension="ARB_gpu_shader_int64")
1645 f('op-lt', 2, 150, lambda x, y: x < y, match_args(0, 1),
1646 [int64s+uint64s,
1647 int64s+uint64s],
1648 template = '({0} < {1})',
1649 extension="ARB_gpu_shader_int64")
1650 f('op-ge', 2, 150, lambda x, y: x >= y, match_args(0, 1),
1651 [int64s+uint64s,
1652 int64s+uint64s],
1653 template = '({0} >= {1})',
1654 extension="ARB_gpu_shader_int64")
1655 f('op-le', 2, 150, lambda x, y: x <= y, match_args(0, 1),
1656 [int64s+uint64s,
1657 int64s+uint64s],
1658 template = '({0} <= {1})',
1659 extension="ARB_gpu_shader_int64")
1660 f('op-eq', 2, 150, lambda x, y: x == y, match_args(0, 1),
1661 [int64s+uint64s,
1662 int64s+uint64s],
1663 template = '({0} == {1})',
1664 extension="ARB_gpu_shader_int64")
1665 f('op-ne', 2, 150, lambda x, y: x != y, match_args(0, 1),
1666 [int64s+uint64s,
1667 int64s+uint64s],
1668 template = '({0} != {1})',
1669 extension="ARB_gpu_shader_int64")
1670 f('op-bitand', 2, 150, lambda x, y: x & y, match_simple_binop,
1671 [int64s+uint64s, int64s+uint64s],
1672 template='({0} & {1})',
1673 extension="ARB_gpu_shader_int64")
1674 f('op-bitor', 2, 150, lambda x, y: x | y, match_simple_binop,
1675 [int64s+uint64s, int64s+uint64s],
1676 template='({0} | {1})',
1677 extension="ARB_gpu_shader_int64")
1678 f('op-bitxor', 2, 150, lambda x, y: x ^ y, match_simple_binop,
1679 [int64s+uint64s, int64s+uint64s],
1680 template='({0} ^ {1})',
1681 extension="ARB_gpu_shader_int64")
1682 f('op-lshift', 2, 150, _lshift, match_shift,
1683 [int64s+int64vecs+uint64s+uint64vecs,
1684 small_ints+small_ivecs+small_uints+small_uvecs+small_ivec64s+small_uint64s+small_uvec64s],
1685 template='({0} << {1})',
1686 extension="ARB_gpu_shader_int64")
1687 f('op-rshift', 2, 150, _rshift, match_shift,
1688 [int64s+int64vecs+uint64s+uint64vecs,
1689 small_ints+small_ivecs+small_uints+small_uvecs+small_ivec64s+small_uint64s+small_uvec64s],
1690 template='({0} >> {1})',
1691 extension="ARB_gpu_shader_int64")
1692 _make_vector_or_matrix_test_vectors(test_suite)
1695 def _check_signature_safety(test_suite_dict):
1696 """As a final safety check, verify that for each possible
1697 combination of name and argtypes, there is exactly one
1698 signature.
1700 name_argtype_combos = set()
1701 for signature in test_suite_dict:
1702 name_argtype_combo = (signature.name, signature.argtypes)
1703 if name_argtype_combo in name_argtype_combos:
1704 raise Exception(
1705 'Duplicate signature found for {0}'.format(name_argtype_combo))
1706 name_argtype_combos.add(name_argtype_combo)
1707 _check_signature_safety(test_suite)