1use core::ops::{Neg, Not};
2use cubecl_common::{e2m1, e2m1x2, e4m3, e5m2, ue8m0};
3use cubecl_ir::{Bitwise, Comparison, Operator};
4use half::{bf16, f16};
5
6use crate::{
7 flex32,
8 ir::{Arithmetic, Scope, Value},
9 prelude::{
10 CubePrimitive, CubePrimitiveExpand, CubeType, IntoExpand, NativeExpand, Reinterpret,
11 },
12 tf32, unexpanded,
13};
14
15use super::base::{unary_expand, unary_expand_fixed_output};
16
17pub mod not {
18 use super::*;
19
20 pub fn expand<T: CubeNot>(scope: &Scope, x: NativeExpand<T>) -> NativeExpand<T> {
21 if x.expand.ty.is_bool() {
22 unary_expand(scope, x.into(), Operator::Not).into()
23 } else {
24 unary_expand(scope, x.into(), Bitwise::BitwiseNot).into()
25 }
26 }
27}
28
29macro_rules! impl_unary_func {
30 ($trait_name:ident, $method_name:ident, $operator:expr, $($type:ty),*) => {
31 paste::paste! {
32 pub trait $trait_name: CubePrimitive + CubeType<ExpandType: [<$trait_name Expand>]> + Sized {
33 #[allow(unused_variables)]
34 fn $method_name(self) -> Self {
35 unexpanded!()
36 }
37
38 fn [<__expand_ $method_name>](scope: &Scope, x: NativeExpand<Self>) -> NativeExpand<Self> {
39 x.[<__expand_ $method_name _method>](scope)
40 }
41 }
42
43 pub trait [<$trait_name Expand>] {
44 fn [<__expand_ $method_name _method>](self, scope: &Scope) -> Self;
45 }
46
47 $(impl $trait_name for $type {})*
48 impl<T: $trait_name + CubePrimitive> [<$trait_name Expand>] for NativeExpand<T> {
49 fn [<__expand_ $method_name _method>](self, scope: &Scope) -> Self {
50 unary_expand(scope, self.into(), $operator).into()
51 }
52 }
53 }
54 }
55}
56
57impl Exp for f32 {
58 fn exp(self) -> Self {
59 self.exp()
60 }
61}
62
63macro_rules! impl_unary_func_scalar_out {
64 ($trait_name:ident, $method_name:ident, $operator:expr, $($type:ty),*) => {
65 paste::paste! {
66 pub trait $trait_name: CubePrimitive
67 + CubeType<ExpandType: [<$trait_name Expand>]
68 + CubePrimitiveExpand<Scalar = NativeExpand<Self::Scalar>>>
69 + Sized {
70 #[allow(unused_variables)]
71 fn $method_name(self) -> Self::Scalar {
72 unexpanded!()
73 }
74
75 fn [<__expand_ $method_name>](scope: &Scope, x: NativeExpand<Self>) -> NativeExpand<Self::Scalar> {
76 x.[<__expand_ $method_name _method>](scope)
77 }
78 }
79
80 pub trait [<$trait_name Expand>]: CubePrimitiveExpand {
81 fn [<__expand_ $method_name _method>](self, scope: &Scope) -> Self::Scalar;
82 }
83
84 $(impl $trait_name for $type {})*
85 impl<T: $trait_name + CubePrimitive> [<$trait_name Expand>] for NativeExpand<T> {
86 fn [<__expand_ $method_name _method>](self, scope: &Scope) -> Self::Scalar {
87 let expand_element = self.expand;
88 let item = expand_element.value_type().with_vector_size(0);
89 unary_expand_fixed_output(scope, expand_element, item, $operator).into()
90 }
91 }
92 }
93 }
94}
95
96macro_rules! impl_unary_func_fixed_out_ty {
97 ($trait_name:ident, $method_name:ident, $out_ty: ty, $operator:expr, $($type:ty),*) => {
98 paste::paste! {
99 pub trait $trait_name: CubePrimitive + CubeType<ExpandType: [<$trait_name Expand>]
100 + CubePrimitiveExpand<WithScalar<$out_ty> = NativeExpand<Self::WithScalar<$out_ty>>>> + Sized {
101 #[allow(unused_variables, clippy::wrong_self_convention)]
102 fn $method_name(self) -> Self::WithScalar<$out_ty> {
103 unexpanded!()
104 }
105
106 fn [<__expand_ $method_name>](scope: &Scope, x: NativeExpand<Self>) -> NativeExpand<Self::WithScalar<$out_ty>> {
107 x.[<__expand_ $method_name _method>](scope)
108 }
109 }
110
111 pub trait [<$trait_name Expand>]: CubePrimitiveExpand {
112 fn [<__expand_ $method_name _method>](self, scope: &Scope) -> Self::WithScalar<$out_ty>;
113 }
114
115 $(impl $trait_name for $type {})*
116 impl<T: $trait_name + CubePrimitive> [<$trait_name Expand>] for NativeExpand<T> {
117 fn [<__expand_ $method_name _method>](self, scope: &Scope) -> Self::WithScalar<$out_ty> {
118 let expand_element: Value = self.into();
119 let item = <$out_ty as CubePrimitive>::__expand_as_type(scope).with_vector_size(expand_element.ty.vector_size());
120 unary_expand_fixed_output(scope, expand_element, item, $operator).into()
121 }
122 }
123 }
124 }
125}
126
127macro_rules! impl_not {
129 ($trait_name:ident, $method_name:ident, $($type:ty),*) => {
130 paste::paste! {
131 pub trait [<Cube $trait_name>]:
132 $trait_name<Output = Self>
133 + CubePrimitive
134 + CubeType<ExpandType: [<$trait_name Expand>]>
135 + IntoExpand<Expand = <Self as CubeType>::ExpandType> {
136 fn [<__expand_ $method_name _method>](self, scope: &Scope) -> NativeExpand<Self> {
137 let this = self.into_expand(scope);
138 this.[<__expand_ $method_name _method>](scope)
139 }
140
141 fn [<__expand_ $method_name>](scope: &Scope, x: NativeExpand<Self>) -> NativeExpand<Self> {
142 x.[<__expand_ $method_name _method>](scope)
143 }
144 }
145
146 pub trait [<$trait_name Expand>] {
147 fn [<__expand_ $method_name _method>](self, scope: &Scope) -> Self;
148 }
149
150 $(impl [<Cube $trait_name>] for $type {})*
151 impl<T: [<Cube $trait_name>] + CubePrimitive> [<$trait_name Expand>] for NativeExpand<T> {
152 fn [<__expand_ $method_name _method>](self, scope: &Scope) -> Self {
153 not::expand(scope, self.into())
154 }
155 }
156 }
157 }
158}
159
160macro_rules! impl_core_unop {
161 ($trait: ident, $method: ident, $op: expr) => {
162 paste::paste! {
163 pub trait [<Cube $trait>]: $trait<Output = Self> + CubePrimitive + Into<Value> + CubeType<ExpandType: [<$trait Expand>]> + Sized {
164 fn [<__expand_ $method _method>](self, scope: &Scope) -> NativeExpand<Self> {
165 let this: Value = self.into();
166 let this: NativeExpand<Self> = this.into();
167 this.[<__expand_ $method _method>](scope)
168 }
169
170 fn [<__expand_ $method>](
171 scope: &Scope,
172 lhs: NativeExpand<Self>,
173 ) -> NativeExpand<Self> {
174 lhs.[<__expand_ $method _method>](scope)
175 }
176 }
177
178 pub trait [<$trait Expand>] {
179 fn [<__expand_ $method _method>](self, scope: &Scope) -> Self;
180 }
181
182 impl<T: $trait<Output = T> + CubePrimitive + Into<Value>> [<Cube $trait>] for T {}
183 impl<T: $trait<Output = T> + CubePrimitive> [<$trait Expand>] for NativeExpand<T> {
184 fn [<__expand_ $method _method>](self, scope: &Scope) -> Self {
185 unary_expand(scope, self.into(), $op).into()
186 }
187 }
188 }
189 };
190}
191
192impl_not!(
193 Not, not, bool, u8, u16, u32, u64, i8, i16, i32, i64, isize, usize
194);
195
196impl_core_unop!(Neg, neg, Arithmetic::Neg);
197
198impl_unary_func!(
199 Abs,
200 abs,
201 Arithmetic::Abs,
202 e2m1,
203 e4m3,
204 e5m2,
205 ue8m0,
206 f16,
207 bf16,
208 flex32,
209 tf32,
210 f32,
211 f64,
212 i8,
213 i16,
214 i32,
215 i64,
216 u8,
217 u16,
218 u32,
219 u64,
220 usize,
221 isize
222);
223impl_unary_func!(
224 Exp,
225 exp,
226 Arithmetic::Exp,
227 f16,
228 bf16,
229 flex32,
230 tf32,
231 f64
233);
234impl_unary_func!(Log, ln, Arithmetic::Log, f16, bf16, flex32, tf32, f32, f64);
235impl_unary_func!(
236 Log1p,
237 log1p,
238 Arithmetic::Log1p,
239 f16,
240 bf16,
241 flex32,
242 tf32,
243 f32,
244 f64
245);
246impl_unary_func!(
247 Expm1,
248 exp_m1,
249 Arithmetic::Expm1,
250 f16,
251 bf16,
252 flex32,
253 tf32,
254 f32,
255 f64
256);
257impl_unary_func!(Cos, cos, Arithmetic::Cos, f16, bf16, flex32, tf32, f32, f64);
258impl_unary_func!(Sin, sin, Arithmetic::Sin, f16, bf16, flex32, tf32, f32, f64);
259impl_unary_func!(Tan, tan, Arithmetic::Tan, f16, bf16, flex32, tf32, f32, f64);
260impl_unary_func!(
261 Tanh,
262 tanh,
263 Arithmetic::Tanh,
264 f16,
265 bf16,
266 flex32,
267 tf32,
268 f32,
269 f64
270);
271impl_unary_func!(
272 Sinh,
273 sinh,
274 Arithmetic::Sinh,
275 f16,
276 bf16,
277 flex32,
278 tf32,
279 f32,
280 f64
281);
282impl_unary_func!(
283 Cosh,
284 cosh,
285 Arithmetic::Cosh,
286 f16,
287 bf16,
288 flex32,
289 tf32,
290 f32,
291 f64
292);
293impl_unary_func!(
294 ArcCos,
295 acos,
296 Arithmetic::ArcCos,
297 f16,
298 bf16,
299 flex32,
300 tf32,
301 f32,
302 f64
303);
304impl_unary_func!(
305 ArcSin,
306 asin,
307 Arithmetic::ArcSin,
308 f16,
309 bf16,
310 flex32,
311 tf32,
312 f32,
313 f64
314);
315impl_unary_func!(
316 ArcTan,
317 atan,
318 Arithmetic::ArcTan,
319 f16,
320 bf16,
321 flex32,
322 tf32,
323 f32,
324 f64
325);
326impl_unary_func!(
327 ArcSinh,
328 asinh,
329 Arithmetic::ArcSinh,
330 f16,
331 bf16,
332 flex32,
333 tf32,
334 f32,
335 f64
336);
337impl_unary_func!(
338 ArcCosh,
339 acosh,
340 Arithmetic::ArcCosh,
341 f16,
342 bf16,
343 flex32,
344 tf32,
345 f32,
346 f64
347);
348impl_unary_func!(
349 ArcTanh,
350 atanh,
351 Arithmetic::ArcTanh,
352 f16,
353 bf16,
354 flex32,
355 tf32,
356 f32,
357 f64
358);
359impl_unary_func!(
360 Degrees,
361 to_degrees,
362 Arithmetic::Degrees,
363 f16,
364 bf16,
365 flex32,
366 tf32,
367 f32,
368 f64
369);
370impl_unary_func!(
371 Radians,
372 to_radians,
373 Arithmetic::Radians,
374 f16,
375 bf16,
376 flex32,
377 tf32,
378 f32,
379 f64
380);
381impl_unary_func!(
382 Sqrt,
383 sqrt,
384 Arithmetic::Sqrt,
385 f16,
386 bf16,
387 flex32,
388 tf32,
389 f32,
390 f64
391);
392impl_unary_func!(
393 InverseSqrt,
394 inverse_sqrt,
395 Arithmetic::InverseSqrt,
396 f16,
397 bf16,
398 flex32,
399 tf32,
400 f32,
401 f64
402);
403impl_unary_func!(
404 Round,
405 round,
406 Arithmetic::Round,
407 f16,
408 bf16,
409 flex32,
410 tf32,
411 f32,
412 f64
413);
414impl_unary_func!(
415 Floor,
416 floor,
417 Arithmetic::Floor,
418 f16,
419 bf16,
420 flex32,
421 tf32,
422 f32,
423 f64
424);
425impl_unary_func!(
426 Ceil,
427 ceil,
428 Arithmetic::Ceil,
429 f16,
430 bf16,
431 flex32,
432 tf32,
433 f32,
434 f64
435);
436impl_unary_func!(
437 Trunc,
438 trunc,
439 Arithmetic::Trunc,
440 f16,
441 bf16,
442 flex32,
443 tf32,
444 f32,
445 f64
446);
447impl_unary_func!(Erf, erf, Arithmetic::Erf, f16, bf16, flex32, tf32, f32, f64);
448impl_unary_func!(
449 Recip,
450 recip,
451 Arithmetic::Recip,
452 f16,
453 bf16,
454 flex32,
455 tf32,
456 f32,
457 f64
458);
459impl_unary_func_scalar_out!(
460 Magnitude,
461 magnitude,
462 Arithmetic::Magnitude,
463 f16,
464 bf16,
465 flex32,
466 tf32,
467 f32,
468 f64
469);
470impl_unary_func_scalar_out!(
471 VectorSum,
472 vector_sum,
473 Arithmetic::VectorSum,
474 e2m1,
475 e4m3,
476 e5m2,
477 ue8m0,
478 f16,
479 bf16,
480 flex32,
481 tf32,
482 f32,
483 f64,
484 i8,
485 i16,
486 i32,
487 i64,
488 u8,
489 u16,
490 u32,
491 u64,
492 usize,
493 isize
494);
495impl_unary_func!(
496 Normalize,
497 normalize,
498 Arithmetic::Normalize,
499 f16,
500 bf16,
501 flex32,
502 tf32,
503 f32,
504 f64
505);
506impl_unary_func_fixed_out_ty!(
507 CountOnes,
508 count_ones,
509 u32,
510 Bitwise::CountOnes,
511 u8,
512 i8,
513 u16,
514 i16,
515 u32,
516 i32,
517 u64,
518 i64,
519 usize,
520 isize
521);
522impl_unary_func!(
523 ReverseBits,
524 reverse_bits,
525 Bitwise::ReverseBits,
526 u8,
527 i8,
528 u16,
529 i16,
530 u32,
531 i32,
532 u64,
533 i64,
534 usize,
535 isize
536);
537
538impl_unary_func_fixed_out_ty!(
539 LeadingZeros,
540 leading_zeros,
541 u32,
542 Bitwise::LeadingZeros,
543 u8,
544 i8,
545 u16,
546 i16,
547 u32,
548 i32,
549 u64,
550 i64,
551 usize,
552 isize
553);
554impl_unary_func_fixed_out_ty!(
555 TrailingZeros,
556 trailing_zeros,
557 u32,
558 Bitwise::TrailingZeros,
559 u8,
560 i8,
561 u16,
562 i16,
563 u32,
564 i32,
565 u64,
566 i64,
567 usize,
568 isize
569);
570impl_unary_func_fixed_out_ty!(
571 FindFirstSet,
572 find_first_set,
573 u32,
574 Bitwise::FindFirstSet,
575 u8,
576 i8,
577 u16,
578 i16,
579 u32,
580 i32,
581 u64,
582 i64,
583 usize,
584 isize
585);
586impl_unary_func_fixed_out_ty!(
587 IsNan,
588 is_nan,
589 bool,
590 Comparison::IsNan,
591 f16,
592 bf16,
593 flex32,
594 tf32,
595 f32,
596 f64
597);
598impl_unary_func_fixed_out_ty!(
599 IsInf,
600 is_inf,
601 bool,
602 Comparison::IsInf,
603 f16,
604 bf16,
605 flex32,
606 tf32,
607 f32,
608 f64
609);
610
611pub trait FloatBits:
612 CubePrimitive + CubeType<ExpandType: FloatBitsExpand<Bits = Self::Bits>>
613{
614 type Bits: CubePrimitive;
615
616 fn __expand_from_bits(scope: &Scope, bits: NativeExpand<Self::Bits>) -> NativeExpand<Self> {
617 Self::__expand_reinterpret(scope, bits)
618 }
619
620 fn __expand_to_bits(scope: &Scope, this: NativeExpand<Self>) -> NativeExpand<Self::Bits> {
621 <Self::Bits as Reinterpret>::__expand_reinterpret(scope, this)
622 }
623}
624
625pub trait FloatBitsExpand: Sized {
626 type Bits: CubePrimitive;
627
628 fn __expand_to_bits_method(self, scope: &Scope) -> NativeExpand<Self::Bits>;
629}
630
631impl<F: FloatBits> FloatBitsExpand for NativeExpand<F> {
632 type Bits = F::Bits;
633
634 fn __expand_to_bits_method(self, scope: &Scope) -> NativeExpand<Self::Bits> {
635 <Self::Bits as Reinterpret>::__expand_reinterpret(scope, self)
636 }
637}
638
639impl FloatBits for e2m1x2 {
640 type Bits = u8;
641}
642
643impl FloatBits for e5m2 {
644 type Bits = u8;
645}
646
647impl FloatBits for e4m3 {
648 type Bits = u8;
649}
650
651impl FloatBits for f16 {
652 type Bits = u16;
653}
654
655impl FloatBits for bf16 {
656 type Bits = u16;
657}
658
659impl FloatBits for f32 {
660 type Bits = u32;
661}
662
663impl FloatBits for f64 {
664 type Bits = u64;
665}