Repository: prometheus/prometheus
File: promql/engine.go (Go)

Code before:
		}
		return lhs * rhs, nil, true, nil
	case parser.DIV:
		if hlhs != nil && hrhs == nil {
			return 0, hlhs.Copy().Div(rhs), true, nil
		}
		if hrhs != nil {
			if hlhs != nil {
				return 0, nil, false, annotations.NewIncompatibleTypesInBinOpInfo("histogram", "/", "histogram", pos)
			}
			return 0, nil, false, annotations.NewIncompatibleTypesInBinOpInfo("float", "/", "histogram", pos)
		}
		return lhs / rhs, nil, true, nil
	case parser.POW:
		return math.Pow(lhs, rhs), nil, true, nil
	case parser.MOD:
		return math.Mod(lhs, rhs), nil, true, nil
	case parser.EQLC:
		if hlhs != nil && hrhs == nil {
			return 0, nil, false, annotations.NewIncompatibleTypesInBinOpInfo("histogram", "==", "float", pos)
		}
		if hlhs == nil && hrhs != nil {
			return 0, nil, false, annotations.NewIncompatibleTypesInBinOpInfo("float", "==", "histogram", pos)
		}
		if hlhs != nil && hrhs != nil {
			return 0, hlhs, hlhs.Equals(hrhs), nil
		}
		return lhs, nil, lhs == rhs, nil
	case parser.NEQ:
		if hlhs != nil && hrhs == nil {
			return 0, nil, false, annotations.NewIncompatibleTypesInBinOpInfo("histogram", "!=", "float", pos)
		}
		if hlhs == nil && hrhs != nil {
			return 0, nil, false, annotations.NewIncompatibleTypesInBinOpInfo("float", "!=", "histogram", pos)
		}
		if hlhs != nil && hrhs != nil {
			return 0, hlhs, !hlhs.Equals(hrhs), nil
		}
		return lhs, nil, lhs != rhs, nil
	case parser.GTR:
		if hlhs != nil && hrhs == nil {
			return 0, nil, false, annotations.NewIncompatibleTypesInBinOpInfo("histogram", ">", "float", pos)
		}
		if hlhs == nil && hrhs != nil {
			return 0, nil, false, annotations.NewIncompatibleTypesInBinOpInfo("float", ">", "histogram", pos)
		}
		if hlhs != nil && hrhs != nil {
			return 0, hlhs, false, annotations.NewIncompatibleTypesInBinOpInfo("histogram", ">", "histogram", pos)
		}
		return lhs, nil, lhs > rhs, nil
	case parser.LSS:

Review comment (suggestion):
There should be a comment that this expects that both sides are compacted (`Compact(0)` would not change them). I believe this is the case already, or at least the intention, but we should call this out where it matters.

(I was wondering if we could compact here, just in case, but this will probably create problems because it can mutate the histograms.)

Code after:
			}
		}
	case hlhs != nil && hrhs == nil:
		{
			switch op {
			case parser.MUL:
				return 0, hlhs.Copy().Mul(rhs).Compact(0), true, nil
			case parser.DIV:
				return 0, hlhs.Copy().Div(rhs).Compact(0), true, nil
			case parser.ADD, parser.SUB, parser.POW, parser.MOD, parser.EQLC, parser.NEQ, parser.GTR, parser.LSS, parser.GTE, parser.LTE, parser.ATAN2:
				return 0, nil, false, annotations.NewIncompatibleTypesInBinOpInfo("histogram", opName, "float", pos)
			}
		}
	case hlhs != nil && hrhs != nil:
		{
			switch op {
			case parser.ADD:
				res, err := hlhs.Copy().Add(hrhs)
				if err != nil {
					return 0, nil, false, err
				}
				return 0, res.Compact(0), true, nil
			case parser.SUB:
				res, err := hlhs.Copy().Sub(hrhs)
				if err != nil {
					return 0, nil, false, err
				}
				return 0, res.Compact(0), true, nil
			case parser.EQLC:
				// This operation expects that both histograms are compacted.
				return 0, hlhs, hlhs.Equals(hrhs), nil
			case parser.NEQ:
				// This operation expects that both histograms are compacted.
				return 0, hlhs, !hlhs.Equals(hrhs), nil
			case parser.MUL, parser.DIV, parser.POW, parser.MOD, parser.GTR, parser.LSS, parser.GTE, parser.LTE, parser.ATAN2:
				return 0, nil, false, annotations.NewIncompatibleTypesInBinOpInfo("histogram", opName, "histogram", pos)
			}
		}
	}
	panic(fmt.Errorf("operator %q not allowed for operations between Vectors", op))
}

type groupedAggregation struct {
	floatValue     float64
	histogramValue *histogram.FloatHistogram
	floatMean      float64
	floatKahanC    float64 // "Compensating value" for Kahan summation.
	groupCount     float64
	heap           vectorByValueHeap

	// All bools together for better packing within the struct.