1use core::cmp::Ordering;
2use cubecl_common::*;
3use half::{bf16, f16};
4
5use cubecl_ir::{ExpandValue, dialect::cmp::*};
6
7use crate as cubecl;
8use crate::frontend::NativeExpand;
9use crate::ir::Scope;
10use crate::prelude::*;
11
12pub trait ScalarPartialEq: CubePartialEq + PartialEqNativeExpand {}
14impl<T: CubePartialEq + PartialEqNativeExpand> ScalarPartialEq for T {}
15
16pub trait CubePartialEq:
17 PartialEq
18 + CubePrimitive<Scalar: PartialEqNativeExpand>
19 + CubeType<ExpandType: PartialEqExpand>
20 + Sized
21 + IntoExpand<Expand = <Self as CubeType>::ExpandType>
22{
23 fn __expand_eq_method(&self, scope: &Scope, rhs: &NativeExpand<Self>) -> NativeExpand<bool> {
24 let this = (*self).into_expand(scope);
25 Self::__expand_eq(scope, &this, rhs)
26 }
27 fn __expand_ne_method(&self, scope: &Scope, rhs: &NativeExpand<Self>) -> NativeExpand<bool> {
28 let this = (*self).into_expand(scope);
29 Self::__expand_ne(scope, &this, rhs)
30 }
31
32 fn __expand_eq(
33 scope: &Scope,
34 lhs: &NativeExpand<Self>,
35 rhs: &NativeExpand<Self>,
36 ) -> NativeExpand<bool> {
37 lhs.__expand_eq_method(scope, rhs)
38 }
39 fn __expand_ne(
40 scope: &Scope,
41 lhs: &NativeExpand<Self>,
42 rhs: &NativeExpand<Self>,
43 ) -> NativeExpand<bool> {
44 lhs.__expand_ne_method(scope, rhs)
45 }
46}
47pub trait PartialEqExpand {
48 fn __expand_eq_method(&self, scope: &Scope, rhs: &Self) -> NativeExpand<bool>;
49 fn __expand_ne_method(&self, scope: &Scope, rhs: &Self) -> NativeExpand<bool>;
50}
51pub trait PartialEqNativeExpand {
52 fn __expand_native_eq(scope: &Scope, lhs: ExpandValue, rhs: ExpandValue) -> ExpandValue;
53 fn __expand_native_ne(scope: &Scope, lhs: ExpandValue, rhs: ExpandValue) -> ExpandValue;
54}
55
56impl<
57 T: PartialEq
58 + CubePrimitive<Scalar: PartialEqNativeExpand>
59 + IntoExpand<Expand = <Self as CubeType>::ExpandType>,
60> CubePartialEq for T
61{
62}
63
64impl<T: CubePartialEq> PartialEqExpand for NativeExpand<T> {
65 fn __expand_eq_method(&self, scope: &Scope, rhs: &Self) -> NativeExpand<bool> {
66 let this = self.__expand_deref_method(scope);
67 let rhs = rhs.__expand_deref_method(scope);
68 T::Scalar::__expand_native_eq(scope, this.expand, rhs.expand).into()
69 }
70 fn __expand_ne_method(&self, scope: &Scope, rhs: &Self) -> NativeExpand<bool> {
71 let this = self.__expand_deref_method(scope);
72 let rhs = rhs.__expand_deref_method(scope);
73 T::Scalar::__expand_native_ne(scope, this.expand, rhs.expand).into()
74 }
75}
76
77macro_rules! impl_partial_eq {
78 ($($ty: ty),*; $eq: ty, $ne: ty) => {
79 $(impl PartialEqNativeExpand for $ty {
80 fn __expand_native_eq(
81 scope: &Scope,
82 lhs: ExpandValue,
83 rhs: ExpandValue,
84 ) -> ExpandValue {
85 binary_expand(scope, lhs, rhs, <$eq>::new)
86 }
87 fn __expand_native_ne(
88 scope: &Scope,
89 lhs: ExpandValue,
90 rhs: ExpandValue,
91 ) -> ExpandValue {
92 binary_expand(scope, lhs, rhs, <$ne>::new)
93 }
94 })*
95 };
96}
97
98impl_partial_eq!(i8, i16, i32, i64, isize, u8, u16, u32, u64, usize; IEqualOp, INotEqualOp);
99impl_partial_eq!(f16, bf16, f32, flex32, tf32, f64; FEqualOp, FNotEqualOp);
100impl_partial_eq!(e2m1, e2m1x2, e3m2, e2m3, e4m3, e5m2, ue8m0; FEqualOp, FNotEqualOp);
101impl_partial_eq!(bool; BoolEqualOp, BoolNotEqualOp);
102
103#[derive_expand(CubeType, CubeTypeMut, IntoRuntime)]
104#[cube(runtime_variants, no_constructors)]
105pub enum Ordering {
106 Less = -1,
107 Equal = 0,
108 Greater = 1,
109}
110
111fn ordering_disc(name: &'static str) -> NativeExpand<i32> {
112 OrderingExpand::discriminant_of(name).into()
113}
114
115#[allow(non_snake_case)]
116pub trait CubeOrdering {
117 fn Less() -> Ordering {
118 Ordering::Less
119 }
120 fn Equal() -> Ordering {
121 Ordering::Equal
122 }
123 fn Greater() -> Ordering {
124 Ordering::Greater
125 }
126 fn __expand_Less(_scope: &Scope) -> OrderingExpand {
127 OrderingExpand {
128 discriminant: ordering_disc("Less"),
129 value: (),
130 }
131 }
132 fn __expand_Equal(_scope: &Scope) -> OrderingExpand {
133 OrderingExpand {
134 discriminant: ordering_disc("Equal"),
135 value: (),
136 }
137 }
138 fn __expand_Greater(_scope: &Scope) -> OrderingExpand {
139 OrderingExpand {
140 discriminant: ordering_disc("Greater"),
141 value: (),
142 }
143 }
144}
145
146impl CubeOrdering for Ordering {}
147
148pub trait ScalarOrd: CubeOrd + OrdNativeExpand {}
149impl<T: CubeOrd + OrdNativeExpand> ScalarOrd for T {}
150
151pub trait CubeOrd:
152 Ord
153 + CubePartialOrd
154 + CubeType<ExpandType: OrdExpand>
155 + CubePrimitive<Scalar: OrdNativeExpand>
156 + Sized
157 + IntoExpand<Expand = <Self as CubeType>::ExpandType>
158{
159 fn __expand_min_method(self, scope: &Scope, rhs: Self::ExpandType) -> Self::ExpandType {
160 let this = self.into_expand(scope);
161 Self::__expand_min(scope, this, rhs)
162 }
163 fn __expand_max_method(self, scope: &Scope, rhs: Self::ExpandType) -> Self::ExpandType {
164 let this = self.into_expand(scope);
165 Self::__expand_max(scope, this, rhs)
166 }
167 fn __expand_clamp_method(
168 self,
169 scope: &Scope,
170 min: Self::ExpandType,
171 max: Self::ExpandType,
172 ) -> Self::ExpandType {
173 let this = self.into_expand(scope);
174 Self::__expand_clamp(scope, this, min, max)
175 }
176
177 fn __expand_cmp(
178 scope: &Scope,
179 lhs: &Self::ExpandType,
180 rhs: &Self::ExpandType,
181 ) -> OrderingExpand {
182 lhs.__expand_cmp_method(scope, rhs)
183 }
184
185 fn __expand_min(
186 scope: &Scope,
187 lhs: Self::ExpandType,
188 rhs: Self::ExpandType,
189 ) -> Self::ExpandType {
190 lhs.__expand_min_method(scope, rhs)
191 }
192
193 fn __expand_max(
194 scope: &Scope,
195 lhs: Self::ExpandType,
196 rhs: Self::ExpandType,
197 ) -> Self::ExpandType {
198 lhs.__expand_max_method(scope, rhs)
199 }
200
201 fn __expand_clamp(
202 scope: &Scope,
203 lhs: Self::ExpandType,
204 min: Self::ExpandType,
205 max: Self::ExpandType,
206 ) -> Self::ExpandType {
207 lhs.__expand_clamp_method(scope, min, max)
208 }
209}
210pub trait OrdExpand {
211 fn __expand_cmp_method(&self, scope: &Scope, rhs: &Self) -> OrderingExpand;
212 fn __expand_min_method(self, scope: &Scope, rhs: Self) -> Self;
213 fn __expand_max_method(self, scope: &Scope, rhs: Self) -> Self;
214 fn __expand_clamp_method(self, scope: &Scope, min: Self, max: Self) -> Self;
215}
216pub trait OrdNativeExpand {
217 fn __expand_native_min(scope: &Scope, lhs: ExpandValue, rhs: ExpandValue) -> ExpandValue;
218 fn __expand_native_max(scope: &Scope, lhs: ExpandValue, rhs: ExpandValue) -> ExpandValue;
219 fn __expand_native_clamp(
220 scope: &Scope,
221 input: ExpandValue,
222 min: ExpandValue,
223 max: ExpandValue,
224 ) -> ExpandValue;
225}
226
227macro_rules! impl_ord {
228 ($($ty: ty),*; $min: ty, $max: ty, $clamp: ty) => {
229 $(impl OrdNativeExpand for $ty {
230 fn __expand_native_min(
231 scope: &Scope,
232 lhs: ExpandValue,
233 rhs: ExpandValue,
234 ) -> ExpandValue {
235 binary_expand(scope, lhs, rhs, <$min>::new)
236 }
237 fn __expand_native_max(
238 scope: &Scope,
239 lhs: ExpandValue,
240 rhs: ExpandValue,
241 ) -> ExpandValue {
242 binary_expand(scope, lhs, rhs, <$max>::new)
243 }
244 fn __expand_native_clamp(
245 scope: &Scope,
246 input: ExpandValue,
247 min: ExpandValue,
248 max: ExpandValue,
249 ) -> ExpandValue {
250 let input = input.read_value(scope);
251 let min = min.read_value(scope);
252 let max = max.read_value(scope);
253 let op = <$clamp>::new(scope.ctx_mut(), input, min, max);
254 scope.register_with_result(&op).into()
255 }
256 })*
257 };
258}
259
260impl_ord!(i8, i16, i32, i64, isize; SMinOp, SMaxOp, SClampOp);
261impl_ord!(u8, u16, u32, u64, usize; UMinOp, UMaxOp, UClampOp);
262impl_ord!(f16, bf16, f32, flex32, tf32, f64; FMinOp, FMaxOp, FClampOp);
263
264impl<
265 T: Ord
266 + CubePartialOrd
267 + CubePrimitive<Scalar: OrdNativeExpand>
268 + IntoExpand<Expand = <Self as CubeType>::ExpandType>,
269> CubeOrd for T
270{
271}
272impl<T: CubeOrd> OrdExpand for NativeExpand<T> {
273 fn __expand_cmp_method(&self, scope: &Scope, rhs: &Self) -> OrderingExpand {
274 let lhs_lt_rhs = self.__expand_lt_method(scope, rhs);
275 let lhs_gt_rhs = self.__expand_gt_method(scope, rhs);
276 let less = ordering_disc("Less");
277 let equal = ordering_disc("Equal");
278 let greater = ordering_disc("Greater");
279 let eq_or_gt = select::expand(scope, lhs_gt_rhs, greater, equal);
280 let discriminant = select::expand(scope, lhs_lt_rhs, less, eq_or_gt);
281 OrderingExpand {
282 discriminant,
283 value: (),
284 }
285 }
286 fn __expand_min_method(self, scope: &Scope, rhs: Self) -> Self {
287 min::expand(scope, self, rhs)
288 }
289 fn __expand_max_method(self, scope: &Scope, rhs: Self) -> Self {
290 max::expand(scope, self, rhs)
291 }
292 fn __expand_clamp_method(self, scope: &Scope, min: Self, max: Self) -> Self {
293 clamp::expand(scope, self, min, max)
294 }
295}
296
297pub trait ScalarPartialOrd: CubePartialOrd + PartialOrdNativeExpand + OrdNativeExpand {}
298impl<T: CubePartialOrd + PartialOrdNativeExpand + OrdNativeExpand> ScalarPartialOrd for T {}
299
300pub trait CubePartialOrd:
301 PartialOrd
302 + CubeType<ExpandType: PartialOrdExpand>
303 + CubePrimitive<Scalar: PartialOrdNativeExpand + OrdNativeExpand>
304 + Sized
305{
306 fn __expand_partial_cmp(
307 scope: &Scope,
308 lhs: &Self::ExpandType,
309 rhs: &Self::ExpandType,
310 ) -> OptionExpand<Ordering> {
311 lhs.__expand_partial_cmp_method(scope, rhs)
312 }
313
314 fn __expand_lt(
315 scope: &Scope,
316 lhs: &Self::ExpandType,
317 rhs: &Self::ExpandType,
318 ) -> NativeExpand<bool> {
319 lhs.__expand_lt_method(scope, rhs)
320 }
321
322 fn __expand_le(
323 scope: &Scope,
324 lhs: &Self::ExpandType,
325 rhs: &Self::ExpandType,
326 ) -> NativeExpand<bool> {
327 lhs.__expand_le_method(scope, rhs)
328 }
329
330 fn __expand_gt(
331 scope: &Scope,
332 lhs: &Self::ExpandType,
333 rhs: &Self::ExpandType,
334 ) -> NativeExpand<bool> {
335 lhs.__expand_gt_method(scope, rhs)
336 }
337
338 fn __expand_ge(
339 scope: &Scope,
340 lhs: &Self::ExpandType,
341 rhs: &Self::ExpandType,
342 ) -> NativeExpand<bool> {
343 lhs.__expand_ge_method(scope, rhs)
344 }
345}
346
347pub trait PartialOrdExpand {
348 fn __expand_partial_cmp_method(&self, scope: &Scope, rhs: &Self) -> OptionExpand<Ordering>;
349 fn __expand_lt_method(&self, scope: &Scope, rhs: &Self) -> NativeExpand<bool>;
350 fn __expand_le_method(&self, scope: &Scope, rhs: &Self) -> NativeExpand<bool>;
351 fn __expand_gt_method(&self, scope: &Scope, rhs: &Self) -> NativeExpand<bool>;
352 fn __expand_ge_method(&self, scope: &Scope, rhs: &Self) -> NativeExpand<bool>;
353}
354
355pub trait PartialOrdNativeExpand {
356 fn __expand_native_lt(scope: &Scope, lhs: ExpandValue, rhs: ExpandValue) -> ExpandValue;
357 fn __expand_native_le(scope: &Scope, lhs: ExpandValue, rhs: ExpandValue) -> ExpandValue;
358 fn __expand_native_gt(scope: &Scope, lhs: ExpandValue, rhs: ExpandValue) -> ExpandValue;
359 fn __expand_native_ge(scope: &Scope, lhs: ExpandValue, rhs: ExpandValue) -> ExpandValue;
360}
361
362macro_rules! impl_partial_ord {
363 ($($ty: ty),*; $lt: ty, $le: ty, $gt: ty, $ge: ty) => {
364 $(impl PartialOrdNativeExpand for $ty {
365 fn __expand_native_lt(
366 scope: &Scope,
367 lhs: ExpandValue,
368 rhs: ExpandValue,
369 ) -> ExpandValue {
370 binary_expand(scope, lhs, rhs, <$lt>::new)
371 }
372 fn __expand_native_le(
373 scope: &Scope,
374 lhs: ExpandValue,
375 rhs: ExpandValue,
376 ) -> ExpandValue {
377 binary_expand(scope, lhs, rhs, <$le>::new)
378 }
379 fn __expand_native_gt(
380 scope: &Scope,
381 lhs: ExpandValue,
382 rhs: ExpandValue,
383 ) -> ExpandValue {
384 binary_expand(scope, lhs, rhs, <$gt>::new)
385 }
386 fn __expand_native_ge(
387 scope: &Scope,
388 lhs: ExpandValue,
389 rhs: ExpandValue,
390 ) -> ExpandValue {
391 binary_expand(scope, lhs, rhs, <$ge>::new)
392 }
393 })*
394 };
395}
396
397impl_partial_ord!(i8, i16, i32, i64, isize; SLessThanOp, SLessThanOrEqualOp, SGreaterThanOp, SGreaterThanOrEqualOp);
398impl_partial_ord!(u8, u16, u32, u64, usize; ULessThanOp, ULessThanOrEqualOp, UGreaterThanOp, UGreaterThanOrEqualOp);
399impl_partial_ord!(f16, bf16, f32, flex32, tf32, f64; FLessThanOp, FLessThanOrEqualOp, FGreaterThanOp, FGreaterThanOrEqualOp);
400
401impl<T: PartialOrd + CubePrimitive<Scalar: PartialOrdNativeExpand + OrdNativeExpand>> CubePartialOrd
402 for T
403{
404}
405impl<T: CubePartialOrd> PartialOrdExpand for NativeExpand<T> {
406 fn __expand_partial_cmp_method(&self, scope: &Scope, rhs: &Self) -> OptionExpand<Ordering> {
407 let lhs_lt_rhs = self.__expand_lt_method(scope, rhs);
408 let lhs_gt_rhs = self.__expand_gt_method(scope, rhs);
409 let less = ordering_disc("Less");
410 let equal = ordering_disc("Equal");
411 let greater = ordering_disc("Greater");
412 let eq_or_gt = select::expand(scope, lhs_gt_rhs, greater, equal);
413 let discriminant = select::expand(scope, lhs_lt_rhs, less, eq_or_gt);
414 Option::__expand_new_Some(
415 scope,
416 OrderingExpand {
417 discriminant,
418 value: (),
419 },
420 )
421 }
422 fn __expand_lt_method(&self, scope: &Scope, rhs: &Self) -> NativeExpand<bool> {
423 let this = self.__expand_deref_method(scope);
424 let rhs = rhs.__expand_deref_method(scope);
425 T::Scalar::__expand_native_lt(scope, this.into(), rhs.into()).into()
426 }
427 fn __expand_le_method(&self, scope: &Scope, rhs: &Self) -> NativeExpand<bool> {
428 let this = self.__expand_deref_method(scope);
429 let rhs = rhs.__expand_deref_method(scope);
430 T::Scalar::__expand_native_le(scope, this.into(), rhs.into()).into()
431 }
432 fn __expand_gt_method(&self, scope: &Scope, rhs: &Self) -> NativeExpand<bool> {
433 let this = self.__expand_deref_method(scope);
434 let rhs = rhs.__expand_deref_method(scope);
435 T::Scalar::__expand_native_gt(scope, this.into(), rhs.into()).into()
436 }
437 fn __expand_ge_method(&self, scope: &Scope, rhs: &Self) -> NativeExpand<bool> {
438 let this = self.__expand_deref_method(scope);
439 let rhs = rhs.__expand_deref_method(scope);
440 T::Scalar::__expand_native_ge(scope, this.into(), rhs.into()).into()
441 }
442}