/usr/include/xtensor/xbroadcast.hpp is in xtensor-dev 0.10.11-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 | /***************************************************************************
* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
* *
* Distributed under the terms of the BSD 3-Clause License. *
* *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/
#ifndef XBROADCAST_HPP
#define XBROADCAST_HPP
#include <algorithm>
#include <array>
#include <cstddef>
#include <iterator>
#include <numeric>
#include <type_traits>
#include <utility>
#include "xexpression.hpp"
#include "xiterable.hpp"
#include "xstrides.hpp"
#include "xutils.hpp"
namespace xt
{
/*************
* broadcast *
*************/
template <class E, class S>
auto broadcast(E&& e, const S& s) noexcept;
#ifdef X_OLD_CLANG
template <class E, class I>
auto broadcast(E&& e, std::initializer_list<I> s) noexcept;
#else
template <class E, class I, std::size_t L>
auto broadcast(E&& e, const I (&s)[L]) noexcept;
#endif
/**************
* xbroadcast *
**************/
template <class CT, class X>
class xbroadcast;
template <class CT, class X>
struct xiterable_inner_types<xbroadcast<CT, X>>
{
using xexpression_type = std::decay_t<CT>;
using inner_shape_type = promote_shape_t<typename xexpression_type::shape_type, X>;
using const_stepper = typename xexpression_type::const_stepper;
using stepper = const_stepper;
using const_iterator = xiterator<const_stepper, inner_shape_type*, DEFAULT_LAYOUT>;
using iterator = const_iterator;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
using reverse_iterator = std::reverse_iterator<iterator>;
};
/**
* @class xbroadcast
* @brief Broadcasted xexpression to a specified shape.
*
* The xbroadcast class implements the broadcasting of an \ref xexpression
* to a specified shape. xbroadcast is not meant to be used directly, but
* only with the \ref broadcast helper functions.
*
* @tparam CT the closure type of the \ref xexpression to broadcast
* @tparam X the type of the specified shape.
*
* @sa broadcast
*/
template <class CT, class X>
class xbroadcast : public xexpression<xbroadcast<CT, X>>,
public xexpression_const_iterable<xbroadcast<CT, X>>
{
public:
using self_type = xbroadcast<CT, X>;
using xexpression_type = std::decay_t<CT>;
using value_type = typename xexpression_type::value_type;
using reference = typename xexpression_type::reference;
using const_reference = typename xexpression_type::const_reference;
using pointer = typename xexpression_type::pointer;
using const_pointer = typename xexpression_type::const_pointer;
using size_type = typename xexpression_type::size_type;
using difference_type = typename xexpression_type::difference_type;
using iterable_base = xexpression_const_iterable<self_type>;
using inner_shape_type = typename iterable_base::inner_shape_type;
using shape_type = inner_shape_type;
using stepper = typename iterable_base::stepper;
using const_stepper = typename iterable_base::const_stepper;
static constexpr layout_type static_layout = xexpression_type::static_layout;
//static constexpr bool contiguous_layout = xexpression_type::contiguous_layout;
static constexpr bool contiguous_layout = false;
template <class CTA, class S>
xbroadcast(CTA&& e, S&& s) noexcept;
size_type size() const noexcept;
size_type dimension() const noexcept;
const inner_shape_type& shape() const noexcept;
layout_type layout() const noexcept;
template <class... Args>
const_reference operator()(Args... args) const;
const_reference operator[](const xindex& index) const;
const_reference operator[](size_type i) const;
template <class It>
const_reference element(It, It last) const;
template <class S>
bool broadcast_shape(S& shape) const;
template <class S>
bool is_trivial_broadcast(const S& strides) const noexcept;
template <class S>
const_stepper stepper_begin(const S& shape) const noexcept;
template <class S>
const_stepper stepper_end(const S& shape, layout_type l) const noexcept;
private:
CT m_e;
inner_shape_type m_shape;
};
/****************************
* broadcast implementation *
****************************/
/**
* @brief Returns an \ref xexpression broadcasting the given expression to
* a specified shape.
*
* @tparam e the \ref xexpression to broadcast
* @tparam s the specified shape to broadcast.
*
* The returned expression either hold a const reference to \p e or a copy
* depending on whether \p e is an lvalue or an rvalue.
*/
template <class E, class S>
inline auto broadcast(E&& e, const S& s) noexcept
{
using broadcast_type = xbroadcast<const_xclosure_t<E>, S>;
using shape_type = typename broadcast_type::shape_type;
return broadcast_type(std::forward<E>(e), forward_sequence<shape_type>(s));
}
#ifdef X_OLD_CLANG
template <class E, class I>
inline auto broadcast(E&& e, std::initializer_list<I> s) noexcept
{
using broadcast_type = xbroadcast<const_xclosure_t<E>, std::vector<std::size_t>>;
using shape_type = typename broadcast_type::shape_type;
return broadcast_type(std::forward<E>(e), forward_sequence<shape_type>(s));
}
#else
template <class E, class I, std::size_t L>
inline auto broadcast(E&& e, const I (&s)[L]) noexcept
{
using broadcast_type = xbroadcast<const_xclosure_t<E>, std::array<std::size_t, L>>;
using shape_type = typename broadcast_type::shape_type;
return broadcast_type(std::forward<E>(e), forward_sequence<shape_type>(s));
}
#endif
/*****************************
* xbroadcast implementation *
*****************************/
/**
* @name Constructor
*/
//@{
/**
* Constructs an xbroadcast expression broadcasting the specified
* \ref xexpression to the given shape
*
* @param e the expression to broadcast
* @param s the shape to apply
*/
template <class CT, class X>
template <class CTA, class S>
inline xbroadcast<CT, X>::xbroadcast(CTA&& e, S&& s) noexcept
: m_e(std::forward<CTA>(e)), m_shape(std::forward<S>(s))
{
xt::broadcast_shape(m_e.shape(), m_shape);
}
//@}
/**
* @name Size and shape
*/
/**
* Returns the size of the expression.
*/
template <class CT, class X>
inline auto xbroadcast<CT, X>::size() const noexcept -> size_type
{
return compute_size(shape());
}
/**
* Returns the number of dimensions of the expression.
*/
template <class CT, class X>
inline auto xbroadcast<CT, X>::dimension() const noexcept -> size_type
{
return m_shape.size();
}
/**
* Returns the shape of the expression.
*/
template <class CT, class X>
inline auto xbroadcast<CT, X>::shape() const noexcept -> const inner_shape_type&
{
return m_shape;
}
/**
* Returns the layout_type of the expression.
*/
template <class CT, class X>
inline layout_type xbroadcast<CT, X>::layout() const noexcept
{
return m_e.layout();
}
//@}
/**
* @name Data
*/
/**
* Returns a constant reference to the element at the specified position in the expression.
* @param args a list of indices specifying the position in the function. Indices
* must be unsigned integers, the number of indices should be equal or greater than
* the number of dimensions of the expression.
*/
template <class CT, class X>
template <class... Args>
inline auto xbroadcast<CT, X>::operator()(Args... args) const -> const_reference
{
return detail::get_element(m_e, args...);
}
/**
* Returns a constant reference to the element at the specified position in the expression.
* @param index a sequence of indices specifying the position in the function. Indices
* must be unsigned integers, the number of indices in the sequence should be equal or greater
* than the number of dimensions of the container.
*/
template <class CT, class X>
inline auto xbroadcast<CT, X>::operator[](const xindex& index) const -> const_reference
{
return element(index.cbegin(), index.cend());
}
template <class CT, class X>
inline auto xbroadcast<CT, X>::operator[](size_type i) const -> const_reference
{
return operator()(i);
}
/**
* Returns a constant reference to the element at the specified position in the expression.
* @param first iterator starting the sequence of indices
* @param last iterator ending the sequence of indices
* The number of indices in the sequence should be equal to or greater
* than the number of dimensions of the function.
*/
template <class CT, class X>
template <class It>
inline auto xbroadcast<CT, X>::element(It, It last) const -> const_reference
{
return m_e.element(last - dimension(), last);
}
//@}
/**
* @name Broadcasting
*/
//@{
/**
* Broadcast the shape of the function to the specified parameter.
* @param shape the result shape
* @return a boolean indicating whether the broadcasting is trivial
*/
template <class CT, class X>
template <class S>
inline bool xbroadcast<CT, X>::broadcast_shape(S& shape) const
{
return xt::broadcast_shape(m_shape, shape);
}
/**
* Compares the specified strides with those of the container to see whether
* the broadcasting is trivial.
* @return a boolean indicating whether the broadcasting is trivial
*/
template <class CT, class X>
template <class S>
inline bool xbroadcast<CT, X>::is_trivial_broadcast(const S& strides) const noexcept
{
return dimension() == m_e.dimension() &&
std::equal(m_shape.cbegin(), m_shape.cend(), m_e.shape().cbegin()) &&
m_e.is_trivial_broadcast(strides);
}
//@}
template <class CT, class X>
template <class S>
inline auto xbroadcast<CT, X>::stepper_begin(const S& shape) const noexcept -> const_stepper
{
// Could check if (broadcastable(shape, m_shape)
return m_e.stepper_begin(shape);
}
template <class CT, class X>
template <class S>
inline auto xbroadcast<CT, X>::stepper_end(const S& shape, layout_type l) const noexcept -> const_stepper
{
// Could check if (broadcastable(shape, m_shape)
return m_e.stepper_end(shape, l);
}
}
#endif
|