1use crate::derives::*;
10use crate::typed_om::{
11 MathClamp, MathInvert, MathMax, MathMin, MathNegate, MathProduct, MathSum, MathValue,
12 NumericBaseType, NumericType, NumericValue, ToTyped, TypedValue,
13};
14use crate::values::calc_random;
15use crate::values::specified::NoCalcPercentage;
16use crate::values::generics::Optional;
17use crate::values::generics::length::GenericAnchorSizeFunction;
18use crate::values::generics::position::{GenericAnchorFunction, GenericAnchorSide};
19use num_traits::Zero;
20use smallvec::SmallVec;
21use std::convert::AsRef;
22use std::fmt::{self, Write};
23use std::ops::{Add, Mul, Rem, Sub};
24use std::{cmp, mem};
25use strum_macros::AsRefStr;
26use style_traits::{CssWriter, ToCss};
27
28use thin_vec::ThinVec;
29
30#[derive(
32 Clone,
33 Copy,
34 Debug,
35 Deserialize,
36 MallocSizeOf,
37 PartialEq,
38 Serialize,
39 ToAnimatedZero,
40 ToResolvedValue,
41 ToShmem,
42)]
43#[repr(u8)]
44pub enum MinMaxOp {
45 Min,
47 Max,
49}
50
51#[derive(
53 Clone,
54 Copy,
55 Debug,
56 Deserialize,
57 MallocSizeOf,
58 PartialEq,
59 Serialize,
60 ToAnimatedZero,
61 ToResolvedValue,
62 ToShmem,
63)]
64#[repr(u8)]
65pub enum ModRemOp {
66 Mod,
68 Rem,
70}
71
72impl ModRemOp {
73 fn apply(self, dividend: f32, divisor: f32) -> f32 {
74 if matches!(self, Self::Mod)
78 && divisor.is_infinite()
79 && dividend.is_sign_negative() != divisor.is_sign_negative()
80 {
81 return f32::NAN;
82 }
83
84 let (r, same_sign_as) = match self {
85 Self::Mod => (dividend - divisor * (dividend / divisor).floor(), divisor),
86 Self::Rem => (dividend - divisor * (dividend / divisor).trunc(), dividend),
87 };
88 if r == 0.0 && same_sign_as.is_sign_negative() {
89 -0.0
90 } else {
91 r
92 }
93 }
94}
95
96#[derive(
98 Clone,
99 Copy,
100 Debug,
101 Deserialize,
102 MallocSizeOf,
103 PartialEq,
104 Serialize,
105 ToAnimatedZero,
106 ToResolvedValue,
107 ToShmem,
108)]
109#[repr(u8)]
110pub enum RoundingStrategy {
111 Nearest,
114 Up,
117 Down,
120 ToZero,
123}
124
125#[derive(
127 Clone,
128 Copy,
129 Debug,
130 Deserialize,
131 MallocSizeOf,
132 Parse,
133 PartialEq,
134 Serialize,
135 ToAnimatedZero,
136 ToCss,
137 ToResolvedValue,
138 ToShmem,
139)]
140#[repr(u8)]
141pub enum ProgressClampingMode {
142 #[css(skip)]
145 Clamp,
146 NoClamp,
149}
150
151impl ProgressClampingMode {
152 fn evaluate(self, value: f32, start: f32, end: f32) -> f32 {
153 if start == end && self == Self::Clamp {
154 return 0.;
155 }
156 let progress = crate::values::normalize((value - start) / (end - start));
157 match self {
158 Self::Clamp => progress.max(0.).min(1.),
159 Self::NoClamp => progress,
160 }
161 }
162}
163
164#[derive(
168 AsRefStr, Clone, Copy, Debug, Eq, Ord, Parse, PartialEq, PartialOrd, MallocSizeOf, ToShmem,
169)]
170#[strum(serialize_all = "lowercase")]
171#[allow(missing_docs)]
172pub enum SortKey {
173 #[strum(serialize = "")]
174 Number,
175 #[css(skip)]
176 #[strum(serialize = "%")]
177 Percentage,
178 Cap,
179 Ch,
180 Cqb,
181 Cqh,
182 Cqi,
183 Cqmax,
184 Cqmin,
185 Cqw,
186 Deg,
187 Dppx,
188 Dvb,
189 Dvh,
190 Dvi,
191 Dvmax,
192 Dvmin,
193 Dvw,
194 Em,
195 Ex,
196 Ic,
197 Lh,
198 Lvb,
199 Lvh,
200 Lvi,
201 Lvmax,
202 Lvmin,
203 Lvw,
204 Ms,
205 Px,
206 Rcap,
207 Rch,
208 Rem,
209 Rex,
210 Ric,
211 Rlh,
212 S, Svb,
214 Svh,
215 Svi,
216 Svmax,
217 Svmin,
218 Svw,
219 Vb,
220 Vh,
221 Vi,
222 Vmax,
223 Vmin,
224 Vw,
225 #[css(skip)]
226 ColorComponent,
227 #[css(skip)]
228 Other,
229}
230
231#[repr(C)]
240#[derive(
241 Clone,
242 Debug,
243 Deserialize,
244 MallocSizeOf,
245 PartialEq,
246 Serialize,
247 ToAnimatedZero,
248 ToResolvedValue,
249 ToShmem,
250)]
251pub struct GenericAnchorFunctionFallback<L> {
252 #[animation(constant)]
254 is_calc_node: bool,
255 pub node: GenericCalcNode<L>,
258}
259
260impl<L> GenericAnchorFunctionFallback<L> {
261 pub fn new(is_calc_node: bool, node: GenericCalcNode<L>) -> Self {
263 Self { is_calc_node, node }
264 }
265}
266
267impl<L: CalcNodeLeaf> ToCss for GenericAnchorFunctionFallback<L> {
268 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
269 where
270 W: Write,
271 {
272 self.node.to_css_impl(
273 dest,
274 if self.is_calc_node {
275 ArgumentLevel::CalculationRoot
276 } else {
277 ArgumentLevel::ArgumentRoot
278 },
279 )
280 }
281}
282
283pub type GenericCalcAnchorFunction<L> =
285 GenericAnchorFunction<Box<GenericCalcNode<L>>, Box<GenericAnchorFunctionFallback<L>>>;
286pub type GenericCalcAnchorSizeFunction<L> =
288 GenericAnchorSizeFunction<Box<GenericAnchorFunctionFallback<L>>>;
289
290#[repr(C)]
293#[derive(
294 Clone,
295 Debug,
296 Deserialize,
297 MallocSizeOf,
298 PartialEq,
299 Serialize,
300 ToAnimatedZero,
301 ToResolvedValue,
302 ToShmem,
303)]
304pub struct GenericRandomFunction<L> {
305 pub key: GenericCalcNode<L>,
307 pub min: GenericCalcNode<L>,
309 pub max: GenericCalcNode<L>,
311 pub step: Optional<GenericCalcNode<L>>,
313}
314
315#[repr(u8)]
327#[derive(
328 Clone,
329 Debug,
330 Deserialize,
331 MallocSizeOf,
332 PartialEq,
333 Serialize,
334 ToAnimatedZero,
335 ToResolvedValue,
336 ToShmem,
337)]
338pub enum GenericCalcNode<L> {
339 Leaf(L),
341 Negate(Box<Self>),
343 Invert(Box<Self>),
346 Sum(crate::OwnedSlice<Self>),
349 Product(crate::OwnedSlice<Self>),
352 MinMax(crate::OwnedSlice<Self>, MinMaxOp),
354 Clamp {
356 min: Box<Self>,
358 center: Box<Self>,
360 max: Box<Self>,
362 },
363 Round {
365 strategy: RoundingStrategy,
367 value: Box<Self>,
369 step: Box<Self>,
371 },
372 ModRem {
374 dividend: Box<Self>,
376 divisor: Box<Self>,
378 op: ModRemOp,
380 },
381 Sin(Box<Self>),
383 Cos(Box<Self>),
385 Tan(Box<Self>),
387 Asin(Box<Self>),
389 Acos(Box<Self>),
391 Atan(Box<Self>),
393 Atan2(Box<Self>, Box<Self>),
395 Pow(Box<Self>, Box<Self>),
397 Sqrt(Box<Self>),
399 Hypot(crate::OwnedSlice<Self>),
401 Log(Box<Self>, Optional<Box<Self>>),
403 Exp(Box<Self>),
405 Abs(Box<Self>),
407 Sign(Box<Self>),
409 Progress {
411 clamping_mode: ProgressClampingMode,
413 value: Box<Self>,
415 start: Box<Self>,
417 end: Box<Self>,
419 },
420 Random(Box<GenericRandomFunction<L>>),
422 Anchor(Box<GenericCalcAnchorFunction<L>>),
424 AnchorSize(Box<GenericCalcAnchorSizeFunction<L>>),
426}
427
428pub use self::GenericCalcNode as CalcNode;
429
430fn typed_arithmetic_enabled() -> bool {
431 crate::pref!("layout.css.calc-typed-arithmetic.enabled")
432}
433
434#[derive(Clone, Copy, PartialEq, Eq)]
445#[repr(u8)]
446pub enum CalcType {
447 Length,
449 Percentage,
451 Angle,
453 Time,
455 Resolution,
457 Number,
459}
460
461#[derive(
463 Clone,
464 Copy,
465 Debug,
466 Deserialize,
467 MallocSizeOf,
468 PartialEq,
469 Serialize,
470 ToAnimatedZero,
471 ToCss,
472 ToResolvedValue,
473 ToShmem,
474 ToTyped,
475)]
476#[repr(C)]
477pub struct CalcPercentageLeaf {
478 pub value: NoCalcPercentage,
480 #[css(skip)]
484 pub hint: Optional<NumericBaseType>,
485}
486
487impl CalcPercentageLeaf {
488 pub fn new(value: f32, hint: Optional<NumericBaseType>) -> Self {
490 Self {
491 value: NoCalcPercentage::new(value),
492 hint,
493 }
494 }
495
496 pub fn get(&self) -> f32 {
498 self.value.get()
499 }
500
501 pub fn numeric_type(&self) -> NumericType {
503 match self.hint {
504 Optional::Some(hint) => NumericType::percent().with_percent_hint(hint),
505 Optional::None => NumericType::percent(),
506 }
507 }
508
509 pub fn combined_hint(&self, other: &Self) -> Optional<NumericBaseType> {
512 debug_assert_eq!(
513 self.hint, other.hint,
514 "Merging percentages with mismatched hints"
515 );
516 self.hint
517 }
518}
519
520macro_rules! compare_helpers {
521 () => {
522 #[allow(unused)]
524 fn gt(&self, other: &Self) -> bool {
525 self.compare(other) == Some(cmp::Ordering::Greater)
526 }
527
528 fn lt(&self, other: &Self) -> bool {
530 self.compare(other) == Some(cmp::Ordering::Less)
531 }
532
533 fn lte(&self, other: &Self) -> bool {
535 match self.compare(other) {
536 Some(cmp::Ordering::Less) => true,
537 Some(cmp::Ordering::Equal) => true,
538 Some(cmp::Ordering::Greater) => false,
539 None => false,
540 }
541 }
542 };
543}
544
545pub trait CalcNodeLeaf: Clone + Sized + PartialEq + ToCss + ToTyped + fmt::Debug {
547 fn numeric_type(&self) -> NumericType;
549
550 fn unitless_value(&self) -> Option<f32>;
552
553 fn as_percentage(&self) -> Option<(f32, Optional<NumericBaseType>)>;
555
556 fn canonical_value(&self) -> Option<f32>;
560
561 fn as_angle_radians(&self) -> Option<f32>;
563
564 fn new_angle_from_radians(radians: f32) -> Self;
566
567 fn is_same_unit_as(&self, other: &Self) -> bool {
570 std::mem::discriminant(self) == std::mem::discriminant(other)
571 }
572
573 fn compare(&self, other: &Self) -> Option<cmp::Ordering>;
575 compare_helpers!();
576
577 fn new_number(value: f32) -> Self;
579
580 fn as_number(&self) -> Option<f32>;
582
583 fn as_number_or_angle_radians(&self) -> Option<f32> {
585 self.as_number().or_else(|| self.as_angle_radians())
586 }
587
588 fn new_from_typed_value(value: f32, numeric_type: NumericType) -> Result<Self, ()>;
591
592 fn is_negative(&self) -> Result<bool, ()> {
594 self.unitless_value()
595 .map(|v| Ok(v.is_sign_negative()))
596 .unwrap_or_else(|| Err(()))
597 }
598
599 fn is_infinite(&self) -> Result<bool, ()> {
601 self.unitless_value()
602 .map(|v| Ok(v.is_infinite()))
603 .unwrap_or_else(|| Err(()))
604 }
605
606 fn is_zero(&self) -> Result<bool, ()> {
608 self.unitless_value()
609 .map(|v| Ok(v.is_zero()))
610 .unwrap_or_else(|| Err(()))
611 }
612
613 fn is_nan(&self) -> Result<bool, ()> {
615 self.unitless_value()
616 .map(|v| Ok(v.is_nan()))
617 .unwrap_or_else(|| Err(()))
618 }
619
620 fn try_sum_in_place(&mut self, other: &Self) -> Result<(), ()>;
622
623 fn try_product_in_place(&mut self, other: &mut Self) -> bool;
626
627 fn try_op<O>(&self, other: &Self, op: O) -> Result<Self, ()>
629 where
630 O: Fn(f32, f32) -> f32;
631
632 fn map(&mut self, op: impl FnMut(f32) -> f32) -> Result<(), ()>;
634
635 fn simplify(&mut self) -> SimplificationResult;
637
638 fn sort_key(&self) -> SortKey;
640
641 fn sign_from(leaf: &impl CalcNodeLeaf) -> Result<Self, ()> {
643 if leaf
646 .as_percentage()
647 .is_some_and(|(_, hint)| hint != Optional::Some(NumericBaseType::Percent))
648 {
649 return Err(());
650 }
651
652 let Some(value) = leaf.unitless_value() else {
653 return Err(());
654 };
655
656 Ok(Self::new_number(crate::values::calc_sign(value)))
657 }
658
659 fn should_serialize_with_root_calc_wrapper(&self) -> bool {
662 true
663 }
664}
665
666#[derive(Clone)]
668enum ArgumentLevel {
669 CalculationRoot,
671 ArgumentRoot,
674 Nested,
676}
677
678#[derive(Clone, Copy)]
680pub enum SimplificationResult {
681 Simplified,
683 Unchanged,
685}
686
687impl<L: CalcNodeLeaf> CalcNode<L> {
688 fn dummy() -> Self {
690 Self::MinMax(Default::default(), MinMaxOp::Max)
691 }
692
693 fn coerce_to_value(&mut self, value: f32) -> Result<(), ()> {
697 self.map(|_| value)
698 }
699
700 #[inline]
704 pub fn is_product_distributive(&self) -> bool {
705 match self {
706 Self::Leaf(l) => l.unitless_value().is_some(),
708 Self::Sum(children) => children.iter().all(|c| c.is_product_distributive()),
709 _ => false,
710 }
711 }
712
713 pub fn numeric_type(&self) -> Result<NumericType, ()> {
717 Ok(match self {
718 CalcNode::Leaf(l) => l.numeric_type(),
719 CalcNode::Negate(child) | CalcNode::Abs(child) => child.numeric_type()?,
720 CalcNode::Sum(children) => {
721 let mut ty = children.first().unwrap().numeric_type()?;
722 for child in children.iter().skip(1) {
723 let child_ty = child.numeric_type()?;
724 ty = NumericType::add_two_types(&ty, &child_ty)?;
725 }
726 ty
727 },
728 CalcNode::Product(children) => {
729 let mut ty = children.first().unwrap().numeric_type()?;
730
731 for child in children.iter().skip(1) {
732 let child_ty = child.numeric_type()?;
733
734 if !typed_arithmetic_enabled() && !ty.is_number() && !child_ty.is_number() {
737 return Err(());
738 }
739
740 ty = NumericType::multiply_two_types(&ty, &child_ty)?;
741 }
742
743 ty
744 },
745 CalcNode::MinMax(children, _) | CalcNode::Hypot(children) => {
746 let mut ty = children.first().unwrap().numeric_type()?;
747 for child in children.iter().skip(1) {
748 let child_ty = child.numeric_type()?;
749 ty = NumericType::add_two_types(&ty, &child_ty)?;
750 }
751 ty
752 },
753 CalcNode::Clamp { min, center, max } => {
754 let min_ty = min.numeric_type()?;
755 let center_ty = center.numeric_type()?;
756 let max_ty = max.numeric_type()?;
757
758 let mut ty = NumericType::add_two_types(&min_ty, ¢er_ty)?;
759 ty = NumericType::add_two_types(&ty, &max_ty)?;
760 ty
761 },
762 CalcNode::Round { value, step, .. } => {
763 let value_ty = value.numeric_type()?;
764 let step_ty = step.numeric_type()?;
765 NumericType::add_two_types(&value_ty, &step_ty)?
766 },
767 CalcNode::ModRem {
768 dividend, divisor, ..
769 } => {
770 let dividend_ty = dividend.numeric_type()?;
771 let divisor_ty = divisor.numeric_type()?;
772 NumericType::add_two_types(÷nd_ty, &divisor_ty)?
773 },
774 CalcNode::Sign(child) => {
775 let _ = child.numeric_type()?;
778 NumericType::number()
779 },
780 CalcNode::Anchor(..) | CalcNode::AnchorSize(..) => {
781 NumericType::length().with_percent_hint(NumericBaseType::Length)
782 },
783 CalcNode::Sin(child) | CalcNode::Cos(child) | CalcNode::Tan(child) => {
784 let child_ty = child.numeric_type_as_calc_type()?;
785 if child_ty != CalcType::Number && child_ty != CalcType::Angle {
786 return Err(());
787 }
788 NumericType::number()
789 },
790 CalcNode::Asin(child) | CalcNode::Acos(child) | CalcNode::Atan(child) => {
791 if child.numeric_type_as_calc_type()? != CalcType::Number {
792 return Err(());
793 }
794 NumericType::angle()
795 },
796 CalcNode::Atan2(a, b) => {
797 let a_ty = a.numeric_type()?;
799 let b_ty = b.numeric_type()?;
800 let _ = NumericType::add_two_types(&a_ty, &b_ty)?;
801 NumericType::angle()
802 },
803 CalcNode::Pow(a, b) => {
804 let a_ty = a.numeric_type_as_calc_type()?;
805 let b_ty = b.numeric_type_as_calc_type()?;
806 if a_ty != CalcType::Number || b_ty != CalcType::Number {
807 return Err(());
808 }
809 NumericType::number()
810 },
811 CalcNode::Invert(c) => {
812 if typed_arithmetic_enabled() {
813 let mut ty = c.numeric_type()?;
814 ty.invert();
815 ty
816 } else {
817 if c.numeric_type_as_calc_type()? != CalcType::Number {
818 return Err(());
819 }
820 NumericType::number()
821 }
822 },
823 CalcNode::Sqrt(c) | CalcNode::Exp(c) => {
824 if c.numeric_type_as_calc_type()? != CalcType::Number {
825 return Err(());
826 }
827 NumericType::number()
828 },
829 CalcNode::Log(a, b) => {
830 let a_ty = a.numeric_type_as_calc_type()?;
831 let b_ty = match b {
832 Optional::Some(b) => b.numeric_type_as_calc_type()?,
833 Optional::None => CalcType::Number,
834 };
835 if a_ty != CalcType::Number || b_ty != CalcType::Number {
836 return Err(());
837 }
838 NumericType::number()
839 },
840 CalcNode::Progress {
841 value, start, end, ..
842 } => {
843 let value_ty = value.numeric_type()?;
844 let start_ty = start.numeric_type()?;
845 let end_ty = end.numeric_type()?;
846
847 let _ = NumericType::add_two_types(&value_ty, &start_ty)?;
849 let _ = NumericType::add_two_types(&value_ty, &end_ty)?;
850 NumericType::number()
851 },
852 CalcNode::Random(random) => {
853 let min_ty = random.min.numeric_type()?;
854 let max_ty = random.max.numeric_type()?;
855 let mut ty = NumericType::add_two_types(&min_ty, &max_ty)?;
856 if let Some(step) = random.step.as_ref() {
857 let step_ty = step.numeric_type()?;
858 ty = NumericType::add_two_types(&ty, &step_ty)?;
859 }
860 ty
861 },
862 })
863 }
864
865 pub fn numeric_type_as_calc_type(&self) -> Result<CalcType, ()> {
868 self.numeric_type()?.as_calc_type()
869 }
870
871 pub fn negate(&mut self) {
874 fn wrap_self_in_negate<L: CalcNodeLeaf>(s: &mut CalcNode<L>) {
876 let result = mem::replace(s, CalcNode::dummy());
877 *s = CalcNode::Negate(Box::new(result));
878 }
879
880 match *self {
881 CalcNode::Leaf(ref mut leaf) => {
882 if leaf.map(std::ops::Neg::neg).is_err() {
883 wrap_self_in_negate(self)
884 }
885 },
886 CalcNode::Negate(ref mut value) => {
887 let result = mem::replace(value.as_mut(), Self::dummy());
889 *self = result;
890 },
891 CalcNode::Invert(_) => {
892 wrap_self_in_negate(self)
894 },
895 CalcNode::Sum(ref mut children) => {
896 for child in children.iter_mut() {
897 child.negate();
898 }
899 },
900 CalcNode::Product(_) => {
901 wrap_self_in_negate(self);
903 },
904 CalcNode::MinMax(ref mut children, ref mut op) => {
905 for child in children.iter_mut() {
906 child.negate();
907 }
908
909 *op = match *op {
911 MinMaxOp::Min => MinMaxOp::Max,
912 MinMaxOp::Max => MinMaxOp::Min,
913 };
914 },
915 CalcNode::Clamp {
916 ref mut min,
917 ref mut center,
918 ref mut max,
919 } => {
920 if min.lte(max) {
921 min.negate();
922 center.negate();
923 max.negate();
924
925 mem::swap(min, max);
926 } else {
927 wrap_self_in_negate(self);
928 }
929 },
930 CalcNode::Round {
931 ref mut strategy,
932 ref mut value,
933 ref mut step,
934 } => {
935 match *strategy {
936 RoundingStrategy::Nearest => {
937 wrap_self_in_negate(self);
942 return;
943 },
944 RoundingStrategy::Up => *strategy = RoundingStrategy::Down,
945 RoundingStrategy::Down => *strategy = RoundingStrategy::Up,
946 RoundingStrategy::ToZero => (),
947 }
948 value.negate();
949 step.negate();
950 },
951 CalcNode::ModRem {
952 ref mut dividend,
953 ref mut divisor,
954 ..
955 } => {
956 dividend.negate();
957 divisor.negate();
958 },
959 CalcNode::Hypot(ref mut children) => {
960 for child in children.iter_mut() {
961 child.negate();
962 }
963 },
964 CalcNode::Sign(ref mut child) => {
965 child.negate();
966 },
967 CalcNode::Sin(..)
968 | CalcNode::Cos(..)
969 | CalcNode::Tan(..)
970 | CalcNode::Asin(..)
971 | CalcNode::Acos(..)
972 | CalcNode::Atan(..)
973 | CalcNode::Atan2(..)
974 | CalcNode::Pow(..)
975 | CalcNode::Sqrt(..)
976 | CalcNode::Log(..)
977 | CalcNode::Exp(..)
978 | CalcNode::Abs(..)
979 | CalcNode::Progress { .. }
980 | CalcNode::Random(..)
981 | CalcNode::Anchor(..)
982 | CalcNode::AnchorSize(..) => {
983 wrap_self_in_negate(self);
984 },
985 }
986 }
987
988 fn sort_key(&self) -> SortKey {
989 match *self {
990 Self::Leaf(ref l) => l.sort_key(),
991 Self::Anchor(..) | Self::AnchorSize(..) => SortKey::Px,
992 _ => SortKey::Other,
993 }
994 }
995
996 pub fn as_leaf(&self) -> Option<&L> {
998 match *self {
999 Self::Leaf(ref l) => Some(l),
1000 _ => None,
1001 }
1002 }
1003
1004 pub fn try_sum_in_place(&mut self, other: &Self) -> Result<(), ()> {
1006 match (self, other) {
1007 (&mut CalcNode::Leaf(ref mut one), CalcNode::Leaf(other)) => {
1008 one.try_sum_in_place(other)
1009 },
1010 _ => Err(()),
1011 }
1012 }
1013
1014 pub fn try_product_in_place(&mut self, other: &mut Self) -> bool {
1016 if let Ok(resolved) = other.resolve()
1017 && let Some(number) = resolved.as_number()
1018 {
1019 if number == 1.0 {
1020 return true;
1021 }
1022
1023 if self.is_product_distributive() {
1024 if self.map(|v| v * number).is_err() {
1025 return false;
1026 }
1027 return true;
1028 }
1029 }
1030
1031 if let Ok(resolved) = self.resolve()
1032 && let Some(number) = resolved.as_number()
1033 {
1034 if number == 1.0 {
1035 std::mem::swap(self, other);
1036 return true;
1037 }
1038
1039 if other.is_product_distributive() {
1040 if other.map(|v| v * number).is_err() {
1041 return false;
1042 }
1043 std::mem::swap(self, other);
1044 return true;
1045 }
1046 }
1047
1048 false
1049 }
1050
1051 fn try_op<O>(&self, other: &Self, op: O) -> Result<Self, ()>
1053 where
1054 O: Fn(f32, f32) -> f32,
1055 {
1056 match (self, other) {
1057 (CalcNode::Leaf(one), CalcNode::Leaf(other)) => {
1058 Ok(CalcNode::Leaf(one.try_op(other, op)?))
1059 },
1060 _ => Err(()),
1061 }
1062 }
1063
1064 pub fn map(&mut self, mut op: impl FnMut(f32) -> f32) -> Result<(), ()> {
1066 fn map_internal<L: CalcNodeLeaf>(
1067 node: &mut CalcNode<L>,
1068 op: &mut impl FnMut(f32) -> f32,
1069 ) -> Result<(), ()> {
1070 match node {
1071 CalcNode::Leaf(l) => l.map(op),
1072 CalcNode::Negate(v) | CalcNode::Invert(v) => map_internal(v, op),
1073 CalcNode::Sum(children) | CalcNode::Product(children) => {
1074 for node in &mut **children {
1075 map_internal(node, op)?;
1076 }
1077 Ok(())
1078 },
1079 CalcNode::MinMax(children, _) => {
1080 for node in &mut **children {
1081 map_internal(node, op)?;
1082 }
1083 Ok(())
1084 },
1085 CalcNode::Clamp { min, center, max } => {
1086 map_internal(min, op)?;
1087 map_internal(center, op)?;
1088 map_internal(max, op)
1089 },
1090 CalcNode::Round { value, step, .. } => {
1091 map_internal(value, op)?;
1092 map_internal(step, op)
1093 },
1094 CalcNode::ModRem {
1095 dividend, divisor, ..
1096 } => {
1097 map_internal(dividend, op)?;
1098 map_internal(divisor, op)
1099 },
1100 CalcNode::Hypot(children) => {
1101 for node in &mut **children {
1102 map_internal(node, op)?;
1103 }
1104 Ok(())
1105 },
1106 CalcNode::Abs(child) | CalcNode::Sign(child) => map_internal(child, op),
1107 CalcNode::Anchor(_) | CalcNode::AnchorSize(_) => Err(()),
1110 CalcNode::Sin(_)
1113 | CalcNode::Cos(_)
1114 | CalcNode::Tan(_)
1115 | CalcNode::Asin(_)
1116 | CalcNode::Acos(_)
1117 | CalcNode::Atan(_)
1118 | CalcNode::Atan2(..)
1119 | CalcNode::Pow(..)
1120 | CalcNode::Sqrt(_)
1121 | CalcNode::Log(..)
1122 | CalcNode::Exp(_)
1123 | CalcNode::Progress { .. }
1124 | CalcNode::Random(_) => Err(()),
1125 }
1126 }
1127
1128 map_internal(self, &mut op)
1129 }
1130
1131 pub fn map_leaves<O, F>(&self, mut map: F) -> CalcNode<O>
1133 where
1134 O: CalcNodeLeaf,
1135 F: FnMut(&L) -> O,
1136 {
1137 self.map_leaves_internal(&mut map)
1138 }
1139
1140 fn map_leaves_internal<O, F>(&self, map: &mut F) -> CalcNode<O>
1141 where
1142 O: CalcNodeLeaf,
1143 F: FnMut(&L) -> O,
1144 {
1145 fn map_children<L, O, F>(
1146 children: &[CalcNode<L>],
1147 map: &mut F,
1148 ) -> crate::OwnedSlice<CalcNode<O>>
1149 where
1150 L: CalcNodeLeaf,
1151 O: CalcNodeLeaf,
1152 F: FnMut(&L) -> O,
1153 {
1154 children
1155 .iter()
1156 .map(|c| c.map_leaves_internal(map))
1157 .collect()
1158 }
1159
1160 match *self {
1161 Self::Leaf(ref l) => CalcNode::Leaf(map(l)),
1162 Self::Negate(ref c) => CalcNode::Negate(Box::new(c.map_leaves_internal(map))),
1163 Self::Invert(ref c) => CalcNode::Invert(Box::new(c.map_leaves_internal(map))),
1164 Self::Sum(ref c) => CalcNode::Sum(map_children(c, map)),
1165 Self::Product(ref c) => CalcNode::Product(map_children(c, map)),
1166 Self::MinMax(ref c, op) => CalcNode::MinMax(map_children(c, map), op),
1167 Self::Clamp {
1168 ref min,
1169 ref center,
1170 ref max,
1171 } => {
1172 let min = Box::new(min.map_leaves_internal(map));
1173 let center = Box::new(center.map_leaves_internal(map));
1174 let max = Box::new(max.map_leaves_internal(map));
1175 CalcNode::Clamp { min, center, max }
1176 },
1177 Self::Round {
1178 strategy,
1179 ref value,
1180 ref step,
1181 } => {
1182 let value = Box::new(value.map_leaves_internal(map));
1183 let step = Box::new(step.map_leaves_internal(map));
1184 CalcNode::Round {
1185 strategy,
1186 value,
1187 step,
1188 }
1189 },
1190 Self::ModRem {
1191 ref dividend,
1192 ref divisor,
1193 op,
1194 } => {
1195 let dividend = Box::new(dividend.map_leaves_internal(map));
1196 let divisor = Box::new(divisor.map_leaves_internal(map));
1197 CalcNode::ModRem {
1198 dividend,
1199 divisor,
1200 op,
1201 }
1202 },
1203 Self::Sin(ref c) => CalcNode::Sin(Box::new(c.map_leaves_internal(map))),
1204 Self::Cos(ref c) => CalcNode::Cos(Box::new(c.map_leaves_internal(map))),
1205 Self::Tan(ref c) => CalcNode::Tan(Box::new(c.map_leaves_internal(map))),
1206 Self::Asin(ref c) => CalcNode::Asin(Box::new(c.map_leaves_internal(map))),
1207 Self::Acos(ref c) => CalcNode::Acos(Box::new(c.map_leaves_internal(map))),
1208 Self::Atan(ref c) => CalcNode::Atan(Box::new(c.map_leaves_internal(map))),
1209 Self::Atan2(ref a, ref b) => CalcNode::Atan2(
1210 Box::new(a.map_leaves_internal(map)),
1211 Box::new(b.map_leaves_internal(map)),
1212 ),
1213 Self::Pow(ref a, ref b) => CalcNode::Pow(
1214 Box::new(a.map_leaves_internal(map)),
1215 Box::new(b.map_leaves_internal(map)),
1216 ),
1217 Self::Sqrt(ref c) => CalcNode::Sqrt(Box::new(c.map_leaves_internal(map))),
1218 Self::Hypot(ref c) => CalcNode::Hypot(map_children(c, map)),
1219 Self::Log(ref a, ref b) => CalcNode::Log(
1220 Box::new(a.map_leaves_internal(map)),
1221 b.as_ref()
1222 .map(|b| Box::new(b.map_leaves_internal(map)))
1223 .into(),
1224 ),
1225 Self::Exp(ref c) => CalcNode::Exp(Box::new(c.map_leaves_internal(map))),
1226 Self::Abs(ref c) => CalcNode::Abs(Box::new(c.map_leaves_internal(map))),
1227 Self::Sign(ref c) => CalcNode::Sign(Box::new(c.map_leaves_internal(map))),
1228 Self::Progress {
1229 clamping_mode,
1230 ref value,
1231 ref start,
1232 ref end,
1233 } => {
1234 let value = Box::new(value.map_leaves_internal(map));
1235 let start = Box::new(start.map_leaves_internal(map));
1236 let end = Box::new(end.map_leaves_internal(map));
1237 CalcNode::Progress {
1238 clamping_mode,
1239 value,
1240 start,
1241 end,
1242 }
1243 },
1244 Self::Random(ref r) => CalcNode::Random(Box::new(GenericRandomFunction {
1245 key: r.key.map_leaves_internal(map),
1246 min: r.min.map_leaves_internal(map),
1247 max: r.max.map_leaves_internal(map),
1248 step: r
1249 .step
1250 .as_ref()
1251 .map(|step| step.map_leaves_internal(map))
1252 .into(),
1253 })),
1254 Self::Anchor(ref f) => CalcNode::Anchor(Box::new(GenericAnchorFunction {
1255 target_element: f.target_element.clone(),
1256 side: match &f.side {
1257 GenericAnchorSide::Keyword(k) => GenericAnchorSide::Keyword(*k),
1258 GenericAnchorSide::Percentage(p) => {
1259 GenericAnchorSide::Percentage(Box::new(p.map_leaves_internal(map)))
1260 },
1261 },
1262 fallback: f
1263 .fallback
1264 .as_ref()
1265 .map(|fb| {
1266 Box::new(GenericAnchorFunctionFallback::new(
1267 fb.is_calc_node,
1268 fb.node.map_leaves_internal(map),
1269 ))
1270 })
1271 .into(),
1272 })),
1273 Self::AnchorSize(ref f) => CalcNode::AnchorSize(Box::new(GenericAnchorSizeFunction {
1274 target_element: f.target_element.clone(),
1275 size: f.size,
1276 fallback: f
1277 .fallback
1278 .as_ref()
1279 .map(|fb| {
1280 Box::new(GenericAnchorFunctionFallback::new(
1281 fb.is_calc_node,
1282 fb.node.map_leaves_internal(map),
1283 ))
1284 })
1285 .into(),
1286 })),
1287 }
1288 }
1289
1290 pub fn resolve(&self) -> Result<L, ()> {
1292 self.resolve_map(|l| Ok(l.clone()))
1293 }
1294
1295 pub fn resolve_map<F>(&self, mut leaf_to_output_fn: F) -> Result<L, ()>
1297 where
1298 F: FnMut(&L) -> Result<L, ()>,
1299 {
1300 let (value, ty) = self.resolve_internal(&mut leaf_to_output_fn)?;
1301 L::new_from_typed_value(value, ty)
1302 }
1303
1304 fn resolve_internal<F>(&self, leaf_to_output_fn: &mut F) -> Result<(f32, NumericType), ()>
1305 where
1306 F: FnMut(&L) -> Result<L, ()>,
1307 {
1308 match self {
1309 Self::Leaf(l) => {
1310 let result = leaf_to_output_fn(l)?;
1311 let value = result.canonical_value().ok_or(())?;
1312 let ty = result.numeric_type();
1313 Ok((value, ty))
1314 },
1315 Self::Negate(child) => {
1316 let (value, ty) = child.resolve_internal(leaf_to_output_fn)?;
1317 Ok((-value, ty))
1318 },
1319 Self::Invert(child) => {
1320 let (value, mut ty) = child.resolve_internal(leaf_to_output_fn)?;
1321 if !typed_arithmetic_enabled() && !ty.is_number() {
1322 return Err(());
1323 }
1324 ty.invert();
1325 Ok((1.0 / value, ty))
1326 },
1327 Self::Sum(children) => {
1328 let (mut value, mut ty) = children[0].resolve_internal(leaf_to_output_fn)?;
1329
1330 for child in children.iter().skip(1) {
1331 let (right, right_ty) = child.resolve_internal(leaf_to_output_fn)?;
1332 value += right;
1333 ty = NumericType::add_two_types(&ty, &right_ty)?;
1334 }
1335
1336 Ok((value, ty))
1337 },
1338 Self::Product(children) => {
1339 let (mut value, mut ty) = children[0].resolve_internal(leaf_to_output_fn)?;
1340
1341 for child in children.iter().skip(1) {
1342 let (leaf, leaf_ty) = child.resolve_internal(leaf_to_output_fn)?;
1343
1344 if !typed_arithmetic_enabled() && !ty.is_number() && !leaf_ty.is_number() {
1347 return Err(());
1348 }
1349
1350 value *= leaf;
1351 ty = NumericType::multiply_two_types(&ty, &leaf_ty)?;
1352 }
1353
1354 Ok((value, ty))
1355 },
1356 Self::MinMax(children, op) => {
1357 let (mut value, mut ty) = children[0].resolve_internal(leaf_to_output_fn)?;
1358
1359 if value.is_nan() {
1360 return Ok((value, ty));
1361 }
1362
1363 for child in children.iter().skip(1) {
1364 let (candidate, candidate_ty) = child.resolve_internal(leaf_to_output_fn)?;
1365
1366 ty = NumericType::add_two_types(&ty, &candidate_ty)?;
1368
1369 if candidate.is_nan() {
1370 value = candidate;
1371 break;
1372 }
1373
1374 value = match op {
1375 MinMaxOp::Min => crate::values::calc_min(value, candidate),
1376 MinMaxOp::Max => crate::values::calc_max(value, candidate),
1377 };
1378 }
1379
1380 Ok((value, ty))
1381 },
1382 Self::Clamp { min, center, max } => {
1383 let (min, min_ty) = min.resolve_internal(leaf_to_output_fn)?;
1384 let (center, center_ty) = center.resolve_internal(leaf_to_output_fn)?;
1385 let (max, max_ty) = max.resolve_internal(leaf_to_output_fn)?;
1386
1387 let mut ty = NumericType::add_two_types(&min_ty, ¢er_ty)?;
1388 ty = NumericType::add_two_types(&ty, &max_ty)?;
1389
1390 if min.is_nan() {
1391 return Ok((min, ty));
1392 }
1393
1394 if center.is_nan() {
1395 return Ok((center, ty));
1396 }
1397
1398 if max.is_nan() {
1399 return Ok((max, ty));
1400 }
1401
1402 let value = crate::values::calc_max(min, crate::values::calc_min(center, max));
1404 Ok((value, ty))
1405 },
1406 Self::Round {
1407 strategy,
1408 value,
1409 step,
1410 } => {
1411 let (mut value, value_ty) = value.resolve_internal(leaf_to_output_fn)?;
1412 let (step, step_ty) = step.resolve_internal(leaf_to_output_fn)?;
1413 let ty = NumericType::add_two_types(&value_ty, &step_ty)?;
1414
1415 let step = step.abs();
1416
1417 if step.is_zero() {
1421 value = f32::NAN;
1422 } else if value.is_infinite() {
1423 if step.is_infinite() {
1424 value = f32::NAN
1425 }
1426 } else if step.is_infinite() {
1427 value = match strategy {
1428 RoundingStrategy::Nearest | RoundingStrategy::ToZero => {
1429 if value.is_sign_negative() { -0.0 } else { 0.0 }
1430 },
1431 RoundingStrategy::Up => {
1432 if !value.is_sign_negative() && !value.is_zero() {
1433 f32::INFINITY
1434 } else if !value.is_sign_negative() && value.is_zero() {
1435 value
1436 } else {
1437 -0.0
1438 }
1439 },
1440 RoundingStrategy::Down => {
1441 if value.is_sign_negative() && !value.is_zero() {
1442 -f32::INFINITY
1443 } else if value.is_sign_negative() && value.is_zero() {
1444 value
1445 } else {
1446 0.0
1447 }
1448 },
1449 };
1450 } else {
1451 let div = value / step;
1452 let lower_bound = div.floor() * step;
1453 let upper_bound = div.ceil() * step;
1454
1455 value = match strategy {
1456 RoundingStrategy::Nearest => {
1457 if value - lower_bound < upper_bound - value {
1459 lower_bound
1460 } else {
1461 upper_bound
1462 }
1463 },
1464 RoundingStrategy::Up => upper_bound,
1465 RoundingStrategy::Down => lower_bound,
1466 RoundingStrategy::ToZero => {
1467 if lower_bound.abs() < upper_bound.abs() {
1469 lower_bound
1470 } else {
1471 upper_bound
1472 }
1473 },
1474 }
1475 }
1476
1477 Ok((value, ty))
1478 },
1479 Self::ModRem {
1480 dividend,
1481 divisor,
1482 op,
1483 } => {
1484 let (dividend, dividend_ty) = dividend.resolve_internal(leaf_to_output_fn)?;
1485 let (divisor, divisor_ty) = divisor.resolve_internal(leaf_to_output_fn)?;
1486 let ty = NumericType::add_two_types(÷nd_ty, &divisor_ty)?;
1487 let value = op.apply(dividend, divisor);
1488 Ok((value, ty))
1489 },
1490 Self::Sin(c) => {
1491 let (value, ty) = c.resolve_internal(leaf_to_output_fn)?;
1492 let radians = match ty.as_calc_type()? {
1493 CalcType::Number => value,
1494 CalcType::Angle => value.to_radians(),
1495 _ => return Err(()),
1496 };
1497 Ok((radians.sin(), NumericType::number()))
1498 },
1499 Self::Cos(c) => {
1500 let (value, ty) = c.resolve_internal(leaf_to_output_fn)?;
1501 let radians = match ty.as_calc_type()? {
1502 CalcType::Number => value,
1503 CalcType::Angle => value.to_radians(),
1504 _ => return Err(()),
1505 };
1506 Ok((radians.cos(), NumericType::number()))
1507 },
1508 Self::Tan(c) => {
1509 let (value, ty) = c.resolve_internal(leaf_to_output_fn)?;
1510 let radians = match ty.as_calc_type()? {
1511 CalcType::Number => value,
1512 CalcType::Angle => value.to_radians(),
1513 _ => return Err(()),
1514 };
1515 Ok((radians.tan(), NumericType::number()))
1516 },
1517 Self::Asin(c) => {
1518 let (value, ty) = c.resolve_internal(leaf_to_output_fn)?;
1519 if !ty.is_number() {
1520 return Err(());
1521 }
1522 Ok((value.asin().to_degrees(), NumericType::angle()))
1523 },
1524 Self::Acos(c) => {
1525 let (value, ty) = c.resolve_internal(leaf_to_output_fn)?;
1526 if !ty.is_number() {
1527 return Err(());
1528 }
1529 Ok((value.acos().to_degrees(), NumericType::angle()))
1530 },
1531 Self::Atan(c) => {
1532 let (value, ty) = c.resolve_internal(leaf_to_output_fn)?;
1533 if !ty.is_number() {
1534 return Err(());
1535 }
1536 Ok((value.atan().to_degrees(), NumericType::angle()))
1537 },
1538 Self::Atan2(a, b) => {
1539 let (a, a_ty) = a.resolve_internal(leaf_to_output_fn)?;
1540 let (b, b_ty) = b.resolve_internal(leaf_to_output_fn)?;
1541 let _ = NumericType::add_two_types(&a_ty, &b_ty)?;
1542 Ok((a.atan2(b).to_degrees(), NumericType::angle()))
1543 },
1544 Self::Pow(a, b) => {
1545 let (a, a_ty) = a.resolve_internal(leaf_to_output_fn)?;
1546 let (b, b_ty) = b.resolve_internal(leaf_to_output_fn)?;
1547 if !a_ty.is_number() || !b_ty.is_number() {
1548 return Err(());
1549 }
1550 Ok((a.powf(b), NumericType::number()))
1551 },
1552 Self::Sqrt(c) => {
1553 let (value, ty) = c.resolve_internal(leaf_to_output_fn)?;
1554 if !ty.is_number() {
1555 return Err(());
1556 }
1557 Ok((value.sqrt(), NumericType::number()))
1558 },
1559 Self::Hypot(children) => {
1560 let (mut value, mut ty) = children[0].resolve_internal(leaf_to_output_fn)?;
1561 value = value.powi(2);
1562
1563 for child in children.iter().skip(1) {
1564 let (child_value, child_ty) = child.resolve_internal(leaf_to_output_fn)?;
1565 ty = NumericType::add_two_types(&ty, &child_ty)?;
1566 value += child_value.powi(2);
1567 }
1568
1569 Ok((value.sqrt(), ty))
1570 },
1571 Self::Log(a, b) => {
1572 let (a, a_ty) = a.resolve_internal(leaf_to_output_fn)?;
1573 if !a_ty.is_number() {
1574 return Err(());
1575 }
1576 let value = match b {
1577 Optional::Some(b) => {
1578 let (b, b_ty) = b.resolve_internal(leaf_to_output_fn)?;
1579 if !b_ty.is_number() {
1580 return Err(());
1581 }
1582 a.log(b)
1583 },
1584 Optional::None => a.ln(),
1585 };
1586 Ok((value, NumericType::number()))
1587 },
1588 Self::Exp(c) => {
1589 let (value, ty) = c.resolve_internal(leaf_to_output_fn)?;
1590 if !ty.is_number() {
1591 return Err(());
1592 }
1593 Ok((value.exp(), NumericType::number()))
1594 },
1595 Self::Abs(c) => {
1596 let (value, ty) = c.resolve_internal(leaf_to_output_fn)?;
1597 Ok((value.abs(), ty))
1598 },
1599 Self::Sign(c) => {
1600 let (value, _) = c.resolve_internal(leaf_to_output_fn)?;
1601 let sign = crate::values::calc_sign(value);
1602 Ok((sign, NumericType::number()))
1603 },
1604 Self::Progress {
1605 clamping_mode,
1606 value,
1607 start,
1608 end,
1609 } => {
1610 let (value, value_ty) = value.resolve_internal(leaf_to_output_fn)?;
1611 let (start, start_ty) = start.resolve_internal(leaf_to_output_fn)?;
1612 let (end, end_ty) = end.resolve_internal(leaf_to_output_fn)?;
1613
1614 let _ = NumericType::add_two_types(&value_ty, &start_ty)?;
1615 let _ = NumericType::add_two_types(&value_ty, &end_ty)?;
1616 let _ = NumericType::add_two_types(&start_ty, &end_ty)?;
1617
1618 let progress = clamping_mode.evaluate(value, start, end);
1619 Ok((progress, NumericType::number()))
1620 },
1621 Self::Random(r) => {
1622 let (base, base_ty) = r.key.resolve_internal(leaf_to_output_fn)?;
1623 if !base_ty.is_number() {
1624 return Err(());
1625 }
1626
1627 let (min, min_ty) = r.min.resolve_internal(leaf_to_output_fn)?;
1628 let (max, max_ty) = r.max.resolve_internal(leaf_to_output_fn)?;
1629 let mut ty = NumericType::add_two_types(&min_ty, &max_ty)?;
1630
1631 let step = match r.step.as_ref() {
1632 Some(step) => {
1633 let (step, step_ty) = step.resolve_internal(leaf_to_output_fn)?;
1634 ty = NumericType::add_two_types(&ty, &step_ty)?;
1635 Some(step)
1636 },
1637 None => None,
1638 };
1639
1640 let value = calc_random(base, min, max, step);
1641 Ok((value, ty))
1642 },
1643 Self::Anchor(_) | Self::AnchorSize(_) => Err(()),
1644 }
1645 }
1646
1647 pub fn map_node<F>(&mut self, mut mapping_fn: F) -> Result<(), ()>
1649 where
1650 F: FnMut(&CalcNode<L>) -> Result<Option<CalcNode<L>>, ()>,
1651 {
1652 self.map_node_internal(&mut mapping_fn)
1653 }
1654
1655 fn map_node_internal<F>(&mut self, mapping_fn: &mut F) -> Result<(), ()>
1656 where
1657 F: FnMut(&CalcNode<L>) -> Result<Option<CalcNode<L>>, ()>,
1658 {
1659 if let Some(node) = mapping_fn(self)? {
1660 *self = node;
1661 return Ok(());
1663 }
1664 match self {
1665 Self::Leaf(_) | Self::Anchor(_) | Self::AnchorSize(_) => (),
1666 Self::Negate(child)
1667 | Self::Invert(child)
1668 | Self::Abs(child)
1669 | Self::Sign(child)
1670 | Self::Sin(child)
1671 | Self::Cos(child)
1672 | Self::Tan(child)
1673 | Self::Asin(child)
1674 | Self::Acos(child)
1675 | Self::Atan(child)
1676 | Self::Sqrt(child)
1677 | Self::Exp(child) => {
1678 child.map_node_internal(mapping_fn)?;
1679 },
1680 Self::Atan2(a, b) => {
1681 a.map_node_internal(mapping_fn)?;
1682 b.map_node_internal(mapping_fn)?;
1683 },
1684 Self::Pow(a, b) => {
1685 a.map_node_internal(mapping_fn)?;
1686 b.map_node_internal(mapping_fn)?;
1687 },
1688 Self::Log(a, b) => {
1689 a.map_node_internal(mapping_fn)?;
1690 if let Optional::Some(b) = b {
1691 b.map_node_internal(mapping_fn)?;
1692 }
1693 },
1694 Self::Sum(children)
1695 | Self::Product(children)
1696 | Self::Hypot(children)
1697 | Self::MinMax(children, _) => {
1698 for child in children.iter_mut() {
1699 child.map_node_internal(mapping_fn)?;
1700 }
1701 },
1702 Self::Clamp { min, center, max } => {
1703 min.map_node_internal(mapping_fn)?;
1704 center.map_node_internal(mapping_fn)?;
1705 max.map_node_internal(mapping_fn)?;
1706 },
1707 Self::Round { value, step, .. } => {
1708 value.map_node_internal(mapping_fn)?;
1709 step.map_node_internal(mapping_fn)?;
1710 },
1711 Self::ModRem {
1712 dividend, divisor, ..
1713 } => {
1714 dividend.map_node_internal(mapping_fn)?;
1715 divisor.map_node_internal(mapping_fn)?;
1716 },
1717 Self::Progress {
1718 value, start, end, ..
1719 } => {
1720 value.map_node_internal(mapping_fn)?;
1721 start.map_node_internal(mapping_fn)?;
1722 end.map_node_internal(mapping_fn)?;
1723 },
1724 Self::Random(random) => {
1725 random.key.map_node_internal(mapping_fn)?;
1726 random.min.map_node_internal(mapping_fn)?;
1727 random.max.map_node_internal(mapping_fn)?;
1728 if let Some(step) = random.step.as_mut() {
1729 step.map_node_internal(mapping_fn)?;
1730 }
1731 },
1732 };
1733 Ok(())
1734 }
1735
1736 fn is_negative_leaf(&self) -> Result<bool, ()> {
1737 Ok(match *self {
1738 Self::Leaf(ref l) => l.is_negative()?,
1739 _ => false,
1740 })
1741 }
1742
1743 fn is_zero_leaf(&self) -> Result<bool, ()> {
1744 Ok(match *self {
1745 Self::Leaf(ref l) => l.is_zero()?,
1746 _ => false,
1747 })
1748 }
1749
1750 fn is_infinite_leaf(&self) -> Result<bool, ()> {
1751 Ok(match *self {
1752 Self::Leaf(ref l) => l.is_infinite()?,
1753 _ => false,
1754 })
1755 }
1756
1757 fn is_nan_leaf(&self) -> Result<bool, ()> {
1758 Ok(match *self {
1759 Self::Leaf(ref l) => l.is_nan()?,
1760 _ => false,
1761 })
1762 }
1763
1764 pub fn visit_depth_first(&mut self, mut f: impl FnMut(&mut Self)) {
1770 self.visit_depth_first_internal(&mut f)
1771 }
1772
1773 fn visit_depth_first_internal(&mut self, f: &mut impl FnMut(&mut Self)) {
1774 match *self {
1775 Self::Clamp {
1776 ref mut min,
1777 ref mut center,
1778 ref mut max,
1779 } => {
1780 min.visit_depth_first_internal(f);
1781 center.visit_depth_first_internal(f);
1782 max.visit_depth_first_internal(f);
1783 },
1784 Self::Round {
1785 ref mut value,
1786 ref mut step,
1787 ..
1788 } => {
1789 value.visit_depth_first_internal(f);
1790 step.visit_depth_first_internal(f);
1791 },
1792 Self::ModRem {
1793 ref mut dividend,
1794 ref mut divisor,
1795 ..
1796 } => {
1797 dividend.visit_depth_first_internal(f);
1798 divisor.visit_depth_first_internal(f);
1799 },
1800 Self::Sum(ref mut children)
1801 | Self::Product(ref mut children)
1802 | Self::MinMax(ref mut children, _)
1803 | Self::Hypot(ref mut children) => {
1804 for child in &mut **children {
1805 child.visit_depth_first_internal(f);
1806 }
1807 },
1808 Self::Negate(ref mut value) | Self::Invert(ref mut value) => {
1809 value.visit_depth_first_internal(f);
1810 },
1811 Self::Sin(ref mut value)
1812 | Self::Cos(ref mut value)
1813 | Self::Tan(ref mut value)
1814 | Self::Asin(ref mut value)
1815 | Self::Acos(ref mut value)
1816 | Self::Atan(ref mut value)
1817 | Self::Sqrt(ref mut value)
1818 | Self::Exp(ref mut value) => {
1819 value.visit_depth_first_internal(f);
1820 },
1821 Self::Atan2(ref mut a, ref mut b) => {
1822 a.visit_depth_first_internal(f);
1823 b.visit_depth_first_internal(f);
1824 },
1825 Self::Pow(ref mut a, ref mut b) => {
1826 a.visit_depth_first_internal(f);
1827 b.visit_depth_first_internal(f);
1828 },
1829 Self::Log(ref mut a, ref mut b) => {
1830 a.visit_depth_first_internal(f);
1831 if let Optional::Some(b) = b {
1832 b.visit_depth_first_internal(f);
1833 }
1834 },
1835 Self::Abs(ref mut value) | Self::Sign(ref mut value) => {
1836 value.visit_depth_first_internal(f);
1837 },
1838 Self::Progress {
1839 ref mut value,
1840 ref mut start,
1841 ref mut end,
1842 ..
1843 } => {
1844 value.visit_depth_first_internal(f);
1845 start.visit_depth_first_internal(f);
1846 end.visit_depth_first_internal(f);
1847 },
1848 Self::Random(ref mut random) => {
1849 random.key.visit_depth_first_internal(f);
1850 random.min.visit_depth_first_internal(f);
1851 random.max.visit_depth_first_internal(f);
1852 if let Some(step) = random.step.as_mut() {
1853 step.visit_depth_first_internal(f);
1854 }
1855 },
1856 Self::Leaf(..) | Self::Anchor(..) | Self::AnchorSize(..) => {},
1857 }
1858 f(self);
1859 }
1860
1861 pub fn simplify_and_sort_direct_children(&mut self) -> SimplificationResult {
1872 macro_rules! replace_self_with {
1873 ($slot:expr) => {{
1874 let result = mem::replace($slot, Self::dummy());
1875 *self = result;
1876 }};
1877 }
1878
1879 macro_rules! value_or_stop {
1880 ($op:expr) => {{
1881 match $op {
1882 Ok(value) => value,
1883 Err(_) => return SimplificationResult::Unchanged,
1884 }
1885 }};
1886 }
1887
1888 match *self {
1889 Self::Clamp {
1890 ref mut min,
1891 ref mut center,
1892 ref mut max,
1893 } => {
1894 let min_cmp_center = match min.compare(center) {
1896 Some(o) => o,
1897 None => return SimplificationResult::Unchanged,
1898 };
1899
1900 if matches!(min_cmp_center, cmp::Ordering::Greater) {
1903 replace_self_with!(&mut **min);
1904 return SimplificationResult::Simplified;
1905 }
1906
1907 let max_cmp_center = match max.compare(center) {
1909 Some(o) => o,
1910 None => return SimplificationResult::Unchanged,
1911 };
1912
1913 if matches!(max_cmp_center, cmp::Ordering::Less) {
1914 let max_cmp_min = match max.compare(min) {
1917 Some(o) => o,
1918 None => return SimplificationResult::Unchanged,
1919 };
1920
1921 if matches!(max_cmp_min, cmp::Ordering::Less) {
1922 replace_self_with!(&mut **min);
1923 return SimplificationResult::Simplified;
1924 }
1925
1926 replace_self_with!(&mut **max);
1927 return SimplificationResult::Simplified;
1928 }
1929
1930 replace_self_with!(&mut **center);
1932 SimplificationResult::Simplified
1933 },
1934 Self::Round {
1935 strategy,
1936 ref mut value,
1937 ref mut step,
1938 } => {
1939 if value_or_stop!(step.is_zero_leaf()) {
1940 value_or_stop!(value.coerce_to_value(f32::NAN));
1941 replace_self_with!(&mut **value);
1942 return SimplificationResult::Simplified;
1943 }
1944
1945 if value_or_stop!(value.is_infinite_leaf())
1946 && value_or_stop!(step.is_infinite_leaf())
1947 {
1948 value_or_stop!(value.coerce_to_value(f32::NAN));
1949 replace_self_with!(&mut **value);
1950 return SimplificationResult::Simplified;
1951 }
1952
1953 if value_or_stop!(value.is_infinite_leaf()) {
1954 replace_self_with!(&mut **value);
1955 return SimplificationResult::Simplified;
1956 }
1957
1958 if value_or_stop!(step.is_infinite_leaf()) {
1959 match strategy {
1960 RoundingStrategy::Nearest | RoundingStrategy::ToZero => {
1961 value_or_stop!(value.coerce_to_value(0.0));
1962 replace_self_with!(&mut **value);
1963 return SimplificationResult::Simplified;
1964 },
1965 RoundingStrategy::Up => {
1966 if !value_or_stop!(value.is_negative_leaf())
1967 && !value_or_stop!(value.is_zero_leaf())
1968 {
1969 value_or_stop!(value.coerce_to_value(f32::INFINITY));
1970 replace_self_with!(&mut **value);
1971 return SimplificationResult::Simplified;
1972 } else if !value_or_stop!(value.is_negative_leaf())
1973 && value_or_stop!(value.is_zero_leaf())
1974 {
1975 replace_self_with!(&mut **value);
1976 return SimplificationResult::Simplified;
1977 } else {
1978 value_or_stop!(value.coerce_to_value(0.0));
1979 replace_self_with!(&mut **value);
1980 return SimplificationResult::Simplified;
1981 }
1982 },
1983 RoundingStrategy::Down => {
1984 if value_or_stop!(value.is_negative_leaf())
1985 && !value_or_stop!(value.is_zero_leaf())
1986 {
1987 value_or_stop!(value.coerce_to_value(-f32::INFINITY));
1988 replace_self_with!(&mut **value);
1989 return SimplificationResult::Simplified;
1990 } else if value_or_stop!(value.is_negative_leaf())
1991 && value_or_stop!(value.is_zero_leaf())
1992 {
1993 replace_self_with!(&mut **value);
1994 return SimplificationResult::Simplified;
1995 } else {
1996 value_or_stop!(value.coerce_to_value(0.0));
1997 replace_self_with!(&mut **value);
1998 return SimplificationResult::Simplified;
1999 }
2000 },
2001 }
2002 }
2003
2004 if value_or_stop!(step.is_negative_leaf()) {
2005 step.negate();
2006 }
2007
2008 let remainder = value_or_stop!(value.try_op(step, Rem::rem));
2009 if value_or_stop!(remainder.is_zero_leaf()) {
2010 replace_self_with!(&mut **value);
2011 return SimplificationResult::Simplified;
2012 }
2013
2014 let (mut lower_bound, mut upper_bound) = if value_or_stop!(value.is_negative_leaf())
2015 {
2016 let upper_bound = value_or_stop!(value.try_op(&remainder, Sub::sub));
2017 let lower_bound = value_or_stop!(upper_bound.try_op(step, Sub::sub));
2018
2019 (lower_bound, upper_bound)
2020 } else {
2021 let lower_bound = value_or_stop!(value.try_op(&remainder, Sub::sub));
2022 let upper_bound = value_or_stop!(lower_bound.try_op(step, Add::add));
2023
2024 (lower_bound, upper_bound)
2025 };
2026
2027 match strategy {
2028 RoundingStrategy::Nearest => {
2029 let lower_diff = value_or_stop!(value.try_op(&lower_bound, Sub::sub));
2030 let upper_diff = value_or_stop!(upper_bound.try_op(value, Sub::sub));
2031 if lower_diff.lt(&upper_diff) {
2033 replace_self_with!(&mut lower_bound);
2034 } else {
2035 replace_self_with!(&mut upper_bound);
2036 }
2037 },
2038 RoundingStrategy::Up => {
2039 replace_self_with!(&mut upper_bound);
2040 },
2041 RoundingStrategy::Down => {
2042 replace_self_with!(&mut lower_bound);
2043 },
2044 RoundingStrategy::ToZero => {
2045 let mut lower_diff = lower_bound.clone();
2046 let mut upper_diff = upper_bound.clone();
2047
2048 if value_or_stop!(lower_diff.is_negative_leaf()) {
2049 lower_diff.negate();
2050 }
2051
2052 if value_or_stop!(upper_diff.is_negative_leaf()) {
2053 upper_diff.negate();
2054 }
2055
2056 if lower_diff.lt(&upper_diff) {
2058 replace_self_with!(&mut lower_bound);
2059 } else {
2060 replace_self_with!(&mut upper_bound);
2061 }
2062 },
2063 };
2064 SimplificationResult::Simplified
2065 },
2066 Self::ModRem {
2067 ref dividend,
2068 ref divisor,
2069 op,
2070 } => {
2071 let mut result = value_or_stop!(dividend.try_op(divisor, |a, b| op.apply(a, b)));
2072 replace_self_with!(&mut result);
2073 SimplificationResult::Simplified
2074 },
2075 Self::MinMax(ref mut children, op) => {
2076 let winning_order = match op {
2077 MinMaxOp::Min => cmp::Ordering::Less,
2078 MinMaxOp::Max => cmp::Ordering::Greater,
2079 };
2080
2081 if value_or_stop!(children[0].is_nan_leaf()) {
2082 replace_self_with!(&mut children[0]);
2083 return SimplificationResult::Simplified;
2084 }
2085
2086 let mut result = 0;
2087 for i in 1..children.len() {
2088 if value_or_stop!(children[i].is_nan_leaf()) {
2089 replace_self_with!(&mut children[i]);
2090 return SimplificationResult::Simplified;
2091 }
2092 let o = match children[i].compare(&children[result]) {
2093 None => return SimplificationResult::Unchanged,
2100 Some(o) => o,
2101 };
2102
2103 if o == winning_order {
2104 result = i;
2105 }
2106 }
2107
2108 replace_self_with!(&mut children[result]);
2109 SimplificationResult::Simplified
2110 },
2111 Self::Sum(ref mut children_slot) => {
2112 let mut sums_to_merge = SmallVec::<[_; 3]>::new();
2113 let mut extra_kids = 0;
2114 for (i, child) in children_slot.iter().enumerate() {
2115 if let Self::Sum(ref children) = *child {
2116 extra_kids += children.len();
2117 sums_to_merge.push(i);
2118 }
2119 }
2120
2121 if children_slot.len() == 1 {
2125 replace_self_with!(&mut children_slot[0]);
2126 return SimplificationResult::Simplified;
2127 }
2128
2129 let mut children = mem::take(children_slot).into_vec();
2130
2131 if !sums_to_merge.is_empty() {
2132 children.reserve(extra_kids - sums_to_merge.len());
2133 for i in sums_to_merge.drain(..).rev() {
2136 let kid_children = match children.swap_remove(i) {
2137 Self::Sum(c) => c,
2138 _ => unreachable!(),
2139 };
2140
2141 children.extend(kid_children.into_vec());
2144 }
2145 }
2146
2147 let children_len = children.len();
2148 debug_assert!(children_len >= 2, "Should still have multiple kids!");
2149
2150 children.sort_unstable_by_key(|c| c.sort_key());
2152
2153 children.dedup_by(|a, b| b.try_sum_in_place(a).is_ok());
2156
2157 let updated_children_len = children.len();
2158 if updated_children_len == 1 {
2159 replace_self_with!(&mut children[0]);
2161 } else {
2162 *children_slot = children.into_boxed_slice().into();
2164 }
2165
2166 if updated_children_len != children_len {
2167 SimplificationResult::Simplified
2168 } else {
2169 SimplificationResult::Unchanged
2170 }
2171 },
2172 Self::Product(ref mut children_slot) => {
2173 let mut products_to_merge = SmallVec::<[_; 3]>::new();
2174 let mut extra_kids = 0;
2175 for (i, child) in children_slot.iter().enumerate() {
2176 if let Self::Product(ref children) = *child {
2177 extra_kids += children.len();
2178 products_to_merge.push(i);
2179 }
2180 }
2181
2182 if children_slot.len() == 1 {
2186 replace_self_with!(&mut children_slot[0]);
2187 return SimplificationResult::Unchanged;
2188 }
2189
2190 let mut children = mem::take(children_slot).into_vec();
2191 if !products_to_merge.is_empty() {
2192 children.reserve(extra_kids - products_to_merge.len());
2193 for i in products_to_merge.drain(..).rev() {
2196 let kid_children = match children.swap_remove(i) {
2197 Self::Product(c) => c,
2198 _ => unreachable!(),
2199 };
2200
2201 children.extend(kid_children.into_vec());
2204 }
2205 }
2206
2207 debug_assert!(children.len() >= 2, "Should still have multiple kids!");
2208
2209 children.sort_unstable_by_key(|c| c.sort_key());
2211
2212 children.dedup_by(|right, left| left.try_product_in_place(right));
2215
2216 if children.len() == 1 {
2217 replace_self_with!(&mut children[0]);
2219 return SimplificationResult::Simplified;
2220 }
2221
2222 if typed_arithmetic_enabled() {
2223 let mut result = 1.0;
2232 let mut ty = Ok(NumericType::number());
2233
2234 for child in children.iter() {
2235 let (leaf, is_inverted) = match child {
2236 Self::Leaf(leaf) => (leaf, false),
2237 Self::Invert(inner) if inner.as_leaf().is_some() => {
2238 (inner.as_leaf().unwrap(), true)
2239 },
2240 _ => {
2241 ty = Err(());
2242 break;
2243 },
2244 };
2245
2246 let Some(value) = leaf.canonical_value() else {
2248 ty = Err(());
2249 break;
2250 };
2251 let (multiplicand, child_ty) = if is_inverted {
2252 let mut ty = leaf.numeric_type();
2253 ty.invert();
2254 (1.0 / value, ty)
2255 } else {
2256 (value, leaf.numeric_type())
2257 };
2258
2259 result *= multiplicand;
2260 ty = ty.and_then(|ty| NumericType::multiply_two_types(&ty, &child_ty));
2261 }
2262
2263 if let Ok(leaf) = ty.and_then(|ty| L::new_from_typed_value(result, ty)) {
2264 let mut result = Self::Leaf(leaf);
2265 replace_self_with!(&mut result);
2266 return SimplificationResult::Simplified;
2267 }
2268 }
2269
2270 *children_slot = children.into_boxed_slice().into();
2272 SimplificationResult::Unchanged
2273 },
2274 Self::Sin(ref mut child) => {
2275 if let CalcNode::Leaf(ref leaf) = **child
2276 && let Some(radians) = leaf.as_number_or_angle_radians()
2277 {
2278 let mut result = Self::Leaf(L::new_number(radians.sin()));
2279 replace_self_with!(&mut result);
2280 return SimplificationResult::Simplified;
2281 }
2282 SimplificationResult::Unchanged
2283 },
2284 Self::Cos(ref mut child) => {
2285 if let CalcNode::Leaf(ref leaf) = **child
2286 && let Some(radians) = leaf.as_number_or_angle_radians()
2287 {
2288 let mut result = Self::Leaf(L::new_number(radians.cos()));
2289 replace_self_with!(&mut result);
2290 return SimplificationResult::Simplified;
2291 }
2292 SimplificationResult::Unchanged
2293 },
2294 Self::Tan(ref mut child) => {
2295 if let CalcNode::Leaf(ref leaf) = **child
2296 && let Some(radians) = leaf.as_number_or_angle_radians()
2297 {
2298 let mut result = Self::Leaf(L::new_number(radians.tan()));
2299 replace_self_with!(&mut result);
2300 return SimplificationResult::Simplified;
2301 }
2302 SimplificationResult::Unchanged
2303 },
2304 Self::Asin(ref mut child) => {
2305 if let CalcNode::Leaf(ref leaf) = **child
2306 && let Some(value) = leaf.as_number()
2307 {
2308 let mut result = Self::Leaf(L::new_angle_from_radians(value.asin()));
2309 replace_self_with!(&mut result);
2310 return SimplificationResult::Simplified;
2311 }
2312 SimplificationResult::Unchanged
2313 },
2314 Self::Acos(ref mut child) => {
2315 if let CalcNode::Leaf(ref leaf) = **child
2316 && let Some(value) = leaf.as_number()
2317 {
2318 let mut result = Self::Leaf(L::new_angle_from_radians(value.acos()));
2319 replace_self_with!(&mut result);
2320 return SimplificationResult::Simplified;
2321 }
2322 SimplificationResult::Unchanged
2323 },
2324 Self::Atan(ref mut child) => {
2325 if let CalcNode::Leaf(ref leaf) = **child
2326 && let Some(value) = leaf.as_number()
2327 {
2328 let mut result = Self::Leaf(L::new_angle_from_radians(value.atan()));
2329 replace_self_with!(&mut result);
2330 return SimplificationResult::Simplified;
2331 }
2332 SimplificationResult::Unchanged
2333 },
2334 Self::Atan2(ref mut a, ref mut b) => {
2335 if let (CalcNode::Leaf(la), CalcNode::Leaf(lb)) = (&**a, &**b)
2336 && la.is_same_unit_as(lb)
2337 && let (Some(a_val), Some(b_val)) = (la.unitless_value(), lb.unitless_value())
2338 {
2339 let mut result = Self::Leaf(L::new_angle_from_radians(a_val.atan2(b_val)));
2340 replace_self_with!(&mut result);
2341 return SimplificationResult::Simplified;
2342 }
2343 SimplificationResult::Unchanged
2344 },
2345 Self::Pow(ref mut a, ref mut b) => {
2346 if let (CalcNode::Leaf(la), CalcNode::Leaf(lb)) = (&**a, &**b)
2347 && let (Some(a_val), Some(b_val)) = (la.as_number(), lb.as_number())
2348 {
2349 let mut result = Self::Leaf(L::new_number(a_val.powf(b_val)));
2350 replace_self_with!(&mut result);
2351 return SimplificationResult::Simplified;
2352 }
2353 SimplificationResult::Unchanged
2354 },
2355 Self::Sqrt(ref mut child) => {
2356 if let CalcNode::Leaf(ref leaf) = **child
2357 && let Some(value) = leaf.as_number()
2358 {
2359 let mut result = Self::Leaf(L::new_number(value.sqrt()));
2360 replace_self_with!(&mut result);
2361 return SimplificationResult::Simplified;
2362 }
2363 SimplificationResult::Unchanged
2364 },
2365 Self::Hypot(ref children) => {
2366 let mut result = value_or_stop!(children[0].try_op(&children[0], Mul::mul));
2367
2368 for child in children.iter().skip(1) {
2369 let square = value_or_stop!(child.try_op(child, Mul::mul));
2370 result = value_or_stop!(result.try_op(&square, Add::add));
2371 }
2372
2373 result = value_or_stop!(result.try_op(&result, |a, _| a.sqrt()));
2374
2375 replace_self_with!(&mut result);
2376 SimplificationResult::Simplified
2377 },
2378 Self::Log(ref mut a, ref mut b) => {
2379 if let CalcNode::Leaf(ref la) = **a
2380 && let Some(a_val) = la.as_number()
2381 {
2382 let folded = match b {
2383 &mut Optional::Some(ref b) => {
2384 if let CalcNode::Leaf(ref lb) = **b {
2385 lb.as_number().map(|b_val| a_val.log(b_val))
2386 } else {
2387 None
2388 }
2389 },
2390 Optional::None => Some(a_val.ln()),
2391 };
2392 if let Some(number) = folded {
2393 let mut result = Self::Leaf(L::new_number(number));
2394 replace_self_with!(&mut result);
2395 return SimplificationResult::Simplified;
2396 }
2397 }
2398 SimplificationResult::Unchanged
2399 },
2400 Self::Exp(ref mut child) => {
2401 if let CalcNode::Leaf(ref leaf) = **child
2402 && let Some(value) = leaf.as_number()
2403 {
2404 let mut result = Self::Leaf(L::new_number(value.exp()));
2405 replace_self_with!(&mut result);
2406 return SimplificationResult::Simplified;
2407 }
2408 SimplificationResult::Unchanged
2409 },
2410 Self::Abs(ref mut child) => {
2411 if let CalcNode::Leaf(leaf) = child.as_mut() {
2412 value_or_stop!(leaf.map(|v| v.abs()));
2413 replace_self_with!(&mut **child);
2414 return SimplificationResult::Simplified;
2415 }
2416 SimplificationResult::Unchanged
2417 },
2418 Self::Sign(ref mut child) => {
2419 if let CalcNode::Leaf(leaf) = child.as_mut() {
2420 let mut result = Self::Leaf(value_or_stop!(L::sign_from(leaf)));
2421 replace_self_with!(&mut result);
2422 return SimplificationResult::Simplified;
2423 }
2424 SimplificationResult::Unchanged
2425 },
2426 Self::Negate(ref mut child) => {
2427 match &mut **child {
2429 CalcNode::Leaf(_) => {
2430 child.negate();
2433 replace_self_with!(&mut **child);
2434 SimplificationResult::Simplified
2435 },
2436 CalcNode::Negate(value) => {
2437 replace_self_with!(&mut **value);
2439 SimplificationResult::Simplified
2440 },
2441 _ => {
2442 SimplificationResult::Unchanged
2444 },
2445 }
2446 },
2447 Self::Invert(ref mut child) => {
2448 match &mut **child {
2450 CalcNode::Leaf(leaf) => {
2451 if leaf.numeric_type().is_number() {
2454 value_or_stop!(child.map(|v| 1.0 / v));
2455 replace_self_with!(&mut **child);
2456 return SimplificationResult::Simplified;
2457 }
2458 SimplificationResult::Unchanged
2459 },
2460 CalcNode::Invert(value) => {
2461 replace_self_with!(&mut **value);
2463 SimplificationResult::Simplified
2464 },
2465 _ => {
2466 SimplificationResult::Unchanged
2468 },
2469 }
2470 },
2471 Self::Progress {
2472 clamping_mode,
2473 ref mut value,
2474 ref mut start,
2475 ref mut end,
2476 } => {
2477 if let (CalcNode::Leaf(value), CalcNode::Leaf(start), CalcNode::Leaf(end)) =
2478 (&**value, &**start, &**end)
2479 && value.is_same_unit_as(start)
2480 && value.is_same_unit_as(end)
2481 && let (Some(value), Some(start), Some(end)) = (
2482 value.unitless_value(),
2483 start.unitless_value(),
2484 end.unitless_value(),
2485 )
2486 {
2487 let mut result =
2488 Self::Leaf(L::new_number(clamping_mode.evaluate(value, start, end)));
2489 replace_self_with!(&mut result);
2490 return SimplificationResult::Simplified;
2491 }
2492 SimplificationResult::Unchanged
2493 },
2494 Self::Random(ref mut r) => {
2495 let (
2496 CalcNode::Leaf(key_leaf),
2497 CalcNode::Leaf(min_leaf),
2498 CalcNode::Leaf(max_leaf),
2499 ) = (&r.key, &r.min, &r.max)
2500 else {
2501 return SimplificationResult::Unchanged;
2502 };
2503
2504 if !min_leaf.is_same_unit_as(max_leaf) {
2505 return SimplificationResult::Unchanged;
2506 }
2507
2508 let (Some(base), Some(min), Some(max)) = (
2509 key_leaf.canonical_value(),
2510 min_leaf.canonical_value(),
2511 max_leaf.canonical_value(),
2512 ) else {
2513 return SimplificationResult::Unchanged;
2514 };
2515
2516 let step = match &r.step {
2517 Optional::Some(step) => {
2518 let CalcNode::Leaf(step_leaf) = step else {
2519 return SimplificationResult::Unchanged;
2520 };
2521 if !min_leaf.is_same_unit_as(step_leaf) {
2522 return SimplificationResult::Unchanged;
2523 }
2524 let Some(step) = step_leaf.unitless_value() else {
2525 return SimplificationResult::Unchanged;
2526 };
2527 Some(step)
2528 },
2529 Optional::None => None,
2530 };
2531
2532 let result = calc_random(base, min, max, step);
2533 if r.min.coerce_to_value(result).is_err() {
2534 return SimplificationResult::Unchanged;
2535 }
2536 replace_self_with!(&mut r.min);
2537 SimplificationResult::Simplified
2538 },
2539 Self::Leaf(ref mut l) => l.simplify(),
2540 Self::Anchor(ref mut f) => {
2541 if let GenericAnchorSide::Percentage(ref mut n) = f.side {
2542 n.simplify_and_sort();
2543 return SimplificationResult::Simplified;
2544 }
2545 if let Some(fallback) = f.fallback.as_mut() {
2546 return fallback.node.simplify_and_sort();
2547 }
2548 SimplificationResult::Unchanged
2549 },
2550 Self::AnchorSize(ref mut f) => {
2551 if let Some(fallback) = f.fallback.as_mut() {
2552 return fallback.node.simplify_and_sort();
2553 }
2554 SimplificationResult::Unchanged
2555 },
2556 }
2557 }
2558
2559 pub fn simplify_and_sort(&mut self) -> SimplificationResult {
2561 let mut res = SimplificationResult::Unchanged;
2562 self.visit_depth_first(|node| {
2563 if let SimplificationResult::Simplified = node.simplify_and_sort_direct_children() {
2564 res = SimplificationResult::Simplified;
2565 }
2566 });
2567 res
2568 }
2569
2570 fn to_css_impl<W>(&self, dest: &mut CssWriter<W>, level: ArgumentLevel) -> fmt::Result
2571 where
2572 W: Write,
2573 {
2574 let write_closing_paren = match self {
2575 Self::MinMax(_, op) => {
2576 dest.write_str(match op {
2577 MinMaxOp::Max => "max(",
2578 MinMaxOp::Min => "min(",
2579 })?;
2580 true
2581 },
2582 Self::Clamp { .. } => {
2583 dest.write_str("clamp(")?;
2584 true
2585 },
2586 Self::Round { strategy, .. } => {
2587 match strategy {
2588 RoundingStrategy::Nearest => dest.write_str("round("),
2589 RoundingStrategy::Up => dest.write_str("round(up, "),
2590 RoundingStrategy::Down => dest.write_str("round(down, "),
2591 RoundingStrategy::ToZero => dest.write_str("round(to-zero, "),
2592 }?;
2593
2594 true
2595 },
2596 Self::ModRem { op, .. } => {
2597 dest.write_str(match op {
2598 ModRemOp::Mod => "mod(",
2599 ModRemOp::Rem => "rem(",
2600 })?;
2601
2602 true
2603 },
2604 Self::Sin(_) => {
2605 dest.write_str("sin(")?;
2606 true
2607 },
2608 Self::Cos(_) => {
2609 dest.write_str("cos(")?;
2610 true
2611 },
2612 Self::Tan(_) => {
2613 dest.write_str("tan(")?;
2614 true
2615 },
2616 Self::Asin(_) => {
2617 dest.write_str("asin(")?;
2618 true
2619 },
2620 Self::Acos(_) => {
2621 dest.write_str("acos(")?;
2622 true
2623 },
2624 Self::Atan(_) => {
2625 dest.write_str("atan(")?;
2626 true
2627 },
2628 Self::Atan2(..) => {
2629 dest.write_str("atan2(")?;
2630 true
2631 },
2632 Self::Pow(..) => {
2633 dest.write_str("pow(")?;
2634 true
2635 },
2636 Self::Sqrt(_) => {
2637 dest.write_str("sqrt(")?;
2638 true
2639 },
2640 Self::Hypot(_) => {
2641 dest.write_str("hypot(")?;
2642 true
2643 },
2644 Self::Log(..) => {
2645 dest.write_str("log(")?;
2646 true
2647 },
2648 Self::Exp(_) => {
2649 dest.write_str("exp(")?;
2650 true
2651 },
2652 Self::Abs(_) => {
2653 dest.write_str("abs(")?;
2654 true
2655 },
2656 Self::Sign(_) => {
2657 dest.write_str("sign(")?;
2658 true
2659 },
2660 Self::Progress { .. } => {
2661 dest.write_str("progress(")?;
2662 true
2663 },
2664 Self::Random(_) => {
2665 dest.write_str("random(")?;
2666 true
2667 },
2668 Self::Negate(_) => {
2669 debug_assert!(
2673 false,
2674 "We never serialize Negate nodes as they are handled inside Sum nodes."
2675 );
2676 dest.write_str("(-1 * ")?;
2677 true
2678 },
2679 Self::Invert(_) => {
2680 if matches!(level, ArgumentLevel::CalculationRoot) {
2681 dest.write_str("calc")?;
2682 }
2683 dest.write_str("(1 / ")?;
2684 true
2685 },
2686 Self::Sum(_) | Self::Product(_) => match level {
2687 ArgumentLevel::CalculationRoot => {
2688 dest.write_str("calc(")?;
2689 true
2690 },
2691 ArgumentLevel::ArgumentRoot => false,
2692 ArgumentLevel::Nested => {
2693 dest.write_str("(")?;
2694 true
2695 },
2696 },
2697 Self::Leaf(leaf) => match level {
2698 ArgumentLevel::CalculationRoot => {
2699 if leaf.should_serialize_with_root_calc_wrapper() {
2700 dest.write_str("calc(")?;
2701 true
2702 } else {
2703 false
2704 }
2705 },
2706 ArgumentLevel::ArgumentRoot | ArgumentLevel::Nested => false,
2707 },
2708 Self::Anchor(_) | Self::AnchorSize(_) => false,
2709 };
2710
2711 match *self {
2712 Self::MinMax(ref children, _) | Self::Hypot(ref children) => {
2713 let mut first = true;
2714 for child in &**children {
2715 if !first {
2716 dest.write_str(", ")?;
2717 }
2718 first = false;
2719 child.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2720 }
2721 },
2722 Self::Negate(ref value) | Self::Invert(ref value) => {
2723 value.to_css_impl(dest, ArgumentLevel::Nested)?
2724 },
2725 Self::Sum(ref children) => {
2726 let mut first = true;
2727 for child in &**children {
2728 if !first {
2729 match child {
2730 Self::Leaf(l) => {
2731 if let Ok(true) = l.is_negative() {
2732 dest.write_str(" - ")?;
2733 let mut negated = l.clone();
2734 negated.map(std::ops::Neg::neg).unwrap();
2737 negated.to_css(dest)?;
2738 } else {
2739 dest.write_str(" + ")?;
2740 l.to_css(dest)?;
2741 }
2742 },
2743 Self::Negate(n) => {
2744 dest.write_str(" - ")?;
2745 n.to_css_impl(dest, ArgumentLevel::Nested)?;
2746 },
2747 _ => {
2748 dest.write_str(" + ")?;
2749 child.to_css_impl(dest, ArgumentLevel::Nested)?;
2750 },
2751 }
2752 } else {
2753 first = false;
2754 child.to_css_impl(dest, ArgumentLevel::Nested)?;
2755 }
2756 }
2757 },
2758 Self::Product(ref children) => {
2759 let mut first = true;
2760 for child in &**children {
2761 if !first {
2762 match child {
2763 Self::Invert(n) => {
2764 dest.write_str(" / ")?;
2765 n.to_css_impl(dest, ArgumentLevel::Nested)?;
2766 },
2767 _ => {
2768 dest.write_str(" * ")?;
2769 child.to_css_impl(dest, ArgumentLevel::Nested)?;
2770 },
2771 }
2772 } else {
2773 first = false;
2774 child.to_css_impl(dest, ArgumentLevel::Nested)?;
2775 }
2776 }
2777 },
2778 Self::Clamp {
2779 ref min,
2780 ref center,
2781 ref max,
2782 } => {
2783 min.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2784 dest.write_str(", ")?;
2785 center.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2786 dest.write_str(", ")?;
2787 max.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2788 },
2789 Self::Round {
2790 ref value,
2791 ref step,
2792 ..
2793 } => {
2794 value.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2795 dest.write_str(", ")?;
2796 step.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2797 },
2798 Self::ModRem {
2799 ref dividend,
2800 ref divisor,
2801 ..
2802 } => {
2803 dividend.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2804 dest.write_str(", ")?;
2805 divisor.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2806 },
2807 Self::Sin(ref v)
2808 | Self::Cos(ref v)
2809 | Self::Tan(ref v)
2810 | Self::Asin(ref v)
2811 | Self::Acos(ref v)
2812 | Self::Atan(ref v) => v.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?,
2813 Self::Atan2(ref a, ref b) => {
2814 a.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2815 dest.write_str(", ")?;
2816 b.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2817 },
2818 Self::Pow(ref a, ref b) => {
2819 a.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2820 dest.write_str(", ")?;
2821 b.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2822 },
2823 Self::Sqrt(ref v) | Self::Exp(ref v) => {
2824 v.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?
2825 },
2826 Self::Log(ref a, ref b) => {
2827 a.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2828 if let Optional::Some(b) = b {
2829 dest.write_str(", ")?;
2830 b.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2831 }
2832 },
2833 Self::Abs(ref v) | Self::Sign(ref v) => {
2834 v.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?
2835 },
2836 Self::Progress {
2837 clamping_mode,
2838 ref value,
2839 ref start,
2840 ref end,
2841 } => {
2842 if clamping_mode == ProgressClampingMode::NoClamp {
2843 clamping_mode.to_css(dest)?;
2844 dest.write_char(' ')?;
2845 }
2846 value.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2847 dest.write_str(", ")?;
2848 start.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2849 dest.write_str(", ")?;
2850 end.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2851 },
2852 Self::Random(ref r) => {
2853 if r.key.as_leaf().and_then(|l| l.as_number()).is_some() {
2855 dest.write_str("fixed ")?;
2856 }
2857 r.key.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2858 dest.write_str(", ")?;
2859 r.min.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2860 dest.write_str(", ")?;
2861 r.max.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2862 if let Some(step) = r.step.as_ref() {
2863 dest.write_str(", ")?;
2864 step.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2865 }
2866 },
2867 Self::Leaf(ref l) => l.to_css(dest)?,
2868 Self::Anchor(ref f) => f.to_css(dest)?,
2869 Self::AnchorSize(ref f) => f.to_css(dest)?,
2870 }
2871
2872 if write_closing_paren {
2873 dest.write_char(')')?;
2874 }
2875 Ok(())
2876 }
2877
2878 fn to_typed_impl(
2879 &self,
2880 dest: &mut ThinVec<TypedValue>,
2881 level: ArgumentLevel,
2882 ) -> Result<(), ()> {
2883 match *self {
2887 Self::Leaf(ref l) => match l.to_typed_value() {
2888 Some(TypedValue::Numeric(inner)) => {
2889 match level {
2890 ArgumentLevel::CalculationRoot => {
2891 dest.push(TypedValue::Numeric(NumericValue::Math(MathValue::Sum(
2892 MathSum::try_from_numeric_values(ThinVec::from([inner]))?,
2893 ))));
2894 },
2895 ArgumentLevel::ArgumentRoot | ArgumentLevel::Nested => {
2896 dest.push(TypedValue::Numeric(inner));
2897 },
2898 }
2899 Ok(())
2900 },
2901 _ => Err(()),
2902 },
2903 Self::Negate(_) => {
2904 debug_assert!(
2908 false,
2909 "We never reify Negate nodes as they are handled inside Sum nodes."
2910 );
2911
2912 Err(())
2913 },
2914 Self::Invert(ref value) => {
2915 let inner = CalcNodeWithLevel::nested(value)
2916 .to_numeric_value()
2917 .ok_or(())?;
2918
2919 dest.push(TypedValue::Numeric(NumericValue::Math(MathValue::Invert(
2920 MathInvert::from_numeric_value(inner),
2921 ))));
2922 Ok(())
2923 },
2924 Self::Sum(ref children) => {
2925 let mut values = ThinVec::new();
2926 let mut first = true;
2927
2928 for child in &**children {
2929 if !first {
2930 match child {
2931 Self::Leaf(l) => {
2932 if let Ok(true) = l.is_negative() {
2933 let mut negated = l.clone();
2934
2935 negated.map(std::ops::Neg::neg).unwrap();
2938
2939 let inner = negated.to_numeric_value().ok_or(())?;
2940
2941 values.push(NumericValue::Math(MathValue::Negate(
2942 MathNegate::from_numeric_value(inner),
2943 )));
2944 } else {
2945 let inner = l.to_numeric_value().ok_or(())?;
2946
2947 values.push(inner);
2948 }
2949 },
2950 Self::Negate(n) => {
2951 let inner = CalcNodeWithLevel::nested(n.as_ref())
2952 .to_numeric_value()
2953 .ok_or(())?;
2954
2955 values.push(NumericValue::Math(MathValue::Negate(
2956 MathNegate::from_numeric_value(inner),
2957 )));
2958 },
2959 _ => {
2960 let inner = CalcNodeWithLevel::nested(child)
2961 .to_numeric_value()
2962 .ok_or(())?;
2963
2964 values.push(inner);
2965 },
2966 }
2967 } else {
2968 first = false;
2969
2970 let inner = CalcNodeWithLevel::nested(child)
2971 .to_numeric_value()
2972 .ok_or(())?;
2973
2974 values.push(inner);
2975 }
2976 }
2977
2978 dest.push(TypedValue::Numeric(NumericValue::Math(MathValue::Sum(
2979 MathSum::try_from_numeric_values(values)?,
2980 ))));
2981 Ok(())
2982 },
2983 Self::Product(ref children) => {
2984 let mut values = ThinVec::new();
2985 let mut first = true;
2986
2987 for child in &**children {
2988 if !first {
2989 match child {
2990 Self::Invert(n) => {
2991 let inner = CalcNodeWithLevel::nested(n.as_ref())
2992 .to_numeric_value()
2993 .ok_or(())?;
2994
2995 values.push(NumericValue::Math(MathValue::Invert(
2996 MathInvert::from_numeric_value(inner),
2997 )));
2998 },
2999 _ => {
3000 let inner = CalcNodeWithLevel::nested(child)
3001 .to_numeric_value()
3002 .ok_or(())?;
3003
3004 values.push(inner);
3005 },
3006 }
3007 } else {
3008 first = false;
3009
3010 let inner = CalcNodeWithLevel::nested(child)
3011 .to_numeric_value()
3012 .ok_or(())?;
3013
3014 values.push(inner);
3015 }
3016 }
3017
3018 dest.push(TypedValue::Numeric(NumericValue::Math(MathValue::Product(
3019 MathProduct::try_from_numeric_values(values)?,
3020 ))));
3021 Ok(())
3022 },
3023 Self::MinMax(ref children, op) => {
3024 let mut values = ThinVec::new();
3025
3026 for child in &**children {
3027 let inner = CalcNodeWithLevel::argument_root(child)
3028 .to_numeric_value()
3029 .ok_or(())?;
3030
3031 values.push(inner);
3032 }
3033
3034 let math_value = match op {
3035 MinMaxOp::Min => MathValue::Min(MathMin::try_from_numeric_values(values)?),
3036 MinMaxOp::Max => MathValue::Max(MathMax::try_from_numeric_values(values)?),
3037 };
3038
3039 dest.push(TypedValue::Numeric(NumericValue::Math(math_value)));
3040 Ok(())
3041 },
3042 Self::Clamp {
3043 ref min,
3044 ref center,
3045 ref max,
3046 } => {
3047 let lower = CalcNodeWithLevel::argument_root(min)
3048 .to_numeric_value()
3049 .ok_or(())?;
3050
3051 let value = CalcNodeWithLevel::argument_root(center)
3052 .to_numeric_value()
3053 .ok_or(())?;
3054
3055 let upper = CalcNodeWithLevel::argument_root(max)
3056 .to_numeric_value()
3057 .ok_or(())?;
3058
3059 dest.push(TypedValue::Numeric(NumericValue::Math(MathValue::Clamp(
3060 MathClamp::try_from_numeric_values([lower, value, upper].into())?,
3061 ))));
3062 Ok(())
3063 },
3064 _ => Err(()),
3065 }
3066 }
3067
3068 fn compare(&self, other: &Self) -> Option<cmp::Ordering> {
3069 match (self, other) {
3070 (CalcNode::Leaf(one), CalcNode::Leaf(other)) => one.compare(other),
3071 _ => None,
3072 }
3073 }
3074
3075 compare_helpers!();
3076}
3077
3078impl<L: CalcNodeLeaf> ToCss for CalcNode<L> {
3079 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
3081 where
3082 W: Write,
3083 {
3084 self.to_css_impl(dest, ArgumentLevel::CalculationRoot)
3085 }
3086}
3087
3088impl<L: CalcNodeLeaf> ToTyped for CalcNode<L> {
3089 fn to_typed(&self, dest: &mut ThinVec<TypedValue>) -> Result<(), ()> {
3090 CalcNodeWithLevel::calculation_root(self).to_typed(dest)
3091 }
3092}
3093
3094struct CalcNodeWithLevel<'a, L> {
3095 node: &'a CalcNode<L>,
3096 level: ArgumentLevel,
3097}
3098
3099impl<'a, L> CalcNodeWithLevel<'a, L> {
3100 #[inline]
3101 fn new(node: &'a CalcNode<L>, level: ArgumentLevel) -> Self {
3102 Self { node, level }
3103 }
3104
3105 #[inline]
3106 fn calculation_root(node: &'a CalcNode<L>) -> Self {
3107 Self::new(node, ArgumentLevel::CalculationRoot)
3108 }
3109
3110 #[inline]
3111 fn argument_root(node: &'a CalcNode<L>) -> Self {
3112 Self::new(node, ArgumentLevel::ArgumentRoot)
3113 }
3114
3115 #[inline]
3116 fn nested(node: &'a CalcNode<L>) -> Self {
3117 Self::new(node, ArgumentLevel::Nested)
3118 }
3119}
3120
3121impl<'a, L: CalcNodeLeaf> ToTyped for CalcNodeWithLevel<'a, L> {
3122 fn to_typed(&self, dest: &mut ThinVec<TypedValue>) -> Result<(), ()> {
3123 self.node.to_typed_impl(dest, self.level.clone())
3124 }
3125}