We're pretty close to being able to make MeanNode a special case of ReduceNode. You can define a ufunc like
template< DType T>
structMean : BinaryFunctionMixin<Mean<T>> {
/// @copydoc Add::result_typeusing result_type = std::conditional<std::integral<T>, double, T>::type;
// we use the same convention as NumPy/// @copydoc Add::reduction_typeclassreduction_type {
public:reduction_type() = delete;
reduction_type(T value) noexcept : sum_(value), count_(1) {}
booloperator==(const result_type& rhs) const {
returnstatic_cast<result_type>(*this) == rhs;
}
booloperator==(const reduction_type& rhs) const {
return sum_ == rhs.sum_and count_ == rhs.count_;
}
explicitoperatorresult_type() constnoexcept { return sum_ / count_; }
private:friend Mean;
result_type sum_; // could use Kahan summation here if we wantedssize_t count_;
};
/// @brief Return the average of `lhs` and `rhs`./// @copydetails Add::operator()
result_type operator()(const DType auto& lhs, const DType auto& rhs) constnoexcept {
return (lhs + rhs) / 2;
}
reduction_type operator()(reduction_type lhs, const DType auto& rhs) constnoexcept {
lhs.sum_ += rhs;
lhs.count_ += 1;
return lhs;
}
/// @brief Revert an average./// @copydetails Add::inverse()static std::optional<result_type> inverse(const DType auto& lhs, const DType auto& rhs) noexcept {
return2 * lhs - rhs;
}
static std::optional<reduction_type> inverse(reduction_type lhs, const DType auto& rhs) noexcept {
lhs.sum_ -= rhs;
lhs.count_ -= 1;
return lhs;
}
static ValuesInfo result_bounds(ValuesInfo lhs, ValuesInfo rhs) {
returnValuesInfo((lhs.max + rhs.max) / 2, (lhs.min + rhs.min) / 2, false);
}
static ValuesInfo result_bounds(ValuesInfo bounds, ssize_t) { return bounds; }
static ValuesInfo result_bounds(ValuesInfo bounds, limit_type) { return bounds; }
staticconstexprbool associative = false;
staticconstexprbool commutative = true;
staticconstexprbool invertible = true;
};the hitch is around the definition of associative. It works in the reduction case, but not for the bounds calculation. Needs more thought.
We're pretty close to being able to make
MeanNodea special case ofReduceNode. You can define a ufunc likethe hitch is around the definition of
associative. It works in the reduction case, but not for the bounds calculation. Needs more thought.