xerus
a general purpose tensor library
index.cpp
Go to the documentation of this file.
1 // Xerus - A General Purpose Tensor Library
2 // Copyright (C) 2014-2017 Benjamin Huber and Sebastian Wolf.
3 //
4 // Xerus is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as published
6 // by the Free Software Foundation, either version 3 of the License,
7 // or (at your option) any later version.
8 //
9 // Xerus is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
13 //
14 // You should have received a copy of the GNU Affero General Public License
15 // along with Xerus. If not, see <http://www.gnu.org/licenses/>.
16 //
17 // For further information on Xerus visit https://libXerus.org
18 // or contact us at contact@libXerus.org.
19 
25 #include <xerus/index.h>
26 
27 #include <xerus/misc/standard.h>
28 #include <xerus/misc/check.h>
29 #include <xerus/misc/internal.h>
30 
31 namespace xerus {
32 
33  std::atomic<uint64> Index::idThreadInitCounter(0);
34  thread_local uint64 Index::idCounter = (idThreadInitCounter++)<<54;
35 
36 
37  Index::Index() : valueId(idCounter++), span(1) { }
38 
39 
40  Index::Index(const int32 _i) : Index(static_cast<uint64>(_i)) {
41  REQUIRE(_i >= 0, "Negative valueId= " <<_i<< " given");
42  }
43 
44  Index::Index(const uint32 _i) noexcept : valueId(_i), span(1) {
45  flags[Flag::FIXED] = true;
46  }
47 
48  Index::Index(const int64 _i) : Index(static_cast<uint64>(_i)) {
49  REQUIRE(_i >= 0, "Negative valueId= " <<_i<< " given");
50  }
51 
52  Index::Index(const uint64 _i) noexcept : valueId(_i), span(1) {
53  flags[Flag::FIXED] = true;
54  }
55 
56  Index::Index(const uint64 _valueId, const size_t _span) noexcept : valueId(_valueId), span(_span) {}
57 
58 
59  Index::Index(const uint64 _valueId, const size_t _span, const Flag _flag1) noexcept : valueId(_valueId), span(_span) {
60  flags[_flag1] = true;
61  }
62 
63 
64  void Index::set_span(const size_t _degree) {
65  REQUIRE(!flags[Flag::FIXED] || span == 1, "Fixed indices must have span one.");
66  if(flags[Flag::INVERSE_SPAN]) {
67  REQUIRE(!flags[Flag::FIXED], "Fixed indices must not have inverse span.");
68  REQUIRE(span <= _degree, "Index with inverse span would have negative actual span. Tensor degree: " << _degree << ", inverse span " << span);
69  span = _degree-span;
70  flags.reset();
71  } else if( flags[Flag::FRACTIONAL_SPAN] ) {
72  REQUIRE(!flags[Flag::FIXED], "Fixed indices must not have fractional span.");
73  REQUIRE(_degree%span == 0, "Fractional span must divide the tensor degree. Here tensor degree = " << _degree << ", span = " << span);
74  span = _degree/span;
75  flags.reset();
76  }
77  }
78 
79 
80  size_t Index::actual_span(const size_t _degree) const {
81  if(flags[Flag::INVERSE_SPAN]) {
82  REQUIRE(!flags[Flag::FIXED], "Fixed indices must not have inverse span.");
83  REQUIRE(span <= _degree, "Index with inverse span would have negative actual span. Tensor degree: " << _degree << ", inverse span " << span);
84  return _degree-span;
85  }
86  if( flags[Flag::FRACTIONAL_SPAN] ) {
87  REQUIRE(!flags[Flag::FIXED], "Fixed indices must not have fractional span.");
88  REQUIRE(_degree%span == 0, "Fractional span must divide the tensor degree. Here tensor degree = " << _degree << ", span = " << span);
89  return _degree/span;
90  }
91  REQUIRE(!flags[Flag::FIXED] || span == 1, "Fixed indices must have span one.");
92  return span;
93  }
94 
95 
96  bool Index::fixed() const {
97  #ifndef XERUS_DISABLE_RUNTIME_CHECKS
98  if(flags[Index::Flag::FIXED]) {
99  REQUIRE(!flags[Flag::INVERSE_SPAN], "Fixed indices must not have inverse span.");
100  REQUIRE(!flags[Flag::FRACTIONAL_SPAN], "Fixed indices must not have fractional span.");
101  REQUIRE(span == 1, "Fixed indices must have span one.");
102  return true;
103  }
104  return false;
105  #else
106  return flags[Index::Flag::FIXED];
107  #endif
108  }
109 
110 
111  bool Index::open() const {
112  REQUIRE(flags[Index::Flag::ASSINGED], "Check for index openness only allowed if the index is assinged.");
113  return flags[Index::Flag::OPEN];
114  }
115 
116 
117  void Index::open(const bool _open) {
118  flags[Flag::OPEN] = _open;
119  IF_CHECK( flags[Flag::ASSINGED] = true; )
120  }
121 
122 
123  size_t Index::dimension() const {
124  REQUIRE(flags[Index::Flag::ASSINGED], "Check for index dimension only allowed if the index is assinged.");
125  return assingedDimension;
126  }
127 
128 
129  size_t Index::fixed_position() const {
130  REQUIRE(flags[Index::Flag::FIXED], "fixed_position() must only be called for fixed indices.");
131  return size_t(valueId);
132  }
133 
134 
135  Index Index::operator^(const size_t _span) const {
136  REQUIRE(flags.none(), "Cannot apply ^ operator to an index that has any flag set.");
137  return Index(valueId, _span);
138  }
139 
140 
141  Index Index::operator&(const size_t _span) const {
142  REQUIRE(flags.none(), "Cannot apply & operator to an index that has any flag set.");
143  return Index(valueId, _span, Flag::INVERSE_SPAN);
144  }
145 
146 
147  Index Index::operator/(const size_t _span) const {
148  REQUIRE(flags.none(), "Cannot apply & operator to an index that has any flag set.");
149  return Index(valueId, _span, Flag::FRACTIONAL_SPAN);
150  }
151 
152 
153  bool Index::all_open(const std::vector<Index>& _indices) {
154  for(const Index& idx : _indices) {
155  if(!idx.open()) { return false; }
156  }
157  return true;
158  }
159 
160 
161 
162 
163  bool operator==(const Index& _a, const Index& _b) {
164  return _a.valueId == _b.valueId && !_a.fixed() && !_b.fixed();
165  }
166 
167  bool operator!=(const Index& _a, const Index& _b) {
168  return _a.valueId != _b.valueId || _a.fixed() || _b.fixed();
169  }
170 
171  bool operator<(const Index& _a, const Index& _b) {
172  return _a.valueId < _b.valueId;
173  }
174 
175  std::ostream& operator<<(std::ostream& _out, const xerus::Index& _idx) {
176  _out << "index#" << _idx.valueId << (_idx.flags[Index::Flag::INVERSE_SPAN] ? "&" : (_idx.flags[Index::Flag::FRACTIONAL_SPAN] ? "/" : "^")) << _idx.span;
177  return _out;
178  }
179 } // namespace xerus
Header file for CHECK and REQUIRE macros.
static bool all_open(const std::vector< Index > &_indices)
: Checks whether all indices in _indices are open. This is naturally only usefull for assinged indice...
Definition: index.cpp:153
Header file for the Index class.
size_t actual_span(const size_t _degree) const
Returns the span this index actually represents in a tensor of given order.
Definition: index.cpp:80
uint64_t uint64
Definition: standard.h:63
Flag
Enum defining the possible flags an Index my possess.
Definition: index.h:47
#define REQUIRE
Definition: internal.h:33
bool open() const
Checks whether the index is open.
Definition: index.cpp:111
#define IF_CHECK
Definition: internal.h:35
The main namespace of xerus.
Definition: basic.h:37
Index operator^(const size_t _span) const
: Allow the creation of Indices covering more than one dimension using the power operator. E.g. A(i^2) = B(i^2) + C(i^2), defines A as the entriewise sum of the matrices B and C.
Definition: index.cpp:135
size_t fixed_position() const
: Returns the fixed position of a fixed index.
Definition: index.cpp:129
std::ostream & operator<<(std::ostream &_out, const xerus::Index &_idx)
Allows to pretty print indices, giving the valueId and span.
Definition: index.cpp:175
int64_t int64
Definition: standard.h:58
bool operator==(const Index &_a, const Index &_b)
Two Indices are equal if their valueId coincides. Fixed indices are never equal.
Definition: index.cpp:163
std::bitset< NUM_FLAGS > flags
Bitset of all possible flags the index may possess.
Definition: index.h:71
void set_span(const size_t _degree)
Returns the span this index actually represents in a tensor of given order.
Definition: index.cpp:64
uint64 valueId
Unqiue ID of the index. In case the fixed flag is set, this is the fixed position.
Definition: index.h:62
size_t assingedDimension
The product of the external dimensions this index correstponds to. Only set for assinged indices...
Definition: index.h:68
bool operator<(const Index &_a, const Index &_b)
The Comparision operator is needed for indices to be orderable in std::set, the valueId is used...
Definition: index.cpp:171
uint32_t uint32
Definition: standard.h:62
Header file for comfort functions and macros that should not be exported in the library.
Index operator/(const size_t _span) const
: Allow the creation of Indices covering an x-th fraction of the indices. E.g. A(i&0) = B(i/2...
Definition: index.cpp:147
bool operator!=(const Index &_a, const Index &_b)
Two Indices are equal if their valueId coincides. Fixed indices are never equal.
Definition: index.cpp:167
Class used to represent indices that can be used to write tensor calculations in index notation...
Definition: index.h:43
Index operator &(const size_t _span) const
: Allow the creation of Indices covering all but x dimensions using the and operator. E.g. A() = B(i&0) * C(i&0), defines A as the full contraction between B and C, indifferent of the actual degree of B and C.
size_t dimension() const
Returns the (mult)Dimension assinged to this index.
Definition: index.cpp:123
size_t span
The span states how many dimensions are covered by the index.
Definition: index.h:65
bool fixed() const
Checks whether the Index represents a fixed number.
Definition: index.cpp:96
int32_t int32
Definition: standard.h:57
Header file for global shorthand notations of elementary integer types and attribute lists...
Index()
Empty constructor that creates a new Index with new ID. Use this to create indices.
Definition: index.cpp:37