1 # OpenCL built-in library: type conversion functions
3 # Copyright (c) 2013 Victor Oliveira <victormatheus@gmail.com>
4 # Copyright (c) 2013 Jesse Towner <jessetowner@lavabit.com>
6 # Permission is hereby granted, free of charge, to any person obtaining a copy
7 # of this software and associated documentation files (the "Software"), to deal
8 # in the Software without restriction, including without limitation the rights
9 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 # copies of the Software, and to permit persons to whom the Software is
11 # furnished to do so, subject to the following conditions:
13 # The above copyright notice and this permission notice shall be included in
14 # all copies or substantial portions of the 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 THE
19 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 # This script generates the file convert_type.cl, which contains all of the
25 # OpenCL functions in the form:
27 # convert_<destTypen><_sat><_roundingMode>(<sourceTypen>)
41 int_types
= ["char", "uchar", "short", "ushort", "int", "uint", "long", "ulong"]
42 unsigned_types
= ["uchar", "ushort", "uint", "ulong"]
43 float_types
= ["float", "double"]
44 int64_types
= ["long", "ulong"]
45 float64_types
= ["double"]
46 vector_sizes
= ["", "2", "3", "4", "8", "16"]
47 half_sizes
= [("2", ""), ("4", "2"), ("8", "4"), ("16", "8")]
49 saturation
= ["", "_sat"]
50 rounding_modes
= ["_rtz", "_rte", "_rtp", "_rtn"]
51 float_prefix
= {"float": "FLT_", "double": "DBL_"}
52 float_suffix
= {"float": "f", "double": ""}
95 "ushort": "USHRT_MAX",
114 def conditional_guard(src
, dst
):
117 if src
in int64_types
:
118 int64_count
= int64_count
+ 1
119 elif src
in float64_types
:
120 float64_count
= float64_count
+ 1
121 if dst
in int64_types
:
122 int64_count
= int64_count
+ 1
123 elif dst
in float64_types
:
124 float64_count
= float64_count
+ 1
125 if float64_count
> 0:
126 # In embedded profile, if cl_khr_fp64 is supported cles_khr_int64 has to be
127 print("#ifdef cl_khr_fp64")
129 elif int64_count
> 0:
130 print("#if defined cles_khr_int64 || !defined(__EMBEDDED_PROFILE__)")
136 """/* !!!! AUTOGENERATED FILE generated by convert_type.py !!!!!
138 DON'T CHANGE THIS FILE. MAKE YOUR CHANGES TO convert_type.py AND RUN:
139 $ ./generate-conversion-type-cl.sh
141 OpenCL type conversion functions
143 Copyright (c) 2013 Victor Oliveira <victormatheus@gmail.com>
144 Copyright (c) 2013 Jesse Towner <jessetowner@lavabit.com>
146 Permission is hereby granted, free of charge, to any person obtaining a copy
147 of this software and associated documentation files (the "Software"), to deal
148 in the Software without restriction, including without limitation the rights
149 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
150 copies of the Software, and to permit persons to whom the Software is
151 furnished to do so, subject to the following conditions:
153 The above copyright notice and this permission notice shall be included in
154 all copies or substantial portions of the Software.
156 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
157 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
158 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
159 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
160 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
161 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
168 #pragma OPENCL EXTENSION cl_khr_fp64 : enable
170 #if defined(__EMBEDDED_PROFILE__) && !defined(cles_khr_int64)
171 #error Embedded profile that supports cl_khr_fp64 also has to support cles_khr_int64
176 #ifdef cles_khr_int64
177 #pragma OPENCL EXTENSION cles_khr_int64 : enable
184 # Default Conversions
186 # All conversions are in accordance with the OpenCL specification,
187 # which cites the C99 conversion rules.
189 # Casting from floating point to integer results in conversions
190 # with truncation, so it should be suitable for the default convert
193 # Conversions from integer to floating-point, and floating-point to
194 # floating-point through casting is done with the default rounding
195 # mode. While C99 allows dynamically changing the rounding mode
196 # during runtime, it is not a supported feature in OpenCL according
197 # to Section 7.1 - Rounding Modes in the OpenCL 1.2 specification.
199 # Therefore, we can assume for optimization purposes that the
200 # rounding mode is fixed to round-to-nearest-even. Platform target
201 # authors should ensure that the rounding-control registers remain
202 # in this state, and that this invariant holds.
204 # Also note, even though the OpenCL specification isn't entirely
205 # clear on this matter, we implement all rounding mode combinations
206 # even for integer-to-integer conversions. When such a conversion
207 # is used, the rounding mode is ignored.
211 def generate_default_conversion(src
, dst
, mode
):
212 close_conditional
= conditional_guard(src
, dst
)
216 """_CLC_DEF _CLC_OVERLOAD
217 {DST} convert_{DST}{M}({SRC} x)
222 SRC
=src
, DST
=dst
, M
=mode
226 # vector conversions, done through decomposition to components
227 for size
, half_size
in half_sizes
:
229 """_CLC_DEF _CLC_OVERLOAD
230 {DST}{N} convert_{DST}{N}{M}({SRC}{N} x)
232 return ({DST}{N})(convert_{DST}{H}(x.lo), convert_{DST}{H}(x.hi));
235 SRC
=src
, DST
=dst
, N
=size
, H
=half_size
, M
=mode
239 # 3-component vector conversions
241 """_CLC_DEF _CLC_OVERLOAD
242 {DST}3 convert_{DST}3{M}({SRC}3 x)
244 return ({DST}3)(convert_{DST}2(x.s01), convert_{DST}(x.s2));
246 SRC
=src
, DST
=dst
, M
=mode
250 if close_conditional
:
256 generate_default_conversion(src
, dst
, "")
258 for src
in int_types
:
259 for dst
in int_types
:
260 for mode
in rounding_modes
:
261 generate_default_conversion(src
, dst
, mode
)
264 # Saturated Conversions To Integers
266 # These functions are dependent on the unsaturated conversion functions
267 # generated above, and use clamp, max, min, and select to eliminate
268 # branching and vectorize the conversions.
270 # Again, as above, we allow all rounding modes for integer-to-integer
271 # conversions with saturation.
275 def generate_saturated_conversion(src
, dst
, size
):
277 close_conditional
= conditional_guard(src
, dst
)
279 """_CLC_DEF _CLC_OVERLOAD
280 {DST}{N} convert_{DST}{N}_sat({SRC}{N} x)
282 DST
=dst
, SRC
=src
, N
=size
286 # FIXME: This is a work around for lack of select function with
287 # signed third argument when the first two arguments are unsigned types.
288 # We cast to the signed type for sign-extension, then do a bitcast to
290 if dst
in unsigned_types
:
291 bool_prefix
= "as_{DST}{N}(convert_{BOOL}{N}".format(
292 DST
=dst
, BOOL
=bool_type
[dst
], N
=size
296 bool_prefix
= "convert_{BOOL}{N}".format(BOOL
=bool_type
[dst
], N
=size
)
302 # Conversion between same types
305 elif src
in float_types
:
307 # Conversion from float to int
309 """ {DST}{N} y = convert_{DST}{N}(x);
310 y = select(y, ({DST}{N}){DST_MIN}, {BP}(x < ({SRC}{N}){DST_MIN}){BS});
311 y = select(y, ({DST}{N}){DST_MAX}, {BP}(x > ({SRC}{N}){DST_MAX}){BS});
316 DST_MIN
=limit_min
[dst
],
317 DST_MAX
=limit_max
[dst
],
325 # Integer to integer convesion with sizeof(src) == sizeof(dst)
326 if sizeof_type
[src
] == sizeof_type
[dst
]:
327 if src
in unsigned_types
:
329 " x = min(x, ({SRC}){DST_MAX});".format(
330 SRC
=src
, DST_MAX
=limit_max
[dst
]
334 print(" x = max(x, ({SRC})0);".format(SRC
=src
))
336 # Integer to integer conversion where sizeof(src) > sizeof(dst)
337 elif sizeof_type
[src
] > sizeof_type
[dst
]:
338 if src
in unsigned_types
:
340 " x = min(x, ({SRC}){DST_MAX});".format(
341 SRC
=src
, DST_MAX
=limit_max
[dst
]
346 " x = clamp(x, ({SRC}){DST_MIN}, ({SRC}){DST_MAX});".format(
347 SRC
=src
, DST_MIN
=limit_min
[dst
], DST_MAX
=limit_max
[dst
]
351 # Integer to integer conversion where sizeof(src) < sizeof(dst)
352 elif src
not in unsigned_types
and dst
in unsigned_types
:
353 print(" x = max(x, ({SRC})0);".format(SRC
=src
))
355 print(" return convert_{DST}{N}(x);".format(DST
=dst
, N
=size
))
359 if close_conditional
:
364 for dst
in int_types
:
365 for size
in vector_sizes
:
366 generate_saturated_conversion(src
, dst
, size
)
369 def generate_saturated_conversion_with_rounding(src
, dst
, size
, mode
):
371 close_conditional
= conditional_guard(src
, dst
)
375 """_CLC_DEF _CLC_OVERLOAD
376 {DST}{N} convert_{DST}{N}_sat{M}({SRC}{N} x)
378 return convert_{DST}{N}_sat(x);
381 DST
=dst
, SRC
=src
, N
=size
, M
=mode
386 if close_conditional
:
390 for src
in int_types
:
391 for dst
in int_types
:
392 for size
in vector_sizes
:
393 for mode
in rounding_modes
:
394 generate_saturated_conversion_with_rounding(src
, dst
, size
, mode
)
397 # Conversions To/From Floating-Point With Rounding
399 # Note that we assume as above that casts from floating-point to
400 # integer are done with truncation, and that the default rounding
401 # mode is fixed to round-to-nearest-even, as per C99 and OpenCL
404 # These functions rely on the use of abs, ceil, fabs, floor,
405 # nextafter, sign, rint and the above generated conversion functions.
407 # Only conversions to integers can have saturation.
411 def generate_float_conversion(src
, dst
, size
, mode
, sat
):
413 close_conditional
= conditional_guard(src
, dst
)
415 """_CLC_DEF _CLC_OVERLOAD
416 {DST}{N} convert_{DST}{N}{S}{M}({SRC}{N} x)
418 SRC
=src
, DST
=dst
, N
=size
, M
=mode
, S
=sat
425 print(" x = rint(x);")
427 print(" x = ceil(x);")
429 print(" x = floor(x);")
430 print(" return convert_{DST}{N}{S}(x);".format(DST
=dst
, N
=size
, S
=sat
))
432 print(" return convert_{DST}{N}(x);".format(DST
=dst
, N
=size
))
434 print(" {DST}{N} r = convert_{DST}{N}(x);".format(DST
=dst
, N
=size
))
435 print(" {SRC}{N} y = convert_{SRC}{N}(r);".format(SRC
=src
, N
=size
))
439 " {USRC}{N} abs_x = abs(x);".format(
440 USRC
=unsigned_type
[src
], N
=size
444 " {USRC}{N} abs_y = abs(y);".format(
445 USRC
=unsigned_type
[src
], N
=size
449 print(" {SRC}{N} abs_x = fabs(x);".format(SRC
=src
, N
=size
))
450 print(" {SRC}{N} abs_y = fabs(y);".format(SRC
=src
, N
=size
))
452 " return select(r, nextafter(r, sign(r) * ({DST}{N})-INFINITY), convert_{BOOL}{N}(abs_y > abs_x));".format(
453 DST
=dst
, N
=size
, BOOL
=bool_type
[dst
]
458 " return select(r, nextafter(r, ({DST}{N})INFINITY), convert_{BOOL}{N}(y < x));".format(
459 DST
=dst
, N
=size
, BOOL
=bool_type
[dst
]
464 " return select(r, nextafter(r, ({DST}{N})-INFINITY), convert_{BOOL}{N}(y > x));".format(
465 DST
=dst
, N
=size
, BOOL
=bool_type
[dst
]
471 if close_conditional
:
475 for src
in float_types
:
476 for dst
in int_types
:
477 for size
in vector_sizes
:
478 for mode
in rounding_modes
:
479 for sat
in saturation
:
480 generate_float_conversion(src
, dst
, size
, mode
, sat
)
484 for dst
in float_types
:
485 for size
in vector_sizes
:
486 for mode
in rounding_modes
:
487 generate_float_conversion(src
, dst
, size
, mode
, "")