tensor-0.1.0
 All Data Structures Namespaces Functions Variables Typedefs Enumerations Enumerator Groups Pages
range.cc
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 #include <cassert>
21 #include <iostream>
22 #include <tensor/indices.h>
23 
24 namespace tensor {
25 
26  Range::Range()
27  : base_(0), limit_(0), factor_(1)
28  {
29  }
30 
31  Range::~Range()
32  {
33  }
34 
35  index
36  Range::pop()
37  {
38  return nomore();
39  }
40 
41  void
42  Range::set_factor(index factor)
43  {
44  factor_ = factor;
45  }
46 
47  void
48  Range::set_limit(index limit)
49  {
50  assert(limit >= 0);
51  limit_ = limit;
52  }
53 
54  index
55  Range::size() const
56  {
57  return 0;
58  }
59 
60  void
61  Range::reset()
62  {
63  }
64 
65  /************************************************************
66  * ALL-INDEX RANGE
67  */
68 
69  FullRange::FullRange()
70  : Range(), counter_(0), counter_end_(0)
71  {
72  }
73 
74  index
75  FullRange::pop()
76  {
77  if (counter_ >= counter_end_) {
78  return nomore();
79  } else {
80  index output = counter_;
81  counter_ += get_factor();
82  return output;
83  }
84  }
85 
86  void
87  FullRange::set_factor(index factor)
88  {
89  index old = get_factor();
90  counter_ = 0;
91  counter_end_ = get_limit() * factor;
92  Range::set_factor(factor);
93  }
94 
95  void
96  FullRange::set_limit(index limit)
97  {
98  counter_end_ = limit * get_factor();
99  Range::set_limit(limit);
100  }
101 
102  index
103  FullRange::size() const
104  {
105  return get_limit();
106  }
107 
108  void
109  FullRange::reset()
110  {
111  counter_ = 0;
112  }
113 
114  /************************************************************
115  * SINGLE INDEX RANGE
116  */
117  SingleRange::SingleRange(index ndx)
118  : Range(), ndx_(ndx), counter_(ndx)
119  {
120  }
121 
122  index
123  SingleRange::pop()
124  {
125  if (counter_)
126  return nomore();
127  ++counter_;
128  return ndx_;
129  }
130 
131  void
132  SingleRange::set_factor(index factor)
133  {
134  index old = get_factor();
135  ndx_ = (ndx_ / old) * factor;
136  Range::set_factor(factor);
137  }
138 
139  void
140  SingleRange::set_limit(index limit)
141  {
142  assert(limit > ndx_);
143  Range::set_limit(limit);
144  }
145 
146  index
147  SingleRange::size() const
148  {
149  return 1;
150  }
151 
152  void
153  SingleRange::reset()
154  {
155  counter_ = 0;
156  }
157 
158  /************************************************************
159  * EQUALLY SPACED INDICES RANGE
160  */
161 
162  StepRange::StepRange(index start, index end, index step) :
163  Range(), start_(start), end_(end), step_(step), ndx_(0)
164  {
165  }
166 
167  index
168  StepRange::pop()
169  {
170  if (ndx_ > end_) {
171  return nomore();
172  } else {
173  index output = ndx_;
174  ndx_ += step_;
175  return output;
176  }
177  }
178 
179  void
180  StepRange::set_factor(index factor)
181  {
182  index old = get_factor();
183  end_ = (end_ / old) * factor;
184  step_ = (step_ / old) * factor;
185  ndx_ = start_ = (start_ / old) * factor;
186  Range::set_factor(factor);
187  }
188 
189  void
190  StepRange::set_limit(index limit)
191  {
192  assert(limit > end_);
193  Range::set_limit(limit);
194  }
195 
196  index
197  StepRange::size() const
198  {
199  return (end_ - start_) / step_ + 1;
200  }
201 
202  void
203  StepRange::reset()
204  {
205  ndx_ = start_;
206  }
207 
208  /************************************************************
209  * RANGE WITH A VECTOR OF INDICES
210  */
211  IndexRange::IndexRange(const Indices &i)
212  : Range(), indices_(i), counter_(0)
213  {
214  }
215 
216  index
217  IndexRange::pop()
218  {
219  if (counter_ >= indices_.size())
220  return nomore();
221  return indices_[counter_++];
222  }
223 
224  void
225  IndexRange::set_factor(index factor)
226  {
227  index old = get_factor();
228  for (Indices::iterator it = indices_.begin(); it != indices_.end(); it++) {
229  *it = (*it / old) * factor;
230  }
231  counter_ = 0;
232  Range::set_factor(factor);
233  }
234 
235  void
236  IndexRange::set_limit(index limit)
237  {
238 #ifndef NDEBUG
239  for (Indices::const_iterator it = indices_.begin(); it != indices_.end(); it++) {
240  assert(*it <= limit);
241  }
242 #endif
243  Range::set_limit(limit);
244  }
245 
246  index
247  IndexRange::size() const
248  {
249  return indices_.size();
250  }
251 
252  void
253  IndexRange::reset()
254  {
255  counter_ = 0;
256  }
257 
258  /************************************************************
259  * TENSOR PRODUCT RANGE
260  */
261  ProductRange::ProductRange(Range *r1, Range *r2) : r1_(r1), r2_(r2)
262  {
263  r2_->set_factor(r1_->get_factor() * r1_->get_limit());
264  }
265 
266  ProductRange::~ProductRange()
267  {
268  delete r1_;
269  delete r2_;
270  }
271 
272  index
273  ProductRange::pop()
274  {
275  index out = base_;
276  do {
277  if (out == nomore())
278  return out;
279  index n = r1_->pop();
280  if (n != nomore())
281  return n + out;
282  out = base_ = r2_->pop();
283  r1_->reset();
284  } while (1);
285  }
286 
287  void
288  ProductRange::reset()
289  {
290  r1_->reset();
291  r2_->reset();
292  base_ = r2_->pop();
293  }
294 
295  void
296  ProductRange::set_factor(index factor)
297  {
298  r1_->set_factor(factor);
299  r2_->set_factor(factor * r1_->get_limit());
300  }
301 
302  void
303  ProductRange::set_limit(index limit)
304  {
305  assert(0);
306  }
307 
308  index
309  ProductRange::size() const
310  {
311  return r1_->size() * r2_->size();
312  }
313 
314  Range *product(Range *r1, Range *r2)
315  {
316  return new ProductRange(r1, r2);
317  }
318 
319 } // namespace tensor