tensor-0.1.0
 All Data Structures Namespaces Functions Variables Typedefs Enumerations Enumerator Groups Pages
tensor.h
1 // -*- mode: c++; fill-column: 80; c-basic-offset: 2; indent-tabs-mode: nil -*-
2 /*
3  Copyright (c) 2010 Juan Jose Garcia Ripoll
4 
5  Tensor is free software; you can redistribute it and/or modify it
6  under the terms of the GNU Library General Public License as published
7  by the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU Library General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License along
16  with this program; if not, write to the Free Software Foundation, Inc.,
17  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 
20 
21 #ifndef TENSOR_TENSOR_H
22 #define TENSOR_TENSOR_H
23 
24 #include <cassert>
25 #include <vector>
26 #include <tensor/numbers.h>
27 #include <tensor/vector.h>
28 #include <tensor/gen.h>
29 #include <tensor/indices.h>
30 #include <tensor/detail/functional.h>
31 
32 namespace tensor {
33 
35 // BASE CLASS
36 //
37 
39 /* @{ */
46 template<typename elt>
47 class Tensor {
48  public:
49  typedef elt elt_t;
50  typedef elt_t *iterator;
51  typedef const elt_t *const_iterator;
52 
54  Tensor();
55 
57  explicit Tensor(const Indices &new_dims);
58 
60  Tensor(const Indices &new_dims, const Tensor<elt_t> &data);
61 
63  Tensor(const Vector<elt_t> &data);
64 
66  Tensor(const std::vector<elt_t> &data) :
67  data_(data.size()), dims_(1)
68  {
69  dims_.at(0) = data.size();
70  std::copy(data.begin(), data.end(), begin());
71  }
72 
74  Tensor(const Tensor &other);
75 
77  template<typename e2> Tensor(const Tensor<e2> &other) :
78  data_(other.size()), dims_(other.dimensions())
79  {
80  std::copy(other.begin(), other.end(), begin());
81  }
82 
84  template<size_t n> Tensor(const StaticVector<elt_t,n> &t) :
85  data_(t), dims_(igen << t.size())
86  {}
87 
89  template<size_t n> Tensor(const StaticVector<elt_t,n> &t, const Indices &d) :
90  data_(t), dims_(d)
91  {
92  assert(data_.size() == d.total_size());
93  }
94 
96  explicit Tensor(index length);
98  Tensor(index rows, index cols);
100  Tensor(index d1, index d2, index d3);
102  Tensor(index d1, index d2, index d3, index d4);
104  Tensor(index d1, index d2, index d3, index d4, index d5);
106  Tensor(index d1, index d2, index d3, index d4, index d5, index d6);
107 
108  operator Vector<elt_t>() const { return data_; }
109 
111  const Tensor &operator=(const Tensor<elt_t> &other);
112 
114  index size() const { return data_.size(); }
116  bool is_empty() const { return size() == 0; }
117 
119  int rank() const { return dims_.size(); }
121  const Indices &dimensions() const { return dims_; }
123  index dimension(int which) const;
125  void get_dimensions(index *length) const;
127  void get_dimensions(index *rows, index *cols) const;
129  void get_dimensions(index *d0, index *d1, index *d2) const;
131  void get_dimensions(index *d0, index *d1, index *d2, index *d3) const;
133  void get_dimensions(index *d0, index *d1, index *d2, index *d3, index *d4) const;
135  void get_dimensions(index *d0, index *d1, index *d2, index *d3, index *d4, index *d5) const;
137  index columns() const { return dimension(1); }
139  index rows() const { return dimension(0); }
140 
142  void reshape(const Indices &new_dims);
143 
145  const elt_t &operator[](index i) const;
147  const elt_t &operator()(index i) const;
149  const elt_t &operator()(index row, index col) const;
151  const elt_t &operator()(index d0, index d1, index d2) const;
153  const elt_t &operator()(index d0, index d1, index d2, index d3) const;
155  const elt_t &operator()(index d0, index d1, index d2, index d3, index d4) const;
157  const elt_t &operator()(index d0, index d1, index d2, index d3, index d4, index d5w) const;
158 
160  elt_t &at_seq(index i);
162  elt_t &at(index i);
164  elt_t &at(index row, index col);
166  elt_t &at(index d1, index d2, index d3);
168  elt_t &at(index d1, index d2, index d3, index d4);
170  elt_t &at(index d1, index d2, index d3, index d4, index d5);
172  elt_t &at(index d1, index d2, index d3, index d4, index d5, index d6);
173 
175  void fill_with(const elt_t &e);
177  void fill_with_zeros() { fill_with(number_zero<elt_t>()); }
179  void randomize();
180 
182  static const Tensor<elt_t> random(index length);
184  static const Tensor<elt_t> random(index rows, index cols);
186  static const Tensor<elt_t> random(index d1, index d2, index d3);
188  static const Tensor<elt_t> random(index d1, index d2, index d3, index d4);
190  static const Tensor<elt_t> random(index d1, index d2, index d3, index d4, index d5);
192  static const Tensor<elt_t> random(index d1, index d2, index d3, index d4, index d5, index d6);
194  static const Tensor<elt_t> random(const Indices &dimensions);
195 
196  //
197  // Tensor slicing
198  //
199  class view;
201  const view operator()(PRange r) const;
203  const view operator()(PRange r1, PRange r2) const;
205  const view operator()(PRange r1, PRange r2, PRange r3) const;
207  const view operator()(PRange r1, PRange r2, PRange r3, PRange r4) const;
209  const view operator()(PRange r1, PRange r2, PRange r3, PRange r4, PRange r5) const;
211  const view operator()(PRange r1, PRange r2, PRange r3, PRange r4, PRange r5, PRange r6) const;
212 
213  class mutable_view;
215  mutable_view at(PRange r);
217  mutable_view at(PRange r1, PRange r2);
219  mutable_view at(PRange r1, PRange r2, PRange r3);
221  mutable_view at(PRange r1, PRange r2, PRange r3, PRange r4);
223  mutable_view at(PRange r1, PRange r2, PRange r3, PRange r4, PRange r5);
225  mutable_view at(PRange r1, PRange r2, PRange r3, PRange r4, PRange r5, PRange r6);
226 
227  //
228  // Matrix operations
229  //
231  static const Tensor<elt_t> eye(index rows) { return eye(rows, rows); }
233  static const Tensor<elt_t> eye(index rows, index cols);
235  static const Tensor<elt_t> zeros(index rows) { return zeros(rows, rows); }
237  static const Tensor<elt_t> zeros(index rows, index cols);
239  static const Tensor<elt_t> zeros(index d1, index d2, index d3);
241  static const Tensor<elt_t> zeros(index d1, index d2, index d3, index d4);
243  static const Tensor<elt_t> zeros(index d1, index d2, index d3, index d4, index d5);
245  static const Tensor<elt_t> zeros(index d1, index d2, index d3, index d4, index d5, index d6);
247  static const Tensor<elt_t> zeros(const Indices &dimensions);
249  static const Tensor<elt_t> ones(index rows) { return ones(rows, rows); }
251  static const Tensor<elt_t> ones(index rows, index cols);
253  static const Tensor<elt_t> ones(const Indices &dimensions);
254 
256  iterator begin() { return data_.begin(); }
258  const_iterator begin() const { return data_.begin_const(); }
260  const_iterator begin_const() const { return data_.begin_const(); }
262  const_iterator end_const() const { return data_.end_const(); }
264  const_iterator end() const { return data_.end_const(); }
266  iterator end() { return data_.end(); }
267 
268  // Only for testing purposes
269  int ref_count() const { return data_.ref_count(); }
270 
272  const Tensor<elt_t> diag(int which = 0, int ndx1 = 0, int ndx2 = -1) {
273  return take_diag(*this, which, ndx1, ndx2);
274  }
275 
276  private:
277  Vector<elt_t> data_;
278  Indices dims_;
279 };
280 
282 // ALGEBRA
283 //
284 //
285 // Unary operations
286 //
287 template<typename t>
288 Tensor<t> operator-(const Tensor<t> &);
289 
290 //
291 // Binary operations
292 //
293 template<typename t1, typename t2>
294 Tensor<typename Binop<t1,t2>::type> operator+(const Tensor<t1> &a, const Tensor<t2> &b);
295 template<typename t1, typename t2>
296 Tensor<typename Binop<t1,t2>::type> operator-(const Tensor<t1> &a, const Tensor<t2> &b);
297 template<typename t1, typename t2>
298 Tensor<typename Binop<t1,t2>::type> operator*(const Tensor<t1> &a, const Tensor<t2> &b);
299 template<typename t1, typename t2>
300 Tensor<typename Binop<t1,t2>::type> operator/(const Tensor<t1> &a, const Tensor<t2> &b);
301 
302 template<typename t1, typename t2>
303 Tensor<typename Binop<t1,t2>::type> operator+(const Tensor<t1> &a, const t2 &b);
304 template<typename t1, typename t2>
305 Tensor<typename Binop<t1,t2>::type> operator-(const Tensor<t1> &a, const t2 &b);
306 template<typename t1, typename t2>
307 Tensor<typename Binop<t1,t2>::type> operator*(const Tensor<t1> &a, const t2 &b);
308 template<typename t1, typename t2>
309 Tensor<typename Binop<t1,t2>::type> operator/(const Tensor<t1> &a, const t2 &b);
310 
311 template<typename t1, typename t2>
312 Tensor<typename Binop<t1,t2>::type> operator+(const t1 &a, const Tensor<t2> &b);
313 template<typename t1, typename t2>
314 Tensor<typename Binop<t1,t2>::type> operator-(const t1 &a, const Tensor<t2> &b);
315 template<typename t1, typename t2>
316 Tensor<typename Binop<t1,t2>::type> operator*(const t1 &a, const Tensor<t2> &b);
317 template<typename t1, typename t2>
318 Tensor<typename Binop<t1,t2>::type> operator/(const t1 &a, const Tensor<t2> &b);
319 
320  template<typename elt_t>
321  const Tensor<elt_t> kron(const Tensor<elt_t> &a, const Tensor<elt_t> &b);
322  template<typename elt_t>
323  const Tensor<elt_t> kron2(const Tensor<elt_t> &a, const Tensor<elt_t> &b);
324  template<typename elt_t>
325  const Tensor<elt_t> kron2_sum(const Tensor<elt_t> &a, const Tensor<elt_t> &b);
326 
327 } // namespace tensor
328 
330 // IMPLEMENTATIONS
331 //
332 #ifdef TENSOR_LOAD_IMPL
333 #include <tensor/detail/tensor_base.hpp>
334 #include <tensor/detail/tensor_matrix.hpp>
335 #include <tensor/detail/tensor_kron.hpp>
336 #endif
337 #include <tensor/detail/tensor_slice.hpp>
338 #include <tensor/detail/tensor_ops.hpp>
339 
341 // EXPLICIT INSTANTIATIONS
342 //
343 
344 namespace tensor {
345 
346  extern template class Tensor<double>;
348 #ifdef DOXYGEN_ONLY
349  struct RTensor : public Tensor<double> {}
350 #else
351  typedef Tensor<double> RTensor;
352 #endif
353 
354  const RTensor change_dimension(const RTensor &U, int dimension, index new_size);
355 
356  double sum(const RTensor &r);
357  double mean(const RTensor &r);
358  const RTensor mean(const RTensor &r, int which);
359 
360  double norm0(const RTensor &r);
361  double scprod(const RTensor &a, const RTensor &b);
362  double norm2(const RTensor &r);
363  double matrix_norminf(const RTensor &r);
364 
365  RTensor abs(const RTensor &t);
366  RTensor cos(const RTensor &t);
367  RTensor sin(const RTensor &t);
368  RTensor tan(const RTensor &t);
369  RTensor cosh(const RTensor &t);
370  RTensor sinh(const RTensor &t);
371  RTensor tanh(const RTensor &t);
372  RTensor exp(const RTensor &t);
373  RTensor sqrt(const RTensor &t);
374 
375  RTensor round(const RTensor &t);
376 
377  const RTensor diag(const RTensor &d, int which, int rows, int cols);
378  const RTensor diag(const RTensor &d, int which = 0);
379  const RTensor take_diag(const RTensor &d, int which = 0, int ndx1 = 0, int ndx2 = -1);
380  double trace(const RTensor &d);
381  const RTensor trace(const RTensor &A, index i1, index i2);
382 
383  const RTensor reshape(const RTensor &t, const Indices &new_dims);
384  const RTensor reshape(const RTensor &t, index length);
385  const RTensor reshape(const RTensor &t, index rows, index columns);
386  const RTensor reshape(const RTensor &t, index d1, index d2, index d3);
387  const RTensor reshape(const RTensor &t, index d1, index d2, index d3, index d4);
388  const RTensor reshape(const RTensor &t, index d1, index d2, index d3, index d4, index d5);
389  const RTensor reshape(const RTensor &t, index d1, index d2, index d3, index d4, index d5, index d6);
390 
391  const RTensor squeeze(const RTensor &t);
392  const RTensor permute(const RTensor &a, index ndx1 = 0, index ndx2 = -1);
393  const RTensor transpose(const RTensor &a);
394  inline const RTensor adjoint(const RTensor &a) { return transpose(a); }
395 
396  const RTensor fold(const RTensor &a, int ndx1, const RTensor &b, int ndx2);
397  const RTensor foldc(const RTensor &a, int ndx1, const RTensor &b, int ndx2);
398  const RTensor foldin(const RTensor &a, int ndx1, const RTensor &b, int ndx2);
399  const RTensor mmult(const RTensor &a, const RTensor &b);
400 
401  void fold_into(RTensor &output, const RTensor &a, int ndx1, const RTensor &b, int ndx2);
402  void foldin_into(RTensor &output, const RTensor &a, int ndx1, const RTensor &b, int ndx2);
403  void mmult_into(RTensor &output, const RTensor &a, const RTensor &b);
404 
405  bool all_equal(const RTensor &a, const RTensor &b);
406  bool all_equal(const RTensor &a, double b);
407  inline bool all_equal(double b, const RTensor &a) { return all_equal(a, b); }
408  template<typename t1, typename t2>
409  inline bool some_unequal(const t1 &a, const t2 &b) { return !all_equal(a,b); }
410 
411  const Booleans operator==(const RTensor &a, const RTensor &b);
412  const Booleans operator<(const RTensor &a, const RTensor &b);
413  const Booleans operator>(const RTensor &a, const RTensor &b);
414  const Booleans operator<=(const RTensor &a, const RTensor &b);
415  const Booleans operator>=(const RTensor &a, const RTensor &b);
416  const Booleans operator!=(const RTensor &a, const RTensor &b);
417 
418  const Booleans operator==(const RTensor &a, double b);
419  const Booleans operator<(const RTensor &a, double b);
420  const Booleans operator>(const RTensor &a, double b);
421  const Booleans operator<=(const RTensor &a, double b);
422  const Booleans operator>=(const RTensor &a, double b);
423  const Booleans operator!=(const RTensor &a, double b);
424 
425  inline const Booleans operator==(double a, const RTensor &b) { return b == a; }
426  inline const Booleans operator<(double a, const RTensor &b) { return b >= a; }
427  inline const Booleans operator>(double a, const RTensor &b) { return b <= a; }
428  inline const Booleans operator<=(double a, const RTensor &b) { return b > a; }
429  inline const Booleans operator>=(double a, const RTensor &b) { return b < a; }
430  inline const Booleans operator!=(double a, const RTensor &b) { return b != a; }
431 
432  extern template class Tensor<cdouble>;
434 #ifdef DOXYGEN_ONLY
435  struct CTensor : public Tensor<cdouble> {}
436 #else
437  typedef Tensor<cdouble> CTensor;
438 #endif
439 
440  const CTensor change_dimension(const CTensor &U, int dimension, index new_size);
441 
442  cdouble sum(const CTensor &r);
443  cdouble mean(const CTensor &r);
444  const CTensor mean(const CTensor &r, int ndx);
445 
446  double norm0(const CTensor &r);
447  cdouble scprod(const CTensor &a, const CTensor &b);
448  double norm2(const CTensor &r);
449  double matrix_norminf(const CTensor &r);
450 
451  inline const RTensor real(const RTensor &r) { return r; }
452  const RTensor imag(const RTensor &r);
453  const RTensor real(const CTensor &r);
454  const RTensor imag(const CTensor &r);
455 
456  const CTensor to_complex(const RTensor &r);
457  inline const CTensor to_complex(const CTensor &r) { return r; }
458  const CTensor to_complex(const RTensor &r, const RTensor &i);
459 
461  inline const RTensor conj(const RTensor &r) { return r; }
462  const CTensor conj(const CTensor &c);
463 
464  RTensor abs(const CTensor &t);
465  CTensor cos(const CTensor &t);
466  CTensor sin(const CTensor &t);
467  CTensor tan(const CTensor &t);
468  CTensor cosh(const CTensor &t);
469  CTensor sinh(const CTensor &t);
470  CTensor tanh(const CTensor &t);
471  CTensor exp(const CTensor &t);
472  CTensor sqrt(const CTensor &t);
473 
474  const CTensor diag(const CTensor &d, int which, int rows, int cols);
475  const CTensor diag(const CTensor &d, int which = 0);
476  const CTensor take_diag(const CTensor &d, int which = 0, int ndx1 = 0, int ndx2 = -1);
477  cdouble trace(const CTensor &d);
478  const CTensor trace(const CTensor &A, index i1, index i2);
479 
480  const CTensor reshape(const CTensor &t, const Indices &new_dims);
481  const CTensor reshape(const CTensor &t, index length);
482  const CTensor reshape(const CTensor &t, index rows, index columns);
483  const CTensor reshape(const CTensor &t, index d1, index d2, index d3);
484  const CTensor reshape(const CTensor &t, index d1, index d2, index d3, index d4);
485  const CTensor reshape(const CTensor &t, index d1, index d2, index d3, index d4, index d5);
486  const CTensor reshape(const CTensor &t, index d1, index d2, index d3, index d4, index d5, index d6);
487 
488  const CTensor squeeze(const CTensor &t);
489  const CTensor permute(const CTensor &a, index ndx1 = 0, index ndx2 = -1);
490  const CTensor transpose(const CTensor &a);
491  const CTensor adjoint(const CTensor &a);
492 
493  const CTensor fold(const CTensor &a, int ndx1, const CTensor &b, int ndx2);
494  const CTensor fold(const RTensor &a, int ndx1, const CTensor &b, int ndx2);
495  const CTensor fold(const CTensor &a, int ndx1, const RTensor &b, int ndx2);
496 
497  const CTensor foldc(const CTensor &a, int ndx1, const CTensor &b, int ndx2);
498  const CTensor foldc(const RTensor &a, int ndx1, const CTensor &b, int ndx2);
499  const CTensor foldc(const CTensor &a, int ndx1, const RTensor &b, int ndx2);
500 
501  const CTensor mmult(const CTensor &a, const CTensor &b);
502  const CTensor mmult(const RTensor &a, const CTensor &b);
503  const CTensor mmult(const CTensor &a, const RTensor &b);
504 
505  const RTensor scale(const RTensor &t, int ndx1, const RTensor &v);
506  const CTensor scale(const CTensor &t, int ndx1, const CTensor &v);
507  const CTensor scale(const CTensor &t, int ndx1, const RTensor &v);
508  void scale_inplace(RTensor &t, int ndx1, const RTensor &v);
509  void scale_inplace(CTensor &t, int ndx1, const CTensor &v);
510  void scale_inplace(CTensor &t, int ndx1, const RTensor &v);
511 
512  const CTensor foldin(const CTensor &a, int ndx1, const CTensor &b, int ndx2);
513 
514  const RTensor linspace(double min, double max, index n = 100);
515  const RTensor linspace(const RTensor &min, const RTensor &max, index n = 100);
516  const CTensor linspace(cdouble min, cdouble max, index n = 100);
517  const CTensor linspace(const CTensor &min, const CTensor &max, index n = 100);
518 
519  const RTensor sort(const RTensor &v, bool reverse = false);
520  const Indices sort_indices(const RTensor &v, bool reverse = false);
521 
522  const CTensor sort(const CTensor &v, bool reverse = false);
523  const Indices sort_indices(const CTensor &v, bool reverse = false);
524 
525  bool all_equal(const CTensor &a, const CTensor &b);
526  bool all_equal(const CTensor &a, const cdouble &b);
527  inline bool all_equal(cdouble b, const CTensor &a) { return all_equal(a, b); }
528 
529  const Booleans operator==(const CTensor &a, const CTensor &b);
530  const Booleans operator!=(const CTensor &a, const CTensor &b);
531  const Booleans operator==(const CTensor &a, cdouble b);
532  const Booleans operator!=(const CTensor &a, cdouble b);
533  inline const Booleans operator==(cdouble a, const CTensor &b) { return b == a; }
534  inline const Booleans operator!=(cdouble a, const CTensor &b) { return b != a; }
535 
536 } // namespace tensor
537 
538 /* @} */
539 
540 #endif // !TENSOR_H
const Tensor & operator=(const Tensor< elt_t > &other)
Assignment operator.
void randomize()
Fills with random numbers.
int rank() const
Number of Tensor indices.
Definition: tensor.h:119
Tensor(const StaticVector< elt_t, n > &t)
Create a one-dimensional tensor from data created with "gen" expressions.
Definition: tensor.h:84
const CTensor reshape(const CTensor &t, index d1, index d2, index d3, index d4, index d5, index d6)
Return a CTensor with same data and given dimensions.
Tensor(const Tensor< e2 > &other)
Implicit coercion.
Definition: tensor.h:77
Tensor()
Constructs an empty Tensor.
An N-dimensional array of numbers.
Definition: tensor.h:47
const CTensor linspace(const CTensor &min, const CTensor &max, index n=100)
Tensor of 'n' equally spaced vectors in the interval [min, max].
Definition: linspace_z.cc:36
index columns() const
Query the size of 2nd index.
Definition: tensor.h:137
static const Tensor< elt_t > eye(index rows)
Identity matrix.
Definition: tensor.h:231
static const Tensor< elt_t > zeros(index rows)
Matrix of zeros.
Definition: tensor.h:235
iterator end()
Iterator at the end.
Definition: tensor.h:266
index rows() const
Query then size of 1st index.
Definition: tensor.h:139
Real Tensor with elements of type "double".
Definition: tensor.h:349
const_iterator begin_const() const
Iterator at the beginning for const objects.
Definition: tensor.h:260
void fill_with_zeros()
Fill with zeros.
Definition: tensor.h:177
bool is_empty() const
Does the tensor have elements?
Definition: tensor.h:116
iterator begin()
Iterator at the beginning.
Definition: tensor.h:256
static const Tensor< elt_t > ones(index rows)
Matrix of ones.
Definition: tensor.h:249
Complex Tensor with elements of type "cdouble".
Definition: tensor.h:435
static const Tensor< elt_t > random(index length)
Build a random 1D Tensor.
const_iterator begin() const
Iterator at the beginning.
Definition: tensor.h:258
index size() const
Returns total number of elements in Tensor.
Definition: tensor.h:114
Vector of 'index' type, where 'index' fits the indices of a tensor.
Definition: indices.h:35
const_iterator end_const() const
Iterator at the end for const objects.
Definition: tensor.h:262
Tensor(const std::vector< elt_t > &data)
Constructs a 1-D Tensor from a vector.
Definition: tensor.h:66
void fill_with(const elt_t &e)
Fill with an element.
index dimension(int which) const
Length of a given Tensor index.
Tensor(const StaticVector< elt_t, n > &t, const Indices &d)
Create a general tensor from data created with "gen" expressions.
Definition: tensor.h:89
void reshape(const Indices &new_dims)
Change the dimensions, while keeping the data.
const CTensor squeeze(const CTensor &t)
Eliminate all singleton dimensions from a tensor, preserving the data.
const elt_t & operator()(index i) const
Return an element of a 1D Tensor.
const Indices & dimensions() const
Return Tensor dimensions.
Definition: tensor.h:121
elt_t & at_seq(index i)
Return a mutable reference to the i-th element of a Tensor, in column major order.
void get_dimensions(index *length) const
Query dimensions of 1D Tensor.
const_iterator end() const
Iterator at the end for const objects.
Definition: tensor.h:264
const CTensor take_diag(const CTensor &d, int which=0, int ndx1=0, int ndx2=-1)
Extract a diagonal from a matrix or tensor.
const elt_t & operator[](index i) const
Return the i-th element, accessed in column major order.
elt_t & at(index i)
Return a mutable reference to an element of a 1D Tensor.
const Tensor< elt_t > diag(int which=0, int ndx1=0, int ndx2=-1)
Take a diagonal from a tensor.
Definition: tensor.h:272