static Tensor evaluate(Tensor argument, List<String> dimensions, Aggregator aggregator) {
        if (!dimensions.isEmpty() && !argument.type().dimensionNames().containsAll(dimensions))
            throw new IllegalArgumentException("Cannot reduce " + argument + " over dimensions " +
                    dimensions + ": Not all those dimensions are present in this tensor");

        // Special case: Reduce all
        if (dimensions.isEmpty() || dimensions.size() == argument.type().dimensions().size()) {
            if (argument.isEmpty())
                return Tensor.from(0.0);
            else if (argument.type().dimensions().size() == 1 && argument instanceof IndexedTensor)
                return reduceIndexedVector((IndexedTensor) argument, aggregator);
            else
                return reduceAllGeneral(argument, aggregator);
        }

        TensorType reducedType = outputType(argument.type(), dimensions);
        int[] indexesToReduce = createIndexesToReduce(argument.type(), dimensions);
        int[] indexesToKeep = createIndexesToKeep(argument.type(), indexesToReduce);
        if (argument instanceof IndexedTensor indexedTensor && reducedType.hasOnlyIndexedBoundDimensions()) {
            return reduceIndexedTensor(indexedTensor, reducedType, indexesToKeep, indexesToReduce, aggregator);
        } else {
            return reduceGeneral(argument, reducedType, indexesToKeep, aggregator);
        }
    }
Creates a reduce function.

@param argument the tensor to reduce
@param aggregator the aggregator function to use
@param dimensions the list of dimensions to remove. If an empty list is given, all dimensions are reduced,
                  producing a dimensionless tensor (a scalar).
@throws IllegalArgumentException if any of the tensor dimensions are not present in the input tensor
vespajlib/src/main/java/com/yahoo/tensor/functions/Reduce.java