From 3757c00ea3e3a44c40eaec1a43adc2dd730accb9 Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Fri, 22 May 2026 13:02:56 +0300 Subject: refactor(rpn): extract shared hyperLog helper for log operations Replace the near-duplicate HyperLog2, HyperLog10, and HyperLn implementations with a single hyperLog helper that accepts the operation name, log function, and error message as parameters. Each public method is now a one-line call to the shared helper. --- internal/rpn/operations_hyper.go | 69 +++++++++++----------------------------- 1 file changed, 19 insertions(+), 50 deletions(-) diff --git a/internal/rpn/operations_hyper.go b/internal/rpn/operations_hyper.go index c6c4beb..955832f 100644 --- a/internal/rpn/operations_hyper.go +++ b/internal/rpn/operations_hyper.go @@ -4,6 +4,7 @@ package rpn import ( + "errors" "fmt" "math" ) @@ -222,24 +223,24 @@ func (o *Operations) HyperModulo(stack *Stack) error { return nil } -// HyperLog2 pops all values from stack, computes sum of log2 for all values, and pushes result. -// No metric validation; uses raw float64 values. Result is always Cool (unitless). -func (o *Operations) HyperLog2(stack *Stack) error { - values, err := popAll(stack, "[lg]") +// hyperLog computes the sum of a log function over all stack values. +// Each value must be positive. Result is pushed with Cool metric. +func (o *Operations) hyperLog(stack *Stack, opName string, logFn func(float64) float64, errMsg string) error { + values, err := popAll(stack, opName) if err != nil { return err } - var result float64 = 0 - for i := 0; i < len(values); i++ { - val, err := values[i].Float64() + var result float64 + for i, v := range values { + val, err := v.Float64() if err != nil { - return buildError("[lg]", fmt.Errorf("operand %d: %w", i, err)) + return buildError(opName, fmt.Errorf("operand %d: %w", i, err)) } if val <= 0 { - return buildError("[lg]", fmt.Errorf("log2 undefined for non-positive numbers")) + return buildError(opName, errors.New(errMsg)) } - result += math.Log2(val) + result += logFn(val) } cool := coolMetric(o.metricRegistry) @@ -247,54 +248,22 @@ func (o *Operations) HyperLog2(stack *Stack) error { return nil } +// HyperLog2 pops all values from stack, computes sum of log2 for all values, and pushes result. +// No metric validation; uses raw float64 values. Result is always Cool (unitless). +func (o *Operations) HyperLog2(stack *Stack) error { + return o.hyperLog(stack, "[lg]", math.Log2, "log2 undefined for non-positive numbers") +} + // HyperLog10 pops all values from stack, computes sum of log10 for all values, and pushes result. // No metric validation; uses raw float64 values. Result is always Cool (unitless). func (o *Operations) HyperLog10(stack *Stack) error { - values, err := popAll(stack, "[log]") - if err != nil { - return err - } - - var result float64 = 0 - for i := 0; i < len(values); i++ { - val, err := values[i].Float64() - if err != nil { - return buildError("[log]", fmt.Errorf("operand %d: %w", i, err)) - } - if val <= 0 { - return buildError("[log]", fmt.Errorf("log10 undefined for non-positive numbers")) - } - result += math.Log10(val) - } - - cool := coolMetric(o.metricRegistry) - stack.Push(NewNumber(result, o.GetMode(), cool)) - return nil + return o.hyperLog(stack, "[log]", math.Log10, "log10 undefined for non-positive numbers") } // HyperLn pops all values from stack, computes sum of natural log for all values, and pushes result. // No metric validation; uses raw float64 values. Result is always Cool (unitless). func (o *Operations) HyperLn(stack *Stack) error { - values, err := popAll(stack, "[ln]") - if err != nil { - return err - } - - var result float64 = 0 - for i := 0; i < len(values); i++ { - val, err := values[i].Float64() - if err != nil { - return buildError("[ln]", fmt.Errorf("operand %d: %w", i, err)) - } - if val <= 0 { - return buildError("[ln]", fmt.Errorf("ln undefined for non-positive numbers")) - } - result += math.Log(val) - } - - cool := coolMetric(o.metricRegistry) - stack.Push(NewNumber(result, o.GetMode(), cool)) - return nil + return o.hyperLog(stack, "[ln]", math.Log, "ln undefined for non-positive numbers") } -- cgit v1.2.3