1use cubecl_common::{e2m1, e2m1x2, e4m3, e5m2, flex32, tf32, ue8m0};
2
3use crate::{
4 ir::{ElemType, FloatKind, IntKind, UIntKind},
5 prelude::{Numeric, Scalar},
6};
7
8pub trait CubeElement: core::fmt::Debug + Send + Sync + 'static + Clone + bytemuck::Pod {
10 fn type_name() -> &'static str;
12 fn as_bytes(slice: &[Self]) -> &[u8];
14 fn from_bytes(bytes: &[u8]) -> &[Self];
16 fn cube_type() -> ElemType;
18 fn maximum_value() -> Self;
20 fn minimum_value() -> Self;
22}
23
24pub trait ScalarArgType: CubeElement + Scalar + num_traits::NumCast {}
25
26impl<E: CubeElement + Scalar + num_traits::NumCast> ScalarArgType for E {}
27
28impl CubeElement for u64 {
29 fn type_name() -> &'static str {
30 "u64"
31 }
32 fn as_bytes(slice: &[Self]) -> &[u8] {
33 bytemuck::cast_slice(slice)
34 }
35 fn from_bytes(bytes: &[u8]) -> &[Self] {
36 bytemuck::cast_slice(bytes)
37 }
38 fn cube_type() -> ElemType {
39 ElemType::UInt(UIntKind::U64)
40 }
41 fn maximum_value() -> Self {
42 u64::MAX
43 }
44 fn minimum_value() -> Self {
45 u64::MIN
46 }
47}
48
49impl CubeElement for u32 {
50 fn type_name() -> &'static str {
51 "u32"
52 }
53 fn as_bytes(slice: &[Self]) -> &[u8] {
54 bytemuck::cast_slice(slice)
55 }
56 fn from_bytes(bytes: &[u8]) -> &[Self] {
57 bytemuck::cast_slice(bytes)
58 }
59 fn cube_type() -> ElemType {
60 ElemType::UInt(UIntKind::U32)
61 }
62 fn maximum_value() -> Self {
63 u32::MAX
64 }
65 fn minimum_value() -> Self {
66 u32::MIN
67 }
68}
69
70impl CubeElement for u16 {
71 fn type_name() -> &'static str {
72 "u16"
73 }
74 fn as_bytes(slice: &[Self]) -> &[u8] {
75 bytemuck::cast_slice(slice)
76 }
77 fn from_bytes(bytes: &[u8]) -> &[Self] {
78 bytemuck::cast_slice(bytes)
79 }
80 fn cube_type() -> ElemType {
81 ElemType::UInt(UIntKind::U16)
82 }
83 fn maximum_value() -> Self {
84 u16::MAX
85 }
86 fn minimum_value() -> Self {
87 u16::MIN
88 }
89}
90
91impl CubeElement for u8 {
92 fn type_name() -> &'static str {
93 "u8"
94 }
95 fn as_bytes(slice: &[Self]) -> &[u8] {
96 bytemuck::cast_slice(slice)
97 }
98 fn from_bytes(bytes: &[u8]) -> &[Self] {
99 bytemuck::cast_slice(bytes)
100 }
101 fn cube_type() -> ElemType {
102 ElemType::UInt(UIntKind::U8)
103 }
104 fn maximum_value() -> Self {
105 u8::MAX
106 }
107 fn minimum_value() -> Self {
108 u8::MIN
109 }
110}
111
112impl CubeElement for i64 {
113 fn type_name() -> &'static str {
114 "i64"
115 }
116 fn as_bytes(slice: &[Self]) -> &[u8] {
117 bytemuck::cast_slice(slice)
118 }
119 fn from_bytes(bytes: &[u8]) -> &[Self] {
120 bytemuck::cast_slice(bytes)
121 }
122 fn cube_type() -> ElemType {
123 ElemType::Int(IntKind::I64)
124 }
125 fn maximum_value() -> Self {
126 i64::MAX - 1
128 }
129 fn minimum_value() -> Self {
130 i64::MIN + 1
132 }
133}
134
135impl CubeElement for i32 {
136 fn type_name() -> &'static str {
137 "i32"
138 }
139 fn as_bytes(slice: &[Self]) -> &[u8] {
140 bytemuck::cast_slice(slice)
141 }
142 fn from_bytes(bytes: &[u8]) -> &[Self] {
143 bytemuck::cast_slice(bytes)
144 }
145 fn cube_type() -> ElemType {
146 ElemType::Int(IntKind::I32)
147 }
148 fn maximum_value() -> Self {
149 i32::MAX - 1
151 }
152 fn minimum_value() -> Self {
153 i32::MIN + 1
155 }
156}
157
158impl CubeElement for i16 {
159 fn type_name() -> &'static str {
160 "i16"
161 }
162 fn as_bytes(slice: &[Self]) -> &[u8] {
163 bytemuck::cast_slice(slice)
164 }
165 fn from_bytes(bytes: &[u8]) -> &[Self] {
166 bytemuck::cast_slice(bytes)
167 }
168 fn cube_type() -> ElemType {
169 ElemType::Int(IntKind::I16)
170 }
171 fn maximum_value() -> Self {
172 i16::MAX - 1
174 }
175 fn minimum_value() -> Self {
176 i16::MIN + 1
178 }
179}
180
181impl CubeElement for i8 {
182 fn type_name() -> &'static str {
183 "i8"
184 }
185 fn as_bytes(slice: &[Self]) -> &[u8] {
186 bytemuck::cast_slice(slice)
187 }
188 fn from_bytes(bytes: &[u8]) -> &[Self] {
189 bytemuck::cast_slice(bytes)
190 }
191 fn cube_type() -> ElemType {
192 ElemType::Int(IntKind::I8)
193 }
194 fn maximum_value() -> Self {
195 i8::MAX - 1
197 }
198 fn minimum_value() -> Self {
199 i8::MIN + 1
201 }
202}
203
204impl CubeElement for f64 {
205 fn type_name() -> &'static str {
206 "f64"
207 }
208 fn as_bytes(slice: &[Self]) -> &[u8] {
209 bytemuck::cast_slice(slice)
210 }
211 fn from_bytes(bytes: &[u8]) -> &[Self] {
212 bytemuck::cast_slice(bytes)
213 }
214 fn cube_type() -> ElemType {
215 ElemType::Float(FloatKind::F64)
216 }
217 fn maximum_value() -> Self {
218 f64::MAX
219 }
220 fn minimum_value() -> Self {
221 f64::MIN
222 }
223}
224
225impl CubeElement for f32 {
226 fn type_name() -> &'static str {
227 "f32"
228 }
229 fn as_bytes(slice: &[Self]) -> &[u8] {
230 bytemuck::cast_slice(slice)
231 }
232 fn from_bytes(bytes: &[u8]) -> &[Self] {
233 bytemuck::cast_slice(bytes)
234 }
235 fn cube_type() -> ElemType {
236 ElemType::Float(FloatKind::F32)
237 }
238 fn maximum_value() -> Self {
239 f32::MAX
240 }
241 fn minimum_value() -> Self {
242 f32::MIN
243 }
244}
245
246impl CubeElement for half::f16 {
247 fn type_name() -> &'static str {
248 "f16"
249 }
250 fn as_bytes(slice: &[Self]) -> &[u8] {
251 bytemuck::cast_slice(slice)
252 }
253 fn from_bytes(bytes: &[u8]) -> &[Self] {
254 bytemuck::cast_slice(bytes)
255 }
256 fn cube_type() -> ElemType {
257 ElemType::Float(FloatKind::F16)
258 }
259 fn maximum_value() -> Self {
260 half::f16::MAX
261 }
262 fn minimum_value() -> Self {
263 half::f16::MIN
264 }
265}
266
267impl CubeElement for half::bf16 {
268 fn type_name() -> &'static str {
269 "bf16"
270 }
271 fn as_bytes(slice: &[Self]) -> &[u8] {
272 bytemuck::cast_slice(slice)
273 }
274 fn from_bytes(bytes: &[u8]) -> &[Self] {
275 bytemuck::cast_slice(bytes)
276 }
277 fn cube_type() -> ElemType {
278 ElemType::Float(FloatKind::BF16)
279 }
280 fn maximum_value() -> Self {
281 half::bf16::MAX
282 }
283 fn minimum_value() -> Self {
284 half::bf16::MIN
285 }
286}
287
288impl CubeElement for flex32 {
289 fn type_name() -> &'static str {
290 "flex32"
291 }
292 fn as_bytes(slice: &[Self]) -> &[u8] {
293 bytemuck::cast_slice(slice)
294 }
295 fn from_bytes(bytes: &[u8]) -> &[Self] {
296 bytemuck::cast_slice(bytes)
297 }
298 fn cube_type() -> ElemType {
299 ElemType::Float(FloatKind::Flex32)
300 }
301 fn maximum_value() -> Self {
302 <flex32 as num_traits::Float>::max_value()
303 }
304 fn minimum_value() -> Self {
305 <flex32 as num_traits::Float>::min_value()
306 }
307}
308
309impl CubeElement for tf32 {
310 fn type_name() -> &'static str {
311 "tf32"
312 }
313
314 fn as_bytes(slice: &[Self]) -> &[u8] {
315 bytemuck::cast_slice(slice)
316 }
317
318 fn from_bytes(bytes: &[u8]) -> &[Self] {
319 bytemuck::cast_slice(bytes)
320 }
321
322 fn cube_type() -> ElemType {
323 ElemType::Float(FloatKind::TF32)
324 }
325
326 fn maximum_value() -> Self {
327 tf32::max_value()
328 }
329
330 fn minimum_value() -> Self {
331 tf32::min_value()
332 }
333}
334
335impl CubeElement for e4m3 {
336 fn type_name() -> &'static str {
337 "e4m3"
338 }
339
340 fn as_bytes(slice: &[Self]) -> &[u8] {
341 bytemuck::cast_slice(slice)
342 }
343
344 fn from_bytes(bytes: &[u8]) -> &[Self] {
345 bytemuck::cast_slice(bytes)
346 }
347
348 fn cube_type() -> ElemType {
349 ElemType::Float(FloatKind::E4M3)
350 }
351
352 fn maximum_value() -> Self {
353 e4m3::from_f64(e4m3::MAX.to_f64())
354 }
355
356 fn minimum_value() -> Self {
357 e4m3::from_f64(e4m3::MIN.to_f64())
358 }
359}
360
361impl CubeElement for e5m2 {
362 fn type_name() -> &'static str {
363 "e5m2"
364 }
365
366 fn as_bytes(slice: &[Self]) -> &[u8] {
367 bytemuck::cast_slice(slice)
368 }
369
370 fn from_bytes(bytes: &[u8]) -> &[Self] {
371 bytemuck::cast_slice(bytes)
372 }
373
374 fn cube_type() -> ElemType {
375 ElemType::Float(FloatKind::E5M2)
376 }
377
378 fn maximum_value() -> Self {
379 e5m2::from_f64(e5m2::MAX.to_f64())
380 }
381
382 fn minimum_value() -> Self {
383 e5m2::from_f64(e5m2::MIN.to_f64())
384 }
385}
386
387impl CubeElement for ue8m0 {
388 fn type_name() -> &'static str {
389 "ue8m0"
390 }
391
392 fn as_bytes(slice: &[Self]) -> &[u8] {
393 bytemuck::cast_slice(slice)
394 }
395
396 fn from_bytes(bytes: &[u8]) -> &[Self] {
397 bytemuck::cast_slice(bytes)
398 }
399
400 fn cube_type() -> ElemType {
401 ElemType::Float(FloatKind::UE8M0)
402 }
403
404 fn maximum_value() -> Self {
405 ue8m0::MAX
406 }
407
408 fn minimum_value() -> Self {
409 ue8m0::MIN
410 }
411}
412
413impl CubeElement for e2m1x2 {
414 fn type_name() -> &'static str {
415 "e2m1x2"
416 }
417
418 fn as_bytes(slice: &[Self]) -> &[u8] {
419 bytemuck::cast_slice(slice)
420 }
421
422 fn from_bytes(bytes: &[u8]) -> &[Self] {
423 bytemuck::cast_slice(bytes)
424 }
425
426 fn cube_type() -> ElemType {
427 ElemType::Float(FloatKind::E2M1x2)
428 }
429
430 fn maximum_value() -> Self {
431 let max = e2m1::MAX.to_bits();
432 e2m1x2::from_bits(max << 4 | max)
433 }
434
435 fn minimum_value() -> Self {
436 let min = e2m1::MIN.to_bits();
437 e2m1x2::from_bits(min << 4 | min)
438 }
439}