3535 ConstantValue ,
3636 Divider ,
3737 FormulaStep ,
38+ Maximizer ,
3839 MetricFetcher ,
40+ Minimizer ,
3941 Multiplier ,
4042 OpenParen ,
4143 Subtractor ,
4547_logger = logging .Logger (__name__ )
4648
4749_operator_precedence = {
48- "(" : 0 ,
49- "/" : 1 ,
50- "*" : 2 ,
51- "-" : 3 ,
52- "+" : 4 ,
53- ")" : 5 ,
50+ "max" : 0 ,
51+ "min" : 1 ,
52+ "(" : 2 ,
53+ "/" : 3 ,
54+ "*" : 4 ,
55+ "-" : 5 ,
56+ "+" : 6 ,
57+ ")" : 7 ,
5458}
5559
5660
@@ -168,6 +172,36 @@ def __truediv__(
168172 """
169173 return self ._higher_order_builder (self , self ._create_method ) / other # type: ignore
170174
175+ def _max (
176+ self , other : _GenericEngine | _GenericHigherOrderBuilder | QuantityT
177+ ) -> _GenericHigherOrderBuilder :
178+ """Return a formula engine that outputs the maximum of `self` and `other`.
179+
180+ Args:
181+ other: A formula receiver, a formula builder or a QuantityT instance
182+ corresponding to a sub-expression.
183+
184+ Returns:
185+ A formula builder that can take further expressions, or can be built
186+ into a formula engine.
187+ """
188+ return self ._higher_order_builder (self , self ._create_method ).max (other ) # type: ignore
189+
190+ def _min (
191+ self , other : _GenericEngine | _GenericHigherOrderBuilder | QuantityT
192+ ) -> _GenericHigherOrderBuilder :
193+ """Return a formula engine that outputs the minimum of `self` and `other`.
194+
195+ Args:
196+ other: A formula receiver, a formula builder or a QuantityT instance
197+ corresponding to a sub-expression.
198+
199+ Returns:
200+ A formula builder that can take further expressions, or can be built
201+ into a formula engine.
202+ """
203+ return self ._higher_order_builder (self , self ._create_method ).min (other ) # type: ignore
204+
171205
172206class FormulaEngine (
173207 Generic [QuantityT ],
@@ -466,6 +500,10 @@ def push_oper(self, oper: str) -> None:
466500 self ._build_stack .append (Divider ())
467501 elif oper == "(" :
468502 self ._build_stack .append (OpenParen ())
503+ elif oper == "max" :
504+ self ._build_stack .append (Maximizer ())
505+ elif oper == "min" :
506+ self ._build_stack .append (Minimizer ())
469507
470508 def push_metric (
471509 self ,
@@ -650,15 +688,15 @@ def _push(
650688 self ._steps .append ((TokenType .OPER , ")" ))
651689 self ._steps .append ((TokenType .OPER , oper ))
652690
653- # pylint: disable=protected-access
654691 if isinstance (other , (FormulaEngine , FormulaEngine3Phase )):
655692 self ._steps .append ((TokenType .COMPONENT_METRIC , other ))
656- elif isinstance (other , (Quantity , float )):
693+ elif isinstance (other , (Quantity , float , int )):
657694 match oper :
658- case "+" | "-" :
695+ case "+" | "-" | "max" | "min" :
659696 if not isinstance (other , Quantity ):
660697 raise RuntimeError (
661- f"A Quantity must be provided for addition or subtraction to { other } "
698+ "A Quantity must be provided for addition,"
699+ f" subtraction, min or max to { other } "
662700 )
663701 case "*" | "/" :
664702 if not isinstance (other , (float , int )):
@@ -668,9 +706,8 @@ def _push(
668706 self ._steps .append ((TokenType .CONSTANT , other ))
669707 elif isinstance (other , _BaseHOFormulaBuilder ):
670708 self ._steps .append ((TokenType .OPER , "(" ))
671- self ._steps .extend (other ._steps )
709+ self ._steps .extend (other ._steps ) # pylint: disable=protected-access
672710 self ._steps .append ((TokenType .OPER , ")" ))
673- # pylint: enable=protected-access
674711 else :
675712 raise RuntimeError (f"Can't build a formula from: { other } " )
676713 assert isinstance (
@@ -801,6 +838,66 @@ def __truediv__(
801838 """
802839 return self ._push ("/" , other )
803840
841+ @overload
842+ def max (
843+ self , other : _CompositionType1Phase
844+ ) -> HigherOrderFormulaBuilder [QuantityT ]:
845+ ...
846+
847+ @overload
848+ def max (
849+ self , other : _CompositionType3Phase | QuantityT
850+ ) -> HigherOrderFormulaBuilder3Phase [QuantityT ]:
851+ ...
852+
853+ def max (
854+ self , other : _CompositionType | QuantityT
855+ ) -> (
856+ HigherOrderFormulaBuilder [QuantityT ]
857+ | HigherOrderFormulaBuilder3Phase [QuantityT ]
858+ ):
859+ """Return a formula builder that calculates the maximum of `self` and `other`.
860+
861+ Args:
862+ other: A formula receiver, or a formula builder instance corresponding to a
863+ sub-expression.
864+
865+ Returns:
866+ A formula builder that can take further expressions, or can be built
867+ into a formula engine.
868+ """
869+ return self ._push ("max" , other )
870+
871+ @overload
872+ def min (
873+ self , other : _CompositionType1Phase
874+ ) -> HigherOrderFormulaBuilder [QuantityT ]:
875+ ...
876+
877+ @overload
878+ def min (
879+ self , other : _CompositionType3Phase | QuantityT
880+ ) -> HigherOrderFormulaBuilder3Phase [QuantityT ]:
881+ ...
882+
883+ def min (
884+ self , other : _CompositionType | QuantityT
885+ ) -> (
886+ HigherOrderFormulaBuilder [QuantityT ]
887+ | HigherOrderFormulaBuilder3Phase [QuantityT ]
888+ ):
889+ """Return a formula builder that calculates the minimum of `self` and `other`.
890+
891+ Args:
892+ other: A formula receiver, or a formula builder instance corresponding to a
893+ sub-expression.
894+
895+ Returns:
896+ A formula builder that can take further expressions, or can be built
897+ into a formula engine.
898+ """
899+ return self ._push ("min" , other )
900+
804901
805902class HigherOrderFormulaBuilder (Generic [QuantityT ], _BaseHOFormulaBuilder [QuantityT ]):
806903 """A specialization of the _BaseHOFormulaBuilder for `FormulaReceiver`."""
0 commit comments