summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-05-24 18:43:34 +0300
committerPaul Buetow <paul@buetow.org>2026-05-24 18:43:34 +0300
commita03e4511536a3cdafb51e187aa3bb9df764e8fec (patch)
tree14da6319172e99c23e8f6bcc1c1ae8765b3f7a34
parentdfe36f2e29199b5a864ff02b0a6de0bd0f2010f4 (diff)
fix(rpn): delegate Modulo to binaryMetricOp (task gk)
-rw-r--r--internal/rpn/operations_arithmetic.go60
1 files changed, 18 insertions, 42 deletions
diff --git a/internal/rpn/operations_arithmetic.go b/internal/rpn/operations_arithmetic.go
index 4468edb..d47adef 100644
--- a/internal/rpn/operations_arithmetic.go
+++ b/internal/rpn/operations_arithmetic.go
@@ -170,48 +170,24 @@ func (o *Operations) Power(stack *Stack) error {
// Modulo pops two values from stack, computes modulo (a % b), and pushes result.
func (o *Operations) Modulo(stack *Stack) error {
- a, b, err := popTwo(stack, "%")
- if err != nil {
- return err
- }
-
- bF, err := toFloat64(b, "%")
- if err != nil {
- return err
- }
- if bF == 0 {
- return buildError("%", fmt.Errorf("modulo by zero"))
- }
-
- aM, err := resolveMetric(o.metricRegistry, a)
- if err != nil {
- return buildError("%", err)
- }
- bM, err := resolveMetric(o.metricRegistry, b)
- if err != nil {
- return buildError("%", err)
- }
- if !categoriesCompatible(aM, bM) {
- return metricError("%", aM, bM)
- }
-
- pm := o.GetPrefixMode()
- resultMetric := compatibleMetric(o.metricRegistry, aM, bM)
- aBase, err := convertToBase(o.metricRegistry, a, pm, resultMetric)
- if err != nil {
- return buildError("%", err)
- }
- bBase, err := convertToBase(o.metricRegistry, b, pm, resultMetric)
- if err != nil {
- return buildError("%", err)
- }
- resultVal, err := convertFromBase(o.metricRegistry, math.Mod(aBase, bBase), resultMetric, pm)
- if err != nil {
- return buildError("%", err)
- }
-
- stack.Push(NewNumberWithMetric(resultVal, o.GetMode(), resultMetric))
- return nil
+ return o.binaryMetricOp(
+ stack, "%",
+ nil, // no compatibility check — compatibleMetric handles result type
+ func(a, b float64) float64 { return math.Mod(a, b) },
+ func(reg MetricReader, aM, bM *Metric) (*Metric, error) {
+ return compatibleMetric(reg, aM, bM), nil
+ },
+ func(sv StackValue) error {
+ f, err := toFloat64(sv, "%")
+ if err != nil {
+ return err
+ }
+ if f == 0 {
+ return buildError("%", fmt.Errorf("modulo by zero"))
+ }
+ return nil
+ },
+ )
}
// FastPower pops two values from stack, raises first to integer power of second (a ** b), and pushes result.