1use crate::proc::overloads::any_overload_set::AnyOverloadSet;
4use crate::proc::overloads::list::List;
5use crate::proc::overloads::regular::regular;
6use crate::proc::overloads::utils::{
7 float_scalars, float_scalars_unimplemented_abstract, list, pairs, rule, scalar_or_vecn, triples,
8};
9use crate::proc::overloads::OverloadSet;
10use crate::proc::type_methods::{concrete_int_scalars, vector_sizes};
11
12use crate::ir;
13
14impl ir::MathFunction {
15 pub fn overloads(self) -> impl OverloadSet {
16 use ir::MathFunction as Mf;
17
18 let set: AnyOverloadSet = match self {
19 Mf::Abs => regular!(1, SCALAR|VECN of NUMERIC).into(),
21 Mf::Sign => regular!(1, SCALAR|VECN of SIGNED_NUMERIC).into(),
22
23 Mf::Min | Mf::Max => regular!(2, SCALAR|VECN of NUMERIC).into(),
25
26 Mf::Clamp => regular!(3, SCALAR|VECN of NUMERIC).into(),
28
29 Mf::Sin
31 | Mf::Cos
32 | Mf::Tan
33 | Mf::Asin
34 | Mf::Acos
35 | Mf::Atan
36 | Mf::Sinh
37 | Mf::Cosh
38 | Mf::Tanh
39 | Mf::Asinh
40 | Mf::Acosh
41 | Mf::Atanh
42 | Mf::Saturate
43 | Mf::Radians
44 | Mf::Degrees
45 | Mf::Ceil
46 | Mf::Floor
47 | Mf::Round
48 | Mf::Fract
49 | Mf::Trunc
50 | Mf::Exp
51 | Mf::Exp2
52 | Mf::Log
53 | Mf::Log2
54 | Mf::Sqrt
55 | Mf::InverseSqrt => regular!(1, SCALAR|VECN of FLOAT).into(),
56
57 Mf::Atan2 | Mf::Pow | Mf::Step => regular!(2, SCALAR|VECN of FLOAT).into(),
59
60 Mf::Fma | Mf::SmoothStep => regular!(3, SCALAR|VECN of FLOAT).into(),
62
63 Mf::CountTrailingZeros
65 | Mf::CountLeadingZeros
66 | Mf::CountOneBits
67 | Mf::ReverseBits
68 | Mf::FirstTrailingBit
69 | Mf::FirstLeadingBit => regular!(1, SCALAR|VECN of CONCRETE_INTEGER).into(),
70
71 Mf::Pack4x8snorm | Mf::Pack4x8unorm => regular!(1, VEC4 of F32 -> U32).into(),
73 Mf::Pack2x16snorm | Mf::Pack2x16unorm | Mf::Pack2x16float => {
74 regular!(1, VEC2 of F32 -> U32).into()
75 }
76 Mf::Pack4xI8 => regular!(1, VEC4 of I32 -> U32).into(),
77 Mf::Pack4xU8 => regular!(1, VEC4 of U32 -> U32).into(),
78 Mf::Pack4xI8Clamp => regular!(1, VEC4 of I32 -> U32).into(),
79 Mf::Pack4xU8Clamp => regular!(1, VEC4 of U32 -> U32).into(),
80
81 Mf::Unpack4x8snorm | Mf::Unpack4x8unorm => regular!(1, SCALAR of U32 -> Vec4F).into(),
83 Mf::Unpack2x16snorm | Mf::Unpack2x16unorm | Mf::Unpack2x16float => {
84 regular!(1, SCALAR of U32 -> Vec2F).into()
85 }
86 Mf::Unpack4xI8 => regular!(1, SCALAR of U32 -> Vec4I).into(),
87 Mf::Unpack4xU8 => regular!(1, SCALAR of U32 -> Vec4U).into(),
88 Mf::Dot4I8Packed => regular!(2, SCALAR of U32 -> I32).into(),
89 Mf::Dot4U8Packed => regular!(2, SCALAR of U32 -> U32).into(),
90
91 Mf::Dot => regular!(2, VECN of NUMERIC -> Scalar).into(),
93 Mf::Modf => regular!(1, SCALAR|VECN of FLOAT_ABSTRACT_UNIMPLEMENTED -> Modf).into(),
94 Mf::Frexp => regular!(1, SCALAR|VECN of FLOAT_ABSTRACT_UNIMPLEMENTED -> Frexp).into(),
95 Mf::Ldexp => ldexp().into(),
96 Mf::Outer => outer().into(),
97 Mf::Cross => regular!(2, VEC3 of FLOAT).into(),
98 Mf::Distance => {
99 regular!(2, SCALAR|VECN of FLOAT_ABSTRACT_UNIMPLEMENTED -> Scalar).into()
100 }
101 Mf::Length => regular!(1, SCALAR|VECN of FLOAT -> Scalar).into(),
102 Mf::Normalize => regular!(1, VECN of FLOAT).into(),
103 Mf::FaceForward => regular!(3, VECN of FLOAT_ABSTRACT_UNIMPLEMENTED).into(),
104 Mf::Reflect => regular!(2, VECN of FLOAT_ABSTRACT_UNIMPLEMENTED).into(),
105 Mf::Refract => refract().into(),
106 Mf::Mix => mix().into(),
107 Mf::Inverse => regular!(1, MAT2X2|MAT3X3|MAT4X4 of FLOAT).into(),
108 Mf::Transpose => transpose().into(),
109 Mf::Determinant => regular!(1, MAT2X2|MAT3X3|MAT4X4 of FLOAT -> Scalar).into(),
110 Mf::QuantizeToF16 => regular!(1, SCALAR|VECN of F32).into(),
111 Mf::ExtractBits => extract_bits().into(),
112 Mf::InsertBits => insert_bits().into(),
113 };
114
115 set
116 }
117}
118
119fn ldexp() -> List {
120 fn exponent_from_mantissa(mantissa: ir::Scalar) -> ir::Scalar {
122 match mantissa.kind {
123 ir::ScalarKind::AbstractFloat => ir::Scalar::ABSTRACT_INT,
124 ir::ScalarKind::Float => ir::Scalar::I32,
125 _ => unreachable!("not a float scalar"),
126 }
127 }
128
129 list(
130 float_scalars_unimplemented_abstract().flat_map(|mantissa_scalar| {
132 let exponent_scalar = exponent_from_mantissa(mantissa_scalar);
134 scalar_or_vecn(mantissa_scalar)
136 .zip(scalar_or_vecn(exponent_scalar))
137 .map(move |(mantissa, exponent)| {
138 let result = mantissa.clone();
139 rule([mantissa, exponent], result)
140 })
141 }),
142 )
143}
144
145fn outer() -> List {
146 list(
147 triples(
148 vector_sizes(),
149 vector_sizes(),
150 float_scalars_unimplemented_abstract(),
151 )
152 .map(|(cols, rows, scalar)| {
153 let left = ir::TypeInner::Vector { size: cols, scalar };
154 let right = ir::TypeInner::Vector { size: rows, scalar };
155 let result = ir::TypeInner::Matrix {
156 columns: cols,
157 rows,
158 scalar,
159 };
160 rule([left, right], result)
161 }),
162 )
163}
164
165fn refract() -> List {
166 list(
167 pairs(vector_sizes(), float_scalars_unimplemented_abstract()).map(|(size, scalar)| {
168 let incident = ir::TypeInner::Vector { size, scalar };
169 let normal = incident.clone();
170 let ratio = ir::TypeInner::Scalar(scalar);
171 let result = incident.clone();
172 rule([incident, normal, ratio], result)
173 }),
174 )
175}
176
177fn transpose() -> List {
178 list(
179 triples(vector_sizes(), vector_sizes(), float_scalars()).map(|(a, b, scalar)| {
180 let input = ir::TypeInner::Matrix {
181 columns: a,
182 rows: b,
183 scalar,
184 };
185 let output = ir::TypeInner::Matrix {
186 columns: b,
187 rows: a,
188 scalar,
189 };
190 rule([input], output)
191 }),
192 )
193}
194
195fn extract_bits() -> List {
196 list(concrete_int_scalars().flat_map(|scalar| {
197 scalar_or_vecn(scalar).map(|input| {
198 let offset = ir::TypeInner::Scalar(ir::Scalar::U32);
199 let count = ir::TypeInner::Scalar(ir::Scalar::U32);
200 let output = input.clone();
201 rule([input, offset, count], output)
202 })
203 }))
204}
205
206fn insert_bits() -> List {
207 list(concrete_int_scalars().flat_map(|scalar| {
208 scalar_or_vecn(scalar).map(|input| {
209 let newbits = input.clone();
210 let offset = ir::TypeInner::Scalar(ir::Scalar::U32);
211 let count = ir::TypeInner::Scalar(ir::Scalar::U32);
212 let output = input.clone();
213 rule([input, newbits, offset, count], output)
214 })
215 }))
216}
217
218fn mix() -> List {
219 list(float_scalars().flat_map(|scalar| {
220 scalar_or_vecn(scalar).flat_map(move |input| {
221 let scalar_ratio = ir::TypeInner::Scalar(scalar);
222 [
223 rule([input.clone(), input.clone(), input.clone()], input.clone()),
224 rule([input.clone(), input.clone(), scalar_ratio], input),
225 ]
226 })
227 }))
228}