Cytnx v1.0.0
Loading...
Searching...
No Matches
Tensor.hpp
Go to the documentation of this file.
1#ifndef CYTNX_TENSOR_H_
2#define CYTNX_TENSOR_H_
3
4#include "Type.hpp"
5#include "cytnx_error.hpp"
6#include "Device.hpp"
8#include <iostream>
9#include <fstream>
10#include "utils/dynamic_arg_resolver.hpp"
11#include "Accessor.hpp"
12#include <type_traits>
13#include <utility>
14#include <vector>
15#include <initializer_list>
16#include <string>
17
18#include "backend/Scalar.hpp"
19#include "backend/Storage.hpp"
20#include "backend/Tensor_impl.hpp"
21
22namespace cytnx {
23
24 class Tensor;
25
26 // [Note] The free `Tensor <op> T` operators declared in linalg.hpp are forward-declared below
27 // the class definition rather than here, because their constraint names Tensor::Tproxy, which
28 // is not available until Tensor is complete. Declaring them unconstrained here would defeat the
29 // constraint entirely: a differently-constrained declaration is a *distinct* template, so the
30 // unconstrained candidate would stay viable for every non-scalar T (#1003, Ian's review).
31
33 class Tensor {
34 private:
35 public:
37 // this is a proxy class to allow get/set element using [] as python!
38 struct Tproxy {
39 boost::intrusive_ptr<Tensor_impl> _insimpl;
40 std::vector<cytnx::Accessor> _accs;
41 Tproxy(boost::intrusive_ptr<Tensor_impl> _ptr, const std::vector<cytnx::Accessor> &accs)
42 : _insimpl(std::move(_ptr)), _accs(accs) {}
43
44 // when used to set elems:
45 const Tensor &operator=(const Tensor &rhs) {
46 this->_insimpl->set(_accs, rhs._impl);
47 return rhs;
48 }
49
50 template <class T>
51 const T &operator=(const T &rc) {
52 this->_insimpl->set(_accs, rc);
53 return rc;
54 }
55 const Tproxy &operator=(const Tproxy &rc) {
57 this->_insimpl->set(_accs, tmp._impl);
58 return rc;
59 }
60
61 template <class T>
62 Tensor operator+=(const T &rc) {
64 self._impl = _insimpl->get(_accs);
65 self += rc;
66 _insimpl->set(_accs, self._impl);
67 self._impl = this->_insimpl;
68 return self;
69 }
70 Tensor operator+=(const Tproxy &rc);
71
72 template <class T>
73 Tensor operator-=(const T &rc) {
75 self._impl = _insimpl->get(_accs);
76 self -= rc;
77 _insimpl->set(_accs, self._impl);
78 self._impl = this->_insimpl;
79 return self;
80 }
81 Tensor operator-=(const Tproxy &rc);
82
83 template <class T>
84 Tensor operator/=(const T &rc) {
86 self._impl = _insimpl->get(_accs);
87 self /= rc;
88 _insimpl->set(_accs, self._impl);
89 self._impl = this->_insimpl;
90 return self;
91 }
92 Tensor operator/=(const Tproxy &rc);
93
94 template <class T>
95 Tensor operator*=(const T &rc) {
97 self._impl = _insimpl->get(_accs);
98 self *= rc;
99 _insimpl->set(_accs, self._impl);
100 self._impl = this->_insimpl;
101 return self;
102 }
103 Tensor operator*=(const Tproxy &rc);
104
105 // alias to resolve conflict with op ovld for rc=Tensor
106 /*
107 template<class T>
108 Tensor _operatorADD(const T &rc) const{
109 Tensor out;
110 out._impl = _insimpl->get(_accs);
111 return out.Add(rc);
112 }
113 */
114 Tensor operator+(const cytnx_complex128 &rc) const; //{return this->_operatorADD(rc);};
115 Tensor operator+(const cytnx_complex64 &rc) const; //{return this->_operatorADD(rc);};
116 Tensor operator+(const cytnx_double &rc) const; //{return this->_operatorADD(rc);};
117 Tensor operator+(const cytnx_float &rc) const; //{return this->_operatorADD(rc);};
118 Tensor operator+(const cytnx_uint64 &rc) const; //{return this->_operatorADD(rc);};
119 Tensor operator+(const cytnx_int64 &rc) const; //{return this->_operatorADD(rc);};
120 Tensor operator+(const cytnx_uint32 &rc) const; //{return this->_operatorADD(rc);};
121 Tensor operator+(const cytnx_int32 &rc) const; //{return this->_operatorADD(rc);};
122 Tensor operator+(const cytnx_uint16 &rc) const; //{return this->_operatorADD(rc);};
123 Tensor operator+(const cytnx_int16 &rc) const; //{return this->_operatorADD(rc);};
124 Tensor operator+(const cytnx_bool &rc) const; //{return this->_operatorADD(rc);};
125 Tensor operator+(const Tproxy &rc) const;
126
127 /*
128 template<class T>
129 Tensor _operatorSUB(const T &rc) const{
130 Tensor out;
131 out._impl = _insimpl->get(_accs);
132 return out.Sub(rc);
133 }
134 */
135 Tensor operator-(const cytnx_complex128 &rc) const; //{return this->_operatorSUB(rc);};
136 Tensor operator-(const cytnx_complex64 &rc) const; //{return this->_operatorSUB(rc);};
137 Tensor operator-(const cytnx_double &rc) const; //{return this->_operatorSUB(rc);};
138 Tensor operator-(const cytnx_float &rc) const; //{return this->_operatorSUB(rc);};
139 Tensor operator-(const cytnx_uint64 &rc) const; //{return this->_operatorSUB(rc);};
140 Tensor operator-(const cytnx_int64 &rc) const; //{return this->_operatorSUB(rc);};
141 Tensor operator-(const cytnx_uint32 &rc) const; //{return this->_operatorSUB(rc);};
142 Tensor operator-(const cytnx_int32 &rc) const; //{return this->_operatorSUB(rc);};
143 Tensor operator-(const cytnx_uint16 &rc) const; //{return this->_operatorSUB(rc);};
144 Tensor operator-(const cytnx_int16 &rc) const; //{return this->_operatorSUB(rc);};
145 Tensor operator-(const cytnx_bool &rc) const; //{return this->_operatorSUB(rc);};
146 Tensor operator-(const Tproxy &rc) const;
147
148 Tensor operator-() const;
149
150 /*
151 template<class T>
152 Tensor _operatorMUL(const T &rc) const{
153 Tensor out;
154 out._impl = _insimpl->get(_accs);
155 return out.Mul(rc);
156 }
157 */
158 Tensor operator*(const cytnx_complex128 &rc) const; //{return this->_operatorMUL(rc);};
159 Tensor operator*(const cytnx_complex64 &rc) const; //{return this->_operatorMUL(rc);};
160 Tensor operator*(const cytnx_double &rc) const; //{return this->_operatorMUL(rc);};
161 Tensor operator*(const cytnx_float &rc) const; //{return this->_operatorMUL(rc);};
162 Tensor operator*(const cytnx_uint64 &rc) const; //{return this->_operatorMUL(rc);};
163 Tensor operator*(const cytnx_int64 &rc) const; //{return this->_operatorMUL(rc);};
164 Tensor operator*(const cytnx_uint32 &rc) const; //{return this->_operatorMUL(rc);};
165 Tensor operator*(const cytnx_int32 &rc) const; //{return this->_operatorMUL(rc);};
166 Tensor operator*(const cytnx_uint16 &rc) const; //{return this->_operatorMUL(rc);};
167 Tensor operator*(const cytnx_int16 &rc) const; //{return this->_operatorMUL(rc);};
168 Tensor operator*(const cytnx_bool &rc) const; //{return this->_operatorMUL(rc);};
169 Tensor operator*(const Tproxy &rc) const;
170
171 /*
172 template<class T>
173 Tensor _operatorDIV(const T &rc) const{
174 Tensor out;
175 out._impl = _insimpl->get(_accs);
176 return out.Div(rc);
177 }
178 */
179 Tensor operator/(const cytnx_complex128 &rc) const; //{return this->_operatorDIV(rc);};
180 Tensor operator/(const cytnx_complex64 &rc) const; //{return this->_operatorDIV(rc);};
181 Tensor operator/(const cytnx_double &rc) const; //{return this->_operatorDIV(rc);};
182 Tensor operator/(const cytnx_float &rc) const; //{return this->_operatorDIV(rc);};
183 Tensor operator/(const cytnx_uint64 &rc) const; //{return this->_operatorDIV(rc);};
184 Tensor operator/(const cytnx_int64 &rc) const; //{return this->_operatorDIV(rc);};
185 Tensor operator/(const cytnx_uint32 &rc) const; //{return this->_operatorDIV(rc);};
186 Tensor operator/(const cytnx_int32 &rc) const; //{return this->_operatorDIV(rc);};
187 Tensor operator/(const cytnx_uint16 &rc) const; //{return this->_operatorDIV(rc);};
188 Tensor operator/(const cytnx_int16 &rc) const; //{return this->_operatorDIV(rc);};
189 Tensor operator/(const cytnx_bool &rc) const; //{return this->_operatorDIV(rc);};
190 Tensor operator/(const Tproxy &rc) const;
191
192 template <class T>
193 T item() const {
194 Tensor out;
195 out._impl = _insimpl->get(_accs);
196 return out.item<T>();
197 }
198
199 Scalar::Sproxy item() const {
200 Tensor out;
201 out._impl = _insimpl->get(_accs);
202 return out.item();
203 }
204
205 // when used to get elems:
206 operator Tensor() const {
207 Tensor out;
208 out._impl = _insimpl->get(_accs);
209 return out;
210 }
211
212 Storage storage() const {
213 Tensor out;
214 out._impl = _insimpl->get(_accs);
215 return out.storage();
216 }
217
218 }; // proxy class of Tensor.
219
221
223 // these two are using the python way!
224 //----------------------------------------
225 template <class... Ts>
226 Tproxy operator()(const std::string &e1, const Ts &...elems) {
227 std::vector<cytnx::Accessor> tmp = Indices_resolver(e1, elems...);
228 return (*this)[tmp];
229 }
230 template <class... Ts>
231 Tproxy operator()(const cytnx_int64 &e1, const Ts &...elems) {
232 std::vector<cytnx::Accessor> tmp = Indices_resolver(e1, elems...);
233 return (*this)[tmp];
234 }
235 template <class... Ts>
236 Tproxy operator()(const cytnx::Accessor &e1, const Ts &...elems) {
237 std::vector<cytnx::Accessor> tmp = Indices_resolver(e1, elems...);
238 return (*this)[tmp];
239 }
240 template <class... Ts>
241 const Tproxy operator()(const std::string &e1, const Ts &...elems) const {
242 std::vector<cytnx::Accessor> tmp = Indices_resolver(e1, elems...);
243 return (*this)[tmp];
244 }
245 template <class... Ts>
246 const Tproxy operator()(const cytnx_int64 &e1, const Ts &...elems) const {
247 std::vector<cytnx::Accessor> tmp = Indices_resolver(e1, elems...);
248 return (*this)[tmp];
249 }
250 template <class... Ts>
251 const Tproxy operator()(const cytnx::Accessor &e1, const Ts &...elems) const {
252 std::vector<cytnx::Accessor> tmp = Indices_resolver(e1, elems...);
253 return (*this)[tmp];
254 }
255
256 //-----------------------------------------
257
258 Tproxy operator[](const std::initializer_list<cytnx::Accessor> &accs) {
259 std::vector<cytnx::Accessor> tmp = accs;
260 return (*this)[tmp];
261 }
262 Tproxy operator[](const std::vector<cytnx::Accessor> &accs) {
263 return Tproxy(this->_impl, accs);
264 }
265
266 const Tproxy operator[](const std::vector<cytnx::Accessor> &accs) const {
267 return Tproxy(this->_impl, accs);
268 }
269 const Tproxy operator[](const std::initializer_list<cytnx::Accessor> &accs) const {
270 std::vector<cytnx::Accessor> tmp = accs;
271 return (*this)[tmp];
272 }
273
274 Tproxy operator[](const std::initializer_list<cytnx_int64> &accs) {
275 std::vector<cytnx_int64> tmp = accs;
276 return (*this)[tmp];
277 }
278 Tproxy operator[](const std::vector<cytnx_int64> &accs) {
279 std::vector<cytnx::Accessor> acc_in;
280 for (int i = 0; i < accs.size(); i++) {
281 acc_in.push_back(cytnx::Accessor(accs[i]));
282 }
283 return Tproxy(this->_impl, acc_in);
284 }
285 const Tproxy operator[](const std::initializer_list<cytnx_int64> &accs) const {
286 std::vector<cytnx_int64> tmp = accs;
287 return (*this)[tmp];
288 }
289 const Tproxy operator[](const std::vector<cytnx_uint64> &accs) const {
290 std::vector<cytnx::Accessor> acc_in;
291 for (int i = 0; i < accs.size(); i++) {
292 acc_in.push_back(cytnx::Accessor(accs[i]));
293 }
294 return Tproxy(this->_impl, acc_in);
295 }
296 const Tproxy operator[](const std::vector<cytnx_int64> &accs) const {
297 std::vector<cytnx::Accessor> acc_in;
298 for (int i = 0; i < accs.size(); i++) {
299 acc_in.push_back(cytnx::Accessor(accs[i]));
300 }
301 return Tproxy(this->_impl, acc_in);
302 }
304 //-------------------------------------------
305
307 void _Save(std::fstream &f) const;
308 void _Load(std::fstream &f);
309
311
320 void Save(const std::string &fname) const;
324 void Save(const char *fname) const;
325
334 void Tofile(const std::string &fname) const;
335
339 void Tofile(const char *fname) const;
340
344 void Tofile(std::fstream &f) const;
345
354 static Tensor Load(const std::string &fname);
358 static Tensor Load(const char *fname);
359
380 static Tensor Fromfile(const std::string &fname, const unsigned int &dtype,
381 const cytnx_int64 &count = -1);
382 static Tensor Fromfile(const char *fname, const unsigned int &dtype,
383 const cytnx_int64 &count = -1);
384
385 // static Tensor Frombinary(const std::string &fname);
386
388 boost::intrusive_ptr<Tensor_impl> _impl;
389 Tensor() : _impl(new Tensor_impl()){};
390 Tensor(const Tensor &rhs) { _impl = rhs._impl; }
391
392 /*
393 template<class Tp>
394 Tensor(const std::initializer_list<Tp> &rhs){
395 Storage stmp = std::vector<Tp>(rhs);
396 boost::intrusive_ptr<Tensor_impl> tmp(new Tensor_impl());
397 tmp->Init(stmp);
398 this->_impl = tmp;
399 }
400 */
401
402 Tensor &operator=(const Tensor &rhs) {
403 _impl = rhs._impl;
404 return *this;
405 }
406
407 void operator=(const Tproxy &rhsp) { // this is used to handle proxy assignment
408 this->_impl = rhsp._insimpl->get(rhsp._accs);
409 }
411
413 // default device==Device.cpu (-1)
438 void Init(const std::vector<cytnx_uint64> &shape, unsigned int dtype = Type.Double,
439 int device = -1, bool init_zero = true) {
440 boost::intrusive_ptr<Tensor_impl> tmp(new Tensor_impl());
441 this->_impl = tmp;
442 this->_impl->Init(shape, dtype, device, init_zero);
443 }
444 void Init(std::initializer_list<cytnx_uint64> shape, unsigned int dtype = Type.Double,
445 int device = -1, bool init_zero = true) {
446 this->Init(std::vector<cytnx_uint64>(shape), dtype, device, init_zero);
447 }
448 // void Init(const Storage& storage) {
449 // boost::intrusive_ptr<Tensor_impl> tmp(new Tensor_impl());
450 // this->_impl = tmp;
451 // this->_impl->Init(storage);
452 // }
453 // void Init(const Storage& storage, const std::vector<cytnx_uint64> &shape,
454 // const unsigned int &dtype = Type.Double, const int &device = -1) {
455 // boost::intrusive_ptr<Tensor_impl> tmp(new Tensor_impl());
456 // this->_impl = tmp;
457 // this->_impl->Init(storage, shape, dtype, device);
458 // }
459
472 Tensor(const std::vector<cytnx_uint64> &shape, unsigned int dtype = Type.Double,
473 int device = -1, bool init_zero = true)
474 : _impl(new Tensor_impl()) {
475 this->Init(shape, dtype, device, init_zero);
476 }
477 Tensor(std::initializer_list<cytnx_uint64> shape, unsigned int dtype = Type.Double,
478 int device = -1, bool init_zero = true)
479 : _impl(new Tensor_impl()) {
480 this->Init(shape, dtype, device, init_zero);
481 }
482 // Tensor(const Storage& storage)
483 // : _impl(new Tensor_impl()) {
484 // this->Init(storage);
485 // }
486 // Tensor(const Storage& storage, const std::vector<cytnx_uint64> &shape,
487 // const unsigned int &dtype = Type.Double, const int &device = -1)
488 // : _impl(new Tensor_impl()) {
489 // this->Init(storage, shape, dtype, device);
490 // }
492
493 // This mechanism is to remove the 'void' type from Type_list. Taking advantage of it
494 // appearing first ...
495
497 struct internal {
498 template <typename Variant>
499 struct exclude_first;
500
501 template <typename First, typename... Rest>
502 struct exclude_first<std::variant<First, Rest...>> {
503 using type = std::variant<Rest...>;
504 };
505 }; // internal
507
508 // std::variant of pointers to Type_list, without void ....
511 std::add_pointer>;
512
513 // convert this->_impl->_storage._impl->Mem to a typed variant of pointers, excluding void*
515
516 // Convert storage to the logical Cytnx element pointer type.
517 //
518 // Use ptr_as<T>() for host code and raw memory copies. For complex tensors, T is
519 // std::complex<...>. Use gpu_ptr_as<T>() for CUDA kernel code; for complex tensors, T is
520 // cuda::std::complex<...>. CUDA library APIs that require cuComplex ABI pointers should cast
521 // explicitly at the library-call boundary.
522 template <typename T>
523 T *ptr_as() const {
524 cytnx_error_msg(this->dtype() != Type_class::cy_typeid_v<std::remove_cv_t<T>>,
525 "[ERROR] Attempt to convert dtype %d (%s) to pointer of type %s",
526 this->dtype(), Type_class::getname(this->dtype()).c_str(),
527 Type_class::getname(Type_class::cy_typeid_v<std::remove_cv_t<T>>).c_str());
528 return static_cast<T *>(this->_impl->_storage._impl->data());
529 }
530
531#ifdef UNI_GPU
532 // std::variant of pointers to Type_list_gpu, without void ....
533 using gpu_pointer_types =
535 std::add_pointer>;
536
537 // convert this->_impl->_storage->Mem to a typed variant of pointers, excluding void*
539
540 // Convert storage to the CUDA kernel element pointer type.
541 //
542 // This is for CUDA kernel interfaces. Generic host code should use ptr_as<T>() so the logical
543 // Cytnx dtype mapping is checked. CUDA library APIs that require cuComplex ABI pointers should
544 // cast explicitly at the library-call boundary.
545 template <typename T>
546 T *gpu_ptr_as() const {
548 this->dtype() != Type_class::cy_typeid_gpu_v<std::remove_cv_t<T>>,
549 "[ERROR] Attempt to convert dtype %d (%s) to GPU pointer of type %s", this->dtype(),
550 Type_class::getname(this->dtype()).c_str(),
551 Type_class::getname(Type_class::cy_typeid_gpu_v<std::remove_cv_t<T>>).c_str());
552 return static_cast<T *>(this->_impl->_storage._impl->data());
553 }
554#endif
555
561 static Tensor from_storage(const Storage &in) {
562 Tensor out;
563 boost::intrusive_ptr<Tensor_impl> tmp(new Tensor_impl());
564 out._impl = tmp;
565 out._impl->Init(in);
566 return out;
567 }
568
574 unsigned int dtype() const { return this->_impl->dtype(); }
575
581 int device() const { return this->_impl->device(); }
582
588 std::string dtype_str() const { return this->_impl->dtype_str(); }
589
595 std::string device_str() const { return this->_impl->device_str(); }
596
601 const std::vector<cytnx_uint64> &shape() const { return this->_impl->shape(); }
602
612 std::vector<cytnx_int64> strides() const;
613
618 cytnx_uint64 rank() const { return this->_impl->rank(); }
619
624 cytnx_uint64 size() const { return this->_impl->storage().size(); }
625
630 bool is_void() const { return this->_impl->is_void(); }
631
636 bool is_scalar() const { return this->_impl->is_scalar(); }
637
642 bool is_empty() const { return !this->is_void() && this->size() == 0; }
643
661 Tensor clone() const {
662 Tensor out;
663 out._impl = this->_impl->clone();
664 return out;
665 }
666
687 Tensor to(const int &device) const {
688 Tensor out;
689 out._impl = this->_impl->to(device);
690 return out;
691 }
692
710 void to_(const int &device) { this->_impl->to_(device); }
711
716 const bool &is_contiguous() const { return this->_impl->is_contiguous(); }
717
718 Tensor &permute_(const std::vector<cytnx_uint64> &rnks) {
719 this->_impl->permute_(rnks);
720 return *this;
721 }
723 template <class... Ts>
724 Tensor &permute_(const cytnx_uint64 &e1, const Ts &...elems) {
725 std::vector<cytnx_uint64> argv = dynamic_arg_uint64_resolver(e1, elems...);
726 this->_impl->permute_(argv);
727 return *this;
728 }
730
749 Tensor permute(const std::vector<cytnx_uint64> &rnks) const {
750 Tensor out;
751 out._impl = this->_impl->permute(rnks);
752 return out;
753 }
755 template <class... Ts>
756 Tensor permute(const cytnx_uint64 &e1, const Ts &...elems) const {
757 std::vector<cytnx_uint64> argv = dynamic_arg_uint64_resolver(e1, elems...);
758 return this->permute(argv);
759 }
761
780 Tensor out;
781 out._impl = this->_impl->contiguous();
782 return out;
783 }
784
800 this->_impl->contiguous_();
801 return *this;
802 }
803
824 Tensor &reshape_(const std::vector<cytnx_int64> &new_shape) {
825 this->_impl->reshape_(new_shape);
826 return *this;
827 }
829 Tensor &reshape_(const std::vector<cytnx_uint64> &new_shape) {
830 std::vector<cytnx_int64> shape(new_shape.begin(), new_shape.end());
831 this->_impl->reshape_(shape);
832 return *this;
833 }
834 Tensor &reshape_(const std::initializer_list<cytnx_int64> &new_shape) {
835 std::vector<cytnx_int64> shape = new_shape;
836 this->_impl->reshape_(shape);
837 return *this;
838 }
839 template <class... Ts>
840 Tensor &reshape_(const cytnx_int64 &e1, const Ts... elems) {
841 std::vector<cytnx_int64> shape = dynamic_arg_int64_resolver(e1, elems...);
842 this->_impl->reshape_(shape);
843 return *this;
844 }
846
870 Tensor reshape(const std::vector<cytnx_int64> &new_shape) const {
871 Tensor out;
872 out._impl = this->_impl->reshape(new_shape);
873 return out;
874 }
875
879 Tensor reshape(const std::vector<cytnx_uint64> &new_shape) const {
880 std::vector<cytnx_int64> tmp(new_shape.begin(), new_shape.end());
881 Tensor out;
882 out._impl = this->_impl->reshape(tmp);
883 return out;
884 }
885
889 Tensor reshape(const std::initializer_list<cytnx_int64> &new_shape) const {
890 return this->reshape(std::vector<cytnx_int64>(new_shape));
891 }
892
894 template <class... Ts>
895 Tensor reshape(const cytnx_int64 &e1, const Ts &...elems) const {
896 std::vector<cytnx_int64> argv = dynamic_arg_int64_resolver(e1, elems...);
897 return this->reshape(argv);
898 }
900
922 Tensor astype(const int &new_type) const {
923 Tensor out;
924 out._impl = this->_impl->astype(new_type);
925 return out;
926 }
927
928 // Tensor diagonal(){
929 // for(unsigned int i=0;i<this->shape().size();i++){
930 // if(this->shape()[i] != this->shape()[0],"[ERROR] Tensor.diagonal() can only be called
931 // when the subject has equal dimension in each rank.%s","\n");
932 // }
933 //
934 // }
935
956 template <class T>
957 T &at(const std::vector<cytnx_uint64> &locator) {
958 return this->_impl->at<T>(locator);
959 }
960
964 template <class T>
965 const T &at(const std::vector<cytnx_uint64> &locator) const {
966 return this->_impl->at<T>(locator);
967 }
969 template <class T>
970 T &at(const std::initializer_list<cytnx_uint64> &locator) {
971 return this->at<T>(std::vector<cytnx_uint64>(locator));
972 }
973 template <class T>
974 const T &at(const std::initializer_list<cytnx_uint64> &locator) const {
975 return this->at<T>(std::vector<cytnx_uint64>(locator));
976 }
977 template <class T, class... Ts>
978 const T &at(const cytnx_uint64 &e1, const Ts &...elems) const {
979 std::vector<cytnx_uint64> argv = dynamic_arg_uint64_resolver(e1, elems...);
980 return this->at<T>(argv);
981 }
982 template <class T, class... Ts>
983 T &at(const cytnx_uint64 &e1, const Ts &...elems) {
984 std::vector<cytnx_uint64> argv = dynamic_arg_uint64_resolver(e1, elems...);
985 return this->at<T>(argv);
986 }
987
988 const Scalar::Sproxy at(const std::vector<cytnx_uint64> &locator) const {
989 return this->_impl->at(locator);
990 }
991
992 Scalar::Sproxy at(const std::vector<cytnx_uint64> &locator) { return this->_impl->at(locator); }
993 const Scalar::Sproxy at(const std::initializer_list<cytnx_uint64> &locator) const {
994 return this->at(std::vector<cytnx_uint64>(locator));
995 }
996 Scalar::Sproxy at(const std::initializer_list<cytnx_uint64> &locator) {
997 return this->at(std::vector<cytnx_uint64>(locator));
998 }
1000
1026 template <class T>
1027 T &item() {
1028 cytnx_error_msg(this->_impl->storage().size() != 1, "[ERROR][Tensor.item<T>]%s",
1029 "item can only be called from a Tensor with only one element\n");
1030 return this->_impl->storage().at<T>(0);
1031 }
1032
1034 template <class T>
1035 const T &item() const {
1036 cytnx_error_msg(this->_impl->storage().size() != 1, "[ERROR][Tensor.item<T>]%s",
1037 "item can only be called from a Tensor with only one element\n");
1038 return this->_impl->storage().at<T>(0);
1039 }
1040
1041 const Scalar::Sproxy item() const {
1042 cytnx_error_msg(this->_impl->storage().size() != 1, "[ERROR][Tensor.item]%s",
1043 "item can only be called from a Tensor with only one element\n");
1044 Scalar::Sproxy out(this->storage()._impl, 0);
1045 return out;
1046 }
1047
1048 Scalar::Sproxy item() {
1049 cytnx_error_msg(this->_impl->storage().size() != 1, "[ERROR][Tensor.item]%s",
1050 "item can only be called from a Tensor with only one element\n");
1051 Scalar::Sproxy out(this->storage()._impl, 0);
1052 return out;
1053 }
1054
1056
1081 Tensor get(const std::vector<cytnx::Accessor> &accessors,
1082 std::vector<cytnx_int64> &removed) const {
1083 Tensor out;
1084 out._impl = this->_impl->get(accessors, removed);
1085 return out;
1086 }
1087 Tensor get(const std::vector<cytnx::Accessor> &accessors) const {
1088 Tensor out;
1089 std::vector<cytnx_int64> removed;
1090 out._impl = this->_impl->get(accessors, removed);
1091 return out;
1092 }
1093
1094 /*
1095 Tensor get_v2(const std::vector<cytnx::Accessor> &accessors) const{
1096 Tensor out;
1097 out._impl = this->_impl->get_v2(accessors);
1098 return out;
1099 }
1100 */
1101
1120 void set(const std::vector<cytnx::Accessor> &accessors, const Tensor &rhs) {
1121 this->_impl->set(accessors, rhs._impl);
1122 }
1123
1142 template <class T>
1143 void set(const std::vector<cytnx::Accessor> &accessors, const T &rc) {
1144 this->_impl->set(accessors, rc);
1145 }
1147 template <class T>
1148 void set(const std::initializer_list<cytnx::Accessor> &accessors, const T &rc) {
1149 std::vector<cytnx::Accessor> args = accessors;
1150 this->set(args, rc);
1151 }
1153
1163 Storage &storage() const { return this->_impl->storage(); }
1164
1179 template <class T>
1180 void fill(const T &val) {
1181 this->_impl->fill(val);
1182 }
1183
1188 bool equivshape(const Tensor &rhs) {
1189 if (this->shape() != rhs.shape()) return false;
1190 return true;
1191 }
1192
1201
1210
1211 // Arithmic:
1228 template <class T>
1230
1247 template <class T>
1249
1266 template <class T>
1268
1286 template <class T>
1288
1289 // Tensor &operator+=(const Tproxy &rc);
1290 // Tensor &operator-=(const Tproxy &rc);
1291 // Tensor &operator*=(const Tproxy &rc);
1292 // Tensor &operator/=(const Tproxy &rc);
1293 /*
1294 Tensor operator+(const Tproxy &rc){
1295 return *this + Tensor(rc);
1296 }
1297 Tensor operator-(const Tproxy &rc){
1298 return *this - Tensor(rc);
1299 }
1300 Tensor operator*(const Tproxy &rc){
1301 return *this * Tensor(rc);
1302 }
1303 Tensor operator/(const Tproxy &rc){
1304 return *this / Tensor(rc);
1305 }
1306 */
1312 template <class T>
1313 Tensor Add(const T &rhs) {
1314 return *this + rhs;
1315 }
1316
1322 template <class T>
1323 Tensor &Add_(const T &rhs) {
1324 return *this += rhs;
1325 }
1326
1332 template <class T>
1333 Tensor Sub(const T &rhs) {
1334 return *this - rhs;
1335 }
1336
1342 template <class T>
1343 Tensor &Sub_(const T &rhs) {
1344 return *this -= rhs;
1345 }
1346
1352 template <class T>
1353 Tensor Mul(const T &rhs) {
1354 return *this * rhs;
1355 }
1356
1362 template <class T>
1363 Tensor &Mul_(const T &rhs) {
1364 return *this *= rhs;
1365 }
1366
1373 template <class T>
1374 Tensor Div(const T &rhs) {
1375 return *this / rhs;
1376 }
1377
1384 template <class T>
1385 Tensor &Div_(const T &rhs) {
1386 return *this /= rhs;
1387 }
1388
1395 template <class T>
1396 Tensor Cpr(const T &rhs) {
1397 return *this == rhs;
1398 }
1399
1400 // /**
1401 // * @brief Compare each element of the current tensor with the input tensor.
1402 // * @details This function Compare each element of the current tensor with the input tensor.
1403 // * @param[in] rhs the compared tensor.
1404 // */
1405 // bool approx_eq(const Tensor &rhs, const cytnx_double tol = 0) {
1406 // if (this->device() != rhs.device()) {
1407 // if (User_debug)
1408 // std::cout << "[approx_eq] Tensor device " << this->device()
1409 // << "not equal to rhs tensor device " << rhs.device() << std::endl;
1410 // return false;
1411 // }
1412 // // if (this->dtype() != rhs.dtype()) {
1413 // // std::cout << "[approx_eq] Tensor dtype " << this->dtype()
1414 // // << "not equal to rhs tensor dtype " << rhs.dtype() << std::endl;
1415 // // return false;
1416 // // }
1417 // if (this->shape() != rhs.shape()) {
1418 // if (User_debug)
1419 // std::cout << "[approx_eq] Tensor shape " << this->shape()
1420 // << "not equal to rhs tensor shape " << rhs.shape() << std::endl;
1421 // return false;
1422 // }
1423 // if (this->is_contiguous() != rhs.is_contiguous()) {
1424 // if (User_debug)
1425 // std::cout << "[AreNearlyEqTensor] Tensor contiguous flag " << this->is_contiguous()
1426 // << "not equal to rhs tensor flag " << rhs.is_contiguous() << std::endl;
1427 // return false;
1428 // }
1429 // return this->_impl->_storage.approx_eq(rhs._impl->_storage._impl, tol);
1430 // }
1431
1432 // template<class T>
1433 // Tensor& Cpr_(const T &rhs){
1434 //
1435 // return *this == rhs;
1436 // }
1437
1438 template <class T>
1439 Tensor Mod(const T &rhs) {
1440 return *this % rhs;
1441 }
1442
1449 Tensor operator-() { return this->Mul(-1.); }
1450
1458 Tensor flatten() const {
1459 Tensor out = this->clone();
1460 out.contiguous_();
1461 out.reshape_({-1});
1462 return out;
1463 }
1464
1472 void flatten_() {
1473 this->contiguous_();
1474 this->reshape_({-1});
1475 }
1476
1503 void append(const Tensor &rhs) {
1504 // Tensor in;
1505 // check Tensor in shape:
1506 cytnx_error_msg(rhs.is_void() || this->is_void(), "[ERROR] try to append a null Tensor.%s",
1507 "\n");
1508 cytnx_error_msg(this->is_scalar(), "[ERROR] try to append to a rank-0 Tensor.%s", "\n");
1509 if (!this->is_contiguous()) this->contiguous_();
1510
1511 cytnx_error_msg(rhs.rank() != this->rank() - 1,
1512 "[ERROR] try to append a Tensor with rank not match.%s", "\n");
1513 cytnx_uint64 Nelem = 1;
1514 for (unsigned int i = 0; i < rhs.shape().size(); i++) {
1515 cytnx_error_msg(rhs.shape()[i] != this->shape()[i + 1],
1516 "[ERROR] dimension mismatch @ rhs.rank: [%d] this: [%d] rhs: [%d]\n", i,
1517 this->shape()[i + 1], rhs.shape()[i]);
1518 Nelem *= rhs.shape()[i];
1519 }
1520
1521 // check type:
1522 Tensor in;
1523 if (rhs.dtype() != this->dtype()) {
1524 in = rhs.astype(this->dtype());
1525 if (!in.is_contiguous()) in.contiguous_();
1526 } else {
1527 if (!rhs.is_contiguous())
1528 in = rhs.contiguous();
1529 else
1530 in = rhs;
1531 }
1532 this->_impl->_shape[0] += 1;
1533 cytnx_uint64 oldsize = this->_impl->_storage.size();
1534 this->_impl->_storage.resize(oldsize + Nelem);
1535 memcpy(((char *)this->_impl->_storage.data()) +
1536 oldsize * Type.typeSize(this->dtype()) / sizeof(char),
1537 in._impl->_storage.data(), Type.typeSize(in.dtype()) * Nelem);
1538 }
1566 void append(const Storage &srhs) {
1567 // check Tensor in shape:
1568 cytnx_error_msg(this->is_void(), "[ERROR] try to append to an uninitialized Tensor.%s", "\n");
1569 cytnx_error_msg(srhs.size() == 0, "[ERROR] try to append an empty Storage.%s", "\n");
1570 cytnx_error_msg(this->rank() != 2,
1571 "[ERROR] append a storage to Tensor can only accept rank-2 Tensor.%s", "\n");
1572 if (!this->is_contiguous()) this->contiguous_();
1573
1574 cytnx_error_msg(this->shape().back() != srhs.size(), "[ERROR] Tensor dmension mismatch!%s",
1575 "\n");
1576
1577 // check type:
1578 Storage in;
1579 if (srhs.dtype() != this->dtype()) {
1580 in = srhs.astype(this->dtype());
1581 } else {
1582 in = srhs;
1583 }
1584 this->_impl->_shape[0] += 1;
1585 cytnx_uint64 oldsize = this->_impl->_storage.size();
1586 this->_impl->_storage.resize(oldsize + in.size());
1587 memcpy(((char *)this->_impl->_storage.data()) +
1588 oldsize * Type.typeSize(this->dtype()) / sizeof(char),
1589 in._impl->data(), Type.typeSize(in.dtype()) * in.size());
1590 }
1591 /*
1592 void append(const Tensor &rhs){
1593 // convert to the same type.
1594 Tensor in;
1595 if(rhs.dtype() != this->dtype()){
1596 in = rhs.astype(this->dtype());
1597 }else{
1598 in = rhs;
1599 }
1600
1601 // 1) check rank
1602 if(this->shape().size()==1){
1603 // check if rhs is a scalar tensor (only one element)
1604 cytnx_error_msg(!(rhs.shape().size()==1 && rhs.shape()[0]==1),"[ERROR] trying to append
1605 a scalar into multidimentional Tensor is not allow.\n Only rank-1 Tensor can accept scalar
1606 append.%s","\n"); this->_impl->_shape[0]+=1; this->_impl->_storage.append(0);
1607
1608 }else{
1609 cytnx_error_msg(rhs.shape().size() != this->shape().size()-1,"[ERROR] try to append a
1610 Tensor with rank not match.%s","\n");
1611
1612 }
1613 cytnx_error_msg(!this->is_contiguous(),"[ERROR] append require the Tensor to be contiguous.
1614 suggestion: call contiguous() or contiguous_() first.","\n");
1615 }
1616 */
1628 template <class T>
1629 void append(const T &rhs) {
1630 cytnx_error_msg(this->is_void(), "[ERROR] try to append to an uninitialized Tensor.%s", "\n");
1631 cytnx_error_msg(this->rank() != 1,
1632 "[ERROR] trying to append a scalar into multidimentional Tensor is not "
1633 "allow.\n Only rank-1 Tensor can accept scalar append.%s",
1634 "\n");
1636 "[ERROR] append require the Tensor to be contiguous. suggestion: call "
1637 "contiguous() or contiguous_() first.",
1638 "\n");
1639 this->_impl->_shape[0] += 1;
1640 this->_impl->_storage.append(rhs);
1641 }
1642
1651 bool same_data(const Tensor &rhs) const;
1652
1653 // linalg:
1659 std::vector<Tensor> Svd(const bool &is_UvT = true) const;
1660
1666 std::vector<Tensor> Eigh(const bool &is_V = true, const bool &row_v = false) const;
1667
1673
1678 Tensor InvM() const;
1679
1688 Tensor &Inv_(const double &clip = -1.);
1689
1698 Tensor Inv(const double &clip = -1.) const;
1699
1705
1710 Tensor Conj() const;
1711
1717
1722 Tensor Exp() const;
1723
1729 [[deprecated("use norm() (returns Scalar) instead")]] Tensor Norm() const;
1730
1737 Scalar norm() const;
1738
1743 Tensor Pow(const cytnx_double &p) const;
1744
1750
1755 Tensor Trace(const cytnx_uint64 &a = 0, const cytnx_uint64 &b = 1) const;
1756
1761 Tensor Abs() const;
1762
1768
1773 Tensor Max() const;
1774
1779 Tensor Min() const;
1780
1781 }; // class Tensor
1782
1783 // Scalar-like operand concepts for the free Tensor / UniTensor arithmetic and comparison
1784 // operators. They live here, after the class, because cytnx_scalar_like names Tensor::Tproxy
1785 // and so needs Tensor to be complete; linalg.hpp includes this header and reuses them.
1786 //
1787 // Each concept admits exactly the operand types the corresponding operators are instantiated
1788 // for, so an unsupported operand is rejected at overload resolution instead of surviving to a
1789 // link error. Widening one without adding the matching explicit instantiation reintroduces
1790 // precisely that failure (#1003, operator hygiene -- Ian's review).
1791
1793 // Plain scalar values: the cytnx dtype scalars and cytnx::Scalar. This is the operand set of
1794 // `operator%` (Tensor and UniTensor) and `operator==` (Tensor), which have no element-proxy
1795 // instantiations -- see Mod.cpp and Cpr.cpp.
1796 template <class T>
1797 concept cytnx_scalar_value =
1798 CytnxType<std::remove_cvref_t<T>> || std::is_same_v<std::remove_cvref_t<T>, Scalar>;
1799
1800 // Adds both element proxies: the operand set of the free Tensor `+ - * /` operators.
1801 template <class T>
1802 concept cytnx_scalar_like =
1803 cytnx_scalar_value<T> || std::is_same_v<std::remove_cvref_t<T>, Tensor::Tproxy> ||
1804 std::is_same_v<std::remove_cvref_t<T>, Scalar::Sproxy>;
1805
1806 // Adds only the Scalar proxy: the operand set of the free UniTensor `+ - * /` operators, which
1807 // are instantiated for Scalar::Sproxy but never for Tensor::Tproxy -- see Add.cpp.
1808 template <class T>
1809 concept cytnx_unitensor_scalar_like =
1810 cytnx_scalar_value<T> || std::is_same_v<std::remove_cvref_t<T>, Scalar::Sproxy>;
1811
1812 // [Note] these are fwd from linalg.hpp; the constraint must match linalg.hpp exactly, or the
1813 // two declarations become distinct overloads and the unconstrained one stays viable.
1814 template <cytnx_scalar_like T>
1815 Tensor operator+(const Tensor &lhs, const T &rc);
1816 template <cytnx_scalar_like T>
1817 Tensor operator-(const Tensor &lhs, const T &rhs);
1818 template <cytnx_scalar_like T>
1819 Tensor operator*(const Tensor &lhs, const T &rhs);
1820 template <cytnx_scalar_like T>
1821 Tensor operator/(const Tensor &lhs, const T &rhs);
1823
1824 Tensor operator+(const Tensor &lhs, const Tensor::Tproxy &rhs);
1825 Tensor operator-(const Tensor &lhs, const Tensor::Tproxy &rhs);
1826 Tensor operator*(const Tensor &lhs, const Tensor::Tproxy &rhs);
1827 Tensor operator/(const Tensor &lhs, const Tensor::Tproxy &rhs);
1828
1829 Tensor operator+(const Tensor &lhs, const Scalar::Sproxy &rhs);
1830 Tensor operator-(const Tensor &lhs, const Scalar::Sproxy &rhs);
1831 Tensor operator*(const Tensor &lhs, const Scalar::Sproxy &rhs);
1832 Tensor operator/(const Tensor &lhs, const Scalar::Sproxy &rhs);
1833
1835 std::ostream &operator<<(std::ostream &os, const Tensor &in);
1836 std::ostream &operator<<(std::ostream &os, const Tensor::Tproxy &in);
1838 //{ os << Tensor(in);};
1839} // namespace cytnx
1840
1841#endif // CYTNX_TENSOR_H_
constexpr Type_class Type
data type
Definition Type.hpp:553
object that mimic the python slice to access elements in C++ [this is for c++ API only].
Definition Accessor.hpp:17
an tensor (multi-dimensional array)
Definition Tensor.hpp:33
void append(const Storage &srhs)
the append function of the Storage.
Definition Tensor.hpp:1566
bool is_void() const
whether the Tensor is uninitialized.
Definition Tensor.hpp:630
Tensor & operator*=(const T &rc)
multiplication assignment operator with a Tensor or a scalar.
Tensor & operator/=(const T &rc)
division assignment operator with a Tensor or a scalar.
Tensor operator-()
The negation function.
Definition Tensor.hpp:1449
void fill(const T &val)
fill all the element of current Tensor with the value.
Definition Tensor.hpp:1180
Tensor InvM() const
the InvM member function. Same as cytnx::linalg::InvM(const Tensor &Tin), where Tin is the current Te...
bool same_data(const Tensor &rhs) const
Check whether two tensors share the same internal memory.
void to_(const int &device)
move the current Tensor to the device.
Definition Tensor.hpp:710
Tensor & permute_(const std::vector< cytnx_uint64 > &rnks)
Definition Tensor.hpp:718
bool is_scalar() const
whether the Tensor is an initialized rank-0 scalar Tensor
Definition Tensor.hpp:636
Tensor reshape(const std::vector< cytnx_uint64 > &new_shape) const
Definition Tensor.hpp:879
void append(const T &rhs)
the append function of the scalar.
Definition Tensor.hpp:1629
Tensor & operator-=(const T &rc)
subtraction assignment operator with a Tensor or a scalar.
Tensor & Add_(const T &rhs)
Addition function with a Tensor or a scalar, inplacely. Same as operator+=(const T &rhs).
Definition Tensor.hpp:1323
std::vector< cytnx_int64 > strides() const
the storage strides of the Tensor
Tensor Abs() const
the Abs member function. Same as linalg::Abs(const Tensor &Tin), where Tin is the current Tensor.
Tensor reshape(const std::initializer_list< cytnx_int64 > &new_shape) const
Definition Tensor.hpp:889
std::string device_str() const
the device (in string) of the Tensor
Definition Tensor.hpp:595
Tensor contiguous_()
Make the Tensor contiguous by coalescing the memory (storage), inplacely.
Definition Tensor.hpp:799
Tensor Inv(const double &clip=-1.) const
Apply the inverse on each entry of the Tensor.
Tensor Mul(const T &rhs)
Multiplication function with a Tensor or a scalar. Same as cytnx::operator*(const Tensor &self,...
Definition Tensor.hpp:1353
unsigned int dtype() const
the dtype-id of the Tensor
Definition Tensor.hpp:574
Tensor Sub(const T &rhs)
Subtraction function with a Tensor or a scalar. Same as cytnx::operator-(const Tensor &self,...
Definition Tensor.hpp:1333
Tensor contiguous() const
Make the Tensor contiguous by coalescing the memory (storage).
Definition Tensor.hpp:779
void Tofile(const std::string &fname) const
Save current Tensor to the binary file.
T & at(const std::vector< cytnx_uint64 > &locator)
Get an element at specific location.
Definition Tensor.hpp:957
Tensor reshape(const std::vector< cytnx_int64 > &new_shape) const
return a new Tensor that is reshaped.
Definition Tensor.hpp:870
static Tensor Fromfile(const std::string &fname, const unsigned int &dtype, const cytnx_int64 &count=-1)
Load current Tensor from the binary file.
T & item()
get the element from a rank-0 Tensor.
Definition Tensor.hpp:1027
Tensor clone() const
return a clone of the current Tensor.
Definition Tensor.hpp:661
Tensor(const std::vector< cytnx_uint64 > &shape, unsigned int dtype=Type.Double, int device=-1, bool init_zero=true)
Construct a new Tensor object.
Definition Tensor.hpp:472
std::vector< Tensor > Eigh(const bool &is_V=true, const bool &row_v=false) const
the Eigh member function. Same as cytnx::linalg::Eigh(const Tensor &Tin, const bool &is_V,...
void Tofile(const char *fname) const
void append(const Tensor &rhs)
the append function.
Definition Tensor.hpp:1503
static Tensor Load(const char *fname)
void Save(const char *fname) const
void set(const std::vector< cytnx::Accessor > &accessors, const Tensor &rhs)
set elements with the input Tensor using Accessor (C++ API) / slices (python API)
Definition Tensor.hpp:1120
static Tensor Fromfile(const char *fname, const unsigned int &dtype, const cytnx_int64 &count=-1)
Tensor Norm() const
the Norm member function. Same as linalg::Norm(const Tensor &Tin), where Tin is the current Tensor.
Tensor astype(const int &new_type) const
return a new Tensor that cast to different dtype.
Definition Tensor.hpp:922
Tensor & Div_(const T &rhs)
Division function with a Tensor or a scalar, inplacely. Same as operator/=(const T &rhs).
Definition Tensor.hpp:1385
make_variant_from_transform_t< typename internal::exclude_first< Type_list >::type, std::add_pointer > pointer_types
Definition Tensor.hpp:511
pointer_types ptr() const
static Tensor Load(const std::string &fname)
Load current Tensor from file.
cytnx_uint64 size() const
Return the total number of logical elements in the Tensor.
Definition Tensor.hpp:624
Tensor & operator+=(const T &rc)
addition assignment operator with a Tensor or a scalar.
Tensor Conj() const
the Conj member function. Same as cytnx::linalg::Conj(const Tensor &Tin), where Tin is the current Te...
Tensor Trace(const cytnx_uint64 &a=0, const cytnx_uint64 &b=1) const
the Trace member function. Same as linalg::Trace(const Tensor &Tin, const cytnx_uint64 &a,...
bool is_empty() const
whether the Tensor is initialized and has no elements
Definition Tensor.hpp:642
bool equivshape(const Tensor &rhs)
compare the shape of two tensors.
Definition Tensor.hpp:1188
Tensor & Pow_(const cytnx_double &p)
the Pow_ member function. Same as linalg::Pow_(Tensor &Tin, const cytnx_double &p),...
std::vector< Tensor > Svd(const bool &is_UvT=true) const
the SVD member function. Same as cytnx::linalg::Svd(const Tensor &Tin, const bool &is_UvT) ,...
void Init(const std::vector< cytnx_uint64 > &shape, unsigned int dtype=Type.Double, int device=-1, bool init_zero=true)
initialize a Tensor
Definition Tensor.hpp:438
std::string dtype_str() const
the dtype (in string) of the Tensor
Definition Tensor.hpp:588
Tensor & Mul_(const T &rhs)
Multiplication function with a Tensor or a scalar, inplacely. Same as operator*=(const T &rhs).
Definition Tensor.hpp:1363
cytnx_uint64 rank() const
the rank of the Tensor
Definition Tensor.hpp:618
Tensor get(const std::vector< cytnx::Accessor > &accessors, std::vector< cytnx_int64 > &removed) const
get elements using Accessor (C++ API) / slices (python API)
Definition Tensor.hpp:1081
const bool & is_contiguous() const
return whether the Tensor is contiguous or not.
Definition Tensor.hpp:716
Tensor Exp() const
the Exp member function. Same as linalg::Exp(const Tensor &Tin), where Tin is the current Tensor.
Tensor & Abs_()
the Abs_ member function. Same as linalg::Abs_(Tensor &Tin), where Tin is the current Tensor.
Tensor Add(const T &rhs)
Addition function with a Tensor or a scalar. Same as cytnx::operator+(const Tensor &self,...
Definition Tensor.hpp:1313
void flatten_()
The flatten function, inplacely.
Definition Tensor.hpp:1472
void Save(const std::string &fname) const
Save current Tensor to file.
Tensor flatten() const
The flatten function.
Definition Tensor.hpp:1458
Tensor(std::initializer_list< cytnx_uint64 > shape, unsigned int dtype=Type.Double, int device=-1, bool init_zero=true)
Definition Tensor.hpp:477
Tensor & Conj_()
the Conj_ member function. Same as cytnx::linalg::Conj_(Tensor &Tin), where Tin is the current Tensor...
T * ptr_as() const
Definition Tensor.hpp:523
Tensor Pow(const cytnx_double &p) const
the Pow member function. Same as linalg::Pow(const Tensor &Tin, const cytnx_double &p),...
int device() const
the device-id of the Tensor
Definition Tensor.hpp:581
Tensor real()
return the real part of the tensor.
Tensor imag()
return the imaginary part of the tensor.
void Init(std::initializer_list< cytnx_uint64 > shape, unsigned int dtype=Type.Double, int device=-1, bool init_zero=true)
Definition Tensor.hpp:444
Tensor to(const int &device) const
copy a tensor to new device
Definition Tensor.hpp:687
Tensor & reshape_(const std::vector< cytnx_int64 > &new_shape)
reshape the Tensor, inplacely
Definition Tensor.hpp:824
void Tofile(std::fstream &f) const
Tensor get(const std::vector< cytnx::Accessor > &accessors) const
Definition Tensor.hpp:1087
Scalar norm() const
the norm member function. Same as linalg::norm(const Tensor &Tin), where Tin is the current Tensor....
void set(const std::vector< cytnx::Accessor > &accessors, const T &rc)
set elements with the input constant using Accessor (C++ API) / slices (python API)
Definition Tensor.hpp:1143
Tensor Max() const
the Max member function. Same as linalg::Max(const Tensor &Tin), where Tin is the current Tensor.
Tensor permute(const std::vector< cytnx_uint64 > &rnks) const
perform tensor permute on the cytnx::Tensor and return a new instance.
Definition Tensor.hpp:749
Tensor Div(const T &rhs)
Division function with a Tensor or a scalar. Same as cytnx::operator/(const Tensor &self,...
Definition Tensor.hpp:1374
Tensor Mod(const T &rhs)
Definition Tensor.hpp:1439
Tensor Cpr(const T &rhs)
The comparison function.
Definition Tensor.hpp:1396
Tensor & Inv_(const double &clip=-1.)
Apply the inverse on each entry of the Tensor.
Tensor & Exp_()
the Exp_ member function. Same as linalg::Exp_(Tensor &Tin), where Tin is the current Tensor.
Tensor & InvM_()
the InvM_ member function. Same as cytnx::linalg::InvM_(Tensor &Tin), where Tin is the current Tensor...
const std::vector< cytnx_uint64 > & shape() const
the shape of the Tensor
Definition Tensor.hpp:601
Tensor Min() const
the Min member function. Same as linalg::Min(const Tensor &Tin), where Tin is the current Tensor.
const T & at(const std::vector< cytnx_uint64 > &locator) const
Definition Tensor.hpp:965
Storage & storage() const
return the storage of current Tensor.
Definition Tensor.hpp:1163
static Tensor from_storage(const Storage &in)
Convert a Storage to Tensor.
Definition Tensor.hpp:561
Tensor & Sub_(const T &rhs)
Subtraction function with a Tensor or a scalar, inplacely. Same as operator-=(const T &rhs).
Definition Tensor.hpp:1343
#define cytnx_error_msg(is_true, format,...)
Definition cytnx_error.hpp:118
Definition Accessor.hpp:12
cytnx::UniTensor operator*(const cytnx::UniTensor &Lt, const cytnx::UniTensor &Rt)
The multiplication operator between two UniTensor.
cytnx::UniTensor operator-(const cytnx::UniTensor &Lt, const cytnx::UniTensor &Rt)
The subtraction operator between two UniTensor.
cytnx::UniTensor operator+(const cytnx::UniTensor &Lt, const cytnx::UniTensor &Rt)
The addition operator between two UniTensor.
cytnx::UniTensor operator/(const cytnx::UniTensor &Lt, const cytnx::UniTensor &Rt)
The division operator between two UniTensor.