open_cl_low_level/
cl_number.rs

1use std::ops::Deref;
2
3use half::f16;
4use libc::size_t;
5
6use crate::{NumberType, NumberTypedT, NumberTypeKind};
7
8// primitive types
9use 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
13// vector types
14use 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
24// NOTE: f32 does not implement Eq so it's not here. WHYEEEEE...
25pub unsafe trait ClNumber:
26    Sized + Clone + Copy + Send + Sync + 'static + Zeroed + NumberTypedT
27{
28}
29
30// pub trait TypeName {
31//     fn type_name(&self) -> String;
32// }
33
34// macro_rules! impl_type_name {
35//     ($t:ident) => {
36//         paste::item! {
37//             const [<TYPE_NAME_ $t>]: &'static str = stringify!($t);
38//             impl TypeName for $t {
39//                 fn type_name(&self) -> &'static str {
40//                     [<TYPE_NAME_ $t>]
41//                 }
42//             }
43//         }
44        
45//     }
46// }
47
48// impl_type_name!(cl_char);
49// impl_type_name!(cl_uchar);
50// impl_type_name!(cl_short);
51// impl_type_name!(cl_ushort);
52// impl_type_name!(cl_int);
53// impl_type_name!(cl_uint);
54// impl_type_name!(cl_long);
55// impl_type_name!(cl_ulong);
56// impl_type_name!(cl_half);
57// impl_type_name!(cl_float);
58// impl_type_name!(cl_double);
59// impl_type_name!(size_t);
60
61// #[macro_use]
62// macro_rules! impl_type_name_vector {
63//     ($t:ident) => {
64//         paste::item! {
65//             impl_type_name!([<$t 2>]);
66//             // impl_type_name!([<$t 3>]);
67//             impl_type_name!([<$t 4>]);
68//             impl_type_name!([<$t 8>]);
69//             impl_type_name!([<$t 16>]);
70//         }
71//     }
72// }
73
74
75
76// impl_type_name_vector!(cl_char);
77// impl_type_name_vector!(cl_uchar);
78// impl_type_name_vector!(cl_short);
79// impl_type_name_vector!(cl_ushort);
80// impl_type_name_vector!(cl_int);
81// impl_type_name_vector!(cl_uint);
82// impl_type_name_vector!(cl_long);
83// impl_type_name_vector!(cl_ulong);
84// impl_type_name_vector!(cl_float);
85
86// impl_type_name_vector!(cl_half);
87// impl_type_name_vector!(cl_double);
88// impl_type_name_vector!(size_t);
89
90
91//8
92unsafe 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}
108// unsafe impl ClNumber for Complex64 {}
109//size
110// unsafe impl ClNumber for isize {}
111// unsafe impl ClNumber for usize {}
112
113
114macro_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
141// impl_deref!(ClChar => cl_char);
142// impl_deref!(ClUchar => cl_uchar);
143// impl_deref!(ClShort => cl_short);
144// impl_deref!(ClUshort => cl_ushort);
145// impl_deref!(ClInt => cl_int);
146// impl_deref!(ClUint => cl_uint);
147// impl_deref!(ClLong => cl_long);
148// impl_deref!(ClUlong => cl_ulong);
149// impl_deref!(ClHalf => cl_half);
150// impl_deref!(ClFloat => cl_float);
151// impl_deref!(ClDouble => cl_double);
152// impl_deref!(SizeT => size_t);
153// impl_deref!(ClChar2 => cl_char2);
154// impl_deref!(ClUchar2 => cl_uchar2);
155// impl_deref!(ClShort2 => cl_short2);
156// impl_deref!(ClUshort2 => cl_ushort2);
157// impl_deref!(ClInt2 => cl_int2);
158// impl_deref!(ClUint2 => cl_uint2);
159// impl_deref!(ClLong2 => cl_long2);
160// impl_deref!(ClUlong2 => cl_ulong2);
161// impl_deref!(ClFloat2 => cl_float2);
162// impl_deref!(ClChar3 => cl_char3);
163// impl_deref!(ClUchar3 => cl_uchar3);
164// impl_deref!(ClShort3 => cl_short3);
165// impl_deref!(ClUshort3 => cl_ushort3);
166// impl_deref!(ClInt3 => cl_int3);
167// impl_deref!(ClUint3 => cl_uint3);
168// impl_deref!(ClLong3 => cl_long3);
169// impl_deref!(ClUlong3 => cl_ulong3);
170// impl_deref!(ClFloat3 => cl_float3);
171// impl_deref!(ClChar4 => cl_char4);
172// impl_deref!(ClUchar4 => cl_uchar4);
173// impl_deref!(ClShort4 => cl_short4);
174// impl_deref!(ClUshort4 => cl_ushort4);
175// impl_deref!(ClInt4 => cl_int4);
176// impl_deref!(ClUint4 => cl_uint4);
177// impl_deref!(ClLong4 => cl_long4);
178// impl_deref!(ClUlong4 => cl_ulong4);
179// impl_deref!(ClFloat4 => cl_float4);
180// impl_deref!(ClChar8 => cl_char8);
181// impl_deref!(ClUchar8 => cl_uchar8);
182// impl_deref!(ClShort8 => cl_short8);
183// impl_deref!(ClUshort8 => cl_ushort8);
184// impl_deref!(ClInt8 => cl_int8);
185// impl_deref!(ClUint8 => cl_uint8);
186// impl_deref!(ClLong8 => cl_long8);
187// impl_deref!(ClUlong8 => cl_ulong8);
188// impl_deref!(ClFloat8 => cl_float8);
189// impl_deref!(ClChar16 => cl_char16);
190// impl_deref!(ClUchar16 => cl_uchar16);
191// impl_deref!(ClShort16 => cl_short16);
192// impl_deref!(ClUshort16 => cl_ushort16);
193// impl_deref!(ClInt16 => cl_int16);
194// impl_deref!(ClUint16 => cl_uint16);
195// impl_deref!(ClLong16 => cl_long16);
196// impl_deref!(ClUlong16 => cl_ulong16);
197// impl_deref!(ClFloat16 => cl_float16);
198
199pub 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
291/// A Boolean condition: true (1) or false (0)
292pub enum ClBool {
293    True,
294    False,
295}
296/// Signed two’s complement 8-bit integer
297/// 64-bit floating-point value.
298/// May not be available on some platforms.
299/// Check availability with FFI call to `clGetDeviceInfo` or `device.extensions()`
300/// Enable in kernels with `#pragma OPENCL EXTENSION cl_khr_fp64 : enable`
301pub struct ClDouble(cl_double);
302
303/// Unsigned integer produced by the size of operator
304pub struct SizeT(size_t);
305
306// /// 16-bit floating-point value, IEEE-754-2008 conformant
307pub 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, 3);
430        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            /// Vector containing 2 $rust_t
451            pub struct [<$new_t 2>]([<$t 2>]);
452            
453            /// Vector containing 3 $rust_t
454            pub struct [<$new_t 3>]([<$t 3>]);
455            
456            /// Vector containing 4 $rust_t
457            pub struct [<$new_t 4>]([<$t 4>]);
458
459            /// Vector containing 8 $rust_t
460            pub struct [<$new_t 8>]([<$t 8>]);
461
462            /// Vector containing 16 $rust_t
463            pub struct [<$new_t 16>]([<$t 16>]);
464
465            // unsafe impl ClNumber for $t {}
466            unsafe impl ClNumber for [<$t 2>] {}
467            unsafe impl ClNumber for [<$t 4>] {}
468            // unsafe impl ClNumber for [<$t 3>] {}
469            unsafe impl ClNumber for [<$t 8>] {}
470            unsafe impl ClNumber for [<$t 16>] {}
471
472            impl_zeroed_num!($t);
473
474            // impl_type_name!([<$t 2>]);
475            // impl_type_name!([<$t 4>]);
476            // impl_type_name!([<$t 8>]);
477            // impl_type_name!([<$t 16>]);
478
479            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, 3);
489            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);