Cytnx v0.7.3
Loading...
Searching...
No Matches
UniTensor.hpp
Go to the documentation of this file.
1#ifndef _H_UniTensor_
2#define _H_UniTensor_
3
4#include "Type.hpp"
5#include "cytnx_error.hpp"
6#include "Storage.hpp"
7#include "Device.hpp"
8#include "Tensor.hpp"
9#include "Scalar.hpp"
10#include "utils/utils.hpp"
12#include <iostream>
13#include <vector>
14#include <map>
15#include <utility>
16#include <initializer_list>
17#include <fstream>
18#include <algorithm>
19#include "Symmetry.hpp"
20#include "Bond.hpp"
21//#include "linalg.hpp"
22
23//namespace cytnx{
24namespace cytnx{
25 using namespace cytnx;
27 class UniTensorType_class{
28 public:
29 enum : int{
30 Void=-99,
31 Dense=0,
32 Sparse=1,
33 };
34 std::string getname(const int &ut_type);
35 };
36 extern UniTensorType_class UTenType;
38
40 //class DenseUniTensor;
41 //class SparseUniTensor;
42 class UniTensor_base: public intrusive_ptr_base<UniTensor_base>{
43
44 public:
45 int uten_type_id; //the unitensor type id.
46 bool _is_braket_form;
47 bool _is_tag;
48 bool _is_diag;
49 cytnx_int64 _rowrank;
50 std::string _name;
51 std::vector<cytnx_int64> _labels;
52 std::vector< Bond > _bonds;
53
54
55
56 bool _update_braket(){
57 if(_bonds.size()==0) return false;
58
59 if(this->_bonds[0].type()!= bondType::BD_REG){
60 //check:
61 for(unsigned int i=0;i<this->_bonds.size();i++){
62 if(i<this->_rowrank){
63 if(this->_bonds[i].type()!=bondType::BD_KET) return false;
64 }else{
65 if(this->_bonds[i].type()!=bondType::BD_BRA) return false;
66 }
67 }
68 return true;
69 }else{
70 return false;
71 }
72 }
73
74 friend class UniTensor; // allow wrapper to access the private elems
75 friend class DenseUniTensor;
76 friend class SparseUniTensor;
77
78 UniTensor_base(): _is_tag(false), _name(std::string("")), _is_braket_form(false), _rowrank(-1), _is_diag(false), uten_type_id(UTenType.Void){};
79
80 //copy&assignment constr., use intrusive_ptr's !!
81 UniTensor_base(const UniTensor_base &rhs);
82 UniTensor_base& operator=(UniTensor_base &rhs);
83
84 cytnx_uint64 rowrank() const{return this->_rowrank;}
85 bool is_diag() const{ return this->_is_diag; }
86 const bool& is_braket_form() const{
87 return this->_is_braket_form;
88 }
89 const bool& is_tag() const{
90 return this->_is_tag;
91 }
92 const std::vector<cytnx_int64>& labels() const{ return this->_labels;}
93 const std::vector<Bond> &bonds() const {return this->_bonds;}
94 std::vector<Bond> &bonds(){return this->_bonds;}
95 const std::string& name() const { return this->_name;}
96 cytnx_uint64 rank() const {return this->_labels.size();}
97 void set_name(const std::string &in){ this->_name = in;}
98 void set_label(const cytnx_uint64 &idx, const cytnx_int64 &new_label){
99 cytnx_error_msg(idx>=this->_labels.size(),"[ERROR] index exceed the rank of UniTensor%s","\n");
100 //check in:
101 bool is_dup =false;
102 for(cytnx_uint64 i=0;i<this->_labels.size();i++){
103 if(i==idx) continue;
104 if(new_label == this->_labels[i]){is_dup = true; break;}
105 }
106 cytnx_error_msg(is_dup,"[ERROR] alreay has a label that is the same as the input label%s","\n");
107 this->_labels[idx] = new_label;
108 }
109 void set_labels(const std::vector<cytnx_int64> &new_labels);
110
111
112
113 template<class T>
114 T& at(const std::vector<cytnx_uint64> &locator){
115 //std::cout << "at " << this->is_blockform() << std::endl;
116 if(this->is_blockform()){
117 cytnx_error_msg(true,"[ERROR][SparseUniTensor] UniTensor with Symmetry cannot get element with at(). Use get_elem()/set_elem() instead.%s","\n");
118 }else{
119 return this->get_block_().at<T>(locator);
120 }
121
122 }
123
124 template<class T>
125 const T& at(const std::vector<cytnx_uint64> &locator) const{
126 //std::cout << "at " << this->is_blockform() << std::endl;
127 if(this->is_blockform()){
128 cytnx_error_msg(true,"[ERROR][SparseUniTensor] UniTensor with Symmetry cannot get element with at(). Use get_elem()/set_elem() instead.%s","\n");
129 }else{
130 return this->get_block_().at<T>(locator);
131 }
132
133 }
134
135
136 template<class T>
137 T get_elem(const std::vector<cytnx_uint64> &locator) const{
138 if(this->is_blockform()){
139 if(this->elem_exists(locator)){
140 T aux; // [workaround] use aux to dispatch.
141 return this->at_for_sparse(locator,aux);
142 }else{
143 return 0;
144 }
145 }else{
146 return this->at<T>(locator);
147 }
148 }
149 template<class T>
150 void set_elem(const std::vector<cytnx_uint64> &locator, const T &input){
151 if(this->is_blockform()){
152 if(this->elem_exists(locator)){
153 T aux;
154 this->at_for_sparse(locator,aux) = input;
155 }else{
156 cytnx_error_msg(true,"[ERROR][SparseUniTensor] invalid location. break qnum block.%s","\n");
157 }
158 }else{
159 this->at<T>(locator) = input;
160 }
161 }
162
163 int uten_type(){
164 return this->uten_type_id;
165 }
166 std::string uten_type_str(){
167 return UTenType.getname(this->uten_type_id);
168 }
169
170
171
172
173 virtual void Init(const std::vector<Bond> &bonds, const std::vector<cytnx_int64> &in_labels={}, const cytnx_int64 &rowrank=-1,const unsigned int &dtype=Type.Double,const int &device = Device.cpu,const bool &is_diag=false);
174 virtual void Init_by_Tensor(const Tensor& in, const cytnx_uint64 &rowrank, const bool &is_diag=false);
175 virtual std::vector<cytnx_uint64> shape() const;
176 virtual bool is_blockform() const ;
177 virtual bool is_contiguous() const;
178 virtual void to_(const int &device);
179 virtual boost::intrusive_ptr<UniTensor_base> to(const int &device);
180 virtual boost::intrusive_ptr<UniTensor_base> clone() const;
181 virtual unsigned int dtype() const;
182 virtual int device() const;
183 virtual std::string dtype_str() const;
184 virtual std::string device_str() const;
185 virtual void set_rowrank(const cytnx_uint64 &new_rowrank);
186 virtual boost::intrusive_ptr<UniTensor_base> permute(const std::vector<cytnx_int64> &mapper,const cytnx_int64 &rowrank=-1, const bool &by_label=false);
187 virtual void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank=-1, const bool &by_label=false);
188 virtual boost::intrusive_ptr<UniTensor_base> contiguous_();
189 virtual boost::intrusive_ptr<UniTensor_base> contiguous();
190 virtual void print_diagram(const bool &bond_info=false);
191
192 virtual Tensor get_block(const cytnx_uint64 &idx=0) const; // return a copy of block
193 virtual Tensor get_block(const std::vector<cytnx_int64> &qnum) const; //return a copy of block
194
195 virtual const Tensor& get_block_(const cytnx_uint64 &idx=0) const; // return a share view of block, this only work for non-symm tensor.
196 virtual const Tensor& get_block_(const std::vector<cytnx_int64> &qnum) const; //return a copy of block
197 virtual Tensor& get_block_(const cytnx_uint64 &idx=0); // return a share view of block, this only work for non-symm tensor.
198 virtual Tensor& get_block_(const std::vector<cytnx_int64> &qnum); //return a copy of block
199 virtual bool same_data(const boost::intrusive_ptr<UniTensor_base> &rhs) const;
200
201 virtual std::vector<Tensor> get_blocks() const;
202 virtual const std::vector<Tensor>& get_blocks_(const bool &) const;
203 virtual std::vector<Tensor>& get_blocks_(const bool &);
204
205 virtual void put_block(const Tensor &in, const cytnx_uint64 &idx=0);
206 virtual void put_block_(Tensor &in, const cytnx_uint64 &idx=0);
207 virtual void put_block(const Tensor &in, const std::vector<cytnx_int64> &qnum);
208 virtual void put_block_(Tensor &in, const std::vector<cytnx_int64> &qnum);
209
210 // this will only work on non-symm tensor (DenseUniTensor)
211 virtual boost::intrusive_ptr<UniTensor_base> get(const std::vector<Accessor> &accessors);
212
213 // this will only work on non-symm tensor (DenseUniTensor)
214 virtual void set(const std::vector<Accessor> &accessors, const Tensor &rhs);
215
216 virtual void reshape_(const std::vector<cytnx_int64> &new_shape, const cytnx_uint64 &rowrank=0);
217 virtual boost::intrusive_ptr<UniTensor_base> reshape(const std::vector<cytnx_int64> &new_shape, const cytnx_uint64 &rowrank=0);
218 virtual boost::intrusive_ptr<UniTensor_base> to_dense();
219 virtual void to_dense_();
220 virtual void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &permute_back=false, const bool &by_label=true);
221 virtual boost::intrusive_ptr<UniTensor_base> contract(const boost::intrusive_ptr<UniTensor_base> &rhs, const bool &mv_elem_self=false, const bool &mv_elem_rhs=false);
222 virtual std::vector<Bond> getTotalQnums(const bool &physical=false);
223 virtual std::vector<std::vector<cytnx_int64> > get_blocks_qnums() const;
224 virtual void Trace_(const cytnx_int64 &a, const cytnx_int64 &b, const bool &by_label=false);
225 virtual boost::intrusive_ptr<UniTensor_base> Trace(const cytnx_int64 &a, const cytnx_int64 &b, const bool &by_label=false);
226
227
228 // arithmetic
229 virtual void Add_(const boost::intrusive_ptr<UniTensor_base> &rhs);
230 virtual void Add_(const Scalar &rhs);
231
232 virtual void Mul_(const boost::intrusive_ptr<UniTensor_base> &rhs);
233 virtual void Mul_(const Scalar &rhs);
234
235 virtual void Sub_(const boost::intrusive_ptr<UniTensor_base> &rhs);
236 virtual void Sub_(const Scalar &rhs);
237 virtual void lSub_(const Scalar &lhs);
238
239 virtual void Div_(const boost::intrusive_ptr<UniTensor_base> &rhs);
240 virtual void Div_(const Scalar &rhs);
241 virtual void lDiv_(const Scalar &lhs);
242
243
244
245
246
247
248 virtual boost::intrusive_ptr<UniTensor_base> Conj();
249 virtual void Conj_();
250
251 virtual boost::intrusive_ptr<UniTensor_base> Transpose();
252 virtual void Transpose_();
253
254 virtual boost::intrusive_ptr<UniTensor_base> Dagger();
255 virtual void Dagger_();
256
257 virtual void tag();
258
259 virtual void truncate_(const cytnx_int64 &bond_idx, const cytnx_uint64 &dim, const bool &by_label=false);
260
261 virtual bool elem_exists(const std::vector<cytnx_uint64> &locator) const;
262
263 // this a workaround, as virtual function cannot template.
264 virtual cytnx_complex128& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_complex128 &aux);
265 virtual cytnx_complex64& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_complex64 &aux);
266 virtual cytnx_double& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_double &aux);
267 virtual cytnx_float& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_float &aux);
268 virtual cytnx_uint64& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint64 &aux);
269 virtual cytnx_int64& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int64 &aux);
270 virtual cytnx_uint32& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint32 &aux);
271 virtual cytnx_int32& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int32 &aux);
272 virtual cytnx_uint16& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint16 &aux);
273 virtual cytnx_int16& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int16 &aux);
274
275 virtual const cytnx_complex128& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_complex128 &aux)const ;
276 virtual const cytnx_complex64& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_complex64 &aux)const;
277 virtual const cytnx_double& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_double &aux)const;
278 virtual const cytnx_float& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_float &aux)const;
279 virtual const cytnx_uint64& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint64 &aux) const;
280 virtual const cytnx_int64& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int64 &aux) const;
281 virtual const cytnx_uint32& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint32 &aux) const;
282 virtual const cytnx_int32& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int32 &aux) const;
283 virtual const cytnx_uint16& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint16 &aux) const;
284 virtual const cytnx_int16& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int16 &aux) const;
285
286 virtual void _save_dispatch(std::fstream &f) const;
287 virtual void _load_dispatch(std::fstream &f);
288
289 virtual ~UniTensor_base(){};
290 };
292
293 //======================================================================
295 class DenseUniTensor: public UniTensor_base{
296 protected:
297 public:
298 Tensor _block;
299 std::vector<Tensor> _interface_block; // this is serves as interface for get_blocks_();
300 DenseUniTensor* clone_meta() const{
301 DenseUniTensor* tmp = new DenseUniTensor();
302 tmp->_bonds = vec_clone(this->_bonds);
303 tmp->_labels = this->_labels;
304 tmp->_is_braket_form = this->_is_braket_form;
305 tmp->_rowrank = this->_rowrank;
306 tmp->_is_diag = this->_is_diag;
307 tmp->_name = this->_name;
308 tmp->_is_tag = this->_is_tag;
309 return tmp;
310 }
311 //------------------------------------------
312
313 DenseUniTensor(){this->uten_type_id = UTenType.Dense;};
314 friend class UniTensor; // allow wrapper to access the private elems
315 // virtual functions
316 void Init(const std::vector<Bond> &bonds, const std::vector<cytnx_int64> &in_labels={}, const cytnx_int64 &rowrank=-1, const unsigned int &dtype=Type.Double,const int &device = Device.cpu, const bool &is_diag=false);
317 // this only work for non-symm tensor
318 void Init_by_Tensor(const Tensor& in_tensor, const cytnx_uint64 &rowrank, const bool &is_diag=false);
319 std::vector<cytnx_uint64> shape() const{
320 if(this->_is_diag){
321 std::vector<cytnx_uint64> shape = this->_block.shape();
322 shape.push_back(shape[0]);
323 return shape;
324 }else{
325 return this->_block.shape();
326 }
327 }
328 bool is_blockform() const{ return false;}
329 void to_(const int &device){
330 this->_block.to_(device);
331 }
332 boost::intrusive_ptr<UniTensor_base> to(const int &device){
333 if(this->device() == device){
334 return this;
335 }else{
336 boost::intrusive_ptr<UniTensor_base> out = this->clone();
337 out->to_(device);
338 return out;
339 }
340 }
341 void set_rowrank(const cytnx_uint64 &new_rowrank){
342 cytnx_error_msg(new_rowrank > this->_labels.size(),"[ERROR] rowrank cannot exceed the rank of UniTensor.%s","\n");
343 this->_rowrank = new_rowrank;
344 }
345
346 boost::intrusive_ptr<UniTensor_base> clone() const{
347 DenseUniTensor* tmp = this->clone_meta();
348 tmp->_block = this->_block.clone();
349 boost::intrusive_ptr<UniTensor_base> out(tmp);
350 return out;
351 };
352 bool is_contiguous() const{return this->_block.is_contiguous();}
353 unsigned int dtype() const{return this->_block.dtype();}
354 int device() const{return this->_block.device();}
355 std::string dtype_str() const{ return Type.getname(this->_block.dtype());}
356 std::string device_str() const{ return Device.getname(this->_block.device());}
357 boost::intrusive_ptr<UniTensor_base> permute(const std::vector<cytnx_int64> &mapper,const cytnx_int64 &rowrank=-1,const bool &by_label=false);
358 void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank=-1, const bool &by_label=false);
359 boost::intrusive_ptr<UniTensor_base> contiguous_(){this->_block.contiguous_(); return boost::intrusive_ptr<UniTensor_base>(this);}
360 boost::intrusive_ptr<UniTensor_base> contiguous(){
361 // if contiguous then return self!
362 if(this->is_contiguous()){
363 boost::intrusive_ptr<UniTensor_base> out(this);
364 return out;
365 }else{
366 DenseUniTensor* tmp = this->clone_meta();
367 tmp->_block = this->_block.contiguous();
368 boost::intrusive_ptr<UniTensor_base> out(tmp);
369 return out;
370 }
371 }
372 void print_diagram(const bool &bond_info=false);
373 Tensor get_block(const cytnx_uint64 &idx=0) const{ return this->_block.clone(); }
374
375 Tensor get_block(const std::vector<cytnx_int64> &qnum) const{cytnx_error_msg(true,"[ERROR][DenseUniTensor] try to get_block() using qnum on a non-symmetry UniTensor%s","\n"); return Tensor();}
376 // return a share view of block, this only work for non-symm tensor.
377 const Tensor& get_block_(const std::vector<cytnx_int64> &qnum) const{cytnx_error_msg(true,"[ERROR][DenseUniTensor] try to get_block_() using qnum on a non-symmetry UniTensor%s","\n"); return this->_block;}
378 Tensor& get_block_(const std::vector<cytnx_int64> &qnum){cytnx_error_msg(true,"[ERROR][DenseUniTensor] try to get_block_() using qnum on a non-symmetry UniTensor%s","\n"); return this->_block;}
379
380 // return a share view of block, this only work for non-symm tensor.
381 Tensor& get_block_(const cytnx_uint64 &idx=0){
382 return this->_block;
383 }
384 // return a share view of block, this only work for non-symm tensor.
385 const Tensor& get_block_(const cytnx_uint64 &idx=0) const{
386 return this->_block;
387 }
388
389
390 std::vector<Tensor> get_blocks() const {
391 std::vector<Tensor> out;
392 cytnx_error_msg(true,"[ERROR][DenseUniTensor] cannot use get_blocks(), use get_block() instead!%s","\n");
393 return out; // this will not share memory!!
394 }
395 const std::vector<Tensor>& get_blocks_(const bool &silent=false) const {
396 cytnx_error_msg(true,"[ERROR][DenseUniTensor] cannot use get_blocks_(), use get_block_() instead!%s","\n");
397 return this->_interface_block; // this will not share memory!!
398 }
399 std::vector<Tensor>& get_blocks_(const bool &silent=false){
400 cytnx_error_msg(true,"[ERROR][DenseUniTensor] cannot use get_blocks_(), use get_block_() instead!%s","\n");
401 return this->_interface_block; // this will not share memory!!
402 }
403
404 void put_block(const Tensor &in, const cytnx_uint64 &idx=0){
405 if(this->is_diag()){
406 cytnx_error_msg(in.shape() != this->_block.shape(),"[ERROR][DenseUniTensor] put_block, the input tensor shape does not match.%s","\n");
407 this->_block = in.clone();
408 }else{
409 cytnx_error_msg(in.shape() != this->shape(),"[ERROR][DenseUniTensor] put_block, the input tensor shape does not match.%s","\n");
410 this->_block = in.clone();
411 }
412 }
413 // share view of the block
414 void put_block_(Tensor &in, const cytnx_uint64 &idx=0){
415 if(this->is_diag()){
416 cytnx_error_msg(in.shape() != this->_block.shape(),"[ERROR][DenseUniTensor] put_block, the input tensor shape does not match.%s","\n");
417 this->_block = in;
418 }else{
419 cytnx_error_msg(in.shape() != this->shape(),"[ERROR][DenseUniTensor] put_block, the input tensor shape does not match.%s","\n");
420 this->_block = in;
421 }
422 }
423
424 void put_block(const Tensor &in, const std::vector<cytnx_int64> &qnum){
425 cytnx_error_msg(true,"[ERROR][DenseUniTensor] try to put_block using qnum on a non-symmetry UniTensor%s","\n");
426 }
427 void put_block_(Tensor &in, const std::vector<cytnx_int64> &qnum){
428 cytnx_error_msg(true,"[ERROR][DenseUniTensor] try to put_block using qnum on a non-symmetry UniTensor%s","\n");
429 }
430 // this will only work on non-symm tensor (DenseUniTensor)
431 boost::intrusive_ptr<UniTensor_base> get(const std::vector<Accessor> &accessors){
432 boost::intrusive_ptr<UniTensor_base> out(new DenseUniTensor());
433 out->Init_by_Tensor(this->_block.get(accessors),0); //wrapping around.
434 return out;
435 }
436 // this will only work on non-symm tensor (DenseUniTensor)
437 void set(const std::vector<Accessor> &accessors, const Tensor &rhs){
438 this->_block.set(accessors,rhs);
439 }
440
441 void reshape_(const std::vector<cytnx_int64> &new_shape, const cytnx_uint64 &rowrank=0);
442 boost::intrusive_ptr<UniTensor_base> reshape(const std::vector<cytnx_int64> &new_shape, const cytnx_uint64 &rowrank=0);
443 boost::intrusive_ptr<UniTensor_base> to_dense();
444 void to_dense_();
445
446 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &permute_back=true, const bool &by_label=true);
447 boost::intrusive_ptr<UniTensor_base> contract(const boost::intrusive_ptr<UniTensor_base> &rhs, const bool &mv_elem_self=false, const bool &mv_elem_rhs=false);
448 std::vector<Bond> getTotalQnums(const bool &physical=false){
449 cytnx_error_msg(true,"[ERROR][DenseUniTensor] %s","getTotalQnums can only operate on UniTensor with symmetry.\n");
450 return std::vector<Bond>();
451 }
452
453
454 std::vector<std::vector<cytnx_int64> > get_blocks_qnums() const{
455 cytnx_error_msg(true,"[ERROR][DenseUniTensor] %s","get_blocks_qnums can only operate on UniTensor with symmetry.\n");
456 return std::vector<std::vector<cytnx_int64> >();
457 }
458
459 bool same_data(const boost::intrusive_ptr<UniTensor_base> &rhs) const{
460 if(rhs->uten_type()!=UTenType.Dense) return false;
461
462 return this->get_block_().same_data(rhs->get_block_());
463
464 }
465
466
467 ~DenseUniTensor(){};
468
469
470 // arithmetic
471 void Add_(const boost::intrusive_ptr<UniTensor_base> &rhs);
472 void Add_(const Scalar &rhs);
473
474 void Mul_(const boost::intrusive_ptr<UniTensor_base> &rhs);
475 void Mul_(const Scalar &rhs);
476
477 void Sub_(const boost::intrusive_ptr<UniTensor_base> &rhs);
478 void Sub_(const Scalar &rhs);
479 void lSub_(const Scalar &lhs);
480
481 void Div_(const boost::intrusive_ptr<UniTensor_base> &rhs);
482 void Div_(const Scalar &rhs);
483 void lDiv_(const Scalar &lhs);
484
485
486 void Conj_(){
487 this->_block.Conj_();
488 };
489
490 boost::intrusive_ptr<UniTensor_base> Conj(){
491 boost::intrusive_ptr<UniTensor_base> out = this->clone();
492 out->Conj_();
493 return out;
494 }
495
496 boost::intrusive_ptr<UniTensor_base> Transpose(){
497 boost::intrusive_ptr<UniTensor_base> out = this->clone();
498 out->Transpose_();
499 return out;
500 }
501 void Transpose_();
502
503 boost::intrusive_ptr<UniTensor_base> Dagger(){
504 boost::intrusive_ptr<UniTensor_base> out = this->Conj();
505 out->Transpose_();
506 return out;
507 }
508 void Dagger_(){
509 this->Conj_();
510 this->Transpose_();
511 }
512
513
514 void Trace_(const cytnx_int64 &a, const cytnx_int64 &b, const bool &by_label=false);
515 boost::intrusive_ptr<UniTensor_base> Trace(const cytnx_int64 &a, const cytnx_int64 &b, const bool &by_label=false){
516 boost::intrusive_ptr<UniTensor_base> out = this->clone();
517 out->Trace_(a,b,by_label);
518 return out;
519 }
520 const cytnx_complex128& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_complex128 &aux) const {
521 cytnx_error_msg(true,"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s","\n");
522 //return cytnx_complex128(0,0);
523 }
524 const cytnx_complex64& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_complex64 &aux) const{
525 cytnx_error_msg(true,"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s","\n");
526 //return cytnx_complex64(0,0);
527 }
528 const cytnx_double& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_double &aux) const{
529 cytnx_error_msg(true,"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s","\n");
530 //return 0;
531 }
532 const cytnx_float& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_float &aux) const{
533 cytnx_error_msg(true,"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s","\n");
534 //return 0;
535 }
536 const cytnx_uint64& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint64 &aux) const{
537 cytnx_error_msg(true,"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s","\n");
538 //return 0;
539 }
540 const cytnx_int64& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int64 &aux) const{
541 cytnx_error_msg(true,"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s","\n");
542 //return 0;
543 }
544 const cytnx_uint32& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint32 &aux)const {
545 cytnx_error_msg(true,"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s","\n");
546 //return 0;
547
548 }
549 const cytnx_int32& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int32 &aux) const {
550 cytnx_error_msg(true,"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s","\n");
551 //return 0;
552 }
553 const cytnx_uint16& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint16 &aux)const {
554 cytnx_error_msg(true,"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s","\n");
555 //return 0;
556
557 }
558 const cytnx_int16& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int16 &aux) const {
559 cytnx_error_msg(true,"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s","\n");
560 //return 0;
561 }
562
563 cytnx_complex128& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_complex128 &aux){
564 cytnx_error_msg(true,"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s","\n");
565 //return cytnx_complex128(0,0);
566 }
567 cytnx_complex64& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_complex64 &aux){
568 cytnx_error_msg(true,"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s","\n");
569 //return cytnx_complex64(0,0);
570 }
571 cytnx_double& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_double &aux){
572 cytnx_error_msg(true,"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s","\n");
573 //return 0;
574 }
575 cytnx_float& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_float &aux){
576 cytnx_error_msg(true,"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s","\n");
577 //return 0;
578 }
579 cytnx_uint64& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint64 &aux){
580 cytnx_error_msg(true,"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s","\n");
581 //return 0;
582 }
583 cytnx_int64& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int64 &aux){
584 cytnx_error_msg(true,"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s","\n");
585 //return 0;
586 }
587 cytnx_uint32& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint32 &aux){
588 cytnx_error_msg(true,"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s","\n");
589 //return 0;
590
591 }
592 cytnx_int32& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int32 &aux){
593 cytnx_error_msg(true,"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s","\n");
594 //return 0;
595 }
596 cytnx_uint16& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint16 &aux){
597 cytnx_error_msg(true,"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s","\n");
598 //return 0;
599
600 }
601 cytnx_int16& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int16 &aux){
602 cytnx_error_msg(true,"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s","\n");
603 //return 0;
604 }
605
606
607 bool elem_exists(const std::vector<cytnx_uint64> &locator) const{
608 cytnx_error_msg(true,"[ERROR][DenseUniTensor] elem_exists can only be used on UniTensor with Symmetry.%s","\n");
609 }
610 void tag(){
611 if(!this->is_tag()){
612 for(int i=0;i<this->_rowrank;i++){
613 this->_bonds[i].set_type(BD_KET);
614 }
615 for(int i=this->_rowrank;i<this->_bonds.size();i++){
616 this->_bonds[i].set_type(BD_BRA);
617 }
618 this->_is_tag = true;
619 this->_is_braket_form = this->_update_braket();
620 }
621 }
622 void truncate_(const cytnx_int64 &bond_idx, const cytnx_uint64 &dim, const bool &by_label=false);
623
624 void _save_dispatch(std::fstream &f) const;
625 void _load_dispatch(std::fstream &f);
626 // end virtual function
627
628
629
630 };
632
633
634 //======================================================================
636 class SparseUniTensor: public UniTensor_base{
637 protected:
638
639 public:
640
641 cytnx_uint64 _inner_rowrank;
642 std::vector<std::vector<cytnx_int64> > _blockqnums;
643 std::vector<cytnx_uint64> _mapper;
644 std::vector<cytnx_uint64> _inv_mapper;
645 std::vector<std::vector<cytnx_uint64> > _inner2outer_row;
646 std::vector<std::vector<cytnx_uint64> > _inner2outer_col;
647 std::map<cytnx_uint64,std::pair<cytnx_uint64,cytnx_uint64> > _outer2inner_row;
648 std::map<cytnx_uint64, std::pair<cytnx_uint64,cytnx_uint64> > _outer2inner_col;
649
650 std::vector<Tensor> _blocks;
651
652 bool _contiguous;
653 void set_meta(SparseUniTensor *tmp, const bool &inner, const bool &outer)const{
654 //outer meta
655 if(outer){
656 tmp->_bonds = vec_clone(this->_bonds);
657 tmp->_labels = this->_labels;
658 tmp->_is_braket_form = this->_is_braket_form;
659 tmp->_rowrank = this->_rowrank;
660 tmp->_name = this->_name;
661 }
662 //comm meta
663 tmp->_mapper = this->_mapper;
664 tmp->_inv_mapper = this->_inv_mapper;
665 tmp->_contiguous = this->_contiguous;
666 tmp->_is_diag = this->_is_diag;
667
668 //inner meta
669 if(inner){
670 tmp->_inner_rowrank = this->_inner_rowrank;
671 tmp->_inner2outer_row = this->_inner2outer_row;
672 tmp->_inner2outer_col = this->_inner2outer_col;
673 tmp->_outer2inner_row = this->_outer2inner_row;
674 tmp->_outer2inner_col = this->_outer2inner_col;
675 tmp->_blockqnums = this->_blockqnums;
676 }
677
678 }
679 SparseUniTensor* clone_meta(const bool &inner, const bool &outer) const{
680 SparseUniTensor* tmp = new SparseUniTensor();
681 this->set_meta(tmp,inner,outer);
682 return tmp;
683 };
684
685
686
687
688
689 //===================================
690 friend class UniTensor; // allow wrapper to access the private elems
691 SparseUniTensor(){
692 this->uten_type_id = UTenType.Sparse;
693 this->_is_tag = true;
694 };
695
696 // virtual functions
697 void Init(const std::vector<Bond> &bonds, const std::vector<cytnx_int64> &in_labels={}, const cytnx_int64 &rowrank=-1, const unsigned int &dtype=Type.Double,const int &device = Device.cpu, const bool &is_diag=false);
698 void Init_by_Tensor(const Tensor& in_tensor, const cytnx_uint64 &rowrank, const bool &is_diag=false){
699 cytnx_error_msg(true,"[ERROR][SparseUniTensor] cannot use Init_by_tensor() on a SparseUniTensor.%s","\n");
700 }
701 std::vector<cytnx_uint64> shape() const{
702 std::vector<cytnx_uint64> out(this->_bonds.size());
703 for(cytnx_uint64 i=0;i<out.size();i++){
704 out[i] = this->_bonds[i].dim();
705 }
706 return out;
707 }
708 bool is_blockform() const{return true;}
709 void to_(const int &device){
710 for(cytnx_uint64 i=0;i<this->_blocks.size();i++){
711 this->_blocks[i].to_(device);
712 }
713 };
714 boost::intrusive_ptr<UniTensor_base> to(const int &device){
715 if(this->device() == device){
716 return this;
717 }else{
718 boost::intrusive_ptr<UniTensor_base> out = this->clone();
719 out->to_(device);
720 return out;
721 }
722 };
723 boost::intrusive_ptr<UniTensor_base> clone() const{
724 SparseUniTensor* tmp = this->clone_meta(true,true);
725 tmp->_blocks = vec_clone(this->_blocks);
726 boost::intrusive_ptr<UniTensor_base> out(tmp);
727 return out;
728 };
729 bool is_contiguous() const{
730 return this->_contiguous;
731 };
732 void set_rowrank(const cytnx_uint64 &new_rowrank){
733 cytnx_error_msg((new_rowrank < 1) || (new_rowrank>= this->rank()),"[ERROR][SparseUniTensor] rowrank should be [>=1] and [<UniTensor.rank].%s","\n");
734 cytnx_error_msg(new_rowrank >= this->_labels.size(),"[ERROR] rowrank cannot exceed the rank of UniTensor.%s","\n");
735 if(this->_rowrank!= new_rowrank)
736 this->_contiguous = false;
737 this->_rowrank = new_rowrank;
738 this->_is_braket_form = this->_update_braket();
739 }
740
741 unsigned int dtype() const{
742 #ifdef UNI_DEBUG
743 cytnx_error_msg(this->_blocks.size()==0,"[ERROR][internal] empty blocks for blockform.%s","\n");
744 #endif
745 return this->_blocks[0].dtype();
746 };
747 int device() const{
748 #ifdef UNI_DEBUG
749 cytnx_error_msg(this->_blocks.size()==0,"[ERROR][internal] empty blocks for blockform.%s","\n");
750 #endif
751 return this->_blocks[0].device();
752 };
753 std::string dtype_str() const{
754 #ifdef UNI_DEBUG
755 cytnx_error_msg(this->_blocks.size()==0,"[ERROR][internal] empty blocks for blockform.%s","\n");
756 #endif
757 return this->_blocks[0].dtype_str();
758 };
759 std::string device_str() const{
760 #ifdef UNI_DEBUG
761 cytnx_error_msg(this->_blocks.size()==0,"[ERROR][internal] empty blocks for blockform.%s","\n");
762 #endif
763 return this->_blocks[0].device_str();
764 };
765 void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank=-1,const bool &by_label=false);
766 boost::intrusive_ptr<UniTensor_base> permute(const std::vector<cytnx_int64> &mapper,const cytnx_int64 &rowrank=-1, const bool &by_label=false);
767 boost::intrusive_ptr<UniTensor_base> contiguous();
768 boost::intrusive_ptr<UniTensor_base> contiguous_(){
769 if(!this->_contiguous){
770 boost::intrusive_ptr<UniTensor_base> titr = this->contiguous();
771 SparseUniTensor *tmp = (SparseUniTensor*)titr.get();
772 tmp->set_meta(this,true,true);
773 this->_blocks = tmp->_blocks;
774
775 }
776 return boost::intrusive_ptr<UniTensor_base>(this);
777
778 }
779 void print_diagram(const bool &bond_info=false);
780
781 Tensor get_block(const cytnx_uint64 &idx=0) const{
782 cytnx_error_msg(idx>=this->_blocks.size(),"[ERROR][SparseUniTensor] index out of range%s","\n");
783 if(this->_contiguous){
784 return this->_blocks[idx].clone();
785 }else{
786 cytnx_error_msg(true,"[Developing] get block from a non-contiguous SparseUniTensor is currently not support. Call contiguous()/contiguous_() first.%s","\n");
787 return Tensor();
788 }
789 };
790
791 Tensor get_block(const std::vector<cytnx_int64> &qnum) const{
792 cytnx_error_msg(!this->is_braket_form(),"[ERROR][Un-physical] cannot get the block by qnums when bra-ket/in-out bonds mismatch the row/col space.\n permute to the correct physical space first, then get block.%s","\n");
793 //std::cout << "get_block" <<std::endl;
794 if(this->_contiguous){
795 //std::cout << "contiguous" << std::endl;
796 //get dtype from qnum:
797 cytnx_int64 idx=-1;
798 for(int i=0;i<this->_blockqnums.size();i++){
799 //for(int j=0;j<this->_blockqnums[i].size();j++)
800 // std::cout << this->_blockqnums[i][j]<< " ";
801 //std::cout << std::endl;
802 if(qnum==this->_blockqnums[i]){idx=i; break;}
803 }
804 cytnx_error_msg(idx<0,"[ERROR][SparseUniTensor] no block with [qnum] exists in the current UniTensor.%s","\n");
805 return this->get_block(idx);
806 }else{
807 cytnx_error_msg(true,"[Developing] get block from a non-contiguous SparseUniTensor is currently not support. Call contiguous()/contiguous_() first.%s","\n");
808 return Tensor();
809 }
810 return Tensor();
811 };
812
813 // return a share view of block, this only work for symm tensor in contiguous form.
814 Tensor& get_block_(const cytnx_uint64 &idx=0){
815 cytnx_error_msg(this->is_contiguous()==false,"[ERROR][SparseUniTensor] cannot use get_block_() on non-contiguous UniTensor with symmetry.\n suggest options: \n 1) Call contiguous_()/contiguous() first, then call get_block_()\n 2) Try get_block()/get_blocks()%s","\n");
816
817 cytnx_error_msg(idx >= this->_blocks.size(),"[ERROR][SparseUniTensor] index exceed the number of blocks.%s","\n");
818
819 return this->_blocks[idx];
820 }
821 const Tensor& get_block_(const cytnx_uint64 &idx=0) const{
822 cytnx_error_msg(this->is_contiguous()==false,"[ERROR][SparseUniTensor] cannot use get_block_() on non-contiguous UniTensor with symmetry.\n suggest options: \n 1) Call contiguous_()/contiguous() first, then call get_block_()\n 2) Try get_block()/get_blocks()%s","\n");
823
824 cytnx_error_msg(idx >= this->_blocks.size(),"[ERROR][SparseUniTensor] index exceed the number of blocks.%s","\n");
825
826 return this->_blocks[idx];
827 }
828
829 Tensor& get_block_(const std::vector<cytnx_int64> &qnum){
830 cytnx_error_msg(!this->is_braket_form(),"[ERROR][Un-physical] cannot get the block by qnums when bra-ket/in-out bonds mismatch the row/col space.\n permute to the correct physical space first, then get block.%s","\n");
831 cytnx_error_msg(this->is_contiguous()==false,"[ERROR][SparseUniTensor] cannot use get_block_() on non-contiguous UniTensor with symmetry.\n suggest options: \n 1) Call contiguous_()/contiguous() first, then call get_blocks_()\n 2) Try get_block()/get_blocks()%s","\n");
832
833 //get dtype from qnum:
834 cytnx_int64 idx=-1;
835 for(int i=0;i<this->_blockqnums.size();i++){
836 if(qnum==this->_blockqnums[i]){idx=i; break;}
837 }
838 cytnx_error_msg(idx<0,"[ERROR][SparseUniTensor] no block with [qnum] exists in the current UniTensor.%s","\n");
839 return this->get_block_(idx);
840 //cytnx_error_msg(true,"[Developing]%s","\n");
841 }
842 const Tensor& get_block_(const std::vector<cytnx_int64> &qnum) const{
843 cytnx_error_msg(!this->is_braket_form(),"[ERROR][Un-physical] cannot get the block by qnums when bra-ket/in-out bonds mismatch the row/col space.\n permute to the correct physical space first, then get block.%s","\n");
844 cytnx_error_msg(this->is_contiguous()==false,"[ERROR][SparseUniTensor] cannot use get_block_() on non-contiguous UniTensor with symmetry.\n suggest options: \n 1) Call contiguous_()/contiguous() first, then call get_blocks_()\n 2) Try get_block()/get_blocks()%s","\n");
845
846 //get dtype from qnum:
847 cytnx_int64 idx=-1;
848 for(int i=0;i<this->_blockqnums.size();i++){
849 if(qnum==this->_blockqnums[i]){idx=i; break;}
850 }
851 cytnx_error_msg(idx<0,"[ERROR][SparseUniTensor] no block with [qnum] exists in the current UniTensor.%s","\n");
852 return this->get_block_(idx);
853 }
854
855 std::vector<Tensor> get_blocks() const {
856 if(this->_contiguous){
857 return vec_clone(this->_blocks);
858 }else{
859 //cytnx_error_msg(true,"[Developing]%s","\n");
860 boost::intrusive_ptr<UniTensor_base> tmp = this->clone();
861 tmp->contiguous_();
862 SparseUniTensor *ttmp = (SparseUniTensor*)tmp.get();
863 return ttmp->_blocks;
864 }
865 };
866
867 const std::vector<Tensor>& get_blocks_(const bool &silent=false) const {
868 //cout << "[call this]" << endl;
869 if(this->_contiguous){
870 return this->_blocks;
871 }else{
872 //cytnx_error_msg(true,"[Developing]%s","\n");
873 if(!silent)
874 cytnx_warning_msg(true,"[WARNING][SparseUniTensor] call get_blocks_() with a non-contiguous UniTensor should be used with caution. \ntry: \n1) get_blocks()\n2) call contiguous/contiguous_() first, then get_blocks_() to get concise results%s","\n");
875
876 return this->_blocks;
877 }
878 };
879 std::vector<Tensor>& get_blocks_(const bool &silent=false){
880 //cout << "[call this]" << endl;
881 if(this->_contiguous){
882 return this->_blocks;
883 }else{
884 if(!silent)
885 cytnx_warning_msg(true,"[WARNING][SparseUniTensor] call get_blocks_() with a non-contiguous UniTensor should be used with caution. \ntry: \n1) get_blocks()\n2) call contiguous/contiguous_() first, then get_blocks_() to get concise results%s","\n");
886
887 return this->_blocks;
888 }
889 };
890
891 bool same_data(const boost::intrusive_ptr<UniTensor_base> &rhs) const{
892 if(rhs->uten_type()!=UTenType.Sparse) return false;
893 if(rhs->get_blocks_(1).size() != this->get_blocks_(1).size()) return false;
894
895 for(int i=0;i<rhs->get_blocks_(1).size();i++)
896 if(this->get_blocks_(1)[i].same_data(rhs->get_blocks_(1)[i])==false) return false;
897
898 return true;
899
900 }
901
902
903
904 void put_block_(Tensor &in,const cytnx_uint64 &idx=0){
905 cytnx_error_msg(this->is_contiguous()==false,"[ERROR][SparseUniTensor] cannot use put_block_() on non-contiguous UniTensor with symmetry.\n suggest options: \n 1) Call contiguous_()/contiguous() first, then call put_blocks_()\n 2) Try put_block()/put_blocks()%s","\n");
906
907 cytnx_error_msg(idx>=this->_blocks.size(),"[ERROR][SparseUniTensor] index out of range%s","\n");
908 cytnx_error_msg(in.shape()!=this->_blocks[idx].shape(),"[ERROR][SparseUniTensor] the shape of input tensor does not match the shape of block @ idx=%d\n",idx);
909 this->_blocks[idx] = in;
910 };
911 void put_block(const Tensor &in,const cytnx_uint64 &idx=0){
912 cytnx_error_msg(idx>=this->_blocks.size(),"[ERROR][SparseUniTensor] index out of range%s","\n");
913 if(this->_contiguous){
914 cytnx_error_msg(in.shape()!=this->_blocks[idx].shape(),"[ERROR][SparseUniTensor] the shape of input tensor does not match the shape of block @ idx=%d\n",idx);
915 this->_blocks[idx] = in.clone();
916 }else{
917 cytnx_error_msg(true,"[Developing] put block to a non-contiguous SparseUniTensor is currently not support. Call contiguous()/contiguous_() first.%s","\n");
918 }
919 };
920 void put_block(const Tensor &in, const std::vector<cytnx_int64> &qnum){
921 cytnx_error_msg(!this->is_braket_form(),"[ERROR][Un-physical] cannot get the block by qnums when bra-ket/in-out bonds mismatch the row/col space.\n permute to the correct physical space first, then get block.%s","\n");
922
923 //get dtype from qnum:
924 cytnx_int64 idx=-1;
925 for(int i=0;i<this->_blockqnums.size();i++){
926 if(qnum==this->_blockqnums[i]){idx=i; break;}
927 }
928 cytnx_error_msg(idx<0,"[ERROR][SparseUniTensor] no block with [qnum] exists in the current UniTensor.%s","\n");
929 this->put_block(in,idx);
930
931 };
932 void put_block_(Tensor &in, const std::vector<cytnx_int64> &qnum){
933 cytnx_error_msg(!this->is_braket_form(),"[ERROR][Un-physical] cannot get the block by qnums when bra-ket/in-out bonds mismatch the row/col space.\n permute to the correct physical space first, then get block.%s","\n");
934 cytnx_error_msg(this->is_contiguous()==false,"[ERROR][SparseUniTensor] cannot use put_block_() on non-contiguous UniTensor with symmetry.\n suggest options: \n 1) Call contiguous_()/contiguous() first, then call get_blocks_()\n 2) Try get_block()/get_blocks()%s","\n");
935
936 //get dtype from qnum:
937 cytnx_int64 idx=-1;
938 for(int i=0;i<this->_blockqnums.size();i++){
939 if(qnum==this->_blockqnums[i]){idx=i; break;}
940 }
941 cytnx_error_msg(idx<0,"[ERROR][SparseUniTensor] no block with [qnum] exists in the current UniTensor.%s","\n");
942 this->put_block_(in,idx);
943 };
944
945 // this will only work on non-symm tensor (DenseUniTensor)
946 boost::intrusive_ptr<UniTensor_base> get(const std::vector<Accessor> &accessors){
947 cytnx_error_msg(true,"[ERROR][SparseUniTensor][get] cannot use get on a UniTensor with Symmetry.\n suggestion: try get_block()/get_blocks() first.%s","\n");
948 return nullptr;
949 }
950 // this will only work on non-symm tensor (DenseUniTensor)
951 void set(const std::vector<Accessor> &accessors, const Tensor &rhs){
952 cytnx_error_msg(true,"[ERROR][SparseUniTensor][set] cannot use set on a UniTensor with Symmetry.\n suggestion: try get_block()/get_blocks() first.%s","\n");
953 }
954 void reshape_(const std::vector<cytnx_int64> &new_shape, const cytnx_uint64 &rowrank=0){
955 cytnx_error_msg(true,"[ERROR] cannot reshape a UniTensor with symmetry.%s","\n");
956 }
957 boost::intrusive_ptr<UniTensor_base> reshape(const std::vector<cytnx_int64> &new_shape, const cytnx_uint64 &rowrank=0){
958 cytnx_error_msg(true,"[ERROR] cannot reshape a UniTensor with symmetry.%s","\n");
959 return nullptr;
960 }
961 boost::intrusive_ptr<UniTensor_base> to_dense(){
962 cytnx_error_msg(true,"[ERROR] cannot to_dense a UniTensor with symmetry.%s","\n");
963 return nullptr;
964 }
965 void to_dense_(){
966 cytnx_error_msg(true,"[ERROR] cannot to_dense_ a UniTensor with symmetry.%s","\n");
967 }
968 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &permute_back=true, const bool &by_label=true){
969 cytnx_error_msg(true,"[Developing]%s","\n");
970 };
971 boost::intrusive_ptr<UniTensor_base> contract(const boost::intrusive_ptr<UniTensor_base> &rhs, const bool &mv_elem_self=false, const bool &mv_elem_rhs=false);
972 std::vector<Bond> getTotalQnums(const bool &physical=false);
973 std::vector<std::vector<cytnx_int64> > get_blocks_qnums() const{
974 return this->_blockqnums;
975 }
976 ~SparseUniTensor(){};
977
978
979 // arithmetic
980 void Add_(const boost::intrusive_ptr<UniTensor_base> &rhs);
981 void Add_(const Scalar &rhs);
982
983 void Mul_(const boost::intrusive_ptr<UniTensor_base> &rhs);
984 void Mul_(const Scalar &rhs);
985
986 void Sub_(const boost::intrusive_ptr<UniTensor_base> &rhs);
987 void Sub_(const Scalar &rhs);
988 void lSub_(const Scalar &lhs);
989
990 void Div_(const boost::intrusive_ptr<UniTensor_base> &rhs);
991 void Div_(const Scalar &rhs);
992 void lDiv_(const Scalar &lhs);
993
994
995 boost::intrusive_ptr<UniTensor_base> Conj(){
996 boost::intrusive_ptr<UniTensor_base> out = this->clone();
997 out->Conj_();
998 return out;
999 }
1000
1001 void Conj_(){
1002 for(int i=0;i<this->_blocks.size();i++){
1003 this->_blocks[i].Conj_();
1004 }
1005 };
1006 boost::intrusive_ptr<UniTensor_base> Trace(const cytnx_int64 &a, const cytnx_int64 &b, const bool &by_label=false) const{
1007 cytnx_error_msg(true,"[Developing]%s","\n");
1008 return nullptr;
1009 };
1010 void Trace_(const cytnx_int64 &a, const cytnx_int64 &b, const bool &by_label=false){
1011 cytnx_error_msg(true,"[Developing]%s","\n");
1012 //return nullptr;
1013 }
1014
1015 void Transpose_();
1016 boost::intrusive_ptr<UniTensor_base> Transpose(){
1017 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1018 out->Transpose_();
1019 return out;
1020 }
1021
1022 boost::intrusive_ptr<UniTensor_base> Dagger(){
1023 boost::intrusive_ptr<UniTensor_base> out = this->Conj();
1024 out->Transpose_();
1025 return out;
1026 }
1027 void Dagger_(){
1028 this->Conj_();
1029 this->Transpose_();
1030 }
1031
1032 void tag(){
1033 // no-use!
1034 }
1035
1036 void truncate_(const cytnx_int64 &bond_idx, const cytnx_uint64 &dim, const bool &by_label=false);
1037
1038 const cytnx_complex128& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_complex128 &aux) const;
1039 const cytnx_complex64& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_complex64 &aux) const;
1040 const cytnx_double& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_double &aux) const;
1041 const cytnx_float& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_float &aux) const;
1042 const cytnx_uint64& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint64 &aux) const;
1043 const cytnx_int64& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int64 &aux) const;
1044 const cytnx_uint32& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint32 &aux) const;
1045 const cytnx_int32& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int32 &aux) const;
1046 const cytnx_uint16& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint16 &aux) const;
1047 const cytnx_int16& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int16 &aux) const;
1048
1049 cytnx_complex128& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_complex128 &aux);
1050 cytnx_complex64& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_complex64 &aux);
1051 cytnx_double& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_double &aux);
1052 cytnx_float& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_float &aux);
1053 cytnx_uint64& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint64 &aux);
1054 cytnx_int64& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int64 &aux);
1055 cytnx_uint32& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint32 &aux);
1056 cytnx_int32& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int32 &aux);
1057 cytnx_uint16& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint16 &aux);
1058 cytnx_int16& at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int16 &aux);
1059
1060 bool elem_exists(const std::vector<cytnx_uint64> &locator) const;
1061 void _save_dispatch(std::fstream &f) const;
1062 void _load_dispatch(std::fstream &f);
1063 // end virtual func
1064
1065
1066 };
1068
1069 //======================================================================
1070
1073
1074 public:
1075
1077 boost::intrusive_ptr<UniTensor_base> _impl;
1078 UniTensor(): _impl(new UniTensor_base()){};
1079 UniTensor(const UniTensor &rhs){
1080 this->_impl = rhs._impl;
1081 }
1082 UniTensor& operator=(const UniTensor &rhs){
1083 this->_impl = rhs._impl;
1084 return *this;
1085 }
1087
1089
1110 UniTensor(const Tensor &in_tensor, const cytnx_uint64 &rowrank, const bool &is_diag=false): _impl(new UniTensor_base()){
1111 this->Init(in_tensor,rowrank,is_diag);
1112 }
1113 void Init(const Tensor &in_tensor, const cytnx_uint64 &rowrank, const bool &is_diag=false){
1114 boost::intrusive_ptr<UniTensor_base> out(new DenseUniTensor());
1115 out->Init_by_Tensor(in_tensor, rowrank,is_diag);
1116 this->_impl = out;
1117 }
1119
1120
1122
1137 UniTensor(const std::vector<Bond> &bonds, const std::vector<cytnx_int64> &in_labels={}, const cytnx_int64 &rowrank=-1, const unsigned int &dtype=Type.Double, const int &device = Device.cpu, const bool &is_diag=false): _impl(new UniTensor_base()){
1138 #ifdef UNI_DEBUG
1139 cytnx_warning_msg(true,"[DEBUG] message: entry for UniTensor(const std::vector<Bond> &bonds, const std::vector<cytnx_int64> &in_labels={}, const cytnx_int64 &rowrank=-1, const unsigned int &dtype=Type.Double, const int &device = Device.cpu, const bool &is_diag=false)%s","\n");
1140 #endif
1142 }
1143 void Init(const std::vector<Bond> &bonds, const std::vector<cytnx_int64> &in_labels={}, const cytnx_int64 &rowrank=-1, const unsigned int &dtype=Type.Double, const int &device = Device.cpu, const bool &is_diag=false){
1144
1145 // checking type:
1146 bool is_sym = false;
1147 for(cytnx_uint64 i=0;i<bonds.size();i++){
1148 //check
1149 if(bonds[i].syms().size() != 0) is_sym = true;
1150 else cytnx_error_msg(is_sym,"[ERROR] cannot have bonds with mixing of symmetry and non-symmetry.%s","\n");
1151 }
1152
1153 // dynamical dispatch:
1154 if(is_sym){
1155 #ifdef UNI_DEBUG
1156 cytnx_warning_msg(true,"[DEBUG] message: entry dispatch: UniTensor: symmetric%s","\n");
1157 #endif
1158 //cytnx_warning_msg(true,"[warning, still developing, some functions will display \"[Developing]\"][SparseUniTensor]%s","\n");
1159 boost::intrusive_ptr<UniTensor_base> out(new SparseUniTensor());
1160 this->_impl = out;
1161 }else{
1162 boost::intrusive_ptr<UniTensor_base> out(new DenseUniTensor());
1163 this->_impl = out;
1164 }
1165 this->_impl->Init(bonds, in_labels, rowrank, dtype, device, is_diag);
1166 }
1168
1174 UniTensor& set_name(const std::string &in){
1175 this->_impl->set_name(in);
1176 return *this;
1177 }
1189 this->_impl->set_label(idx,new_label);
1190 return *this;
1191 }
1192
1201 UniTensor& set_labels(const std::vector<cytnx_int64> &new_labels){
1202 this->_impl->set_labels(new_labels);
1203 return *this;
1204 }
1206 this->_impl->set_rowrank(new_rowrank);
1207 return *this;
1208 }
1209
1210 template<class T>
1212
1213 cytnx_error_msg(this->is_blockform(),"[ERROR] cannot use item on UniTensor with Symmetry.\n suggestion: use get_block()/get_blocks() first.%s","\n");
1214
1215 DenseUniTensor* tmp = static_cast<DenseUniTensor*>(this->_impl.get());
1216 return tmp->_block.item<T>();
1217
1218 }
1219
1220 cytnx_uint64 rank() const {return this->_impl->rank();}
1221 cytnx_uint64 rowrank() const{return this->_impl->rowrank();}
1222 unsigned int dtype() const{ return this->_impl->dtype(); }
1223 int uten_type() const{ return this->_impl->uten_type();}
1224 int device() const{ return this->_impl->device(); }
1225 std::string name() const { return this->_impl->name();}
1226 std::string dtype_str() const{ return this->_impl->dtype_str();}
1227 std::string device_str() const{ return this->_impl->device_str();}
1228 std::string uten_type_str() const {return this->_impl->uten_type_str();}
1229 bool is_contiguous() const{ return this->_impl->is_contiguous();}
1230 bool is_diag() const{ return this->_impl->is_diag(); }
1231 bool is_tag() const { return this->_impl->is_tag();}
1232 const bool& is_braket_form() const{
1233 return this->_impl->is_braket_form();
1234 }
1235 const std::vector<cytnx_int64>& labels() const{ return this->_impl->labels();}
1236 const std::vector<Bond> &bonds() const {return this->_impl->bonds();}
1237 std::vector<Bond> &bonds() {return this->_impl->bonds();}
1238 std::vector<cytnx_uint64> shape() const{return this->_impl->shape();}
1239 bool is_blockform() const{ return this->_impl->is_blockform();}
1240
1241 void to_(const int &device){this->_impl->to_(device);}
1242 UniTensor to(const int &device) const{
1243 UniTensor out;
1244 out._impl = this->_impl->to(device);
1245 return out;
1246 }
1248 UniTensor out;
1249 out._impl = this->_impl->clone();
1250 return out;
1251 }
1252 UniTensor permute(const std::vector<cytnx_int64> &mapper,const cytnx_int64 &rowrank=-1,const bool &by_label=false){UniTensor out; out._impl = this->_impl->permute(mapper,rowrank,by_label); return out;}
1253 void permute_(const std::vector<cytnx_int64> &mapper,const cytnx_int64 &rowrank=-1,const bool &by_label=false){
1254 this->_impl->permute_(mapper,rowrank,by_label);
1255 }
1257 UniTensor out;
1258 out._impl = this->_impl->contiguous();
1259 return out;
1260 }
1262 this->_impl = this->_impl->contiguous_();
1263 }
1264 void print_diagram(const bool &bond_info=false){
1265 this->_impl->print_diagram(bond_info);
1266 }
1267
1268 template<class T>
1269 T& at(const std::vector<cytnx_uint64> &locator){
1270 return this->_impl->at<T>(locator);
1271 }
1272
1273
1274 // return a clone of block
1276 return this->_impl->get_block(idx);
1277 };
1278 //================================
1279 // return a clone of block
1280 Tensor get_block(const std::vector<cytnx_int64> &qnum) const{
1281 return this->_impl->get_block(qnum);
1282 }
1283 Tensor get_block(const std::initializer_list<cytnx_int64> &qnum) const{
1284 std::vector<cytnx_int64> tmp = qnum;
1285 return get_block(tmp);
1286 }
1287 //================================
1288 // this only work for non-symm tensor. return a shared view of block
1289 const Tensor& get_block_(const cytnx_uint64 &idx=0) const{
1290 return this->_impl->get_block_(idx);
1291 }
1292 //================================
1293 // this only work for non-symm tensor. return a shared view of block
1295 return this->_impl->get_block_(idx);
1296 }
1297 //================================
1298 // this only work for non-symm tensor. return a shared view of block
1299 Tensor& get_block_(const std::vector<cytnx_int64> &qnum){
1300 return this->_impl->get_block_(qnum);
1301 }
1302 Tensor& get_block_(const std::initializer_list<cytnx_int64> &qnum){
1303 std::vector<cytnx_int64> tmp = qnum;
1304 return get_block_(tmp);
1305 }
1306 //================================
1307
1308 // this only work for non-symm tensor. return a shared view of block
1309 const Tensor& get_block_(const std::vector<cytnx_int64> &qnum) const{
1310 return this->_impl->get_block_(qnum);
1311 }
1312 const Tensor& get_block_(const std::initializer_list<cytnx_int64> &qnum) const{
1313 std::vector<cytnx_int64> tmp = qnum;
1314 return this->_impl->get_block_(tmp);
1315 }
1316 //================================
1317 // this return a shared view of blocks for non-symm tensor.
1318 // for symmetry tensor, it call contiguous first and return a shared view of blocks. [dev]
1319 std::vector<Tensor> get_blocks() const {
1320 return this->_impl->get_blocks();
1321 }
1322 // this return a shared view of blocks for non-symm tensor.
1323 // for symmetry tensor, it call contiguous first and return a shared view of blocks. [dev]
1324 const std::vector<Tensor>& get_blocks_(const bool &silent=false) const {
1325 return this->_impl->get_blocks_(silent);
1326 }
1327 // for symmetry tensor, it call contiguous first and return a shared view of blocks. [dev]
1328 std::vector<Tensor>& get_blocks_(const bool &silent=false){
1329 return this->_impl->get_blocks_(silent);
1330 }
1331
1332 // the put block will have shared view with the internal block, i.e. non-clone.
1333 void put_block(const Tensor &in,const cytnx_uint64 &idx=0){
1334 this->_impl->put_block(in,idx);
1335 }
1336 // the put block will have shared view with the internal block, i.e. non-clone.
1337 void put_block(const Tensor &in, const std::vector<cytnx_int64> &qnum){
1338 this->_impl->put_block(in,qnum);
1339 }
1340 // the put block will have shared view with the internal block, i.e. non-clone.
1342 this->_impl->put_block_(in,idx);
1343 }
1344 // the put block will have shared view with the internal block, i.e. non-clone.
1345 void put_block_(Tensor &in, const std::vector<cytnx_int64> &qnum){
1346 this->_impl->put_block_(in,qnum);
1347 }
1348 UniTensor get(const std::vector<Accessor> &accessors) const{
1349 UniTensor out;
1350 out._impl = this->_impl->get(accessors);
1351 return out;
1352 }
1353 void set(const std::vector<Accessor> &accessors, const Tensor &rhs){
1354 this->_impl->set(accessors, rhs);
1355 }
1356 UniTensor reshape(const std::vector<cytnx_int64> &new_shape, const cytnx_uint64 &rowrank=0){
1357 UniTensor out;
1358 out._impl = this->_impl->reshape(new_shape,rowrank);
1359 return out;
1360 }
1361 void reshape_(const std::vector<cytnx_int64> &new_shape, const cytnx_uint64 &rowrank=0){
1362 this->_impl->reshape_(new_shape,rowrank);
1363 }
1365 UniTensor out;
1366 out._impl = this->_impl->to_dense();
1367 return out;
1368 }
1370 this->_impl->to_dense_();
1371 }
1372 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &permute_back=true, const bool &by_label=true){
1373 this->_impl->combineBonds(indicators,permute_back,by_label);
1374 }
1375 UniTensor contract(const UniTensor &inR, const bool &mv_elem_self=false, const bool &mv_elem_rhs=false) const{
1376 UniTensor out;
1377 out._impl = this->_impl->contract(inR._impl,mv_elem_self,mv_elem_rhs);
1378 return out;
1379 }
1380 std::vector<Bond> getTotalQnums(const bool physical=false) const{
1381 return this->_impl->getTotalQnums(physical);
1382 }
1383 std::vector<std::vector<cytnx_int64> > get_blocks_qnums() const{
1384 return this->_impl->get_blocks_qnums();
1385 }
1386
1387 bool same_data(const UniTensor &rhs) const{
1388
1389 // check same type:
1390 if(this->_impl->uten_type() != rhs._impl->uten_type())
1391 return false;
1392
1393
1394
1395 return this->_impl->same_data(rhs._impl);
1396 }
1397
1399 this->_impl->Add_(rhs._impl);
1400 return *this;
1401 }
1402
1404 this->_impl->Mul_(rhs._impl);
1405 return *this;
1406 }
1407
1409 this->_impl->Sub_(rhs._impl);
1410 return *this;
1411 }
1412
1414 this->_impl->Div_(rhs._impl);
1415 return *this;
1416 }
1417
1419 this->_impl->Add_(rhs);
1420 return *this;
1421 }
1422
1424 this->_impl->Mul_(rhs);
1425 return *this;
1426 }
1427
1429 this->_impl->Sub_(rhs);
1430 return *this;
1431 }
1432
1434 this->_impl->Div_(rhs);
1435 return *this;
1436 }
1437
1438 UniTensor Add(const UniTensor &rhs) const;
1439 UniTensor Add(const Scalar &rhs) const;
1440 UniTensor Mul(const UniTensor &rhs) const;
1441 UniTensor Mul(const Scalar &rhs) const;
1442 UniTensor Div(const UniTensor &rhs) const;
1443 UniTensor Div(const Scalar &rhs) const;
1444 UniTensor Sub(const UniTensor &rhs) const;
1445 UniTensor Sub(const Scalar &rhs) const;
1446
1447
1449 this->Add_(rhs);
1450 return *this;
1451 }
1453 this->Sub_(rhs);
1454 return *this;
1455 }
1457 this->Div_(rhs);
1458 return *this;
1459 }
1461 this->Mul_(rhs);
1462 return *this;
1463 }
1465 this->Add_(rhs);
1466 return *this;
1467 }
1469 this->Sub_(rhs);
1470 return *this;
1471 }
1473 this->Div_(rhs);
1474 return *this;
1475 }
1477 this->Mul_(rhs);
1478 return *this;
1479 }
1480
1481
1482
1484 UniTensor out;
1485 out._impl = this->_impl->Conj();
1486 return out;
1487 }
1488
1490 this->_impl->Conj_();
1491 return *this;
1492 }
1493
1494
1496 UniTensor out;
1497 out._impl = this->_impl->Transpose();
1498 return out;
1499 }
1501 this->_impl->Transpose_();
1502 return *this;
1503 }
1504
1505 UniTensor Trace(const cytnx_int64 &a, const cytnx_int64 &b, const bool &by_label=false) const{
1506 UniTensor out;
1507 out._impl = this->_impl->Trace(a,b,by_label);
1508 return out;
1509 }
1510
1511 UniTensor& Trace_(const cytnx_int64 &a, const cytnx_int64 &b, const bool &by_label=false){
1512 this->_impl->Trace_(a,b,by_label);
1513 return *this;
1514 }
1515
1517 UniTensor out;
1518 out._impl = this->_impl->Dagger();
1519 return out;
1520 }
1521
1523 this->_impl->Dagger_();
1524 return *this;
1525 }
1526
1528 this->_impl->tag();
1529 return *this;
1530 }
1531
1532 UniTensor Pow(const double &p) const;
1533 UniTensor& Pow_(const double &p);
1534
1535
1536
1537
1538
1539 bool elem_exists( const std::vector<cytnx_uint64> &locator) const{
1540 return this->_impl->elem_exists(locator);
1541 }
1542
1543 template<class T>
1544 T get_elem(const std::vector<cytnx_uint64> &locator) const{
1545 return this->_impl->get_elem<T>(locator);
1546 }
1547
1548 template<class T, class T2>
1549 void set_elem(const std::vector<cytnx_uint64> &locator, const T2&rc){
1550 //cytnx_error_msg(true,"[ERROR] invalid type%s","\n");
1551 this->_impl->set_elem<T>(locator,rc);
1552 }
1553
1554
1555 void Save(const std::string &fname) const;
1556 void Save(const char* fname) const;
1557 static UniTensor Load(const std::string &fname);
1558 static UniTensor Load(const char* fname);
1559
1560 UniTensor& truncate_(const cytnx_int64 &bond_idx, const cytnx_uint64 &dim, const bool &by_label=false){
1561 this->_impl->truncate_(bond_idx,dim,by_label);
1562 return *this;
1563 }
1564 UniTensor truncate(const cytnx_int64 &bond_idx, const cytnx_uint64& dim, const bool &by_label=false) const{
1565 UniTensor out = this->clone();
1566 out.truncate_(bond_idx,dim,by_label);
1567 return out;
1568 }
1569
1570
1572 void _Load(std::fstream &f);
1573 void _Save(std::fstream &f) const;
1575
1576 };//class UniTensor
1577
1578
1579
1580
1582 std::ostream& operator<<(std::ostream& os, const UniTensor &in);
1584
1595 UniTensor Contract(const UniTensor &inL, const UniTensor &inR, const bool &cacheL=false, const bool &cacheR=false);
1596
1597
1598}
1599#endif
Definition Scalar.hpp:1630
an tensor (multi-dimensional array)
Definition Tensor.hpp:289
void to_(const int &device)
move the current Tensor to the device.
Definition Tensor.hpp:768
Tensor contiguous_()
Make the Tensor contiguous by coalescing the memory (storage), inplacely.
Definition Tensor.hpp:855
unsigned int dtype() const
the dtype-id of the Tensor
Definition Tensor.hpp:661
Tensor contiguous() const
Make the Tensor contiguous by coalescing the memory (storage).
Definition Tensor.hpp:834
Tensor clone() const
return a clone of the current Tensor.
Definition Tensor.hpp:719
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:1096
const bool & is_contiguous() const
Definition Tensor.hpp:772
Tensor & Conj_()
Definition Tensor.cpp:1174
int device() const
the device-id of the Tensor
Definition Tensor.hpp:668
Tensor get(const std::vector< cytnx::Accessor > &accessors) const
get elements using Accessor (C++ API) / slices (python API)
Definition Tensor.hpp:1063
const std::vector< cytnx_uint64 > & shape() const
the shape of the Tensor
Definition Tensor.hpp:689
An Enhanced tensor specifically designed for physical Tensor network simulation.
Definition UniTensor.hpp:1072
UniTensor to(const int &device) const
Definition UniTensor.hpp:1242
UniTensor & operator*=(const UniTensor &rhs)
Definition UniTensor.hpp:1460
std::vector< Tensor > & get_blocks_(const bool &silent=false)
Definition UniTensor.hpp:1328
UniTensor & operator/=(const UniTensor &rhs)
Definition UniTensor.hpp:1456
T & item()
Definition UniTensor.hpp:1211
void combineBonds(const std::vector< cytnx_int64 > &indicators, const bool &permute_back=true, const bool &by_label=true)
Definition UniTensor.hpp:1372
bool is_contiguous() const
Definition UniTensor.hpp:1229
T get_elem(const std::vector< cytnx_uint64 > &locator) const
Definition UniTensor.hpp:1544
UniTensor Div(const UniTensor &rhs) const
Definition UniTensor.cpp:32
const std::vector< cytnx_int64 > & labels() const
Definition UniTensor.hpp:1235
UniTensor & operator+=(const UniTensor &rhs)
Definition UniTensor.hpp:1448
void to_dense_()
Definition UniTensor.hpp:1369
UniTensor reshape(const std::vector< cytnx_int64 > &new_shape, const cytnx_uint64 &rowrank=0)
Definition UniTensor.hpp:1356
std::vector< Tensor > get_blocks() const
Definition UniTensor.hpp:1319
bool is_tag() const
Definition UniTensor.hpp:1231
std::string uten_type_str() const
Definition UniTensor.hpp:1228
UniTensor permute(const std::vector< cytnx_int64 > &mapper, const cytnx_int64 &rowrank=-1, const bool &by_label=false)
Definition UniTensor.hpp:1252
static UniTensor Load(const std::string &fname)
Definition UniTensor.cpp:152
UniTensor & tag()
Definition UniTensor.hpp:1527
UniTensor & Trace_(const cytnx_int64 &a, const cytnx_int64 &b, const bool &by_label=false)
Definition UniTensor.hpp:1511
UniTensor get(const std::vector< Accessor > &accessors) const
Definition UniTensor.hpp:1348
void Save(const std::string &fname) const
Definition UniTensor.cpp:131
UniTensor & operator-=(const Scalar &rhs)
Definition UniTensor.hpp:1468
cytnx_uint64 rowrank() const
Definition UniTensor.hpp:1221
void Init(const std::vector< Bond > &bonds, const std::vector< cytnx_int64 > &in_labels={}, const cytnx_int64 &rowrank=-1, const unsigned int &dtype=Type.Double, const int &device=Device.cpu, const bool &is_diag=false)
Definition UniTensor.hpp:1143
UniTensor & Sub_(const Scalar &rhs)
Definition UniTensor.hpp:1428
UniTensor & operator/=(const Scalar &rhs)
Definition UniTensor.hpp:1472
const bool & is_braket_form() const
Definition UniTensor.hpp:1232
UniTensor(const std::vector< Bond > &bonds, const std::vector< cytnx_int64 > &in_labels={}, const cytnx_int64 &rowrank=-1, const unsigned int &dtype=Type.Double, const int &device=Device.cpu, const bool &is_diag=false)
Initialize a UniTensor.
Definition UniTensor.hpp:1137
std::vector< cytnx_uint64 > shape() const
Definition UniTensor.hpp:1238
UniTensor to_dense()
Definition UniTensor.hpp:1364
UniTensor & set_label(const cytnx_uint64 &idx, const cytnx_int64 &new_label)
set a new label for bond at the assigned index.
Definition UniTensor.hpp:1188
void reshape_(const std::vector< cytnx_int64 > &new_shape, const cytnx_uint64 &rowrank=0)
Definition UniTensor.hpp:1361
std::string name() const
Definition UniTensor.hpp:1225
UniTensor & Add_(const Scalar &rhs)
Definition UniTensor.hpp:1418
std::vector< Bond > getTotalQnums(const bool physical=false) const
Definition UniTensor.hpp:1380
bool same_data(const UniTensor &rhs) const
Definition UniTensor.hpp:1387
Tensor & get_block_(const std::initializer_list< cytnx_int64 > &qnum)
Definition UniTensor.hpp:1302
void set_elem(const std::vector< cytnx_uint64 > &locator, const T2 &rc)
Definition UniTensor.hpp:1549
UniTensor Transpose() const
Definition UniTensor.hpp:1495
UniTensor & Dagger_()
Definition UniTensor.hpp:1522
void print_diagram(const bool &bond_info=false)
Definition UniTensor.hpp:1264
std::vector< Bond > & bonds()
Definition UniTensor.hpp:1237
T & at(const std::vector< cytnx_uint64 > &locator)
Definition UniTensor.hpp:1269
UniTensor & truncate_(const cytnx_int64 &bond_idx, const cytnx_uint64 &dim, const bool &by_label=false)
Definition UniTensor.hpp:1560
std::vector< std::vector< cytnx_int64 > > get_blocks_qnums() const
Definition UniTensor.hpp:1383
UniTensor contiguous() const
Definition UniTensor.hpp:1256
Tensor get_block(const cytnx_uint64 &idx=0) const
Definition UniTensor.hpp:1275
UniTensor & operator*=(const Scalar &rhs)
Definition UniTensor.hpp:1476
void contiguous_()
Definition UniTensor.hpp:1261
UniTensor & set_labels(const std::vector< cytnx_int64 > &new_labels)
set new labels for all the bonds.
Definition UniTensor.hpp:1201
UniTensor & Mul_(const UniTensor &rhs)
Definition UniTensor.hpp:1403
void put_block_(Tensor &in, const cytnx_uint64 &idx=0)
Definition UniTensor.hpp:1341
bool is_diag() const
Definition UniTensor.hpp:1230
int device() const
Definition UniTensor.hpp:1224
UniTensor & Pow_(const double &p)
Definition UniTensor.cpp:14
void set(const std::vector< Accessor > &accessors, const Tensor &rhs)
Definition UniTensor.hpp:1353
std::string dtype_str() const
Definition UniTensor.hpp:1226
UniTensor & operator+=(const Scalar &rhs)
Definition UniTensor.hpp:1464
UniTensor & Div_(const UniTensor &rhs)
Definition UniTensor.hpp:1413
UniTensor & Div_(const Scalar &rhs)
Definition UniTensor.hpp:1433
cytnx_uint64 rank() const
Definition UniTensor.hpp:1220
const Tensor & get_block_(const std::vector< cytnx_int64 > &qnum) const
Definition UniTensor.hpp:1309
void to_(const int &device)
Definition UniTensor.hpp:1241
void put_block(const Tensor &in, const std::vector< cytnx_int64 > &qnum)
Definition UniTensor.hpp:1337
Tensor get_block(const std::vector< cytnx_int64 > &qnum) const
Definition UniTensor.hpp:1280
UniTensor & set_name(const std::string &in)
set the name of the UniTensor
Definition UniTensor.hpp:1174
UniTensor & Add_(const UniTensor &rhs)
Definition UniTensor.hpp:1398
unsigned int dtype() const
Definition UniTensor.hpp:1222
UniTensor Pow(const double &p) const
Definition UniTensor.cpp:11
UniTensor & Mul_(const Scalar &rhs)
Definition UniTensor.hpp:1423
UniTensor & operator-=(const UniTensor &rhs)
Definition UniTensor.hpp:1452
bool is_blockform() const
Definition UniTensor.hpp:1239
UniTensor Dagger() const
Definition UniTensor.hpp:1516
const std::vector< Tensor > & get_blocks_(const bool &silent=false) const
Definition UniTensor.hpp:1324
bool elem_exists(const std::vector< cytnx_uint64 > &locator) const
Definition UniTensor.hpp:1539
UniTensor & Sub_(const UniTensor &rhs)
Definition UniTensor.hpp:1408
UniTensor contract(const UniTensor &inR, const bool &mv_elem_self=false, const bool &mv_elem_rhs=false) const
Definition UniTensor.hpp:1375
void put_block(const Tensor &in, const cytnx_uint64 &idx=0)
Definition UniTensor.hpp:1333
const Tensor & get_block_(const cytnx_uint64 &idx=0) const
Definition UniTensor.hpp:1289
Tensor get_block(const std::initializer_list< cytnx_int64 > &qnum) const
Definition UniTensor.hpp:1283
const Tensor & get_block_(const std::initializer_list< cytnx_int64 > &qnum) const
Definition UniTensor.hpp:1312
UniTensor Mul(const UniTensor &rhs) const
Definition UniTensor.cpp:39
const std::vector< Bond > & bonds() const
Definition UniTensor.hpp:1236
void put_block_(Tensor &in, const std::vector< cytnx_int64 > &qnum)
Definition UniTensor.hpp:1345
UniTensor & Transpose_()
Definition UniTensor.hpp:1500
UniTensor clone() const
Definition UniTensor.hpp:1247
UniTensor Trace(const cytnx_int64 &a, const cytnx_int64 &b, const bool &by_label=false) const
Definition UniTensor.hpp:1505
UniTensor truncate(const cytnx_int64 &bond_idx, const cytnx_uint64 &dim, const bool &by_label=false) const
Definition UniTensor.hpp:1564
void Init(const Tensor &in_tensor, const cytnx_uint64 &rowrank, const bool &is_diag=false)
Definition UniTensor.hpp:1113
std::string device_str() const
Definition UniTensor.hpp:1227
UniTensor Sub(const UniTensor &rhs) const
Definition UniTensor.cpp:25
UniTensor & Conj_()
Definition UniTensor.hpp:1489
Tensor & get_block_(const std::vector< cytnx_int64 > &qnum)
Definition UniTensor.hpp:1299
UniTensor Conj()
Definition UniTensor.hpp:1483
UniTensor Add(const UniTensor &rhs) const
Definition UniTensor.cpp:18
UniTensor & set_rowrank(const cytnx_uint64 &new_rowrank)
Definition UniTensor.hpp:1205
void permute_(const std::vector< cytnx_int64 > &mapper, const cytnx_int64 &rowrank=-1, const bool &by_label=false)
Definition UniTensor.hpp:1253
UniTensor(const Tensor &in_tensor, const cytnx_uint64 &rowrank, const bool &is_diag=false)
Initialize a UniTensor with cytnx::Tensor.
Definition UniTensor.hpp:1110
int uten_type() const
Definition UniTensor.hpp:1223
Tensor & get_block_(const cytnx_uint64 &idx=0)
Definition UniTensor.hpp:1294
#define cytnx_warning_msg(is_true, format,...)
Definition cytnx_error.hpp:37
#define cytnx_error_msg(is_true, format,...)
Definition cytnx_error.hpp:18
cytnx::UniTensor Trace(const cytnx::UniTensor &Tin, const cytnx_int64 &a, const cytnx_int64 &b, const bool &by_label=false)
Tensor Conj(const Tensor &Tin)
Conjugate all the element in Tensor.
void Conj_(Tensor &Tin)
inplace perform Conjugate on all the element in Tensor.
Definition Accessor.hpp:12
Device_class Device
Definition Device.cpp:105
double cytnx_double
Definition Type.hpp:20
UniTensorType_class UTenType
Definition UniTensor_base.cpp:21
uint32_t cytnx_uint32
Definition Type.hpp:23
std::complex< double > cytnx_complex128
Definition Type.hpp:30
float cytnx_float
Definition Type.hpp:21
std::ostream & operator<<(std::ostream &os, const Scalar &in)
Definition Scalar.cpp:14
int16_t cytnx_int16
Definition Type.hpp:27
std::complex< float > cytnx_complex64
Definition Type.hpp:29
int32_t cytnx_int32
Definition Type.hpp:26
UniTensor Contract(const UniTensor &inL, const UniTensor &inR, const bool &cacheL=false, const bool &cacheR=false)
Contract two UniTensor by tracing the ranks with common labels.
Definition UniTensor_base.cpp:352
uint16_t cytnx_uint16
Definition Type.hpp:24
uint64_t cytnx_uint64
Definition Type.hpp:22
int64_t cytnx_int64
Definition Type.hpp:25
Type_class Type
Definition Type.cpp:137