27 std::fill_n(data_, totalSize, initValue);
33 std::copy(other.transposeOrder_, other.transposeOrder_ +
getNumDims(), transposeOrder_);
34 transposeOrderSet_ =
true;
37 std::copy(other.data_, other.data_ + totalSize, data_);
43 std::copy(other.transposeOrder_, other.transposeOrder_ +
getNumDims(), transposeOrder_);
44 transposeOrderSet_ =
true;
47 std::move(other.data_, other.data_ + totalSize, data_);
51 template <
typename... Indices>
54 #ifdef COMPILETIME_CHECK_DIMENSIONS_COUNT_MISMATCH
55 static_assert(
sizeof...(indices) ==
sizeof...(Dims),
"Incorrect number of indices");
59 return data_[computeIndex(idxArray)];
63 template <
typename... Indices>
66 #ifdef COMPILETIME_CHECK_DIMENSIONS_COUNT_MISMATCH
67 static_assert(
sizeof...(indices) ==
sizeof...(Dims),
"Incorrect number of indices");
71 return data_[computeIndex(idxArray)];
75 template<my_
size_t length>
78 #ifdef COMPILETIME_CHECK_DIMENSIONS_COUNT_MISMATCH
79 static_assert(length ==
sizeof...(Dims),
"Incorrect number of indicessss");
82 return data_[computeIndex(indices)];
85 template<my_
size_t length>
88 #ifdef COMPILETIME_CHECK_DIMENSIONS_COUNT_MISMATCH
89 static_assert(length ==
sizeof...(Dims),
"Incorrect number of indicessss");
92 return data_[computeIndex(indices)];
100 checkDimensionsMismatch(other);
102 my_size_t indices[
sizeof...(Dims)] = {0};
103 for (
my_size_t i = 0; i < totalSize; ++i)
106 for (
my_size_t j = 0; j <
sizeof...(Dims); ++j)
108 if (indices[j] <
getDim(j) - 1)
132 return !(*
this == other);
145 std::copy(other.transposeOrder_, other.transposeOrder_ +
getNumDims(), transposeOrder_);
146 transposeOrderSet_ =
true;
149 std::copy(other.data_, other.data_ + totalSize, data_);
157 for (
my_size_t i = 0; i < totalSize; ++i)
159 outp.data_[i] += scalar;
167 return tensor + scalar;
175 checkDimensionsMismatch(other);
178 my_size_t indices[
sizeof...(Dims)] = {0};
179 for (
my_size_t i = 0; i < totalSize; ++i)
182 for (
my_size_t j = 0; j <
sizeof...(Dims); ++j)
184 if (indices[j] <
getDim(j) - 1)
196 outp(indices) += other(indices);
205 for (
my_size_t i = 0; i < totalSize; ++i)
207 outp.data_[i] -= scalar;
217 for (
my_size_t i = 0; i < totalSize; ++i)
219 outp.data_[i] = scalar - outp.data_[i];
228 for (
my_size_t i = 0; i < totalSize; ++i)
230 outp.data_[i] = -outp.data_[i];
240 checkDimensionsMismatch(other);
243 my_size_t indices[
sizeof...(Dims)] = {0};
244 for (
my_size_t i = 0; i < totalSize; ++i)
247 for (
my_size_t j = 0; j <
sizeof...(Dims); ++j)
249 if (indices[j] <
getDim(j) - 1)
261 outp(indices) -= other(indices);
270 for (
my_size_t i = 0; i < totalSize; ++i)
272 outp.data_[i] *= scalar;
280 return tensor * scalar;
288 checkDimensionsMismatch(other);
291 my_size_t indices[
sizeof...(Dims)] = {0};
292 for (
my_size_t i = 0; i < totalSize; ++i)
295 for (
my_size_t j = 0; j <
sizeof...(Dims); ++j)
297 if (indices[j] <
getDim(j) - 1)
309 outp(indices) *= other(indices);
322 return *
this * (1 / scalar);
329 for (
my_size_t i = 0; i < tensor.totalSize; ++i)
331 if (tensor.data_[i] == 0)
335 outp.data_[i] = scalar / tensor.data_[i];
345 checkDimensionsMismatch(other);
348 my_size_t indices[
sizeof...(Dims)] = {0};
349 for (
my_size_t i = 0; i < totalSize; ++i)
352 for (
my_size_t j = 0; j <
sizeof...(Dims); ++j)
354 if (indices[j] <
getDim(j) - 1)
366 if (other(indices) == 0)
370 outp(indices) /= other(indices);
380 if (dims[i] != dims[0])
398 constexpr my_size_t total_combinations = (1 * ... * Dims);
399 my_size_t combinations[total_combinations][
sizeof...(Dims)];
400 my_size_t max_vals[
sizeof...(Dims)] = {Dims...};
401 generate_combinations(max_vals, combinations);
403 for (
my_size_t i = 0; i < total_combinations; ++i)
407 bool isElementDiagonal =
true;
410 if (combinations[i][j] != combinations[i][0])
412 isElementDiagonal =
false;
417 if (isElementDiagonal)
445 outp.transposeOrder_[i] = order[i];
455 this->transposeOrder_[i] = order[i];
463 static_assert(
sizeof...(Dims) == 2,
"Transpose is only supported for 2D tensors");
467 if (outp.transposeOrder_[0] == 0)
469 outp.transposeOrder_[0] = 1;
470 outp.transposeOrder_[1] = 0;
474 outp.transposeOrder_[0] = 0;
475 outp.transposeOrder_[1] = 1;
484 if (this->transposeOrder_[0] == 0)
486 this->transposeOrder_[0] = 1;
487 this->transposeOrder_[1] = 0;
491 this->transposeOrder_[0] = 0;
492 this->transposeOrder_[1] = 1;
505 return sizeof...(Dims);
512 std::string shape =
"(";
515 shape += std::to_string(
getDim(i));
525 std::fill_n(data_, totalSize, 0);
531 std::fill_n(data_, totalSize, _val);
537 for (
my_size_t i = 0; i < totalSize; ++i)
540 data_[i] =
static_cast<T
>((rand() % (_maxRand - _minRand + 1)) + _minRand);
548 static_assert(
sizeof...(Dims) >= 2,
"setDiagonal requires at least 2 dimensions.");
565 data_[computeIndex(indices)] = _val;
572 static_assert(
sizeof...(Dims) >= 2,
"Identity requires at least 2 dimensions.");
573 static_assert(
all_equal<Dims...>(),
"All dimensions must be equal for an identity tensor");
581 static_assert(
sizeof...(Dims) >= 2,
"Identity requires at least 2 dimensions.");
582 static_assert(
all_equal<Dims...>(),
"All dimensions must be equal for an identity tensor");
591 for (
my_size_t i = 0; i < totalSize; ++i)
598 template<my_
size_t DiagonalSize>
601 static_assert(
sizeof...(Dims) >= 2,
"Getting diagonal entries requires at least 2 dimensions.");
614 diagonalEntries(i, 0) = data_[computeIndex(indices)];
622 static_assert(
sizeof...(Dims1) >= 2 ,
"Tensor 1 must have at least 2 dimension");
623 static_assert(
sizeof...(Dims2) >= 2 ,
"Tensor 2 must have at least 2 dimension");
626 if (a >=
sizeof...(Dims1) || b >=
sizeof...(Dims2))
638 constexpr my_size_t n_newDims =
sizeof...(Dims1) +
sizeof...(Dims2) - 2;
641 for (
my_size_t i = 0; i <
sizeof...(Dims1); ++i)
645 newDims[k++] = _tensor1.
getDim(i);
649 for (
my_size_t i = 0; i <
sizeof...(Dims2); ++i)
653 newDims[k++] = _tensor2.
getDim(i);
669 for (
my_size_t i = 0; i < n_newDims; ++i)
671 if (newDims[i] != _outp.getDim(i))
678 constexpr my_size_t total_combinations = (1 * ... * Dims);
679 my_size_t combinations[total_combinations][n_newDims];
682 generate_combinations(newDims, combinations);
687 for (
my_size_t comb = 0; comb < total_combinations; ++comb)
702 my_size_t indices1[
sizeof...(Dims1)] = {0};
703 my_size_t indices2[
sizeof...(Dims2)] = {0};
706 for (
my_size_t i = 0; i <
sizeof...(Dims1); ++i)
710 indices1[i] = combinations[comb][l++];
718 l =
sizeof...(Dims1) - 1;
719 for (
my_size_t i = 0; i <
sizeof...(Dims2); ++i)
723 indices2[i] = combinations[comb][l++];
744 sum += _tensor1(indices1) * _tensor2(indices2);
746 _outp(combinations[comb]) =
sum;
813 static_assert(
sizeof...(Dims) <= 4,
"Printing not supported for tensors with more than 4 dimensions");
815 if constexpr (
sizeof...(Dims) == 1) {
818 else if constexpr (
sizeof...(Dims) == 2) {
821 else if constexpr (
sizeof...(Dims) == 3) {
824 else if constexpr (
sizeof...(Dims) == 4) {
832 return dims[transposeOrder_[i]];
837 static constexpr my_size_t totalSize = (Dims * ...);
838 static constexpr my_size_t dims[] = {Dims...};
839 static constexpr my_size_t numDims =
sizeof...(Dims);
842 my_size_t transposeOrder_[
sizeof...(Dims)];
843 bool transposeOrderSet_ =
false;
859 template <my_
size_t N, my_
size_t M>
860 static void print_combinations(
const my_size_t (&combinations)[M][N])
875 template <my_
size_t N, my_
size_t M>
876 static void generate_combinations(
const my_size_t (&max_values)[N],
my_size_t (&combinations)[M][N])
885 combinations[row][i] = combination[i];
900 int position = N - 1;
901 while (position >= 0)
903 ++combination[position];
904 if (combination[position] < max_values[position])
908 combination[position] = 0;
915 void initTransposeOrder()
918 if (transposeOrderSet_)
926 transposeOrder_[i] = i;
931 void print1D()
const {
941 void print2D()
const {
955 void print3D()
const {
968 void print4D()
const {
1000 #ifdef RUNTIME_USE_BOUNDS_CHECKING
1001 if (indices[dimIndex] >= dims[i]) {
1006 index += indices[dimIndex] * factor;
static void log(const T &msg, ErrorLevel level=ErrorLevel::Plain)
Definition error_handler.h:18
static void error(const T &msg)
Definition error_handler.h:30
TensorND & setSequencial(void)
Definition tensor.h:589
friend TensorND operator-(const T scalar, const TensorND &tensor)
Definition tensor.h:213
TensorND(const TensorND &other)
Definition tensor.h:31
TensorND()
Definition tensor.h:18
friend TensorND operator+(const T scalar, const TensorND &tensor)
Definition tensor.h:165
void inplace_transpose(void)
Definition tensor.h:481
std::string getShape() const
Definition tensor.h:509
friend TensorND operator*(const T scalar, const TensorND &tensor)
Definition tensor.h:278
TensorND & operator=(const TensorND &other)
Definition tensor.h:136
constexpr my_size_t getTotalSize() const
Definition tensor.h:497
TensorND & setRandom(my_size_t _maxRand, my_size_t _minRand)
Definition tensor.h:535
TensorND operator/(const T scalar) const
Definition tensor.h:315
TensorND operator*(const T scalar) const
Definition tensor.h:267
TensorND operator+(const TensorND< T, Dims1... > &other) const
Definition tensor.h:172
TensorND operator-(void) const
Definition tensor.h:225
TensorND operator-(const TensorND< T, Dims1... > &other) const
Definition tensor.h:237
TensorND & setDiagonal(T _val)
Definition tensor.h:546
my_size_t getDim(my_size_t i) const
Definition tensor.h:830
TensorND & setToZero(void)
Definition tensor.h:523
T & operator()(Indices... indices)
Definition tensor.h:52
const T & operator()(Indices... indices) const
Definition tensor.h:64
static TensorND I(void)
Definition tensor.h:579
TensorND & setIdentity(void)
Definition tensor.h:570
bool operator!=(const TensorND< T, Dims1... > &other) const
Definition tensor.h:130
constexpr my_size_t getNumDims() const
Definition tensor.h:503
TensorND operator*(const TensorND< T, Dims1... > &other) const
Definition tensor.h:285
void print() const
Definition tensor.h:812
TensorND(TensorND &&other) noexcept
Definition tensor.h:41
friend TensorND operator/(const T scalar, const TensorND &tensor)
Definition tensor.h:326
void getDiagonalEntries(TensorND< T, DiagonalSize, 1 > &diagonalEntries) const
Definition tensor.h:599
const T & operator()(my_size_t(&indices)[length]) const
Definition tensor.h:86
bool isIdentity() const
Definition tensor.h:388
constexpr bool areDimsEqual() const
Definition tensor.h:376
static TensorND einsum(const TensorND< T, Dims1... > &_tensor1, const TensorND< T, Dims2... > &_tensor2, my_size_t a, my_size_t b)
Definition tensor.h:620
void inplace_transpose(const my_size_t order[sizeof...(Dims)])
Definition tensor.h:451
TensorND operator/(const TensorND< T, Dims1... > &other) const
Definition tensor.h:342
TensorND operator-(const T scalar) const
Definition tensor.h:202
TensorND transposed(void) const
Definition tensor.h:460
bool operator==(const TensorND< T, Dims1... > &other) const
Definition tensor.h:97
TensorND transposed(const my_size_t order[sizeof...(Dims)]) const
Definition tensor.h:440
TensorND(T initValue)
Definition tensor.h:24
TensorND & setHomogen(T _val)
Definition tensor.h:529
T & operator()(my_size_t(&indices)[length])
Definition tensor.h:76
TensorND operator+(const T scalar) const
Definition tensor.h:154
Global configuration for the tesseract tensor library.
#define my_size_t
Size/index type used throughout the library.
Definition config.h:126
#define PRECISION_TOLERANCE
Tolerance for floating-point comparisons (e.g. symmetry checks, Cholesky).
Definition config.h:117
consteval bool all_equal()
Check if all values in a parameter pack are equal.
Definition helper_traits.h:20
STL-free memory utilities.
Expr::value_type sum(const BaseExpr< Expr > &expr)
Definition reductions.h:30