feat(const_eval)!: reimpl. clamp

This commit is contained in:
Erich Gubler
2023-12-14 11:20:45 -05:00
parent 6f5b2a64e2
commit 29a46234f4

View File

@@ -820,7 +820,20 @@ impl<'a> ConstantEvaluator<'a> {
})
}
crate::MathFunction::Pow => self.math_pow(arg, arg1.unwrap(), span),
crate::MathFunction::Clamp => self.math_clamp(arg, arg1.unwrap(), arg2.unwrap(), span),
crate::MathFunction::Clamp => {
component_wise_scalar!(
self,
span,
[arg, arg1.unwrap(), arg2.unwrap()],
|e, low, high| {
if low > high {
Err(ConstantEvaluatorError::InvalidClamp)
} else {
Ok([e.clamp(low, high)])
}
}
)
}
crate::MathFunction::Round => {
// TODO: Use `f{32,64}.round_ties_even()` when available on stable. This polyfill
// is shamelessly [~~stolen from~~ inspired by `ndarray-image`][polyfill source],
@@ -879,114 +892,6 @@ impl<'a> ConstantEvaluator<'a> {
component_wise_float!(self, span, [e1, e2], |e1, e2| { Ok([e1.powf(e2)]) })
}
fn math_clamp(
&mut self,
e: Handle<Expression>,
low: Handle<Expression>,
high: Handle<Expression>,
span: Span,
) -> Result<Handle<Expression>, ConstantEvaluatorError> {
let e = self.eval_zero_value_and_splat(e, span)?;
let low = self.eval_zero_value_and_splat(low, span)?;
let high = self.eval_zero_value_and_splat(high, span)?;
let expr = match (
&self.expressions[e],
&self.expressions[low],
&self.expressions[high],
) {
(&Expression::Literal(e), &Expression::Literal(low), &Expression::Literal(high)) => {
let literal = match (e, low, high) {
(Literal::I32(e), Literal::I32(low), Literal::I32(high)) => {
if low > high {
return Err(ConstantEvaluatorError::InvalidClamp);
} else {
Literal::I32(e.clamp(low, high))
}
}
(Literal::U32(e), Literal::U32(low), Literal::U32(high)) => {
if low > high {
return Err(ConstantEvaluatorError::InvalidClamp);
} else {
Literal::U32(e.clamp(low, high))
}
}
(Literal::F32(e), Literal::F32(low), Literal::F32(high)) => {
if low > high {
return Err(ConstantEvaluatorError::InvalidClamp);
} else {
Literal::F32(e.clamp(low, high))
}
}
_ => return Err(ConstantEvaluatorError::InvalidMathArg),
};
Expression::Literal(literal)
}
(
&Expression::Compose {
components: ref src_components0,
ty: ty0,
},
&Expression::Compose {
components: ref src_components1,
ty: ty1,
},
&Expression::Compose {
components: ref src_components2,
ty: ty2,
},
) if ty0 == ty1
&& ty0 == ty2
&& matches!(
self.types[ty0].inner,
crate::TypeInner::Vector {
scalar: crate::Scalar {
kind: ScalarKind::Float,
..
},
..
}
) =>
{
let mut components: Vec<_> = crate::proc::flatten_compose(
ty0,
src_components0,
self.expressions,
self.types,
)
.chain(crate::proc::flatten_compose(
ty1,
src_components1,
self.expressions,
self.types,
))
.chain(crate::proc::flatten_compose(
ty2,
src_components2,
self.expressions,
self.types,
))
.collect();
let chunk_size = components.len() / 3;
let (es, rem) = components.split_at_mut(chunk_size);
let (lows, highs) = rem.split_at(chunk_size);
for ((e, low), high) in es.iter_mut().zip(lows).zip(highs) {
*e = self.math_clamp(*e, *low, *high, span)?;
}
components.truncate(chunk_size);
Expression::Compose {
ty: ty0,
components,
}
}
_ => return Err(ConstantEvaluatorError::InvalidMathArg),
};
self.register_evaluated_expr(expr, span)
}
fn array_length(
&mut self,
array: Handle<Expression>,