00001
00006
00007
00008
00009
00010
00011
00012 #ifndef TBCI_TENSOR_H
00013 #define TBCI_TENSOR_H
00014
00015 #include "vector.h"
00016 #include "index.h"
00017
00018
00019 #if !defined(NO_GD) && !defined(AUTO_DECL)
00020 # include "tensor_gd.h"
00021 #endif
00022
00023 NAMESPACE_TBCI
00024
00025 #ifdef EXCEPT
00026
00027 class TensErr : public NumErr
00028 {
00029 public:
00030 TensErr()
00031 : NumErr("Error in Tensor class") {}
00032 TensErr(const char* t, const long i = 0)
00033 : NumErr(t, i) {}
00034 TensErr(const TensErr& te)
00035 : NumErr(te) {}
00036 virtual ~TensErr() throw() {}
00037 };
00038 #endif
00039
00040 #ifdef PRAGMA_I
00041 # pragma interface "tensor.h"
00042 #endif
00043
00044
00046
00050 template <typename T>
00051 class CTensor
00052 {
00053
00054 protected:
00055 Vector <T> data;
00056 unsigned rank;
00057 unsigned long noel;
00058 Index shape;
00059 Index layout;
00060 unsigned long calcsize (void)
00061 {
00062 noel = 1;
00063 for (register unsigned i = 0; i < rank; i++)
00064 noel *= shape (i);
00065 return noel;
00066 }
00067 unsigned calclayout ()
00068 {
00069 unsigned long fac = 1;
00070 for (register int i = rank-1; i >= 0; i--)
00071 {
00072 layout(i) = fac;
00073 fac *= shape(i);
00074 }
00075 return fac;
00076 }
00077
00078 public:
00079
00080 typedef T value_type;
00081 typedef T element_type;
00082 typedef T aligned_value_type TALIGN(MIN_ALIGN2);
00083
00084 CTensor () { rank = 0; }
00085 explicit CTensor (const unsigned dim_rank);
00086 CTensor (const Index & ix);
00087 CTensor (const T & value, const Index & ix);
00088 CTensor (const CTensor & ct);
00089 CTensor (vararg va, ...);
00090 CTensor (const T, vararg va, ...);
00091
00092 ~CTensor () {}
00093
00094
00095 unsigned long calc_offs (const Index & ix) const;
00096 Index calc_indx (const unsigned long i) const;
00097
00098
00099
00100
00101 T & operator () (const Index & ix)
00102 { return data (calc_offs (ix)); }
00103 typename tbci_traits<T>::const_refval_type
00104 operator () (const Index & ix) const
00105 { return data (calc_offs (ix)); }
00106 T & operator () (vararg va, ...);
00107 typename tbci_traits<T>::const_refval_type
00108 operator () (vararg va, ...) const;
00109
00110 T & operator () (const unsigned long i)
00111 { BCHKNR(i>=noel, TensErr, & op(): out of range, i);
00112 return data(i); }
00113 typename tbci_traits<T>::const_refval_type
00114 operator () (const unsigned long i) const
00115 { BCHKNR(i>=noel, TensErr, op() c: out of range, i);
00116 return data(i); }
00117
00118 const T& getcref (vararg va, ...) const;
00119
00120 T& get_lin_idx (const unsigned long i)
00121 { return (*this)(i); }
00122 typename tbci_traits<T>::const_refval_type
00123 get_lin_idx (const unsigned long i) const
00124 { return (*this)(i); }
00125
00126 #ifndef NO_POD
00127 unsigned lin_read (vararg va, ...);
00128 #endif
00129
00130
00131 CTensor<T>& transpose (const unsigned i, const unsigned j)
00132 {
00133 BCHK (i>=rank, TensErr, swap_idx: idx1 out of range, i, *this);
00134 BCHK (j>=rank, TensErr, swap_idx: idx2 out of range, j, *this);
00135 SWAP (shape(i), shape(j)); SWAP (layout(i), layout(j));
00136 return *this;
00137 }
00138
00139
00140 CTensor <T>& fill (const T & value)
00141 { data.fill (value); return *this; }
00142
00143
00144 CTensor <T> & operator = (const CTensor <T> & ct)
00145 {
00146 rank = ct.rank; shape.resize(ct.shape);
00147 layout.resize (ct.layout);
00148 noel = ct.noel; data.resize(ct.data);
00149 return *this;
00150 }
00151 CTensor <T>& operator = (const T & value)
00152 { return this->fill (value); }
00153
00154
00155 CTensor<T>& resize (const Index& ix)
00156 {
00157 shape.resize(ix); rank = ix.size();
00158 layout.resize(rank); calclayout ();
00159 calcsize(); data.resize (noel);
00160 return *this;
00161 }
00162 CTensor<T>& resize (const T& val, const Index& ix)
00163 {
00164 shape.resize(ix); rank = ix.size();
00165 layout.resize(rank); calclayout ();
00166 calcsize(); data.resize (val, noel);
00167 return *this;
00168 }
00169 CTensor<T>& resize (const CTensor<T>& ct)
00170 {
00171 shape.resize(ct.shape); layout.resize (ct.layout);
00172 rank = ct.rank; noel = ct.noel;
00173 data.resize (ct.data);
00174 return *this;
00175 }
00176
00177 T max (unsigned long& pos) const { return data.max (pos); }
00178 T min (unsigned long& pos) const { return data.min (pos); }
00179
00180 T max () const { return data.max (); }
00181 T min () const { return data.min (); }
00182
00183 T trace () const { return 0; }
00184
00185
00186 bool operator == (const CTensor < T > &ct)
00187 {
00188 if (shape != ct.shape) return false;
00189 if (layout == ct.layout) {
00190 if (data == ct.data) return true; else return false; }
00191
00192 Index ix(0, rank);
00193 while (ix(0) < shape(0))
00194 {
00195 if ((*this)(ix) != ct(ix)) return false;
00196 ix.next_idx (shape);
00197 }
00198 return true;
00199 }
00200
00201 bool operator != (const CTensor < T > &ct)
00202 { return !(this->operator == (ct)); }
00203
00204
00205 unsigned long lin_size (void) const
00206 { return noel; }
00207 Index index_size (void) const
00208 { return shape; }
00209 unsigned rank_size (void) const
00210 { return rank; }
00211
00212
00213 friend STD__ ostream & operator << FGD (STD__ ostream&, const CTensor <T>&);
00214 friend STD__ istream & operator >> FGD (STD__ istream&, CTensor <T>&);
00215
00216 };
00217
00218
00219
00220 template < typename T >
00221 inline CTensor < T >::CTensor (const unsigned dim_rank) :
00222 rank (dim_rank), shape (dim_rank, dim_rank), layout (dim_rank)
00223
00224 {
00225 calcsize (); calclayout ();
00226 data.resize (noel);
00227 }
00228
00229 template < typename T >
00230 inline CTensor < T >::CTensor (const Index & ix) :
00231 rank (ix.size()), shape (ix), layout (ix.size())
00232
00233 {
00234 calcsize (); calclayout ();
00235 data.resize (noel);
00236 }
00237
00238 template < typename T >
00239 inline CTensor < T >::CTensor (const T & value, const Index & ix) :
00240 rank (ix.size()), shape (ix), layout (ix.size())
00241
00242 {
00243
00244 calcsize (); calclayout ();
00245 data.resize (value, noel);
00246 }
00247
00248
00249 template < typename T >
00250 inline CTensor < T >::CTensor (const CTensor & ct)
00251 : data(ct.data), rank(ct.rank), noel(ct.noel),
00252 shape(ct.shape), layout(ct.layout)
00253 {}
00254
00255
00256 template < typename T >
00257 inline CTensor < T >::CTensor (const T value, vararg va, ...) :
00258 rank (va), shape ((unsigned)va), layout ((unsigned)va)
00259 {
00260 va_list vl;
00261 va_start (vl, va);
00262 for (unsigned i = 0; i < (unsigned)va; ++i)
00263 shape (i) = va_arg (vl, unsigned);
00264 va_end (vl);
00265 calcsize (); calclayout ();
00266 data.resize (value, noel);
00267 }
00268
00269
00270 template < typename T >
00271 inline CTensor <T>::CTensor (vararg va, ...) :
00272 rank (va), shape ((unsigned)va), layout ((unsigned)va)
00273 {
00274 va_list vl;
00275 va_start (vl, va);
00276 for (unsigned i = 0; i < rank; ++i)
00277 shape (i) = va_arg (vl, unsigned);
00278 va_end (vl);
00279 calcsize (); calclayout ();
00280 data.resize (noel);
00281 }
00282
00283 #ifndef NO_POD
00284 template < typename T >
00285 unsigned CTensor < T >::lin_read (vararg va, ...)
00286 {
00287 va_list vl;
00288 va_start (vl, va);
00289 unsigned i;
00290 for (i = 0; i < (unsigned)va; ++i)
00291 data (i) = va_arg (vl, T);
00292 va_end (vl);
00293 return i;
00294 }
00295 #endif
00296
00297
00298 template < typename T >
00299 inline unsigned long CTensor < T >::calc_offs (const Index & ix) const
00300 {
00301 BCHK (rank != ix.size(), TensErr, Rank of Tensor and Index size dont match, ix.size(), 0);
00302 unsigned long offs (0);
00303 for (register unsigned i = 0; i < rank; i++)
00304 {
00305 offs += ix (i) * layout (i);
00306 }
00307 BCHK (offs >= noel, TensErr, Too large index, offs, offs);
00308 return offs;
00309 }
00310
00311 #if 0
00312 template < typename T >
00313 inline Index CTensor < T >::calc_indx (const unsigned long i) const
00314 {
00315 Index ix (rank);
00316 unsigned long mod = i;
00317 for (unsigned r = rank; r > 0; r--)
00318 {
00319 ix (r - 1) = mod % shape (r - 1);
00320 mod /= shape (r - 1);
00321 }
00322 BCHK (mod > 0, TensErr, Mapping error, mod, ix);
00323 return ix;
00324 }
00325 #endif
00326
00327
00328 template < typename T >
00329 inline Index CTensor < T >::calc_indx (const unsigned long i) const
00330 {
00331 Index ix (rank); ix.fill (0);
00332 unsigned long mod = i;
00333 BCHK (i >= noel, TensErr, Linear index too large, i, ix);
00334
00335 unsigned long maxdiv = noel;
00336 while (mod)
00337 {
00338
00339 unsigned long div = 0; unsigned ixnr = 0;
00340 for (unsigned i = 0; i < rank; i++)
00341 if (layout(i) > div && layout(i) < maxdiv && shape(i) > 1)
00342 { div = layout(i); ixnr = i; }
00343 maxdiv = div;
00344 ix(ixnr) = mod / div; mod %= div;
00345 }
00346 return ix;
00347 }
00348
00349
00350
00351 template < typename T >
00352 STD__ ostream & operator << (STD__ ostream & os, const CTensor < T > & ct)
00353 {
00354 if (ct.rank > 1)
00355 {
00356
00357 Index ix (0, ct.rank);
00358 for (unsigned long i = 0; i < ct.noel; i++)
00359 {
00360 os << ct(ix) << "\t"; ix.next_idx (ct.shape);
00361 for (unsigned j = ct.rank - 1; j > 0; j--)
00362 if (ix(j) == 0) os << "\n"; else break;
00363 }
00364 }
00365 else
00366 os << ct.data;
00367 return os;
00368 }
00369
00370 template <typename T>
00371 STD__ istream& operator >> (STD__ istream & is, CTensor<T>& ct)
00372 {
00373 Index ix (0, ct.rank);
00374 for (unsigned long i = 0; i < ct.noel; i++)
00375 {
00376 is >> ct(ix); ix.next_idx (ct.shape);
00377 }
00378 return is;
00379 }
00380
00381
00382 #if 0
00383 template <typename T>
00384 T& CTensor <T>::operator () (vararg va, ...)
00385 {
00386 Index ix ((unsigned)va);
00387 va_list vl;
00388 va_start (vl, va);
00389 for (unsigned i = 0; i < (unsigned)va; ++i)
00390 ix (i) = va_arg (vl, int);
00391 va_end (vl);
00392 return (*this) (ix);
00393 }
00394
00395 template <typename T>
00396 typename tbci_traits<T>::const_refval_type
00397 CTensor <T>::operator () (vararg va, ...) const
00398 {
00399 Index ix ((unsigned)va);
00400 va_list vl;
00401 va_start (vl, va);
00402 for (unsigned i = 0; i < (unsigned)va; ++i)
00403 ix (i) = va_arg (vl, int);
00404 va_end (vl);
00405 return (*this) (ix);
00406 }
00407
00408 #else
00409
00410 template <typename T>
00411 T& CTensor <T>::operator () (vararg va, ...)
00412 {
00413 BCHK((unsigned)va != rank, TensErr, vararg no must be eq to rank, (unsigned)va, data(0));
00414 unsigned lin_idx = 0;
00415 va_list vl;
00416 va_start (vl, va);
00417 for (unsigned i = 0; i < rank; ++i)
00418 lin_idx += va_arg (vl, int) * layout(i);
00419 va_end (vl);
00420 return (data (lin_idx));
00421 }
00422
00423 template <typename T>
00424 typename tbci_traits<T>::const_refval_type
00425 CTensor <T>::operator () (vararg va, ...) const
00426 {
00427 BCHK((unsigned)va != rank, TensErr, vararg no must be eq to rank, (unsigned)va, data(0));
00428 unsigned lin_idx = 0;
00429 va_list vl;
00430 va_start (vl, va);
00431 for (unsigned i = 0; i < rank; ++i)
00432 lin_idx += va_arg (vl, int) * layout(i);
00433 va_end (vl);
00434 return (data (lin_idx));
00435 }
00436 #endif
00437
00438
00439 template <typename T>
00440 const T& CTensor <T>::getcref (vararg va, ...) const
00441 {
00442 BCHK((unsigned)va != rank, TensErr, vararg no must be eq to rank, (unsigned)va, data(0));
00443 unsigned lin_idx = 0;
00444 va_list vl;
00445 va_start (vl, va);
00446 for (unsigned i = 0; i < rank; ++i)
00447 lin_idx += va_arg (vl, int) * layout(i);
00448 va_end (vl);
00449 return data.getcref (lin_idx);
00450 }
00451
00452
00453
00454
00455
00460 template<typename T>
00461 class Tensor : public CTensor<T>
00462 {
00463
00464 protected:
00465
00466
00467 public:
00468
00469 typedef T value_type;
00470 typedef T element_type;
00471 typedef T aligned_value_type TALIGN(MIN_ALIGN2);
00472
00473 Tensor () : CTensor <T> () {}
00474 Tensor (const unsigned dim_rank) : CTensor <T> (dim_rank) {}
00475 Tensor (const Index & ix) : CTensor <T> (ix) {}
00476 Tensor (const T & value, const Index & ix) : CTensor <T> (value, ix) {}
00477 Tensor (const Tensor <T>& ct) : CTensor <T> (ct) {}
00478 Tensor (vararg va, ...);
00479 Tensor (const T, vararg va, ...);
00480 ~Tensor () {}
00481
00482
00483 Tensor<T>& operator += (const Tensor<T> &);
00484 Tensor<T>& operator -= (const Tensor<T> &);
00485
00486 Tensor<T> operator + (const Tensor<T> &) const;
00487 Tensor<T> operator - (const Tensor<T> &) const;
00488
00489 Tensor<T>& operator *= (const T m) { this->data *= m; return *this; }
00490 Tensor<T>& operator /= (const T m) { this->data /= m; return *this; }
00491 Tensor<T>& operator += (const T m) { this->data += m; return *this; }
00492 Tensor<T>& operator -= (const T m) { this->data -= m; return *this; }
00493
00494 Tensor<T> operator * (const T m) const
00495 {
00496 Tensor<T> r (this->shape);
00497 for (unsigned long i = 0; i < this->noel; ++i)
00498 r.data(i) = this->data(i) * m;
00499 return r;
00500 }
00501
00502
00503
00504 Tensor<T> mult (const T) const;
00505
00506 Tensor<T> operator / (const T m) const
00507 {
00508 Tensor<T> r (this->shape);
00509 for (unsigned long i = 0; i < this->noel; ++i)
00510 r.data(i) = this->data(i) / m;
00511 return r;
00512 }
00513
00514 Tensor<T> operator - () const
00515 {
00516 Tensor<T> r (this->shape);
00517 for (unsigned long i=0; i < this->noel; ++i)
00518 r.data(i) = - this->data(i);
00519 return r;
00520 }
00521
00522
00523 Tensor<T> contract (const unsigned, const unsigned) const;
00524
00525 Tensor<T> drctmul (const Tensor<T>&) const;
00526 friend Tensor<T> FRIEND_TBCI2__ dctmul FGD (const Tensor<T>&, const Tensor<T>&);
00527
00528 Tensor<T> cntrmul (const Tensor<T>&, const unsigned, const unsigned) const;
00529 friend Tensor<T> FRIEND_TBCI2__ ctrmul FGD (const Tensor<T>&, const Tensor<T>&, const unsigned, const unsigned);
00530
00531 friend Tensor<T> FRIEND_TBCI2__ metrmul FGD (const Tensor<T>&, const Tensor<T>&, const unsigned, const unsigned);
00532
00533 };
00534
00535
00536
00537
00538
00539
00540 template < typename T >
00541 inline Tensor < T >::Tensor (const T value, vararg va, ...)
00542
00543 {
00544 this->rank = va;
00545 this->layout.resize ((unsigned)va);
00546 this->shape.resize ((unsigned)va);
00547 va_list vl;
00548 va_start (vl, va);
00549 for (unsigned i = 0; i < (unsigned)va; ++i)
00550 this->shape (i) = va_arg (vl, unsigned);
00551 va_end (vl);
00552 this->calcsize (); this->calclayout ();
00553 this->data.resize (value, this->noel);
00554 }
00555
00556
00557 template < typename T >
00558 inline Tensor <T>::Tensor (vararg va, ...)
00559
00560 {
00561 this->rank = va;
00562 this->layout.resize ((unsigned)va);
00563 this->shape.resize ((unsigned)va);
00564 va_list vl;
00565 va_start (vl, va);
00566 for (unsigned i = 0; i < this->rank; ++i)
00567 this->shape (i) = va_arg (vl, unsigned);
00568 va_end (vl);
00569 this->calcsize (); this->calclayout ();
00570 this->data.resize (this->noel);
00571 }
00572
00573
00574 template <typename T>
00575 Tensor<T> Tensor <T>::contract (const unsigned i1, const unsigned i2) const
00576 {
00577
00578 Index ix (idx_remove2 (this->shape, i1, i2));
00579 Tensor < T > t (0, ix);
00580
00581 BCHK (this->shape (i1) != this->shape (i2), TensErr, Contraction over diff. sized indices, this->shape (i2), t);
00582
00583 Index bx (0, ix.size());
00584 while (bx(0) < ix(0)) {
00585 unsigned long l = t.calc_offs (bx);
00586 for (unsigned m = 0; m < this->shape (i1); ++m)
00587 t.data (l) += (*this) (idx_fill_in2 (bx, i1, m, i2, m));
00588 bx.next_idx (ix);
00589 }
00590 return t;
00591 }
00592
00593 #if 1
00594 template <typename T>
00595 Tensor<T> Tensor<T>::cntrmul (const Tensor<T>& t2, const unsigned i1, const unsigned i2) const
00596 {
00597 BCHK(this->shape (i1) != t2.shape (i2), TensErr, CntrMul: Diff. sizes, t2.shape(i2), 0);
00598 Index sh2 (this->shape); sh2.append (t2.shape);
00599 Index ix (idx_remove2 (sh2, i1, i2 + this->rank));
00600
00601 Tensor <T> result (0, ix);
00602 Index ixr (0, result.rank);
00603
00604 while (ixr(0) < ix(0)) {
00605 unsigned long i = result.calc_offs (ixr);
00606 for (unsigned m = 0; m < this->shape (i1); ++m) {
00607 Index ix1 (idx_fill_in1 (ixr.slice(0, this->rank-1), i1, m));
00608 Index ix2 (idx_fill_in1 (ixr.slice(this->rank-1, result.rank), i2, m));
00609 result.data(i) += (*this) (ix1) * t2 (ix2);
00610 }
00611 ixr.next_idx (ix);
00612 }
00613 return result;
00614 }
00615
00616 #else
00617
00618 template <typename T>
00619 Tensor<T> Tensor<T>::cntrmul (const Tensor<T>& t2, const unsigned i1, const unsigned i2) const
00620 {
00621 BCHK(this->shape (i1) != t2.shape (i2), TensErr, CrtMul: Diff. sizes, t2.shape(i2), 0);
00622 Index ix (this->rank + t2.rank - 2);
00623 unsigned c = 0;
00624 {
00625 for (unsigned i = 0; i < this->rank; i++)
00626 if (i != i1)
00627 ix (c++) = this->shape (i);
00628 }
00629 {
00630 for (unsigned i = 0; i < t2.rank; i++) i
00631 if (i != i2)
00632 ix (c++) = t2.shape (i);
00633 }
00634
00635 Tensor <T> result (0, ix);
00636 Index ixr (result.rank);
00637 Index ix1 (this->rank);
00638 Index ix2 (t2.rank);
00639 for (unsigned long i = 0; i < result.noel; ++i) {
00640 ixr = result.calc_indx (i);
00641 for (unsigned m = 0; m < this->shape (i1); ++m) {
00642 c = 0;
00643 for (unsigned k = 0; k < this->rank; ++k) {
00644 if (k != i1)
00645 ix1 (k) = ixr (c++);
00646 else
00647 ix1 (k) = m;
00648 }
00649 for (unsigned l = 0; l < t2.rank; ++l) {
00650 if (l != i2)
00651 ix2 (l) = ixr (c++);
00652 else
00653 ix2 (l) = m;
00654 }
00655 result.data(i) += (*this)(ix1) * t2(ix2);
00656 }
00657 }
00658 return result;
00659 }
00660
00661 #endif
00662
00663
00664 template <typename T>
00665 Tensor<T> ctrmul (const Tensor<T>& t1, const Tensor<T>& t2, const unsigned i1, const unsigned i2)
00666 {
00667 BCHK(t1.shape (i1) != t2.shape (i2), TensErr, CtrMul: Diff. sizes, t2.shape(i2), 0);
00668 Index sh2 (t1.shape); sh2.append (t2.shape);
00669 Index ix (idx_remove2 (sh2, i1, i2 + t1.rank));
00670 Tensor < T > result (0, ix);
00671
00672 Index ixr (0, result.rank);
00673 while (ixr(0) < ix(0)) {
00674 unsigned long i = result.calc_offs (ixr);
00675 for (unsigned m = 0; m < t1.shape (i1); ++m) {
00676 result.data(i) += t1 (idx_fill_in1 (ixr.slice(0,t1.rank-1), i1, m))
00677 * t2 (idx_fill_in1 (ixr.slice(t1.rank-1,result.rank), i2, m));
00678 }
00679 ixr.next_idx (ix);
00680 }
00681 return result;
00682 }
00683
00684 template <typename T>
00685 Tensor<T> metrmul (const Tensor<T>& metr, const Tensor<T>& t, const unsigned i1, const unsigned i2)
00686 {
00687 BCHK(metr.shape (i1) != t.shape (i2), TensErr, MetrMul: Diff. sizes, t.shape(i2), 0);
00688 BCHK(metr.rank != 2, TensErr, Metric w/ rank != 2 ?, metr.rank, t);
00689 BCHKNR(metr.shape(0) != metr.shape(1), TensErr, Non-quadr. metric ?, metr.shape(i1));
00690
00691 Index ix (t.shape);
00692 Tensor < T > result (0, ix);
00693
00694 unsigned long io = 1 - i1;
00695
00696 Index ixr (0, result.rank);
00697 Index mix (2);
00698 while (ixr(0) < ix(0)) {
00699 unsigned long i = result.calc_offs (ixr);
00700 for (unsigned m = 0; m < metr.shape (i1); ++m) {
00701 mix (io) = ixr (i2); mix (i1) = m;
00702 result.data (i) += metr (mix) * t (idx_set1 (ixr, i2, m));
00703 }
00704 ixr.next_idx (ix);
00705 }
00706 return result;
00707 }
00708
00709 template <typename T>
00710 Tensor<T> Tensor<T>::drctmul (const Tensor<T> &t1) const
00711 {
00712 Index ix (t1.shape);
00713 ix.append (this->shape);
00714 Tensor < T > result (0, ix);
00715 Index ixr (0, result.rank);
00716 while (ixr(0) < ix(0)) {
00717 result (ixr) = (*this) (ixr.slice (0, this->rank))
00718 * t1 (ixr.slice (this->rank, result.rank));
00719 ixr.next_idx (ix);
00720 }
00721 return result;
00722 }
00723
00724
00725 template <typename T>
00726 Tensor<T> dctmul (const Tensor<T> &t0, const Tensor<T> &t1)
00727 {
00728 Index ix (t1.shape);
00729 ix.append (t0.shape);
00730 Tensor < T > result (0, ix);
00731 Index ixr (0, result.rank);
00732 while (ixr(0) < ix(0)) {
00733 result (ixr) = t0 (ixr.slice (0, t0.rank))
00734 * t1 (ixr.slice (t0.rank, result.rank));
00735 ixr.next_idx (ix);
00736 }
00737 return result;
00738 }
00739
00740 template <typename T>
00741 Tensor<T>& Tensor<T>::operator += (const Tensor<T>& t)
00742 {
00743 BCHK(this->shape!=t.shape, TensErr, Diff Tensor shape in op +=, t.noel, *this);
00744 if (this->layout == t.layout)
00745 for (unsigned long i = 0; i < this->noel; i++)
00746 this->data(i) += t.data(i);
00747 else {
00748 Index ix (0, this->rank);
00749 while (ix(0) < this->shape(0)) {
00750 (*this)(ix) += t(ix);
00751 ix.next_idx(this->shape);
00752 }
00753 }
00754 return *this;
00755 }
00756
00757 template <typename T>
00758 Tensor<T>& Tensor<T>::operator -= (const Tensor<T>& t)
00759 {
00760 BCHK(this->shape!=t.shape, TensErr, Diff Tensor shape in op -=, t.noel, *this);
00761 if (this->layout == t.layout)
00762 for (unsigned long i = 0; i < this->noel; i++)
00763 this->data(i) -= t.data(i);
00764 else {
00765 Index ix (0, this->rank);
00766 while (ix(0) < this->shape(0)) {
00767 (*this)(ix) -= t(ix);
00768 ix.next_idx(this->shape);
00769 }
00770 }
00771 return *this;
00772 }
00773
00774 template <typename T>
00775 Tensor<T> Tensor<T>::operator + (const Tensor<T>& t) const
00776 {
00777 Tensor<T> r (this->shape);
00778 BCHK(this->shape!=t.shape, TensErr, Diff Tensor shape in op +, t.noel, r);
00779 if (this->layout == t.layout)
00780 for (unsigned long i = 0; i < this->noel; i++)
00781 r.data(i) = this->data(i) + t.data(i);
00782 else {
00783 Index ix (0, this->rank);
00784 while (ix(0) < this->shape(0)) {
00785 r(ix) = (*this)(ix) + t(ix);
00786 ix.next_idx(this->shape);
00787 }
00788 }
00789 return r;
00790 }
00791
00792 template <typename T>
00793 Tensor<T> Tensor<T>::operator - (const Tensor<T>& t) const
00794 {
00795 Tensor<T> r (this->shape);
00796 BCHK(this->shape!=t.shape, TensErr, Diff Tensor shape in op -, t.noel, r);
00797 if (this->layout == t.layout)
00798 for (unsigned long i = 0; i < this->noel; i++)
00799 r.data(i) = this->data(i) - t.data(i);
00800 else {
00801 Index ix (0, this->rank);
00802 while (ix(0) < this->shape(0)) {
00803 r(ix) = (*this)(ix) - t(ix);
00804 ix.next_idx(this->shape);
00805 }
00806 }
00807 return r;
00808 }
00809
00810
00811 template <typename T>
00812 Tensor<T> Tensor<T>::mult (const T m) const
00813 {
00814 Tensor<T> res (this->shape);
00815 for (unsigned long i = 0; i < this->noel; ++i)
00816 res.data(i) = m * this->data(i);
00817 return res;
00818 }
00819
00820 INST(template <typename T> class Tensor friend Tensor<T> operator * (const T, const Tensor<T> &);)
00821 template <typename T>
00822 inline Tensor<T> operator * (const T m, const Tensor<T> &t)
00823 { return t.mult (m); }
00824
00825
00826 NAMESPACE_END
00827
00828 #endif