TBCI Numerical high perf. C++ Library  2.8.0
tensor.h
Go to the documentation of this file.
1 
6 // AMB 98/04
7 // last modified AMB 980428
8 // KG, 981205: added layout in order to provide an effective means to
9 // swap indices, Index iterators
10 // $Id: tensor.h,v 1.33.2.30 2022/11/03 17:28:11 garloff Exp $
11 
12 #ifndef TBCI_TENSOR_H
13 #define TBCI_TENSOR_H
14 
15 #include "tbci/vector.h"
16 #include "tbci/index.h"
17 
18 // Avoid -fguiding-decls
19 #if !defined(NO_GD) && !defined(AUTO_DECL)
20 # include "tbci/tensor_gd.h"
21 #endif
22 
24 
25 #ifndef TBCI_DISABLE_EXCEPT
26 //#include "except.h" is included in basics.h
27 class TensErr : public NumErr
28 {
29  public:
31  : NumErr("Error in Tensor class") {}
32  TensErr(const char* t, const long i = 0)
33  : NumErr(t, i) {}
34  TensErr(const TensErr& te)
35  : NumErr(te) {}
36  virtual ~TensErr() throw() {}
37 };
38 #endif
39 
40 #ifdef PRAGMA_I
41 # pragma interface "tensor.h"
42 #endif
43 
44 //----------------------------------------------------------------
46 
50 template <typename T>
51 class CTensor
52 {
53 
54 protected:
55  Vector <T> data; // linear storage
56  unsigned rank; // rank of tensor
57  unsigned long noel; // number of elements
58  Index shape; // shape of tensor, eg. 2x3x4
59  Index layout; // memory layout of tensor, eg. 12,4,1
60  unsigned long calcsize (void)
61  {
62  noel = 1;
63  for (REGISTER unsigned i = 0; i < rank; i++)
64  noel *= shape (i);
65  return noel;
66  }
67  unsigned calclayout ()
68  {
69  unsigned long fac = 1;
70  for (REGISTER int i = rank-1; i >= 0; i--)
71  {
72  layout(i) = fac;
73  fac *= shape(i);
74  }
75  return fac;
76  }
77 
78 public:
79 
80  typedef T value_type;
81  typedef T element_type;
82  typedef T aligned_value_type TALIGN(MIN_ALIGN2);
83 
84  CTensor () { rank = 0; } // default constructor
85  explicit CTensor (const unsigned dim_rank); // "square" constructor
86  CTensor (const Index & ix); // standard constructor
87  CTensor (const T & value, const Index & ix); // standard constructor
88  CTensor (const CTensor & ct); // copy constructor
89  CTensor (vararg va, ...); // arbitrary no of arguments
90  CTensor (const T, vararg va, ...); // arb no of arg & ini value
91 
92  ~CTensor () {}
93 
94  // mapping and reverse mapping
95  unsigned long calc_offs (const Index & ix) const;
96  Index calc_indx (const unsigned long i) const;
97 
98  // access
99  //T & operator ()(const TVector<T> & tv) const
100  // { Vector<T> ix(tv); return data (calc_offs (ix)); }
101  T & operator () (const Index & ix)
102  { return data (calc_offs (ix)); }
103  typename tbci_traits<T>::const_refval_type
104  operator () (const Index & ix) const
105  { return data (calc_offs (ix)); }
106  T & operator () (vararg va, ...);
107  typename tbci_traits<T>::const_refval_type
108  operator () (vararg va, ...) const;
109 
110  T & operator () (const unsigned long i)
111  { BCHKNR(i>=noel, TensErr, & op(): out of range, i);
112  return data(i); }
113  typename tbci_traits<T>::const_refval_type
114  operator () (const unsigned long i) const
115  { BCHKNR(i>=noel, TensErr, op() c: out of range, i);
116  return data(i); }
117 
118  const T& getcref (vararg va, ...) const;
119 
120  T& get_lin_idx (const unsigned long i) //const
121  { return (*this)(i); }
122  typename tbci_traits<T>::const_refval_type
123  get_lin_idx (const unsigned long i) const
124  { return (*this)(i); }
125 
126 #ifndef NO_POD
127  unsigned lin_read (vararg va, ...);
128 #endif
129 
130  // swap indices
131  CTensor<T>& transpose (const unsigned i, const unsigned j)
132  {
133  BCHK (i>=rank, TensErr, swap_idx: idx1 out of range, i, *this);
134  BCHK (j>=rank, TensErr, swap_idx: idx2 out of range, j, *this);
135  SWAP (shape(i), shape(j)); SWAP (layout(i), layout(j));
136  return *this;
137  }
138 
139  // assignment
140  CTensor <T>& fill (const T & value)
141  { data.fill (value); return *this; }
142 
143  // resizing equation operator!
145  {
146  rank = ct.rank; shape.resize(ct.shape);
147  layout.resize (ct.layout);
148  noel = ct.noel; data.resize(ct.data);
149  return *this;
150  }
151  CTensor <T>& operator = (const T & value)
152  { return this->fill (value); }
153 
154  //misc
155  CTensor<T>& resize (const Index& ix)
156  {
157  shape.resize(ix); rank = ix.size();
159  calcsize(); data.resize (noel);
160  return *this;
161  }
162  CTensor<T>& resize (const T& val, const Index& ix)
163  {
164  shape.resize(ix); rank = ix.size();
166  calcsize(); data.resize (val, noel);
167  return *this;
168  }
170  {
171  shape.resize(ct.shape); layout.resize (ct.layout);
172  rank = ct.rank; noel = ct.noel;
173  data.resize (ct.data);
174  return *this;
175  }
176 
177  T max (unsigned long& pos) const { return data.max (pos); }
178  T min (unsigned long& pos) const { return data.min (pos); }
179 
180  T max () const { return data.max (); }
181  T min () const { return data.min (); }
182 
183  T trace () const { return 0; } // ????????????????????????????
184 
185  // compare
186  bool operator == (const CTensor < T > &ct)
187  {
188  if (shape != ct.shape) return false;
189  if (layout == ct.layout) {
190  if (data == ct.data) return true; else return false; }
191  // layout is different, now we are in trouble
192  Index ix(0, rank);
193  while (ix(0) < shape(0))
194  {
195  if ((*this)(ix) != ct(ix)) return false;
196  ix.next_idx (shape);
197  }
198  return true;
199  }
200 
201  bool operator != (const CTensor < T > &ct)
202  { return !(this->operator == (ct)); }
203 
204  // info
205  unsigned long lin_size (void) const
206  { return noel; }
207  Index index_size (void) const
208  { return shape; }
209  unsigned rank_size (void) const
210  { return rank; }
211 
212  // i/o operations
213  friend STD__ ostream & operator << FGD (STD__ ostream&, const CTensor <T>&);
214  friend STD__ istream & operator >> FGD (STD__ istream&, CTensor <T>&);
215 
216 };
217 
218 // class CTensor definitions
219 
220 template < typename T >
221 inline CTensor < T >::CTensor (const unsigned dim_rank) :
222  rank (dim_rank), shape (dim_rank, dim_rank), layout (dim_rank)
223  // "square" constructor
224 {
225  calcsize (); calclayout ();
226  data.resize (noel);
227 }
228 
229 template < typename T >
230 inline CTensor < T >::CTensor (const Index & ix) :
231  rank (ix.size()), shape (ix), layout (ix.size())
232  // standard constructor
233 {
234  calcsize (); calclayout ();
235  data.resize (noel);
236 }
237 
238 template < typename T >
239 inline CTensor < T >::CTensor (const T & value, const Index & ix) :
240  rank (ix.size()), shape (ix), layout (ix.size())
241  // standard constructor
242 {
243  //rank = shape.size ();
244  calcsize (); calclayout ();
245  data.resize (value, noel);
246 }
247 
248 // copy constructor
249 template < typename T >
250 inline CTensor < T >::CTensor (const CTensor & ct)
251  : data(ct.data), rank(ct.rank), noel(ct.noel),
252  shape(ct.shape), layout(ct.layout)
253 {}
254 
255 // arb. arg. & ini
256 template < typename T >
257 inline CTensor < T >::CTensor (const T value, vararg va, ...) :
258  rank (va), shape ((unsigned)va), layout ((unsigned)va)
259 {
260  va_list vl;
261  va_start (vl, va);
262  for (unsigned i = 0; i < (unsigned)va; ++i)
263  shape (i) = va_arg (vl, unsigned);
264  va_end (vl);
265  calcsize (); calclayout ();
266  data.resize (value, noel);
267 }
268 
269 // arb. arg.
270 template < typename T >
271 inline CTensor <T>::CTensor (vararg va, ...) :
272  rank (va), shape ((unsigned)va), layout ((unsigned)va)
273 {
274  va_list vl;
275  va_start (vl, va);
276  for (unsigned i = 0; i < rank; ++i)
277  shape (i) = va_arg (vl, unsigned);
278  va_end (vl);
279  calcsize (); calclayout ();
280  data.resize (noel);
281 }
282 
283 #ifndef NO_POD
284 template < typename T >
285 unsigned CTensor < T >::lin_read (vararg va, ...)
286 {
287  va_list vl;
288  va_start (vl, va);
289  unsigned i;
290 #if !defined(__clang__) || !defined(CPLX)
291  for (i = 0; i < (unsigned)va; ++i)
292  data (i) = va_arg (vl, T);
293 #else
294  throw TensErr("vararg not supported for cplx in clang");
295 #warning no vararg support with cplx numbers and clang
296 #endif
297  va_end (vl);
298  return i;
299 }
300 #endif
301 
302 //Calculates eff. index
303 template < typename T >
304 inline unsigned long CTensor < T >::calc_offs (const Index & ix) const
305 {
306  BCHK (rank != ix.size(), TensErr, Rank of Tensor and Index size dont match, ix.size(), 0);
307  unsigned long offs (0);
308  for (REGISTER unsigned i = 0; i < rank; i++)
309  {
310  offs += ix (i) * layout (i);
311  }
312  BCHK (offs >= noel, TensErr, Too large index, offs, offs);
313  return offs;
314 }
315 
316 #if 0
317 template < typename T >
318 inline Index CTensor < T >::calc_indx (const unsigned long i) const
319 {
320  Index ix (rank);
321  unsigned long mod = i;
322  for (unsigned r = rank; r > 0; r--)
323  {
324  ix (r - 1) = mod % shape (r - 1);
325  mod /= shape (r - 1);
326  }
327  BCHK (mod > 0, TensErr, Mapping error, mod, ix);
328  return ix;
329 }
330 #endif
331 
332 /* This function is inefficient by design! */
333 template < typename T >
334 inline Index CTensor < T >::calc_indx (const unsigned long i) const
335 {
336  Index ix (rank); ix.fill (0);
337  unsigned long mod = i;
338  BCHK (i >= noel, TensErr, Linear index too large, i, ix);
339  // tricky stuff to start here ...
340  unsigned long maxdiv = noel;
341  while (mod)
342  {
343  // find largest divisor
344  unsigned long div = 0; unsigned ixnr = 0;
345  for (unsigned i = 0; i < rank; i++)
346  if (layout(i) > div && layout(i) < maxdiv && shape(i) > 1)
347  { div = layout(i); ixnr = i; }
348  maxdiv = div;
349  ix(ixnr) = mod / div; mod %= div;
350  }
351  return ix;
352 }
353 
354 
355 // formatted output
356 template < typename T >
357 STD__ ostream & operator << (STD__ ostream & os, const CTensor < T > & ct)
358 {
359  if (ct.rank > 1)
360  {
361  //os << "\n";
362  Index ix (0, ct.rank);
363  for (unsigned long i = 0; i < ct.noel; i++)
364  {
365  os << ct(ix) << "\t"; ix.next_idx (ct.shape);
366  for (unsigned j = ct.rank - 1; j > 0; j--)
367  if (ix(j) == 0) os << "\n"; else break;
368  }
369  }
370  else
371  os << ct.data;
372  return os;
373 }
374 
375 template <typename T>
376 STD__ istream& operator >> (STD__ istream & is, CTensor<T>& ct)
377 {
378  Index ix (0, ct.rank);
379  for (unsigned long i = 0; i < ct.noel; i++)
380  {
381  is >> ct(ix); ix.next_idx (ct.shape);
382  }
383  return is;
384 }
385 
386 //access
387 #if 0
388 template <typename T>
389 T& CTensor <T>::operator () (vararg va, ...) //const
390 {
391  Index ix ((unsigned)va);
392  va_list vl;
393  va_start (vl, va);
394  for (unsigned i = 0; i < (unsigned)va; ++i)
395  ix (i) = va_arg (vl, int);
396  va_end (vl);
397  return (*this) (ix);
398 }
399 
400 template <typename T>
401 typename tbci_traits<T>::const_refval_type
402 CTensor <T>::operator () (vararg va, ...) const
403 {
404  Index ix ((unsigned)va);
405  va_list vl;
406  va_start (vl, va);
407  for (unsigned i = 0; i < (unsigned)va; ++i)
408  ix (i) = va_arg (vl, int);
409  va_end (vl);
410  return (*this) (ix);
411 }
412 
413 #else
414 
415 template <typename T>
416 T& CTensor <T>::operator () (vararg va, ...) //const
417 {
418  BCHK((unsigned)va != rank, TensErr, vararg no must be eq to rank, (unsigned)va, data(0));
419  unsigned lin_idx = 0;
420  va_list vl;
421  va_start (vl, va);
422  for (unsigned i = 0; i < rank; ++i)
423  lin_idx += va_arg (vl, int) * layout(i);
424  va_end (vl);
425  return (data (lin_idx));
426 }
427 
428 template <typename T>
429 typename tbci_traits<T>::const_refval_type
430 CTensor <T>::operator () (vararg va, ...) const
431 {
432  BCHK((unsigned)va != rank, TensErr, vararg no must be eq to rank, (unsigned)va, data(0));
433  unsigned lin_idx = 0;
434  va_list vl;
435  va_start (vl, va);
436  for (unsigned i = 0; i < rank; ++i)
437  lin_idx += va_arg (vl, int) * layout(i);
438  va_end (vl);
439  return (data (lin_idx));
440 }
441 #endif
442 
443 
444 template <typename T>
445 const T& CTensor <T>::getcref (vararg va, ...) const
446 {
447  BCHK((unsigned)va != rank, TensErr, vararg no must be eq to rank, (unsigned)va, data.getcref(0));
448  unsigned lin_idx = 0;
449  va_list vl;
450  va_start (vl, va);
451  for (unsigned i = 0; i < rank; ++i)
452  lin_idx += va_arg (vl, int) * layout(i);
453  va_end (vl);
454  return data.getcref (lin_idx);
455 }
456 
457 
458 //-----------------------------------------------------------------------------
459 
460 
465 template<typename T>
466 class Tensor : public CTensor<T>
467 {
468 
469 protected:
470  // additional data structure
471 
472 public:
473 
474  typedef T value_type;
475  typedef T element_type;
476  typedef T aligned_value_type TALIGN(MIN_ALIGN2);
477  // constructors
478  Tensor () : CTensor <T> () {}
479  Tensor (const unsigned dim_rank) : CTensor <T> (dim_rank) {}
480  Tensor (const Index & ix) : CTensor <T> (ix) {}
481  Tensor (const T & value, const Index & ix) : CTensor <T> (value, ix) {}
482  Tensor (const Tensor <T>& ct) : CTensor <T> (ct) {}
483  Tensor (vararg va, ...);
484  Tensor (const T, vararg va, ...);
485  ~Tensor () {}
486 
487  // basic arithmetics
488  Tensor<T>& operator += (const Tensor<T> &);
489  Tensor<T>& operator -= (const Tensor<T> &);
490 
491  Tensor<T> operator + (const Tensor<T> &) const;
492  Tensor<T> operator - (const Tensor<T> &) const;
493 
494  Tensor<T>& operator *= (const T m) { this->data *= m; return *this; }
495  Tensor<T>& operator /= (const T m) { this->data /= m; return *this; }
496  Tensor<T>& operator += (const T m) { this->data += m; return *this; }
497  Tensor<T>& operator -= (const T m) { this->data -= m; return *this; }
498 
499  Tensor<T> operator * (const T m) const
500  {
501  Tensor<T> r (this->shape);
502  for (unsigned long i = 0; i < this->noel; ++i)
503  r.data(i) = this->data(i) * m;
504  return r;
505  }
506 
507 
508  //for friend NOINST Tensor<T> operator * FGD (const T, const Tensor<T> &);
509  Tensor<T> mult (const T) const;
510 
511  Tensor<T> operator / (const T m) const
512  {
513  Tensor<T> r (this->shape);
514  for (unsigned long i = 0; i < this->noel; ++i)
515  r.data(i) = this->data(i) / m;
516  return r;
517  }
518 
520  {
521  Tensor<T> r (this->shape);
522  for (unsigned long i=0; i < this->noel; ++i)
523  r.data(i) = - this->data(i);
524  return r;
525  }
526 
527  // tensor arithmetics
528  Tensor<T> contract (const unsigned, const unsigned) const; // contraction over 2 indices
529  // direct tensor product
530  Tensor<T> drctmul (const Tensor<T>&) const;
531  friend Tensor<T> FRIEND_TBCI2__ dctmul FGD (const Tensor<T>&, const Tensor<T>&);
532  // multiplication with contraction over 2 indices
533  Tensor<T> cntrmul (const Tensor<T>&, const unsigned, const unsigned) const;
534  friend Tensor<T> FRIEND_TBCI2__ ctrmul FGD (const Tensor<T>&, const Tensor<T>&, const unsigned, const unsigned);
535  // multiplication w/ metric results in differently ordered indices comp. to cntrmul
536  friend Tensor<T> FRIEND_TBCI2__ metrmul FGD (const Tensor<T>&, const Tensor<T>&, const unsigned, const unsigned);
537 
538 };
539 
540 
541 //implementations of class Tensor
542 
543 
544 // arb. arg. & ini
545 template < typename T >
546 inline Tensor < T >::Tensor (const T value, vararg va, ...)
547  //: CTensor<T>::rank (va.num), CTensor<T>::layout (va.num), CTensor<T>::shape (va.num)
548 {
549  this->rank = va;
550  this->layout.resize ((unsigned)va);
551  this->shape.resize ((unsigned)va);
552  va_list vl;
553  va_start (vl, va);
554  for (unsigned i = 0; i < (unsigned)va; ++i)
555  this->shape (i) = va_arg (vl, unsigned);
556  va_end (vl);
557  this->calcsize (); this->calclayout ();
558  this->data.resize (value, this->noel);
559 }
560 
561 // arb. arg.
562 template < typename T >
563 inline Tensor <T>::Tensor (vararg va, ...)
564  //: CTensor<T>::rank (va.num), CTensor<T>::layout (va.num), CTensor<T>::shape (va.num)
565 {
566  this->rank = va;
567  this->layout.resize ((unsigned)va);
568  this->shape.resize ((unsigned)va);
569  va_list vl;
570  va_start (vl, va);
571  for (unsigned i = 0; i < this->rank; ++i)
572  this->shape (i) = va_arg (vl, unsigned);
573  va_end (vl);
574  this->calcsize (); this->calclayout ();
575  this->data.resize (this->noel);
576 }
577 
578 
579 template <typename T>
580 Tensor<T> Tensor <T>::contract (const unsigned i1, const unsigned i2) const
581 {
582  // Calculate shape
583  Index ix (idx_remove2 (this->shape, i1, i2));
584  Tensor < T > t (0, ix);
585 
586  BCHK (this->shape (i1) != this->shape (i2), TensErr, Contraction over diff. sized indices, this->shape (i2), t);
587 
588  Index bx (0, ix.size());
589  while (bx(0) < ix(0)) {
590  unsigned long l = t.calc_offs (bx);
591  for (unsigned m = 0; m < this->shape (i1); ++m)
592  t.data (l) += (*this) (idx_fill_in2 (bx, i1, m, i2, m));
593  bx.next_idx (ix);
594  }
595  return t;
596 }
597 
598 #if 1
599 template <typename T>
600 Tensor<T> Tensor<T>::cntrmul (const Tensor<T>& t2, const unsigned i1, const unsigned i2) const
601 {
602  BCHK(this->shape (i1) != t2.shape (i2), TensErr, CntrMul: Diff. sizes, t2.shape(i2), 0);
603  Index sh2 (this->shape); sh2.append (t2.shape);
604  Index ix (idx_remove2 (sh2, i1, i2 + this->rank));
605 
606  Tensor <T> result (0, ix);
607  Index ixr (0, result.rank);
608 
609  while (ixr(0) < ix(0)) {
610  unsigned long i = result.calc_offs (ixr);
611  for (unsigned m = 0; m < this->shape (i1); ++m) {
612  Index ix1 (idx_fill_in1 (ixr.slice(0, this->rank-1), i1, m));
613  Index ix2 (idx_fill_in1 (ixr.slice(this->rank-1, result.rank), i2, m));
614  result.data(i) += (*this) (ix1) * t2 (ix2);
615  }
616  ixr.next_idx (ix);
617  }
618  return result;
619 }
620 
621 #else
622 
623 template <typename T>
624 Tensor<T> Tensor<T>::cntrmul (const Tensor<T>& t2, const unsigned i1, const unsigned i2) const
625 {
626  BCHK(this->shape (i1) != t2.shape (i2), TensErr, CrtMul: Diff. sizes, t2.shape(i2), 0);
627  Index ix (this->rank + t2.rank - 2); // rank of result tensor
628  unsigned c = 0; // counter
629  {
630  for (unsigned i = 0; i < this->rank; i++)
631  if (i != i1)
632  ix (c++) = this->shape (i);
633  } // index from 1rst
634  {
635  for (unsigned i = 0; i < t2.rank; i++) i
636  if (i != i2)
637  ix (c++) = t2.shape (i);
638  } // & from 2nd tensor excl. sum. index
639 
640  Tensor <T> result (0, ix);
641  Index ixr (result.rank);
642  Index ix1 (this->rank);
643  Index ix2 (t2.rank);
644  for (unsigned long i = 0; i < result.noel; ++i) {
645  ixr = result.calc_indx (i);
646  for (unsigned m = 0; m < this->shape (i1); ++m) {
647  c = 0; // reset counter
648  for (unsigned k = 0; k < this->rank; ++k) {
649  if (k != i1)
650  ix1 (k) = ixr (c++);
651  else
652  ix1 (k) = m;
653  }
654  for (unsigned l = 0; l < t2.rank; ++l) {
655  if (l != i2)
656  ix2 (l) = ixr (c++);
657  else
658  ix2 (l) = m;
659  }
660  result.data(i) += (*this)(ix1) * t2(ix2);
661  }
662  }
663  return result;
664 }
665 
666 #endif
667 
668 // Same as cntrmul, but friend instead of member
669 template <typename T>
670 Tensor<T> ctrmul (const Tensor<T>& t1, const Tensor<T>& t2, const unsigned i1, const unsigned i2)
671 {
672  BCHK(t1.shape (i1) != t2.shape (i2), TensErr, CtrMul: Diff. sizes, t2.shape(i2), 0);
673  Index sh2 (t1.shape); sh2.append (t2.shape);
674  Index ix (idx_remove2 (sh2, i1, i2 + t1.rank));
675  Tensor < T > result (0, ix);
676 
677  Index ixr (0, result.rank);
678  while (ixr(0) < ix(0)) {
679  unsigned long i = result.calc_offs (ixr);
680  for (unsigned m = 0; m < t1.shape (i1); ++m) {
681  result.data(i) += t1 (idx_fill_in1 (ixr.slice(0,t1.rank-1), i1, m))
682  * t2 (idx_fill_in1 (ixr.slice(t1.rank-1,result.rank), i2, m));
683  }
684  ixr.next_idx (ix);
685  }
686  return result;
687 }
688 
689 template <typename T>
690 Tensor<T> metrmul (const Tensor<T>& metr, const Tensor<T>& t, const unsigned i1, const unsigned i2)
691 {
692  BCHK(metr.shape (i1) != t.shape (i2), TensErr, MetrMul: Diff. sizes, t.shape(i2), 0);
693  BCHK(metr.rank != 2, TensErr, Metric w/ rank != 2 ?, metr.rank, t);
694  BCHKNR(metr.shape(0) != metr.shape(1), TensErr, Non-quadr. metric ?, metr.shape(i1));
695 
696  Index ix (t.shape);
697  Tensor < T > result (0, ix);
698 
699  unsigned long io = 1 - i1; // other index in metric
700 
701  Index ixr (0, result.rank);
702  Index mix (2);
703  while (ixr(0) < ix(0)) {
704  unsigned long i = result.calc_offs (ixr);
705  for (unsigned m = 0; m < metr.shape (i1); ++m) {
706  mix (io) = ixr (i2); mix (i1) = m;
707  result.data (i) += metr (mix) * t (idx_set1 (ixr, i2, m));
708  }
709  ixr.next_idx (ix);
710  }
711  return result;
712 }
713 
714 template <typename T>
716 {
717  Index ix (t1.shape); // rank of result tensor
718  ix.append (this->shape);
719  Tensor < T > result (0, ix);
720  Index ixr (0, result.rank);
721  while (ixr(0) < ix(0)) {
722  result (ixr) = (*this) (ixr.slice (0, this->rank))
723  * t1 (ixr.slice (this->rank, result.rank));
724  ixr.next_idx (ix);
725  }
726  return result;
727 }
728 
729 // Same as drctmul, but friend
730 template <typename T>
731 Tensor<T> dctmul (const Tensor<T> &t0, const Tensor<T> &t1)
732 {
733  Index ix (t1.shape); // rank of result tensor
734  ix.append (t0.shape);
735  Tensor < T > result (0, ix);
736  Index ixr (0, result.rank);
737  while (ixr(0) < ix(0)) {
738  result (ixr) = t0 (ixr.slice (0, t0.rank))
739  * t1 (ixr.slice (t0.rank, result.rank));
740  ixr.next_idx (ix);
741  }
742  return result;
743 }
744 
745 template <typename T>
747 {
748  BCHK(this->shape!=t.shape, TensErr, Diff Tensor shape in op +=, t.noel, *this);
749  if (this->layout == t.layout)
750  for (unsigned long i = 0; i < this->noel; i++)
751  this->data(i) += t.data(i);
752  else {
753  Index ix (0, this->rank);
754  while (ix(0) < this->shape(0)) {
755  (*this)(ix) += t(ix);
756  ix.next_idx(this->shape);
757  }
758  }
759  return *this;
760 }
761 
762 template <typename T>
764 {
765  BCHK(this->shape!=t.shape, TensErr, Diff Tensor shape in op -=, t.noel, *this);
766  if (this->layout == t.layout)
767  for (unsigned long i = 0; i < this->noel; i++)
768  this->data(i) -= t.data(i);
769  else {
770  Index ix (0, this->rank);
771  while (ix(0) < this->shape(0)) {
772  (*this)(ix) -= t(ix);
773  ix.next_idx(this->shape);
774  }
775  }
776  return *this;
777 }
778 
779 template <typename T>
781 {
782  Tensor<T> r (this->shape);
783  BCHK(this->shape!=t.shape, TensErr, Diff Tensor shape in op +, t.noel, r);
784  if (this->layout == t.layout)
785  for (unsigned long i = 0; i < this->noel; i++)
786  r.data(i) = this->data(i) + t.data(i);
787  else {
788  Index ix (0, this->rank);
789  while (ix(0) < this->shape(0)) {
790  r(ix) = (*this)(ix) + t(ix);
791  ix.next_idx(this->shape);
792  }
793  }
794  return r;
795 }
796 
797 template <typename T>
799 {
800  Tensor<T> r (this->shape);
801  BCHK(this->shape!=t.shape, TensErr, Diff Tensor shape in op -, t.noel, r);
802  if (this->layout == t.layout)
803  for (unsigned long i = 0; i < this->noel; i++)
804  r.data(i) = this->data(i) - t.data(i);
805  else {
806  Index ix (0, this->rank);
807  while (ix(0) < this->shape(0)) {
808  r(ix) = (*this)(ix) - t(ix);
809  ix.next_idx(this->shape);
810  }
811  }
812  return r;
813 }
814 
815 
816 template <typename T>
817 Tensor<T> Tensor<T>::mult (const T m) const
818 {
819  Tensor<T> res (this->shape);
820  for (unsigned long i = 0; i < this->noel; ++i)
821  res.data(i) = m * this->data(i);
822  return res;
823 }
824 
825 INST(template <typename T> class Tensor friend Tensor<T> operator * (const T, const Tensor<T> &);)
826 template <typename T>
827 inline Tensor<T> operator * (const T m, const Tensor<T> &t)
828 { return t.mult (m); }
829 
830 
832 
833 #endif /* TBCI_TENSOR_H */
Tensor< T > metrmul(const Tensor< T > &metr, const Tensor< T > &t, const unsigned i1, const unsigned i2)
Definition: tensor.h:690
Tensor< T > mult(const T) const
Definition: tensor.h:817
Vector< T > & fill(const T &v)
Definition: vector.h:1577
#define BCHKNR(cond, exc, txt, ind)
Definition: basics.h:586
unsigned long calcsize(void)
Definition: tensor.h:60
Tensor< T > dctmul(const Tensor< T > &t0, const Tensor< T > &t1)
Definition: tensor.h:731
Tensor< T > ctrmul(const Tensor< T > &t1, const Tensor< T > &t2, const unsigned i1, const unsigned i2)
Definition: tensor.h:670
CTensor< T > & operator=(const CTensor< T > &ct)
Definition: tensor.h:144
tm fac
Definition: f_matrix.h:1052
unsigned long lin_size(void) const
Definition: tensor.h:205
~CTensor()
Definition: tensor.h:92
CTensor< T > & resize(const Index &ix)
Definition: tensor.h:155
T value_type
Definition: tensor.h:474
TensErr(const char *t, const long i=0)
Definition: tensor.h:32
STD__ istream & operator>>(STD__ istream &istr, BdMatrix< T > &mat)
Definition: band_matrix.h:2739
CTensor()
Definition: tensor.h:84
T element_type
Definition: tensor.h:475
#define large
T value_type
Definition: tensor.h:80
#define REGISTER
Definition: basics.h:108
return c
Definition: f_matrix.h:760
#define NAMESPACE_TBCI
Definition: basics.h:317
Tensor< T > drctmul(const Tensor< T > &) const
Definition: tensor.h:715
Tensor< T > contract(const unsigned, const unsigned) const
Definition: tensor.h:580
Tensor< T > & operator*=(const T m)
Definition: tensor.h:494
exception base class for the TBCI NumLib
Definition: except.h:58
T min(unsigned long &pos) const
Definition: tensor.h:178
Note (KG, 981214): We don&#39;t handle rank == 0.
Definition: tensor.h:51
#define MIN_ALIGN2
Definition: basics.h:424
Tensor< T > operator/(const T m) const
Definition: tensor.h:511
TensErr()
Definition: tensor.h:30
Tensor< T > operator-() const
Definition: tensor.h:519
#define BCHK(cond, exc, txt, ind, rtval)
Definition: basics.h:575
unsigned long calc_offs(const Index &ix) const
Definition: tensor.h:304
TVector< T > slice(unsigned long, unsigned long) const
Definition: vector.h:2335
#define FRIEND_TBCI2__
Definition: basics.h:335
TVector< unsigned > idx_remove2(const Index &idx, const unsigned which1, const unsigned which2)
Definition: index.h:205
T max() const
Definition: tensor.h:180
T & operator()(const Index &ix)
Definition: tensor.h:101
T & get_lin_idx(const unsigned long i)
Definition: tensor.h:120
TVector< unsigned > idx_set1(const Index &idx, const unsigned which, const unsigned what)
Definition: index.h:219
Tensor(const Tensor< T > &ct)
Definition: tensor.h:482
Definition: tensor.h:27
T trace() const
Definition: tensor.h:183
unsigned calclayout()
Definition: tensor.h:67
CTensor< T > & fill(const T &value)
Definition: tensor.h:140
unsigned rank
Definition: tensor.h:56
Index layout
Definition: tensor.h:59
Tensor(const Index &ix)
Definition: tensor.h:480
bool operator!=(const CTensor< T > &ct)
Definition: tensor.h:201
Tensor class including arithmetics.
Definition: f_matrix.h:53
T aligned_value_type TALIGN(MIN_ALIGN2)
Definition: tensor.h:476
Note that this #pragma interface might create problems as the class index is not templated! ...
Definition: index.h:48
long int Vector< T > & index
Definition: LM_fit.h:69
Index next_idx(const Index &max)
Definition: index.h:86
BVector< T > & append(const T &)
performs poorly
Definition: bvector.h:412
Index calc_indx(const unsigned long i) const
Definition: tensor.h:334
Tensor< T > & operator/=(const T m)
Definition: tensor.h:495
unsigned long noel
Definition: tensor.h:57
T max(unsigned long &pos) const
Definition: tensor.h:177
Tensor< T > & operator-=(const Tensor< T > &)
Definition: tensor.h:763
void SWAP(T &a, T &b)
SWAP function Note: We could implement a swap function without temporaries: a -= b b += a a -= b a = ...
Definition: basics.h:813
bool operator==(const CTensor< T > &ct)
Definition: tensor.h:186
Tensor< T > cntrmul(const Tensor< T > &, const unsigned, const unsigned) const
Definition: tensor.h:600
unsigned long size() const
Definition: vector.h:104
#define FGD
Definition: basics.h:144
Index shape
Definition: tensor.h:58
const T & getcref(vararg va,...) const
Definition: tensor.h:445
Vector< T > data
Definition: tensor.h:55
#define INST(x)
Definition: basics.h:238
TensErr(const TensErr &te)
Definition: tensor.h:34
T element_type
Definition: tensor.h:81
int i
Definition: LM_fit.h:71
BVector< T > & resize(const BVector< T > &)
Actually it&#39;s a resize and copy (some people would expect the assignment op to do this) ...
Definition: bvector.h:361
CTensor< T > & transpose(const unsigned i, const unsigned j)
Definition: tensor.h:131
T min() const
Definition: tensor.h:181
#define STD__
Definition: basics.h:338
tbci_traits< T >::const_refval_type get_lin_idx(const unsigned long i) const
Definition: tensor.h:123
Index index_size(void) const
Definition: tensor.h:207
virtual ~TensErr()
Definition: tensor.h:36
Tensor(const T &value, const Index &ix)
Definition: tensor.h:481
~Tensor()
Definition: tensor.h:485
#define NAMESPACE_END
Definition: basics.h:323
Definition: bvector.h:54
CTensor< T > & resize(const T &val, const Index &ix)
Definition: tensor.h:162
const Vector< T > Vector< T > Vector< T > Vector< T > Vector< T > Vector< T > Vector< T > Vector< T > long int res
Definition: LM_fit.h:199
unsigned lin_read(vararg va,...)
Definition: tensor.h:285
#define T
Definition: bdmatlib.cc:20
unsigned rank_size(void) const
Definition: tensor.h:209
Tensor()
Definition: tensor.h:478
Tensor(const unsigned dim_rank)
Definition: tensor.h:479
Tensor< T > & operator+=(const Tensor< T > &)
Definition: tensor.h:746
Tensor< T > operator*(const T m) const
Definition: tensor.h:499
friend Tensor< T > FRIEND_TBCI2__ dctmul FGD(const Tensor< T > &, const Tensor< T > &)
Tensor< T > operator+(const Tensor< T > &) const
Definition: tensor.h:780
TVector< unsigned > idx_fill_in2(const Index &idx, const unsigned where1, const unsigned what1, const unsigned where2, const unsigned what2)
Definition: index.h:168
TVector< unsigned > idx_fill_in1(const Index &idx, const unsigned where, const unsigned what)
Definition: index.h:146
CTensor< T > & resize(const CTensor< T > &ct)
Definition: tensor.h:169
enum _vararg vararg
Definition: basics.h:1276
T aligned_value_type TALIGN(MIN_ALIGN2)
Definition: tensor.h:82