1use std::ops::Deref;
2
3use half::f16;
4use libc::size_t;
5
6use crate::{NumberType, NumberTypedT, NumberTypeKind};
7
8use crate::ffi::{
10 cl_bool, cl_char, cl_double, cl_float, cl_half, cl_int, cl_long, cl_uchar, cl_uint, cl_ulong,
11};
12
13use crate::ffi::{
15 cl_char16, cl_char2, cl_char3, cl_char4, cl_char8,
16 cl_float16, cl_float2, cl_float3, cl_float4, cl_float8, cl_int16, cl_int2,
17 cl_int3, cl_int4, cl_int8, cl_long16, cl_long2, cl_long3, cl_long4, cl_long8,
18 cl_short, cl_short16, cl_short2, cl_short3, cl_short4, cl_short8, cl_uchar16,
19 cl_uchar2, cl_uchar3, cl_uchar4, cl_uchar8, cl_uint16, cl_uint2, cl_uint3, cl_uint4,
20 cl_uint8, cl_ulong16, cl_ulong2, cl_ulong3, cl_ulong4, cl_ulong8, cl_ushort,
21 cl_ushort16, cl_ushort2, cl_ushort3, cl_ushort4, cl_ushort8,
22};
23
24pub unsafe trait ClNumber:
26 Sized + Clone + Copy + Send + Sync + 'static + Zeroed + NumberTypedT
27{
28}
29
30unsafe impl ClNumber for u8 {}
93unsafe impl ClNumber for i8 {}
94unsafe impl ClNumber for u16 {}
95unsafe impl ClNumber for i16 {}
96unsafe impl ClNumber for u32 {}
97unsafe impl ClNumber for i32 {}
98unsafe impl ClNumber for f32 {}
99unsafe impl ClNumber for u64 {}
100unsafe impl ClNumber for i64 {}
101unsafe impl ClNumber for f64 {}
102
103impl NumberTypedT for f64 {
104 fn number_type() -> NumberType {
105 NumberType::ClDouble
106 }
107}
108macro_rules! impl_deref {
115 ($new_t:ty => $t:ty) => {
116 impl Deref for $new_t {
117 type Target = $t;
118
119 fn deref(&self) -> &$t {
120 &self.0
121 }
122 }
123 }
124}
125
126const CL_BOOL_FALSE: cl_bool = 0;
127const CL_BOOL_TRUE: cl_bool = 1;
128
129impl Deref for ClBool {
130 type Target = cl_bool;
131
132 fn deref(&self) -> &cl_bool {
133 match self {
134 ClBool::True => &CL_BOOL_TRUE,
135 ClBool::False => &CL_BOOL_FALSE,
136 }
137 }
138}
139
140
141pub trait ToClNumber<T> {
200 fn to_cl_number(self) -> T;
201}
202
203pub trait FromClNumber<T> {
204 fn from_cl_number(value: T) -> Self;
205}
206
207pub trait Zeroed {
208 fn zeroed() -> Self;
209}
210
211impl ToClNumber<cl_bool> for bool {
212 fn to_cl_number(self) -> cl_bool {
213 match self {
214 true => 1,
215 false => 0,
216 }
217 }
218}
219
220impl ToClNumber<cl_bool> for ClBool {
221 fn to_cl_number(self) -> cl_bool {
222 match self {
223 ClBool::True => 1,
224 ClBool::False => 0,
225 }
226 }
227}
228
229impl FromClNumber<cl_bool> for bool {
230 fn from_cl_number(b: cl_bool) -> bool {
231 match b {
232 0 => false,
233 1 => true,
234 bad => panic!("Invalid cl_bool value {:?}: must be 0 or 1", bad),
235 }
236 }
237}
238
239impl FromClNumber<cl_bool> for ClBool {
240 fn from_cl_number(b: cl_bool) -> ClBool {
241 if bool::from_cl_number(b) {
242 ClBool::True
243 } else {
244 ClBool::False
245 }
246 }
247}
248
249impl_deref!(ClHalf => cl_half);
250
251impl ToClNumber<cl_half> for ClHalf {
252 fn to_cl_number(self) -> cl_half {
253 *self
254 }
255}
256
257impl FromClNumber<cl_half> for ClHalf {
258 fn from_cl_number(val: cl_half) -> ClHalf {
259 ClHalf(val)
260 }
261}
262
263impl FromClNumber<cl_half> for f16 {
264 fn from_cl_number(val: cl_half) -> f16 {
265 f16::from_bits(val)
266 }
267}
268
269macro_rules! impl_primitive_conversion {
270 ($t:ty, $new_t:ident, $rust_t:ty) => {
271 impl ToClNumber<$t> for $new_t {
272 fn to_cl_number(self) -> $t {
273 *self
274 }
275 }
276
277 impl FromClNumber<$t> for $new_t {
278 fn from_cl_number(val: $t) -> $new_t {
279 $new_t(val)
280 }
281 }
282
283 impl FromClNumber<$t> for $rust_t {
284 fn from_cl_number(val: $t) -> $rust_t {
285 val
286 }
287 }
288 }
289}
290
291pub enum ClBool {
293 True,
294 False,
295}
296pub struct ClDouble(cl_double);
302
303pub struct SizeT(size_t);
305
306pub struct ClHalf(cl_half);
308
309macro_rules! from_cl_number_inner_s {
310 ($t:ty, $new_t:ident, $rust_t:ty) => {
311 impl FromClNumber<$t> for $rust_t {
312 fn from_cl_number(num: $t) -> $rust_t {
313 unsafe { num.s }
314 }
315 }
316
317 impl ToClNumber<$t> for $rust_t {
318 fn to_cl_number(self) -> $t {
319 let mut num = unsafe { std::mem::zeroed::<$t>() };
320 num.s = self;
321 num
322 }
323 }
324
325 impl ToClNumber<$t> for $new_t {
326 fn to_cl_number(self) -> $t {
327 self.0
328 }
329 }
330
331 };
332}
333
334macro_rules! from_cl_number_inner_s3 {
335 ($t:ident, $new_t:ident, $rust_t:ident) => {
336 paste::item! {
337 impl FromClNumber<[<$t 3>]> for [$rust_t; 3] {
338 fn from_cl_number(num: [<$t 3>]) -> [$rust_t; 3] {
339 let inner = unsafe { num.s };
340 [inner[0], inner[1], inner[2]]
341 }
342 }
343
344 impl FromClNumber<[<$t 3>]> for [<$new_t 3>] {
345 fn from_cl_number(num: [<$t 3>]) -> [<$new_t 3>] {
346 [<$new_t 3>](num)
347 }
348 }
349
350 impl ToClNumber<[<$t 3>]> for [$rust_t; 3] {
351 fn to_cl_number(self) -> [<$t 3>] {
352 let mut num = unsafe { std::mem::zeroed::<[<$t 3>]>() };
353 let new_inner = [self[0], self[1], self[2], 0 as $t];
354 num.s = new_inner;
355 num
356 }
357 }
358
359 impl ToClNumber<[<$t 3>]> for [<$new_t 3>] {
360 fn to_cl_number(self) -> [<$t 3>] {
361 self.0
362 }
363 }
364 }
365 };
366}
367
368macro_rules! impl_number_typed_t {
369 ($snake:ident, $pascal:ident) => {
370 impl NumberTypedT for $snake {
371 fn number_type() -> NumberType {
372 NumberType::$pascal(NumberTypeKind::Primitive)
373 }
374 }
375
376 impl NumberTypedT for $pascal {
377 fn number_type() -> NumberType {
378 NumberType::$pascal(NumberTypeKind::Primitive)
379 }
380 }
381 };
382
383 ($snake:ident, $pascal:ident, $num:expr) => {
384 paste::item! {
385 impl NumberTypedT for [<$pascal $num>] {
386 fn number_type() -> NumberType {
387 NumberType::[<$pascal>](num_to_kind!($num))
388 }
389 }
390
391 impl NumberTypedT for [<$snake $num>] {
392 fn number_type() -> NumberType {
393 NumberType::[<$pascal>](num_to_kind!($num))
394 }
395 }
396 }
397 }
398}
399
400
401
402macro_rules! impl_zeroed_num_vector {
403 ($t:ident, $num:expr) => {
404 paste::item! {
405 impl Zeroed for [<$t $num>] {
406 fn zeroed() -> Self {
407 unsafe { std::mem::zeroed::<[<$t $num>]>() }
408 }
409 }
410 }
411 }
412}
413
414impl Zeroed for f64 {
415 fn zeroed() -> Self {
416 0.0 as f64
417 }
418}
419
420macro_rules! impl_zeroed_num {
421 ($t:ident) => {
422 impl Zeroed for $t {
423 fn zeroed() -> Self {
424 0 as $t
425 }
426 }
427
428 impl_zeroed_num_vector!($t, 2);
429 impl_zeroed_num_vector!($t, 4);
431 impl_zeroed_num_vector!($t, 8);
432 impl_zeroed_num_vector!($t, 16);
433 }
434}
435
436
437macro_rules! num_to_kind {
438 (1) => { $crate::NumberTypeKind::Primitive };
439 (2) => { $crate::NumberTypeKind::Two };
440 (3) => { $crate::NumberTypeKind::Three };
441 (4) => { $crate::NumberTypeKind::Four };
442 (8) => { $crate::NumberTypeKind::Eight };
443 (16) => { $crate::NumberTypeKind::Sixteen };
444}
445
446macro_rules! newtype_primitive_and_newtype_vectors {
447 ($t:ident, $new_t:ident, $rust_t:ident) => {
448 paste::item! {
449 pub struct $new_t($t);
450 pub struct [<$new_t 2>]([<$t 2>]);
452
453 pub struct [<$new_t 3>]([<$t 3>]);
455
456 pub struct [<$new_t 4>]([<$t 4>]);
458
459 pub struct [<$new_t 8>]([<$t 8>]);
461
462 pub struct [<$new_t 16>]([<$t 16>]);
464
465 unsafe impl ClNumber for [<$t 2>] {}
467 unsafe impl ClNumber for [<$t 4>] {}
468 unsafe impl ClNumber for [<$t 8>] {}
470 unsafe impl ClNumber for [<$t 16>] {}
471
472 impl_zeroed_num!($t);
473
474 impl_deref!($new_t => $t);
480 impl_deref!([<$new_t 2>] => [<$t 2>]);
481 impl_deref!([<$new_t 3>] => [<$t 3>]);
482 impl_deref!([<$new_t 4>] => [<$t 4>]);
483 impl_deref!([<$new_t 8>] => [<$t 8>]);
484 impl_deref!([<$new_t 16>] => [<$t 16>]);
485
486 impl_number_typed_t!($t, $new_t);
487 impl_number_typed_t!($t, $new_t, 2);
488 impl_number_typed_t!($t, $new_t, 4);
490 impl_number_typed_t!($t, $new_t, 8);
491 impl_number_typed_t!($t, $new_t, 16);
492
493 impl_primitive_conversion!($t, $new_t, $rust_t);
494 from_cl_number_inner_s!([<$t 2>], [<$new_t 2>], [$rust_t; 2]);
495 from_cl_number_inner_s!([<$t 4>], [<$new_t 4>], [$rust_t; 4]);
496 from_cl_number_inner_s!([<$t 8>], [<$new_t 8>], [$rust_t; 8]);
497 from_cl_number_inner_s!([<$t 16>], [<$new_t 16>], [$rust_t; 16]);
498 from_cl_number_inner_s3!($t, $new_t, $rust_t);
499 }
500 }
501}
502
503newtype_primitive_and_newtype_vectors!(cl_char, ClChar, i8);
504newtype_primitive_and_newtype_vectors!(cl_uchar, ClUchar, u8);
505newtype_primitive_and_newtype_vectors!(cl_short, ClShort, i16);
506newtype_primitive_and_newtype_vectors!(cl_ushort, ClUshort, u16);
507newtype_primitive_and_newtype_vectors!(cl_int, ClInt, i32);
508newtype_primitive_and_newtype_vectors!(cl_uint, ClUint, u32);
509newtype_primitive_and_newtype_vectors!(cl_long, ClLong, i64);
510newtype_primitive_and_newtype_vectors!(cl_ulong, ClUlong, u64);
511newtype_primitive_and_newtype_vectors!(cl_float, ClFloat, f32);