// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #pragma once #include namespace vespalib::eval { struct DenseSingleReduceSpec { ValueType result_type; size_t outer_size; size_t reduce_size; size_t inner_size; Aggr aggr; }; /** * Decompose the specified reduce operation into a sequence of single * dense reduce operations. Returns an empty list if decomposition * fails. **/ std::vector make_dense_single_reduce_list(const ValueType &type, Aggr aggr, const std::vector &reduce_dims); /** * Tensor function reducing a single dimension of a dense tensor where * the result is also a dense tensor. The optimize function may create * multiple tensor functions to compose a multi-stage reduce * operation. Adjacent reduced dimensions will be handled is if they * were a single dimension. Trivial dimensions will be trivially * reduced along with any other dimension. * TODO: consider if we should extend this to handling mixed tensors * (handling the spare part as a batch dimension). **/ class DenseSingleReduceFunction : public tensor_function::Op1 { private: size_t _outer_size; size_t _reduce_size; size_t _inner_size; Aggr _aggr; public: DenseSingleReduceFunction(const DenseSingleReduceSpec &spec, const TensorFunction &child); ~DenseSingleReduceFunction() override; size_t outer_size() const { return _outer_size; } size_t reduce_size() const { return _reduce_size; } size_t inner_size() const { return _inner_size; } Aggr aggr() const { return _aggr; } bool result_is_mutable() const override { return true; } InterpretedFunction::Instruction compile_self(const ValueBuilderFactory &factory, Stash &stash) const override; static const TensorFunction &optimize(const TensorFunction &expr, Stash &stash); }; } // namespace vespalib::eval