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 <utility>
13#include <vector>
14#include <initializer_list>
15#include <string>
16
17#ifdef BACKEND_TORCH
18#else
19
20 #include "backend/Scalar.hpp"
21 #include "backend/Storage.hpp"
22 #include "backend/Tensor_impl.hpp"
23
24namespace cytnx {
25
26 class Tensor;
27
29 // [Note] these are fwd from linalg.hpp
30 template <class T>
31 Tensor operator+(const Tensor &lhs, const T &rc);
32 template <class T>
33 Tensor operator-(const Tensor &lhs, const T &rhs);
34 template <class T>
35 Tensor operator*(const Tensor &lhs, const T &rhs);
36 template <class T>
37 Tensor operator/(const Tensor &lhs, const T &rhs);
39
41 class Tensor {
42 private:
43 public:
45 // this is a proxy class to allow get/set element using [] as python!
46 struct Tproxy {
47 boost::intrusive_ptr<Tensor_impl> _insimpl;
48 std::vector<cytnx::Accessor> _accs;
49 Tproxy(boost::intrusive_ptr<Tensor_impl> _ptr, const std::vector<cytnx::Accessor> &accs)
50 : _insimpl(std::move(_ptr)), _accs(accs) {}
51
52 // when used to set elems:
53 const Tensor &operator=(const Tensor &rhs) {
54 this->_insimpl->set(_accs, rhs._impl);
55 return rhs;
56 }
57
58 template <class T>
59 const T &operator=(const T &rc) {
60 this->_insimpl->set(_accs, rc);
61 return rc;
62 }
63 const Tproxy &operator=(const Tproxy &rc) {
65 this->_insimpl->set(_accs, tmp._impl);
66 return rc;
67 }
68
69 template <class T>
70 Tensor operator+=(const T &rc) {
72 self._impl = _insimpl->get(_accs);
73 self += rc;
74 _insimpl->set(_accs, self._impl);
75 self._impl = this->_insimpl;
76 return self;
77 }
78 Tensor operator+=(const Tproxy &rc);
79
80 template <class T>
81 Tensor operator-=(const T &rc) {
83 self._impl = _insimpl->get(_accs);
84 self -= rc;
85 _insimpl->set(_accs, self._impl);
86 self._impl = this->_insimpl;
87 return self;
88 }
89 Tensor operator-=(const Tproxy &rc);
90
91 template <class T>
92 Tensor operator/=(const T &rc) {
94 self._impl = _insimpl->get(_accs);
95 self /= rc;
96 _insimpl->set(_accs, self._impl);
97 self._impl = this->_insimpl;
98 return self;
99 }
100 Tensor operator/=(const Tproxy &rc);
101
102 template <class T>
103 Tensor operator*=(const T &rc) {
104 Tensor self;
105 self._impl = _insimpl->get(_accs);
106 self *= rc;
107 _insimpl->set(_accs, self._impl);
108 self._impl = this->_insimpl;
109 return self;
110 }
111 Tensor operator*=(const Tproxy &rc);
112
113 // alias to resolve conflict with op ovld for rc=Tensor
114 /*
115 template<class T>
116 Tensor _operatorADD(const T &rc) const{
117 Tensor out;
118 out._impl = _insimpl->get(_accs);
119 return out.Add(rc);
120 }
121 */
122 Tensor operator+(const cytnx_complex128 &rc) const; //{return this->_operatorADD(rc);};
123 Tensor operator+(const cytnx_complex64 &rc) const; //{return this->_operatorADD(rc);};
124 Tensor operator+(const cytnx_double &rc) const; //{return this->_operatorADD(rc);};
125 Tensor operator+(const cytnx_float &rc) const; //{return this->_operatorADD(rc);};
126 Tensor operator+(const cytnx_uint64 &rc) const; //{return this->_operatorADD(rc);};
127 Tensor operator+(const cytnx_int64 &rc) const; //{return this->_operatorADD(rc);};
128 Tensor operator+(const cytnx_uint32 &rc) const; //{return this->_operatorADD(rc);};
129 Tensor operator+(const cytnx_int32 &rc) const; //{return this->_operatorADD(rc);};
130 Tensor operator+(const cytnx_uint16 &rc) const; //{return this->_operatorADD(rc);};
131 Tensor operator+(const cytnx_int16 &rc) const; //{return this->_operatorADD(rc);};
132 Tensor operator+(const cytnx_bool &rc) const; //{return this->_operatorADD(rc);};
133 Tensor operator+(const Tproxy &rc) const;
134
135 /*
136 template<class T>
137 Tensor _operatorSUB(const T &rc) const{
138 Tensor out;
139 out._impl = _insimpl->get(_accs);
140 return out.Sub(rc);
141 }
142 */
143 Tensor operator-(const cytnx_complex128 &rc) const; //{return this->_operatorSUB(rc);};
144 Tensor operator-(const cytnx_complex64 &rc) const; //{return this->_operatorSUB(rc);};
145 Tensor operator-(const cytnx_double &rc) const; //{return this->_operatorSUB(rc);};
146 Tensor operator-(const cytnx_float &rc) const; //{return this->_operatorSUB(rc);};
147 Tensor operator-(const cytnx_uint64 &rc) const; //{return this->_operatorSUB(rc);};
148 Tensor operator-(const cytnx_int64 &rc) const; //{return this->_operatorSUB(rc);};
149 Tensor operator-(const cytnx_uint32 &rc) const; //{return this->_operatorSUB(rc);};
150 Tensor operator-(const cytnx_int32 &rc) const; //{return this->_operatorSUB(rc);};
151 Tensor operator-(const cytnx_uint16 &rc) const; //{return this->_operatorSUB(rc);};
152 Tensor operator-(const cytnx_int16 &rc) const; //{return this->_operatorSUB(rc);};
153 Tensor operator-(const cytnx_bool &rc) const; //{return this->_operatorSUB(rc);};
154 Tensor operator-(const Tproxy &rc) const;
155
156 Tensor operator-() const;
157
158 /*
159 template<class T>
160 Tensor _operatorMUL(const T &rc) const{
161 Tensor out;
162 out._impl = _insimpl->get(_accs);
163 return out.Mul(rc);
164 }
165 */
166 Tensor operator*(const cytnx_complex128 &rc) const; //{return this->_operatorMUL(rc);};
167 Tensor operator*(const cytnx_complex64 &rc) const; //{return this->_operatorMUL(rc);};
168 Tensor operator*(const cytnx_double &rc) const; //{return this->_operatorMUL(rc);};
169 Tensor operator*(const cytnx_float &rc) const; //{return this->_operatorMUL(rc);};
170 Tensor operator*(const cytnx_uint64 &rc) const; //{return this->_operatorMUL(rc);};
171 Tensor operator*(const cytnx_int64 &rc) const; //{return this->_operatorMUL(rc);};
172 Tensor operator*(const cytnx_uint32 &rc) const; //{return this->_operatorMUL(rc);};
173 Tensor operator*(const cytnx_int32 &rc) const; //{return this->_operatorMUL(rc);};
174 Tensor operator*(const cytnx_uint16 &rc) const; //{return this->_operatorMUL(rc);};
175 Tensor operator*(const cytnx_int16 &rc) const; //{return this->_operatorMUL(rc);};
176 Tensor operator*(const cytnx_bool &rc) const; //{return this->_operatorMUL(rc);};
177 Tensor operator*(const Tproxy &rc) const;
178
179 /*
180 template<class T>
181 Tensor _operatorDIV(const T &rc) const{
182 Tensor out;
183 out._impl = _insimpl->get(_accs);
184 return out.Div(rc);
185 }
186 */
187 Tensor operator/(const cytnx_complex128 &rc) const; //{return this->_operatorDIV(rc);};
188 Tensor operator/(const cytnx_complex64 &rc) const; //{return this->_operatorDIV(rc);};
189 Tensor operator/(const cytnx_double &rc) const; //{return this->_operatorDIV(rc);};
190 Tensor operator/(const cytnx_float &rc) const; //{return this->_operatorDIV(rc);};
191 Tensor operator/(const cytnx_uint64 &rc) const; //{return this->_operatorDIV(rc);};
192 Tensor operator/(const cytnx_int64 &rc) const; //{return this->_operatorDIV(rc);};
193 Tensor operator/(const cytnx_uint32 &rc) const; //{return this->_operatorDIV(rc);};
194 Tensor operator/(const cytnx_int32 &rc) const; //{return this->_operatorDIV(rc);};
195 Tensor operator/(const cytnx_uint16 &rc) const; //{return this->_operatorDIV(rc);};
196 Tensor operator/(const cytnx_int16 &rc) const; //{return this->_operatorDIV(rc);};
197 Tensor operator/(const cytnx_bool &rc) const; //{return this->_operatorDIV(rc);};
198 Tensor operator/(const Tproxy &rc) const;
199
200 template <class T>
201 T item() const {
202 Tensor out;
203 out._impl = _insimpl->get(_accs);
204 return out.item<T>();
205 }
206
207 Scalar::Sproxy item() const {
208 Tensor out;
209 out._impl = _insimpl->get(_accs);
210 return out.item();
211 }
212
213 // when used to get elems:
214 operator Tensor() const {
215 Tensor out;
216 out._impl = _insimpl->get(_accs);
217 return out;
218 }
219
220 Storage storage() const {
221 Tensor out;
222 out._impl = _insimpl->get(_accs);
223 return out.storage();
224 }
225
226 }; // proxy class of Tensor.
227
229
231 // these two are using the python way!
232 //----------------------------------------
233 template <class... Ts>
234 Tproxy operator()(const std::string &e1, const Ts &...elems) {
235 std::vector<cytnx::Accessor> tmp = Indices_resolver(e1, elems...);
236 return (*this)[tmp];
237 }
238 template <class... Ts>
239 Tproxy operator()(const cytnx_int64 &e1, const Ts &...elems) {
240 std::vector<cytnx::Accessor> tmp = Indices_resolver(e1, elems...);
241 return (*this)[tmp];
242 }
243 template <class... Ts>
244 Tproxy operator()(const cytnx::Accessor &e1, const Ts &...elems) {
245 std::vector<cytnx::Accessor> tmp = Indices_resolver(e1, elems...);
246 return (*this)[tmp];
247 }
248 template <class... Ts>
249 const Tproxy operator()(const std::string &e1, const Ts &...elems) const {
250 std::vector<cytnx::Accessor> tmp = Indices_resolver(e1, elems...);
251 return (*this)[tmp];
252 }
253 template <class... Ts>
254 const Tproxy operator()(const cytnx_int64 &e1, const Ts &...elems) const {
255 std::vector<cytnx::Accessor> tmp = Indices_resolver(e1, elems...);
256 return (*this)[tmp];
257 }
258 template <class... Ts>
259 const Tproxy operator()(const cytnx::Accessor &e1, const Ts &...elems) const {
260 std::vector<cytnx::Accessor> tmp = Indices_resolver(e1, elems...);
261 return (*this)[tmp];
262 }
263
264 //-----------------------------------------
265
266 Tproxy operator[](const std::initializer_list<cytnx::Accessor> &accs) {
267 std::vector<cytnx::Accessor> tmp = accs;
268 return (*this)[tmp];
269 }
270 Tproxy operator[](const std::vector<cytnx::Accessor> &accs) {
271 return Tproxy(this->_impl, accs);
272 }
273
274 const Tproxy operator[](const std::vector<cytnx::Accessor> &accs) const {
275 return Tproxy(this->_impl, accs);
276 }
277 const Tproxy operator[](const std::initializer_list<cytnx::Accessor> &accs) const {
278 std::vector<cytnx::Accessor> tmp = accs;
279 return (*this)[tmp];
280 }
281
282 Tproxy operator[](const std::initializer_list<cytnx_int64> &accs) {
283 std::vector<cytnx_int64> tmp = accs;
284 return (*this)[tmp];
285 }
286 Tproxy operator[](const std::vector<cytnx_int64> &accs) {
287 std::vector<cytnx::Accessor> acc_in;
288 for (int i = 0; i < accs.size(); i++) {
289 acc_in.push_back(cytnx::Accessor(accs[i]));
290 }
291 return Tproxy(this->_impl, acc_in);
292 }
293 const Tproxy operator[](const std::initializer_list<cytnx_int64> &accs) const {
294 std::vector<cytnx_int64> tmp = accs;
295 return (*this)[tmp];
296 }
297 const Tproxy operator[](const std::vector<cytnx_uint64> &accs) const {
298 std::vector<cytnx::Accessor> acc_in;
299 for (int i = 0; i < accs.size(); i++) {
300 acc_in.push_back(cytnx::Accessor(accs[i]));
301 }
302 return Tproxy(this->_impl, acc_in);
303 }
304 const Tproxy operator[](const std::vector<cytnx_int64> &accs) const {
305 std::vector<cytnx::Accessor> acc_in;
306 for (int i = 0; i < accs.size(); i++) {
307 acc_in.push_back(cytnx::Accessor(accs[i]));
308 }
309 return Tproxy(this->_impl, acc_in);
310 }
312 //-------------------------------------------
313
315 void _Save(std::fstream &f) const;
316 void _Load(std::fstream &f);
317
319
328 void Save(const std::string &fname) const;
332 void Save(const char *fname) const;
333
342 void Tofile(const std::string &fname) const;
343
347 void Tofile(const char *fname) const;
348
352 void Tofile(std::fstream &f) const;
353
362 static Tensor Load(const std::string &fname);
366 static Tensor Load(const char *fname);
367
388 static Tensor Fromfile(const std::string &fname, const unsigned int &dtype,
389 const cytnx_int64 &count = -1);
390 static Tensor Fromfile(const char *fname, const unsigned int &dtype,
391 const cytnx_int64 &count = -1);
392
393 // static Tensor Frombinary(const std::string &fname);
394
396 boost::intrusive_ptr<Tensor_impl> _impl;
397 Tensor() : _impl(new Tensor_impl()){};
398 Tensor(const Tensor &rhs) { _impl = rhs._impl; }
399
400 /*
401 template<class Tp>
402 Tensor(const std::initializer_list<Tp> &rhs){
403 Storage stmp = std::vector<Tp>(rhs);
404 boost::intrusive_ptr<Tensor_impl> tmp(new Tensor_impl());
405 tmp->Init(stmp);
406 this->_impl = tmp;
407 }
408 */
409
410 Tensor &operator=(const Tensor &rhs) {
411 _impl = rhs._impl;
412 return *this;
413 }
414
415 void operator=(const Tproxy &rhsp) { // this is used to handle proxy assignment
416 this->_impl = rhsp._insimpl->get(rhsp._accs);
417 }
419
421 // default device==Device.cpu (-1)
446 void Init(const std::vector<cytnx_uint64> &shape, const unsigned int &dtype = Type.Double,
447 const int &device = -1, const bool &init_zero = true) {
448 boost::intrusive_ptr<Tensor_impl> tmp(new Tensor_impl());
449 this->_impl = tmp;
450 this->_impl->Init(shape, dtype, device, init_zero);
451 }
452 // void Init(const Storage& storage) {
453 // boost::intrusive_ptr<Tensor_impl> tmp(new Tensor_impl());
454 // this->_impl = tmp;
455 // this->_impl->Init(storage);
456 // }
457 // void Init(const Storage& storage, const std::vector<cytnx_uint64> &shape,
458 // const unsigned int &dtype = Type.Double, const int &device = -1) {
459 // boost::intrusive_ptr<Tensor_impl> tmp(new Tensor_impl());
460 // this->_impl = tmp;
461 // this->_impl->Init(storage, shape, dtype, device);
462 // }
463
476 Tensor(const std::vector<cytnx_uint64> &shape, const unsigned int &dtype = Type.Double,
477 const int &device = -1, const bool &init_zero = 1)
478 : _impl(new Tensor_impl()) {
479 this->Init(shape, dtype, device, init_zero);
480 }
481 // Tensor(const Storage& storage)
482 // : _impl(new Tensor_impl()) {
483 // this->Init(storage);
484 // }
485 // Tensor(const Storage& storage, const std::vector<cytnx_uint64> &shape,
486 // const unsigned int &dtype = Type.Double, const int &device = -1)
487 // : _impl(new Tensor_impl()) {
488 // this->Init(storage, shape, dtype, device);
489 // }
491
492 // This mechanism is to remove the 'void' type from Type_list. Taking advantage of it
493 // appearing first ...
494
496 struct internal {
497 template <typename Variant>
498 struct exclude_first;
499
500 template <typename First, typename... Rest>
501 struct exclude_first<std::variant<First, Rest...>> {
502 using type = std::variant<Rest...>;
503 };
504 }; // internal
506
507 // std::variant of pointers to Type_list, without void ....
510 std::add_pointer>;
511
512 // convert this->_impl->_storage._impl->Mem to a typed variant of pointers, excluding void*
514
515 // Convert storage to the logical Cytnx element pointer type.
516 //
517 // Use ptr_as<T>() for host code and raw memory copies, including cudaMemcpy. For complex
518 // tensors, T is std::complex<...>. Use gpu_ptr_as<T>() only for CUDA APIs that require CUDA
519 // ABI element types such as cuDoubleComplex or cuComplex.
520 template <typename T>
521 T *ptr_as() const {
522 cytnx_error_msg(this->dtype() != Type_class::cy_typeid_v<std::remove_cv_t<T>>,
523 "[ERROR] Attempt to convert dtype %d (%s) to pointer of type %s",
524 this->dtype(), Type_class::getname(this->dtype()).c_str(),
525 Type_class::getname(Type_class::cy_typeid_v<std::remove_cv_t<T>>).c_str());
526 return static_cast<T *>(this->_impl->_storage._impl->data());
527 }
528
529 #ifdef UNI_GPU
530 // std::variant of pointers to Type_list_gpu, without void ....
531 using gpu_pointer_types =
533 std::add_pointer>;
534
535 // convert this->_impl->_storage->Mem to a typed variant of pointers, excluding void*
537
538 // Convert storage to the CUDA ABI element pointer type.
539 //
540 // This is for CUDA/cuBLAS/cuSOLVER/kernel interfaces. Generic host code and cudaMemcpy byte
541 // copies should use ptr_as<T>() so the logical Cytnx dtype mapping is checked.
542 template <typename T>
543 T *gpu_ptr_as() const {
545 this->dtype() != Type_class::cy_typeid_gpu_v<std::remove_cv_t<T>>,
546 "[ERROR] Attempt to convert dtype %d (%s) to GPU pointer of type %s", this->dtype(),
547 Type_class::getname(this->dtype()).c_str(),
548 Type_class::getname(Type_class::cy_typeid_gpu_v<std::remove_cv_t<T>>).c_str());
549 return static_cast<T *>(this->_impl->_storage._impl->data());
550 }
551 #endif
552
558 static Tensor from_storage(const Storage &in) {
559 Tensor out;
560 boost::intrusive_ptr<Tensor_impl> tmp(new Tensor_impl());
561 out._impl = tmp;
562 out._impl->Init(in);
563 return out;
564 }
565
571 unsigned int dtype() const { return this->_impl->dtype(); }
572
578 int device() const { return this->_impl->device(); }
579
585 std::string dtype_str() const { return this->_impl->dtype_str(); }
586
592 std::string device_str() const { return this->_impl->device_str(); }
593
598 const std::vector<cytnx_uint64> &shape() const { return this->_impl->shape(); }
599
604 cytnx_uint64 rank() const { return this->_impl->shape().size(); }
605
623 Tensor clone() const {
624 Tensor out;
625 out._impl = this->_impl->clone();
626 return out;
627 }
628
649 Tensor to(const int &device) const {
650 Tensor out;
651 out._impl = this->_impl->to(device);
652 return out;
653 }
654
672 void to_(const int &device) { this->_impl->to_(device); }
673
678 const bool &is_contiguous() const { return this->_impl->is_contiguous(); }
679
680 Tensor &permute_(const std::vector<cytnx_uint64> &rnks) {
681 this->_impl->permute_(rnks);
682 return *this;
683 }
685 template <class... Ts>
686 Tensor &permute_(const cytnx_uint64 &e1, const Ts &...elems) {
687 std::vector<cytnx_uint64> argv = dynamic_arg_uint64_resolver(e1, elems...);
688 this->_impl->permute_(argv);
689 return *this;
690 }
692
711 Tensor permute(const std::vector<cytnx_uint64> &rnks) const {
712 Tensor out;
713 out._impl = this->_impl->permute(rnks);
714 return out;
715 }
717 template <class... Ts>
718 Tensor permute(const cytnx_uint64 &e1, const Ts &...elems) const {
719 std::vector<cytnx_uint64> argv = dynamic_arg_uint64_resolver(e1, elems...);
720 return this->permute(argv);
721 }
723
742 Tensor out;
743 out._impl = this->_impl->contiguous();
744 return out;
745 }
746
762 this->_impl->contiguous_();
763 return *this;
764 }
765
787 Tensor &reshape_(const std::vector<cytnx_int64> &new_shape) {
788 this->_impl->reshape_(new_shape);
789 return *this;
790 }
792 Tensor &reshape_(const std::vector<cytnx_uint64> &new_shape) {
793 std::vector<cytnx_int64> shape(new_shape.begin(), new_shape.end());
794 this->_impl->reshape_(shape);
795 return *this;
796 }
797 Tensor &reshape_(const std::initializer_list<cytnx_int64> &new_shape) {
798 std::vector<cytnx_int64> shape = new_shape;
799 this->_impl->reshape_(shape);
800 return *this;
801 }
802 template <class... Ts>
803 Tensor &reshape_(const cytnx_int64 &e1, const Ts... elems) {
804 std::vector<cytnx_int64> shape = dynamic_arg_int64_resolver(e1, elems...);
805 this->_impl->reshape_(shape);
806 return *this;
807 }
809
834 Tensor reshape(const std::vector<cytnx_int64> &new_shape) const {
835 Tensor out;
836 out._impl = this->_impl->reshape(new_shape);
837 return out;
838 }
839
843 Tensor reshape(const std::vector<cytnx_uint64> &new_shape) const {
844 std::vector<cytnx_int64> tmp(new_shape.size());
845 memcpy(&tmp[0], &new_shape[0], sizeof(cytnx_uint64) * new_shape.size());
846 Tensor out;
847 out._impl = this->_impl->reshape(tmp);
848 return out;
849 }
850
854 Tensor reshape(const std::initializer_list<cytnx_int64> &new_shape) const {
855 return this->reshape(std::vector<cytnx_int64>(new_shape));
856 }
857
859 template <class... Ts>
860 Tensor reshape(const cytnx_int64 &e1, const Ts &...elems) const {
861 std::vector<cytnx_int64> argv = dynamic_arg_int64_resolver(e1, elems...);
862 return this->reshape(argv);
863 }
865
887 Tensor astype(const int &new_type) const {
888 Tensor out;
889 out._impl = this->_impl->astype(new_type);
890 return out;
891 }
892
893 // Tensor diagonal(){
894 // for(unsigned int i=0;i<this->shape().size();i++){
895 // if(this->shape()[i] != this->shape()[0],"[ERROR] Tensor.diagonal() can only be called
896 // when the subject has equal dimension in each rank.%s","\n");
897 // }
898 //
899 // }
900
921 template <class T>
922 T &at(const std::vector<cytnx_uint64> &locator) {
923 return this->_impl->at<T>(locator);
924 }
925
929 template <class T>
930 const T &at(const std::vector<cytnx_uint64> &locator) const {
931 return this->_impl->at<T>(locator);
932 }
934 template <class T, class... Ts>
935 const T &at(const cytnx_uint64 &e1, const Ts &...elems) const {
936 std::vector<cytnx_uint64> argv = dynamic_arg_uint64_resolver(e1, elems...);
937 return this->at<T>(argv);
938 }
939 template <class T, class... Ts>
940 T &at(const cytnx_uint64 &e1, const Ts &...elems) {
941 std::vector<cytnx_uint64> argv = dynamic_arg_uint64_resolver(e1, elems...);
942 return this->at<T>(argv);
943 }
944
945 const Scalar::Sproxy at(const std::vector<cytnx_uint64> &locator) const {
946 return this->_impl->at(locator);
947 }
948
949 Scalar::Sproxy at(const std::vector<cytnx_uint64> &locator) { return this->_impl->at(locator); }
951
977 template <class T>
978 T &item() {
979 cytnx_error_msg(this->_impl->storage().size() != 1, "[ERROR][Tensor.item<T>]%s",
980 "item can only be called from a Tensor with only one element\n");
981 return this->_impl->storage().at<T>(0);
982 }
983
985 template <class T>
986 const T &item() const {
987 cytnx_error_msg(this->_impl->storage().size() != 1, "[ERROR][Tensor.item<T>]%s",
988 "item can only be called from a Tensor with only one element\n");
989 return this->_impl->storage().at<T>(0);
990 }
991
992 const Scalar::Sproxy item() const {
993 Scalar::Sproxy out(this->storage()._impl, 0);
994 return out;
995 }
996
997 Scalar::Sproxy item() {
998 Scalar::Sproxy out(this->storage()._impl, 0);
999 return out;
1000 }
1001
1003
1028 Tensor get(const std::vector<cytnx::Accessor> &accessors,
1029 std::vector<cytnx_int64> &removed) const {
1030 Tensor out;
1031 out._impl = this->_impl->get(accessors, removed);
1032 return out;
1033 }
1034 Tensor get(const std::vector<cytnx::Accessor> &accessors) const {
1035 Tensor out;
1036 std::vector<cytnx_int64> removed;
1037 out._impl = this->_impl->get(accessors, removed);
1038 return out;
1039 }
1040
1041 /*
1042 Tensor get_v2(const std::vector<cytnx::Accessor> &accessors) const{
1043 Tensor out;
1044 out._impl = this->_impl->get_v2(accessors);
1045 return out;
1046 }
1047 */
1048
1067 void set(const std::vector<cytnx::Accessor> &accessors, const Tensor &rhs) {
1068 this->_impl->set(accessors, rhs._impl);
1069 }
1070
1089 template <class T>
1090 void set(const std::vector<cytnx::Accessor> &accessors, const T &rc) {
1091 this->_impl->set(accessors, rc);
1092 }
1094 template <class T>
1095 void set(const std::initializer_list<cytnx::Accessor> &accessors, const T &rc) {
1096 std::vector<cytnx::Accessor> args = accessors;
1097 this->set(args, rc);
1098 }
1100
1110 Storage &storage() const { return this->_impl->storage(); }
1111
1126 template <class T>
1127 void fill(const T &val) {
1128 this->_impl->fill(val);
1129 }
1130
1135 bool equivshape(const Tensor &rhs) {
1136 if (this->shape() != rhs.shape()) return false;
1137 return true;
1138 }
1139
1148
1157
1158 // Arithmic:
1175 template <class T>
1177
1194 template <class T>
1196
1213 template <class T>
1215
1233 template <class T>
1235
1236 // Tensor &operator+=(const Tproxy &rc);
1237 // Tensor &operator-=(const Tproxy &rc);
1238 // Tensor &operator*=(const Tproxy &rc);
1239 // Tensor &operator/=(const Tproxy &rc);
1240 /*
1241 Tensor operator+(const Tproxy &rc){
1242 return *this + Tensor(rc);
1243 }
1244 Tensor operator-(const Tproxy &rc){
1245 return *this - Tensor(rc);
1246 }
1247 Tensor operator*(const Tproxy &rc){
1248 return *this * Tensor(rc);
1249 }
1250 Tensor operator/(const Tproxy &rc){
1251 return *this / Tensor(rc);
1252 }
1253 */
1259 template <class T>
1260 Tensor Add(const T &rhs) {
1261 return *this + rhs;
1262 }
1263
1269 template <class T>
1270 Tensor &Add_(const T &rhs) {
1271 return *this += rhs;
1272 }
1273
1279 template <class T>
1280 Tensor Sub(const T &rhs) {
1281 return *this - rhs;
1282 }
1283
1289 template <class T>
1290 Tensor &Sub_(const T &rhs) {
1291 return *this -= rhs;
1292 }
1293
1299 template <class T>
1300 Tensor Mul(const T &rhs) {
1301 return *this * rhs;
1302 }
1303
1309 template <class T>
1310 Tensor &Mul_(const T &rhs) {
1311 return *this *= rhs;
1312 }
1313
1320 template <class T>
1321 Tensor Div(const T &rhs) {
1322 return *this / rhs;
1323 }
1324
1331 template <class T>
1332 Tensor &Div_(const T &rhs) {
1333 return *this /= rhs;
1334 }
1335
1342 template <class T>
1343 Tensor Cpr(const T &rhs) {
1344 return *this == rhs;
1345 }
1346
1347 // /**
1348 // * @brief Compare each element of the current tensor with the input tensor.
1349 // * @details This function Compare each element of the current tensor with the input tensor.
1350 // * @param[in] rhs the compared tensor.
1351 // */
1352 // bool approx_eq(const Tensor &rhs, const cytnx_double tol = 0) {
1353 // if (this->device() != rhs.device()) {
1354 // if (User_debug)
1355 // std::cout << "[approx_eq] Tensor device " << this->device()
1356 // << "not equal to rhs tensor device " << rhs.device() << std::endl;
1357 // return false;
1358 // }
1359 // // if (this->dtype() != rhs.dtype()) {
1360 // // std::cout << "[approx_eq] Tensor dtype " << this->dtype()
1361 // // << "not equal to rhs tensor dtype " << rhs.dtype() << std::endl;
1362 // // return false;
1363 // // }
1364 // if (this->shape() != rhs.shape()) {
1365 // if (User_debug)
1366 // std::cout << "[approx_eq] Tensor shape " << this->shape()
1367 // << "not equal to rhs tensor shape " << rhs.shape() << std::endl;
1368 // return false;
1369 // }
1370 // if (this->is_contiguous() != rhs.is_contiguous()) {
1371 // if (User_debug)
1372 // std::cout << "[AreNearlyEqTensor] Tensor contiguous flag " << this->is_contiguous()
1373 // << "not equal to rhs tensor flag " << rhs.is_contiguous() << std::endl;
1374 // return false;
1375 // }
1376 // return this->_impl->_storage.approx_eq(rhs._impl->_storage._impl, tol);
1377 // }
1378
1379 // template<class T>
1380 // Tensor& Cpr_(const T &rhs){
1381 //
1382 // return *this == rhs;
1383 // }
1384
1385 template <class T>
1386 Tensor Mod(const T &rhs) {
1387 return *this % rhs;
1388 }
1389
1396 Tensor operator-() { return this->Mul(-1.); }
1397
1405 Tensor flatten() const {
1406 Tensor out = this->clone();
1407 out.contiguous_();
1408 out.reshape_({-1});
1409 return out;
1410 }
1411
1419 void flatten_() {
1420 this->contiguous_();
1421 this->reshape_({-1});
1422 }
1423
1450 void append(const Tensor &rhs) {
1451 // Tensor in;
1452 if (!this->is_contiguous()) this->contiguous_();
1453
1454 // check Tensor in shape:
1455 cytnx_error_msg(rhs.shape().size() == 0 || this->shape().size() == 0,
1456 "[ERROR] try to append a null Tensor.%s", "\n");
1457 cytnx_error_msg(rhs.shape().size() != (this->shape().size() - 1),
1458 "[ERROR] try to append a Tensor with rank not match.%s", "\n");
1459 cytnx_uint64 Nelem = 1;
1460 for (unsigned int i = 0; i < rhs.shape().size(); i++) {
1461 cytnx_error_msg(rhs.shape()[i] != this->shape()[i + 1],
1462 "[ERROR] dimension mismatch @ rhs.rank: [%d] this: [%d] rhs: [%d]\n", i,
1463 this->shape()[i + 1], rhs.shape()[i]);
1464 Nelem *= rhs.shape()[i];
1465 }
1466
1467 // check type:
1468 Tensor in;
1469 if (rhs.dtype() != this->dtype()) {
1470 in = rhs.astype(this->dtype());
1471 if (!in.is_contiguous()) in.contiguous_();
1472 } else {
1473 if (!in.is_contiguous())
1474 in = rhs.contiguous();
1475 else
1476 in = rhs;
1477 }
1478 this->_impl->_shape[0] += 1;
1479 cytnx_uint64 oldsize = this->_impl->_storage.size();
1480 this->_impl->_storage.resize(oldsize + Nelem);
1481 memcpy(((char *)this->_impl->_storage.data()) +
1482 oldsize * Type.typeSize(this->dtype()) / sizeof(char),
1483 in._impl->_storage.data(), Type.typeSize(in.dtype()) * Nelem);
1484 }
1512 void append(const Storage &srhs) {
1513 if (!this->is_contiguous()) this->contiguous_();
1514
1515 // check Tensor in shape:
1516 cytnx_error_msg(srhs.size() == 0 || this->shape().size() == 0,
1517 "[ERROR] try to append a null Tensor.%s", "\n");
1518 cytnx_error_msg((this->shape().size() - 1) != 1,
1519 "[ERROR] append a storage to Tensor can only accept rank-2 Tensor.%s", "\n");
1520 cytnx_error_msg(this->shape().back() != srhs.size(), "[ERROR] Tensor dmension mismatch!%s",
1521 "\n");
1522
1523 // check type:
1524 Storage in;
1525 if (srhs.dtype() != this->dtype()) {
1526 in = srhs.astype(this->dtype());
1527 } else {
1528 in = srhs;
1529 }
1530 this->_impl->_shape[0] += 1;
1531 cytnx_uint64 oldsize = this->_impl->_storage.size();
1532 this->_impl->_storage.resize(oldsize + in.size());
1533 memcpy(((char *)this->_impl->_storage.data()) +
1534 oldsize * Type.typeSize(this->dtype()) / sizeof(char),
1535 in._impl->data(), Type.typeSize(in.dtype()) * in.size());
1536 }
1537 /*
1538 void append(const Tensor &rhs){
1539 // convert to the same type.
1540 Tensor in;
1541 if(rhs.dtype() != this->dtype()){
1542 in = rhs.astype(this->dtype());
1543 }else{
1544 in = rhs;
1545 }
1546
1547 // 1) check rank
1548 if(this->shape().size()==1){
1549 // check if rhs is a scalar tensor (only one element)
1550 cytnx_error_msg(!(rhs.shape().size()==1 && rhs.shape()[0]==1),"[ERROR] trying to append
1551 a scalar into multidimentional Tensor is not allow.\n Only rank-1 Tensor can accept scalar
1552 append.%s","\n"); this->_impl->_shape[0]+=1; this->_impl->_storage.append(0);
1553
1554 }else{
1555 cytnx_error_msg(rhs.shape().size() != this->shape().size()-1,"[ERROR] try to append a
1556 Tensor with rank not match.%s","\n");
1557
1558 }
1559 cytnx_error_msg(!this->is_contiguous(),"[ERROR] append require the Tensor to be contiguous.
1560 suggestion: call contiguous() or contiguous_() first.","\n");
1561 }
1562 */
1574 template <class T>
1575 void append(const T &rhs) {
1576 cytnx_error_msg(this->shape().size() != 1,
1577 "[ERROR] trying to append a scalar into multidimentional Tensor is not "
1578 "allow.\n Only rank-1 Tensor can accept scalar append.%s",
1579 "\n");
1581 "[ERROR] append require the Tensor to be contiguous. suggestion: call "
1582 "contiguous() or contiguous_() first.",
1583 "\n");
1584 this->_impl->_shape[0] += 1;
1585 this->_impl->_storage.append(rhs);
1586 }
1587
1596 bool same_data(const Tensor &rhs) const;
1597
1598 // linalg:
1604 std::vector<Tensor> Svd(const bool &is_UvT = true) const;
1605
1611 std::vector<Tensor> Eigh(const bool &is_V = true, const bool &row_v = false) const;
1612
1618
1623 Tensor InvM() const;
1624
1633 Tensor &Inv_(const double &clip = -1.);
1634
1643 Tensor Inv(const double &clip = -1.) const;
1644
1650
1655 Tensor Conj() const;
1656
1662
1667 Tensor Exp() const;
1668
1673 Tensor Norm() const;
1674
1679 Tensor Pow(const cytnx_double &p) const;
1680
1686
1691 Tensor Trace(const cytnx_uint64 &a = 0, const cytnx_uint64 &b = 1) const;
1692
1697 Tensor Abs() const;
1698
1704
1709 Tensor Max() const;
1710
1715 Tensor Min() const;
1716
1717 }; // class Tensor
1718
1719 Tensor operator+(const Tensor &lhs, const Tensor::Tproxy &rhs);
1720 Tensor operator-(const Tensor &lhs, const Tensor::Tproxy &rhs);
1721 Tensor operator*(const Tensor &lhs, const Tensor::Tproxy &rhs);
1722 Tensor operator/(const Tensor &lhs, const Tensor::Tproxy &rhs);
1723
1724 Tensor operator+(const Tensor &lhs, const Scalar::Sproxy &rhs);
1725 Tensor operator-(const Tensor &lhs, const Scalar::Sproxy &rhs);
1726 Tensor operator*(const Tensor &lhs, const Scalar::Sproxy &rhs);
1727 Tensor operator/(const Tensor &lhs, const Scalar::Sproxy &rhs);
1728
1730 std::ostream &operator<<(std::ostream &os, const Tensor &in);
1731 std::ostream &operator<<(std::ostream &os, const Tensor::Tproxy &in);
1733 //{ os << Tensor(in);};
1734} // namespace cytnx
1735
1736#endif // BACKEND_TORCH
1737
1738#endif // CYTNX_TENSOR_H_
constexpr Type_class Type
data type
Definition Type.hpp:426
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:41
void append(const Storage &srhs)
the append function of the Storage.
Definition Tensor.hpp:1512
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:1396
void fill(const T &val)
fill all the element of current Tensor with the value.
Definition Tensor.hpp:1127
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:672
Tensor & permute_(const std::vector< cytnx_uint64 > &rnks)
Definition Tensor.hpp:680
Tensor reshape(const std::vector< cytnx_uint64 > &new_shape) const
Definition Tensor.hpp:843
Tensor(const std::vector< cytnx_uint64 > &shape, const unsigned int &dtype=Type.Double, const int &device=-1, const bool &init_zero=1)
Construct a new Tensor object.
Definition Tensor.hpp:476
void append(const T &rhs)
the append function of the scalar.
Definition Tensor.hpp:1575
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:1270
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:854
std::string device_str() const
the device (in string) of the Tensor
Definition Tensor.hpp:592
Tensor contiguous_()
Make the Tensor contiguous by coalescing the memory (storage), inplacely.
Definition Tensor.hpp:761
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:1300
unsigned int dtype() const
the dtype-id of the Tensor
Definition Tensor.hpp:571
Tensor Sub(const T &rhs)
Subtraction function with a Tensor or a scalar. Same as cytnx::operator-(const Tensor &self,...
Definition Tensor.hpp:1280
Tensor contiguous() const
Make the Tensor contiguous by coalescing the memory (storage).
Definition Tensor.hpp:741
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:922
Tensor reshape(const std::vector< cytnx_int64 > &new_shape) const
return a new Tensor that is reshaped.
Definition Tensor.hpp:834
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:978
Tensor clone() const
return a clone of the current Tensor.
Definition Tensor.hpp:623
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:1450
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:1067
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:887
Tensor & Div_(const T &rhs)
Division function with a Tensor or a scalar, inplacely. Same as operator/=(const T &rhs).
Definition Tensor.hpp:1332
make_variant_from_transform_t< typename internal::exclude_first< Type_list >::type, std::add_pointer > pointer_types
Definition Tensor.hpp:510
pointer_types ptr() const
static Tensor Load(const std::string &fname)
Load current Tensor from file.
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 equivshape(const Tensor &rhs)
compare the shape of two tensors.
Definition Tensor.hpp:1135
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) ,...
std::string dtype_str() const
the dtype (in string) of the Tensor
Definition Tensor.hpp:585
Tensor & Mul_(const T &rhs)
Multiplication function with a Tensor or a scalar, inplacely. Same as operator*=(const T &rhs).
Definition Tensor.hpp:1310
cytnx_uint64 rank() const
the rank of the Tensor
Definition Tensor.hpp:604
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:1028
const bool & is_contiguous() const
return whether the Tensor is contiguous or not.
Definition Tensor.hpp:678
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:1260
void flatten_()
The flatten function, inplacely.
Definition Tensor.hpp:1419
void Save(const std::string &fname) const
Save current Tensor to file.
Tensor flatten() const
The flatten function.
Definition Tensor.hpp:1405
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:521
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:578
Tensor real()
return the real part of the tensor.
Tensor imag()
return the imaginary part of the tensor.
Tensor to(const int &device) const
copy a tensor to new device
Definition Tensor.hpp:649
Tensor & reshape_(const std::vector< cytnx_int64 > &new_shape)
reshape the Tensor, inplacely
Definition Tensor.hpp:787
void Tofile(std::fstream &f) const
Tensor get(const std::vector< cytnx::Accessor > &accessors) const
Definition Tensor.hpp:1034
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:1090
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:711
Tensor Div(const T &rhs)
Division function with a Tensor or a scalar. Same as cytnx::operator/(const Tensor &self,...
Definition Tensor.hpp:1321
Tensor Mod(const T &rhs)
Definition Tensor.hpp:1386
void Init(const std::vector< cytnx_uint64 > &shape, const unsigned int &dtype=Type.Double, const int &device=-1, const bool &init_zero=true)
initialize a Tensor
Definition Tensor.hpp:446
Tensor Cpr(const T &rhs)
The comparison function.
Definition Tensor.hpp:1343
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:598
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:930
Storage & storage() const
return the storage of current Tensor.
Definition Tensor.hpp:1110
static Tensor from_storage(const Storage &in)
Convert a Storage to Tensor.
Definition Tensor.hpp:558
Tensor & Sub_(const T &rhs)
Subtraction function with a Tensor or a scalar, inplacely. Same as operator-=(const T &rhs).
Definition Tensor.hpp:1290
#define cytnx_error_msg(is_true, format,...)
Definition cytnx_error.hpp:27
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.