86template <Expression Source,
class... Indexes>
99 : dtype_(source.
dtype())
103 if (source.rank() == 0) {
110 std::array<Shape::size_type, Shape::limit>
shape{};
111 std::array<Strides::size_type, Strides::limit>
strides{};
115 auto process = [&](
const auto& argument) {
116 using Argument = std::decay_t<
decltype(argument)>;
117 if constexpr (std::is_same_v<Argument, indexing::Range>) {
118 auto range = normalize(argument, source.shape()[dimension]);
126 else if constexpr (std::is_integral_v<Argument>) {
128 offset_ += index * source.strides()[dimension] *
dsizeof(dtype_);
137 std::apply([&](
const auto&... arguments) {
138 (process(arguments), ...);
141 while (dimension < source.rank()) {
157 template<Integral Index>
159 return Slice<Source, Indexes..., Index>(source_, std::tuple_cat(indexes_, std::make_tuple(index)));
217 bool operator==(T value)
const;
246 return shape_.
rank();
316 return offset_ + source_.offset();
320 return source_.bytes() + offset_;
324 return source_.bytes() + offset_;
329 void assign(std::byte
const* value, std::ptrdiff_t
offset);
330 void assign(
bool const*, std::ptrdiff_t);
331 bool compare(std::byte
const* value, std::ptrdiff_t
offset)
const;
337 std::ptrdiff_t offset_;
339 std::tuple<Indexes...> indexes_;
343inline std::byte
const*
tobytes(T
const& reference) {
344 return reinterpret_cast<std::byte const*
>(&reference);
350 auto copy = [
this](std::byte
const* value, std::ptrdiff_t offset) {
352 assign(value, offset);
355 std::vector<std::size_t> indexes(rank(), 0);
359 std::size_t position = offset;
360 for (
auto dimension = 0; dimension < rank(); ++dimension) {
361 position += indexes[dimension] * strides_[dimension] *
dsizeof(dtype_);
364 assign(value, position);
366 for (
int dimension = rank() - 1; dimension >= 0; --dimension) {
367 if (++indexes[dimension] < shape_[dimension]) {
371 indexes[dimension] = 0;
377 case int8: { int8_t casted = value; copy(
tobytes(casted), offset());
break; }
378 case int16: { int16_t casted = value; copy(
tobytes(casted), offset());
break; }
379 case int32: { int32_t casted = value; copy(
tobytes(casted), offset());
break; }
380 case int64: { int64_t casted = value; copy(
tobytes(casted), offset());
break; }
381 case float32: {
float casted = value; copy(
tobytes(casted), offset());
break; }
382 case float64: {
double casted = value; copy(
tobytes(casted), offset());
break; }
383 default:
throw Exception(
"Unsupported dtype for assignment");
391 throw Exception(
"Cannot compare an scalar to a non scalar slice");
394 case int8: { int8_t casted = value;
return compare(
tobytes(casted), offset()); }
395 case int16: { int16_t casted = value;
return compare(
tobytes(casted), offset()); }
396 case int32: { int32_t casted = value;
return compare(
tobytes(casted), offset()); }
397 case int64: { int64_t casted = value;
return compare(
tobytes(casted), offset()); }
398 case float32: {
float casted = value;
return compare(
tobytes(casted), offset()); }
399 case float64: {
double casted = value;
return compare(
tobytes(casted), offset()); }
400 default:
throw Exception(
"Unsupported dtype for comparison");
A simple generic exception type for the Tannic Tensor Library.
Definition: exceptions.hpp:44
Represents the shape (dimensions) of an tensor-like expression.
Definition: shape.hpp:79
constexpr rank_type rank() const noexcept
Returns the number of dimensions (rank).
Definition: shape.hpp:207
constexpr auto begin()
Definition: shape.hpp:215
uint8_t rank_type
Type used for rank (number of dimensions).
Definition: shape.hpp:84
Represents the memory strides associated with a tensor shape.
Definition: strides.hpp:87
constexpr auto begin()
Definition: strides.hpp:200
A multidimensional, strided tensor data structure.
Definition: tensor.hpp:99
Expression template representing a tensor slice or subview.
Definition: slices.hpp:87
constexpr Slice(typename Trait< Source >::Reference source, std::tuple< Indexes... > indexes)
Create a slice from a source expression and an index tuple.
Definition: slices.hpp:98
void operator=(T value)
Assigns a scalar value to all elements in the slice.
Definition: slices.hpp:349
std::ptrdiff_t offset() const
Returns the byte offset from the source tensor's data pointer.
Definition: slices.hpp:315
constexpr Shape const & shape() const
Returns the shape (size in each dimension) of this slice.
Definition: slices.hpp:272
constexpr auto operator[](indexing::Range range) const
Index into the slice with a range.
Definition: slices.hpp:167
std::byte * bytes()
Definition: slices.hpp:319
Tensor forward() const
Definition: tensor.hpp:1207
constexpr auto rank() const
Returns the number of dimensions in this slice.
Definition: slices.hpp:245
bool operator==(T value) const
Compares a scalar value to the element in a rank-0 slice.
Definition: slices.hpp:389
std::byte const * bytes() const
Definition: slices.hpp:323
constexpr auto operator[](Index index) const
Index into the slice with an integer.
Definition: slices.hpp:158
bool compare(std::byte const *value, std::ptrdiff_t offset) const
Definition: tensor.hpp:1238
constexpr Strides const & strides() const
Returns the memory strides for this slice.
Definition: slices.hpp:294
void assign(std::byte const *value, std::ptrdiff_t offset)
Definition: tensor.hpp:1213
constexpr auto dtype() const
Returns the runtime data type of elements in this slice.
Definition: slices.hpp:229
Defines the core protocol for all expression-like types in the Tannic Tensor Library.
Definition: concepts.hpp:86
Definition: comparisons.hpp:69
std::byte const * tobytes(T const &reference)
Definition: slices.hpp:343
constexpr Index normalize(Index index, Size bound)
Normalize a possibly-negative index into the valid range [0, bound).
Definition: indexing.hpp:87
Definition: buffer.hpp:41
constexpr std::size_t dsizeof(type type)
Returns the size in bytes of a given tensor data type.
Definition: types.hpp:93
std::decay_t< T > Reference
Definition: traits.hpp:28
Represents a half-open interval [start, stop) for slicing.
Definition: indexing.hpp:56
int start
Definition: indexing.hpp:57
int stop
Definition: indexing.hpp:58