16namespace stratax::core::broadcast_detail {
36 return offset < shape.
rank()
37 ? shape[shape.
rank() - 1 - offset]
65 std::size_t result_index,
69 std::size_t operand_index = 0;
70 std::size_t operand_stride = 1;
72 for (std::size_t result_axis = result_shape.rank(); result_axis-- > 0;)
74 const std::size_t coordinate =
75 result_index % result_shape[result_axis];
76 result_index /= result_shape[result_axis];
78 const std::size_t offset = result_shape.rank() - 1 - result_axis;
79 if (offset >= operand_shape.
rank())
84 const std::size_t operand_axis = operand_shape.
rank() - 1 - offset;
85 const std::size_t operand_dimension = operand_shape[operand_axis];
86 const std::size_t operand_coordinate =
87 operand_dimension == 1 ? 0 : coordinate;
89 operand_index += operand_coordinate * operand_stride;
90 operand_stride *= operand_dimension;
119 const std::size_t result_rank = std::max(shape1.
rank(), shape2.
rank());
121 for (std::size_t offset = 0; offset < result_rank; ++offset)
123 const std::size_t left =
124 stratax::core::broadcast_detail::dimension_from_right(shape1, offset);
125 const std::size_t right =
126 stratax::core::broadcast_detail::dimension_from_right(shape2, offset);
128 if (left != right && left != 1 && right != 1)
162 const std::size_t result_rank = std::max(shape1.
rank(), shape2.
rank());
163 std::vector<std::size_t> result(result_rank);
165 for (std::size_t offset = 0; offset < result_rank; ++offset)
167 const std::size_t left =
168 stratax::core::broadcast_detail::dimension_from_right(shape1, offset);
169 const std::size_t right =
170 stratax::core::broadcast_detail::dimension_from_right(shape2, offset);
172 result[result_rank - 1 - offset] = left == 1 ? right : left;
178namespace stratax::core {
180namespace broadcast_detail {
189template<Array L, Array R>
193 if (result.elements() != 0 && (lhs.empty() || rhs.empty()))
229 const auto result_shape =
230 broadcast_detail::array_result_shape(lhs, rhs);
232 result_type result(result_shape);
234 for (std::size_t i = 0; i < result.size(); ++i)
236 const auto lhs_index =
237 broadcast_detail::flat_operand_index(
242 const auto rhs_index =
243 broadcast_detail::flat_operand_index(
248 result[i] =
static_cast<Result
>(
249 op(lhs[lhs_index], rhs[rhs_index]));
266template<Array L, Array R,
typename Op>
276 using result_value_type =
278 typename L::value_type,
279 typename R::value_type>;
281 return broadcasted_op<result_value_type>(
313template<Array L, Numeric S,
typename Op>
316 using result_value_type =
318 typename L::value_type,
326 result_type result(lhs.shape());
328 for (std::size_t i = 0; i < result.size(); ++i)
330 result[i] =
static_cast<result_value_type
>(
362template<Numeric S, Array R,
typename Op>
365 using result_value_type =
368 typename R::value_type>;
375 result_type result(rhs.shape());
377 for (std::size_t i = 0; i < result.size(); ++i)
379 result[i] =
static_cast<result_value_type
>(
Result-container rebinding and promotion for owning arrays.
typename PromoteArray< std::remove_cvref_t< L >, std::remove_cvref_t< R >, std::remove_cvref_t< T > >::type promote_array_t
Convenience alias for the promoted array container type.
typename RebindArray< std::remove_cvref_t< A >, std::remove_cvref_t< T > >::type rebind_array_t
Convenience alias for rebinding an array to a new value type.
stratax::core::Shape broadcasted_shape(const stratax::core::Shape &shape1, const stratax::core::Shape &shape2)
Computes the common shape produced by broadcasting two shapes.
bool broadcastable(const stratax::core::Shape &shape1, const stratax::core::Shape &shape2)
Tests whether two shapes satisfy trailing-dimension broadcasting.
std::size_t flat_operand_index(std::size_t result_index, const stratax::core::Shape &result_shape, const stratax::core::Shape &operand_shape)
Maps a flat result index to the corresponding operand index.
Shape array_result_shape(const L &lhs, const R &rhs)
Validates shape broadcasting and the availability of operand values.
std::size_t dimension_from_right(const Shape &shape, std::size_t offset)
Returns a shape dimension counted from the trailing axis.
auto broadcasted_op(const L &lhs, const R &rhs, Op op)
Applies a binary callable with broadcasting and an explicit result dtype.
auto broadcasted_op(const L &lhs, const S &rhs, Op op)
Applies a binary callable to every array element and a right scalar.
Dtype and array interface concepts.
Stratax exception types derived from std::runtime_error.
Immutable dimension metadata and checked row-major strides.
Operands cannot broadcast to the requested result.
Stores the dimensions of a multidimensional array.
size_type rank() const noexcept
Returns the number of dimensions.
Identifies array-like types through their common logical interface.
Supported numeric or boolean element dtype.
Supported integer, floating-point, or complex dtype, excluding bool.