v0.7.2
Tensor4_value.hpp
Go to the documentation of this file.
1 /* A general version, not for pointers. */
2 
3 #include <ostream>
4 
5 #ifdef FTENSOR_DEBUG
6 #include <sstream>
7 #include <stdexcept>
8 #endif
9 
10 #pragma once
11 
12 namespace FTensor
13 {
14  template<class T,int Tensor_Dim0,int Tensor_Dim1,int Tensor_Dim2,int Tensor_Dim3>
15  class Tensor4
16  {
17  T data[Tensor_Dim0][Tensor_Dim1][Tensor_Dim2][Tensor_Dim3];
18  public:
19  /* Initialization operators
20  * TODO revisit this operators*/
21  Tensor4(T d0000, T d0001, T d0002, T d0010, T d0011, T d0012, T d0020, T d0021, T d0022,
22  T d0100, T d0101, T d0102, T d0110, T d0111, T d0112, T d0120, T d0121, T d0122,
23  T d0200, T d0201, T d0202, T d0210, T d0211, T d0212, T d0220, T d0221, T d0222,
24  T d1000, T d1001, T d1002, T d1010, T d1011, T d1012, T d1020, T d1021, T d1022,
25  T d1100, T d1101, T d1102, T d1110, T d1111, T d1112, T d1120, T d1121, T d1122,
26  T d1200, T d1201, T d1202, T d1210, T d1211, T d1212, T d1220, T d1221, T d1222,
27  T d2000, T d2001, T d2002, T d2010, T d2011, T d2012, T d2020, T d2021, T d2022,
28  T d2100, T d2101, T d2102, T d2110, T d2111, T d2112, T d2120, T d2121, T d2122,
29  T d2200, T d2201, T d2202, T d2210, T d2211, T d2212, T d2220, T d2221, T d2222)
30  {
31  data[0][0][0][0]=d0000;data[0][0][0][1]=d0001;data[0][0][0][2]=d0002;data[0][0][1][0]=d0010;data[0][0][1][1]=d0011;data[0][0][1][2]=d0012;data[0][0][2][0]=d0020;data[0][0][2][1]=d0021;data[0][0][2][2]=d0022;
32  data[0][1][0][0]=d0100;data[0][1][0][1]=d0101;data[0][1][0][2]=d0102;data[0][1][1][0]=d0110;data[0][1][1][1]=d0111;data[0][1][1][2]=d0112;data[0][1][2][0]=d0120;data[0][1][2][1]=d0121;data[0][1][2][2]=d0122;
33  data[0][2][0][0]=d0200;data[0][2][0][1]=d0201;data[0][2][0][2]=d0202;data[0][2][1][0]=d0210;data[0][2][1][1]=d0211;data[0][2][1][2]=d0212;data[0][2][2][0]=d0220;data[0][2][2][1]=d0221;data[0][2][2][2]=d0222;
34  data[1][0][0][0]=d1000;data[1][0][0][1]=d1001;data[1][0][0][2]=d1002;data[1][0][1][0]=d1010;data[1][0][1][1]=d1011;data[1][0][1][2]=d1012;data[1][0][2][0]=d1020;data[1][0][2][1]=d1021;data[1][0][2][2]=d1022;
35  data[1][1][0][0]=d1100;data[1][1][0][1]=d1101;data[1][1][0][2]=d1102;data[1][1][1][0]=d1110;data[1][1][1][1]=d1111;data[1][1][1][2]=d1112;data[1][1][2][0]=d1120;data[1][1][2][1]=d1121;data[1][1][2][2]=d1122;
36  data[1][2][0][0]=d1200;data[1][2][0][1]=d1201;data[1][2][0][2]=d1202;data[1][2][1][0]=d1210;data[1][2][1][1]=d1211;data[1][2][1][2]=d1212;data[1][2][2][0]=d1220;data[1][2][2][1]=d1221;data[1][2][2][2]=d1222;
37  data[2][0][0][0]=d2000;data[2][0][0][1]=d2001;data[2][0][0][2]=d2002;data[2][0][1][0]=d2010;data[2][0][1][1]=d2011;data[2][0][1][2]=d2012;data[2][0][2][0]=d2020;data[2][0][2][1]=d2021;data[2][0][2][2]=d2022;
38  data[2][1][0][0]=d2100;data[2][1][0][1]=d2101;data[2][1][0][2]=d2102;data[2][1][1][0]=d2110;data[2][1][1][1]=d2111;data[2][1][1][2]=d2112;data[2][1][2][0]=d2120;data[2][1][2][1]=d2121;data[2][1][2][2]=d2122;
39  data[2][2][0][0]=d2200;data[2][2][0][1]=d2201;data[2][2][0][2]=d2202;data[2][2][1][0]=d2210;data[2][2][1][1]=d2211;data[2][2][1][2]=d2212;data[2][2][2][0]=d2220;data[2][2][2][1]=d2221;data[2][2][2][2]=d2222;
40  }
41  Tensor4() {}
42  /* There are two operator(int,int,int,int)'s, one for non-consts
43  that lets you change the value, and one for consts that
44  doesn't. */
45  T & operator()(const int N1,const int N2,const int N3,const int N4)
46  {
47 #ifdef FTENSOR_DEBUG
48  if(N1>=Tensor_Dim0 || N1<0 || N2>=Tensor_Dim1 || N2<0
49  || N3>=Tensor_Dim2 || N3<0 || N4>=Tensor_Dim3 || N4<0)
50  {
51  std::stringstream s;
52  s << "Bad index in Tensor4<T,"
53  << Tensor_Dim0 << "," << Tensor_Dim1 << "," << Tensor_Dim2 << "," << Tensor_Dim3
54  << ">.operator("
55  << N1 << "," << N2 << "," << N3 << "," << N4
56  << ") const"
57  << std::endl;
58  throw std::runtime_error(s.str());
59  }
60 #endif
61  return data[N1][N2][N3][N4];
62  }
63 
64  T operator()(const int N1,const int N2,const int N3,const int N4)
65  const
66  {
67 #ifdef FTENSOR_DEBUG
68  if(N1>=Tensor_Dim0 || N1<0 || N2>=Tensor_Dim1 || N2<0
69  || N3>=Tensor_Dim2 || N3<0 || N4>=Tensor_Dim3 || N4<0)
70  {
71  std::stringstream s;
72  s << "Bad index in Tensor4<T,"
73  << Tensor_Dim0 << "," << Tensor_Dim1 << "," << Tensor_Dim2 << "," << Tensor_Dim3
74  << ">.operator("
75  << N1 << "," << N2 << "," << N3 << "," << N4 << ")"
76  << std::endl;
77  throw std::runtime_error(s.str());
78  }
79 #endif
80  return data[N1][N2][N3][N4];
81  }
82 
83  /* These operator()'s are the first part in constructing template
84  expressions. They can be used to slice off lower dimensional
85  parts. */
86 
87  template<char i,char j,char k,char l,int Dim0,int Dim1,int Dim2,int Dim3>
88  typename std::enable_if<(Tensor_Dim0 >= Dim0 && Tensor_Dim1 >= Dim1 && Tensor_Dim2 >= Dim2 && Tensor_Dim3 >= Dim3),
90  T,Dim0,Dim1,Dim2,Dim3,i,j,k,l> >::type
91  operator()(const Index<i,Dim0> , const Index<j,Dim1> ,
92  const Index<k,Dim2> , const Index<l,Dim3>)
93  {
95  T,Dim0,Dim1,Dim2,Dim3,i,j,k,l> (*this);
96  };
97 
98  template<char i,char j,char k,char l,int Dim0,int Dim1,int Dim2,int Dim3>
99  typename std::enable_if<(Tensor_Dim0 >= Dim0 && Tensor_Dim1 >= Dim1 && Tensor_Dim2 >= Dim2 && Tensor_Dim3 >= Dim3),
101  T,Dim0,Dim1,Dim2,Dim3,i,j,k,l> >::type
102  operator()(const Index<i,Dim0> , const Index<j,Dim1> ,
103  const Index<k,Dim2> , const Index<l,Dim3>) const
104  {
106  T,Dim0,Dim1,Dim2,Dim3,i,j,k,l> (*this);
107  };
108 
109  /* These operators are for internal contractions, resulting in a Tensor2.
110  * For example something like A(k,i,k,j) */
111 
112 
113  template<char i,char j,char k,int Dim02,int Dim1,int Dim3>
114  inline
115  typename std::enable_if<(Tensor_Dim0 >= Dim02 && Tensor_Dim1 >= Dim1 && Tensor_Dim2 >= Dim02 && Tensor_Dim3 >= Dim3),
117  T,Dim02>,T,Dim1,Dim3,i,j> >::type
118  operator()(const Index<k,Dim02> , const Index<i,Dim1> ,
119  const Index<k,Dim02> , const Index<j,Dim3>) const
120  {
122  return Tensor2_Expr<TensorExpr,T,Dim1,Dim3,i,j>(TensorExpr(*this));
123  };
124 
125 
126  /* This is for expressions where a number is used for one slot, and
127  an index for another, yielding a Tensor3_Expr. The non-const
128  versions don't actually create a Tensor3_number_rhs_[0123] object.
129  They create a Tensor3_Expr directly, which provides the
130  appropriate indexing operators. The const versions do create a
131  Tensor3_number_[0123]. */
132  // TODO
133 
134  };
135 }
136 
137 /// JSON compatible output
138 
139 namespace FTensor
140 {
141  template<class T,int Tensor_Dim0,int Tensor_Dim1,int Tensor_Dim2,int Tensor_Dim3>
142  std::ostream & Tensor4_0001(std::ostream &os,
144  const int &iterator0,
145  const int &iterator1,
146  const int &iterator2)
147  {
148  os << '[';
149  for (int i = 0; i < Tensor_Dim3-1; ++i) {
150  os << t(iterator0,iterator1,iterator2,i);
151  os << ',';
152  }
153  os << t(iterator0,iterator1,iterator2,Tensor_Dim3-1);
154  os << ']';
155 
156  return os;
157  }
158 
159  template<class T,int Tensor_Dim0,int Tensor_Dim1,int Tensor_Dim2,int Tensor_Dim3>
160  std::ostream & Tensor4_0010(std::ostream &os,
162  const int &iterator0,
163  const int &iterator1)
164  {
165  os << '[';
166  for (int i = 0; i < Tensor_Dim2-1; ++i) {
167  FTensor::Tensor4_0001(os, t, iterator0, iterator1, i);
168  os << ',';
169  }
170  FTensor::Tensor4_0001(os, t, iterator0, iterator1, Tensor_Dim2-1);
171  os << ']';
172 
173  return os;
174  }
175 
176  template<class T,int Tensor_Dim0,int Tensor_Dim1,int Tensor_Dim2,int Tensor_Dim3>
177  std::ostream & Tensor4_0100(std::ostream &os,
179  const int &iterator0)
180  {
181  os << '[';
182  for (int i = 0; i < Tensor_Dim1-1; ++i) {
183  FTensor::Tensor4_0010(os, t, iterator0, i);
184  os << ',';
185  }
186  FTensor::Tensor4_0010(os, t, iterator0, Tensor_Dim1-1);
187  os << ']';
188 
189  return os;
190  }
191 
192 }
193 
194 template<class T,int Tensor_Dim0,int Tensor_Dim1,int Tensor_Dim2,int Tensor_Dim3>
195 std::ostream & operator<<(std::ostream &os,
197 {
198  os << '[';
199  for (int i = 0; i < Tensor_Dim0-1; ++i) {
200  FTensor::Tensor4_0100(os, t, i);
201  os << ',';
202  }
203  FTensor::Tensor4_0100(os, t, Tensor_Dim0-1);
204  os << ']';
205 
206  return os;
207 }
std::ostream & Tensor4_0010(std::ostream &os, const Tensor4< T, Tensor_Dim0, Tensor_Dim1, Tensor_Dim2, Tensor_Dim3 > &t, const int &iterator0, const int &iterator1)
JSON compatible output.
T operator()(const int N1, const int N2, const int N3, const int N4) const
std::ostream & Tensor4_0001(std::ostream &os, const Tensor4< T, Tensor_Dim0, Tensor_Dim1, Tensor_Dim2, Tensor_Dim3 > &t, const int &iterator0, const int &iterator1, const int &iterator2)
Tensor4(T d0000, T d0001, T d0002, T d0010, T d0011, T d0012, T d0020, T d0021, T d0022, T d0100, T d0101, T d0102, T d0110, T d0111, T d0112, T d0120, T d0121, T d0122, T d0200, T d0201, T d0202, T d0210, T d0211, T d0212, T d0220, T d0221, T d0222, T d1000, T d1001, T d1002, T d1010, T d1011, T d1012, T d1020, T d1021, T d1022, T d1100, T d1101, T d1102, T d1110, T d1111, T d1112, T d1120, T d1121, T d1122, T d1200, T d1201, T d1202, T d1210, T d1211, T d1212, T d1220, T d1221, T d1222, T d2000, T d2001, T d2002, T d2010, T d2011, T d2012, T d2020, T d2021, T d2022, T d2100, T d2101, T d2102, T d2110, T d2111, T d2112, T d2120, T d2121, T d2122, T d2200, T d2201, T d2202, T d2210, T d2211, T d2212, T d2220, T d2221, T d2222)
std::ostream & operator<<(std::ostream &os, const FTensor::Tensor4< T, Tensor_Dim0, Tensor_Dim1, Tensor_Dim2, Tensor_Dim3 > &t)
T data[Tensor_Dim0][Tensor_Dim1][Tensor_Dim2][Tensor_Dim3]
T & operator()(const int N1, const int N2, const int N3, const int N4)
std::ostream & Tensor4_0100(std::ostream &os, const Tensor4< T, Tensor_Dim0, Tensor_Dim1, Tensor_Dim2, Tensor_Dim3 > &t, const int &iterator0)