v0.7.26
Tensor1_value.hpp
Go to the documentation of this file.
1 /* The general version, not for pointers. */
2 
3 #include <iostream>
4 #pragma once
5 
6 namespace FTensor
7 {
8  template <class T, int Tensor_Dim> class Tensor1
9  {
10  T data[Tensor_Dim];
11 
12  public:
13  /* Initializations for varying numbers of elements. */
14  template <class... U> constexpr Tensor1(U... d) : data{d...}
15  {
16  static_assert(sizeof...(d) == sizeof(data) / sizeof(T),
17  "Incorrect number of Arguments. Constructor should "
18  "initialize the entire Tensor");
19  };
20 
21  constexpr Tensor1() {}
22 
23  /* There are two operator(int)'s, one for non-consts that lets you
24  change the value, and one for consts that doesn't. */
25 
26  T &operator()(const int N)
27  {
28 #ifdef FTENSOR_DEBUG
29  if(N >= Tensor_Dim || N < 0)
30  {
31  std::stringstream s;
32  s << "Bad index in Tensor1<T," << Tensor_Dim << ">.operator(" << N
33  << ")" << std::endl;
34  throw std::out_of_range(s.str());
35  }
36 #endif
37  return data[N];
38  }
39  T operator()(const int N) const
40  {
41 #ifdef FTENSOR_DEBUG
42  if(N >= Tensor_Dim || N < 0)
43  {
44  std::stringstream s;
45  s << "Bad index in Tensor1<T," << Tensor_Dim << ">.operator(" << N
46  << ") const" << std::endl;
47  throw std::out_of_range(s.str());
48  }
49 #endif
50  return data[N];
51  }
52 
53  /* These operator()'s are the first part in constructing template
54  expressions. They can be used to slice off lower dimensional
55  parts. They are not entirely safe, since you can accidentaly use a
56  higher dimension than what is really allowed (like Dim=5). */
57 
58  template <char i, int Dim>
59  typename std::enable_if<
60  (Tensor_Dim >= Dim), Tensor1_Expr<Tensor1<T, Tensor_Dim>, T, Dim, i>>::type
61  operator()(const Index<i, Dim> &)
62  {
63  return Tensor1_Expr<Tensor1<T, Tensor_Dim>, T, Dim, i>(*this);
64  }
65 
66  template <char i, int Dim>
67  typename std::enable_if<
68  (Tensor_Dim >= Dim),
69  Tensor1_Expr<const Tensor1<T, Tensor_Dim>, T, Dim, i>>::type
70  operator()(const Index<i, Dim> &) const
71  {
72  return Tensor1_Expr<const Tensor1<T, Tensor_Dim>, T, Dim, i>(*this);
73  }
74 
75  /* Convenience functions */
76 
78  {
79  const Index<'a', Tensor_Dim> a;
80  (*this)(a) /= l2();
81  return *this;
82  }
83 
84  T l2() const { return sqrt(l2_squared(Number<Tensor_Dim>())); }
85 
86  template <int Current_Dim> T l2_squared(const Number<Current_Dim> &) const
87  {
88  return data[Current_Dim - 1] * data[Current_Dim - 1]
90  }
91  T l2_squared(const Number<1> &) const { return data[0] * data[0]; }
92  };
93 }
94 /// JSON compatible output
95 
96 template <class T, int Tensor_Dim>
97 std::ostream &
98 operator<<(std::ostream &os, const FTensor::Tensor1<T, Tensor_Dim> &t)
99 {
100  os << '[';
101  for(int i = 0; i + 1 < Tensor_Dim; ++i)
102  {
103  os << t(i) << ',';
104  }
105  if(Tensor_Dim > 0)
106  {
107  os << t(Tensor_Dim - 1);
108  }
109  os << ']';
110  return os;
111 }
112 
113 template <class T, int Tensor_Dim>
114 std::istream &operator>>(std::istream &is, FTensor::Tensor1<T, Tensor_Dim> &t)
115 {
116  char c;
117  is >> c;
118  for(int i = 0; i + 1 < Tensor_Dim; ++i)
119  {
120  is >> t(i) >> c;
121  }
122  if(Tensor_Dim > 0)
123  {
124  is >> t(Tensor_Dim - 1);
125  }
126  is >> c;
127  return is;
128 }
constexpr Tensor1()
const Tensor1_Expr< const dTensor0< T, Dim, i >, typename promote< T, double >::V, Dim, i > d(const Tensor0< T *> &a, const Index< i, Dim > index, const Tensor1< int, Dim > &d_ijk, const Tensor1< double, Dim > &d_xyz)
Definition: dTensor0.hpp:27
std::istream & operator>>(std::istream &is, FTensor::Tensor1< T, Tensor_Dim > &t)
Fully Antisymmetric Levi-Civita Tensor.
T data[Tensor_Dim]
T l2_squared(const Number< Current_Dim > &) const
T l2_squared(const Number< 1 > &) const
T & operator()(const int N)
T operator()(const int N) const
constexpr Tensor1(U... d)
Tensor1< T, Tensor_Dim > normalize()
const int N
Definition: speed_test.cpp:3