source: trunk/test/iterator_test.cc @ 2282

Last change on this file since 2282 was 2282, checked in by Peter, 12 years ago

document and test that DataIterator? and WeightIterator? works with/requires input_iterator. closes #633

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 16.1 KB
Line 
1// $Id: iterator_test.cc 2282 2010-06-26 01:38:17Z peter $
2
3/*
4  Copyright (C) 2007, 2008 Jari Häkkinen, Peter Johansson, Markus Ringnér
5  Copyright (C) 2009, 2010 Peter Johansson
6
7  This file is part of the yat library, http://dev.thep.lu.se/yat
8
9  The yat library is free software; you can redistribute it and/or
10  modify it under the terms of the GNU General Public License as
11  published by the Free Software Foundation; either version 3 of the
12  License, or (at your option) any later version.
13
14  The yat library is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  General Public License for more details.
18
19  You should have received a copy of the GNU General Public License
20  along with yat. If not, see <http://www.gnu.org/licenses/>.
21*/
22
23#include "Suite.h"
24
25#include "yat/classifier/DataLookup1D.h"
26
27#include "yat/classifier/DataLookupWeighted1D.h"
28#include "yat/classifier/MatrixLookup.h"
29#include "yat/classifier/MatrixLookupWeighted.h"
30#include "yat/utility/Container2DIterator.h"
31#include "yat/utility/DataWeight.h"
32#include "yat/utility/DataWeightProxy.h"
33#include "yat/utility/DataIterator.h"
34#include "yat/utility/Matrix.h"
35#include "yat/utility/MatrixWeighted.h"
36#include "yat/utility/stl_utility.h"
37#include "yat/utility/Vector.h"
38#include "yat/utility/VectorView.h"
39#include "yat/utility/VectorConstView.h"
40#include "yat/utility/WeightedIterator.h"
41#include "yat/utility/WeightIterator.h"
42
43#include <boost/concept_archetype.hpp>
44#include <boost/iterator/transform_iterator.hpp>
45
46#include <algorithm>
47#include <fstream>
48#include <iterator>
49#include <map>
50#include <set>
51#include <string>
52#include <vector>
53
54using namespace theplu::yat;
55
56void old_main(test::Suite&);
57
58template<typename Iterator>
59void is_weighted(Iterator, test::Suite&);
60
61bool is_weighted(utility::unweighted_iterator_tag x) { return false; } 
62bool is_weighted(utility::weighted_iterator_tag x) { return true; }
63
64void test_boost_util(test::Suite&);
65void test_pair_second_iterator(test::Suite&);
66
67void test_data_iterator(test::Suite& suite);
68void test_weight_iterator(test::Suite& suite);
69void test_iterator_traits(test::Suite& suite);
70void test_stride_iterator(test::Suite& suite);
71void test_weighted_iterator(test::Suite& suite);
72void test_matrix_lookup_iterator(test::Suite& suite);
73
74int main(int argc, char* argv[])
75{ 
76  test::Suite suite(argc, argv);
77  suite.err() << "testing iterator" << std::endl;
78
79  test_stride_iterator(suite);
80  old_main(suite);
81  suite.out() << "testing boost_util\n";
82  test_boost_util(suite);
83  suite.out() << "testing iterator_traits\n";
84  test_iterator_traits(suite);
85  suite.out() << "testing pair_second_iterator\n";
86  test_pair_second_iterator(suite);
87  suite.out() << "testing weighted iterator\n";
88  test_weighted_iterator(suite);
89  test_data_iterator(suite);
90  test_weight_iterator(suite);
91  return suite.return_value();
92}
93 
94template<typename Iterator>
95void is_weighted(Iterator i, test::Suite& suite)
96{
97  suite.err() << "testing that iterator is unweighted... ";
98  typename utility::weighted_iterator_traits<Iterator>::type tag;
99  if (is_weighted(tag))
100    suite.err() << "ok.\n";
101  else {
102    suite.err() << "failed.\n";
103    suite.add(false);
104  }
105   
106}
107
108
109void old_main(test::Suite& suite)
110{
111  suite.err() << "testing utility::Vector::iterator" << std::endl;
112  utility::Vector vec(12);
113  classifier::DataLookup1D lookup(vec);
114  utility::Vector::iterator begin=vec.begin();
115  suite.test_random_access_iterator(begin);
116  // test iterator to const_iterator conversion
117  utility::Vector::const_iterator ci = vec.begin();
118  suite.test_random_access_iterator(ci);
119  ci = begin;
120  if (begin!=ci)
121    suite.add(false);
122
123  suite.err() << "sorting...";
124  utility::Vector::iterator end=vec.end();
125  std::sort(begin, end);
126  suite.err() << " sorting done\n";
127
128  suite.err() << "testing classifier::DataLookup1D::const_iterator" << std::endl;
129  classifier::DataLookup1D::const_iterator lbegin=lookup.begin();
130  classifier::DataLookup1D::const_iterator lend=lookup.end();
131  suite.test_random_access_iterator(lbegin);
132 
133  suite.err() << "copy from DataLookup1D to Vector" << std::endl;
134  std::copy(lbegin, lend, begin);
135  suite.err() << "copy from Vector to Vector" << std::endl;
136  std::copy(begin, end, begin);
137  suite.err() << "sort Vector" << std::endl;
138  std::sort(begin, end);
139
140  // test std algorithm on IteratorWeighted
141  utility::MatrixWeighted m_w(1, 3, 1, 1);
142  m_w(0,1).data()=2.0;
143  classifier::MatrixLookupWeighted mw(m_w);
144  classifier::DataLookupWeighted1D aw(mw,0,true);
145  size_t nof1=std::count(aw.begin(),aw.end(),utility::DataWeight(1.0, 1.0));
146  if(nof1!=2) {
147    suite.err() << "std algoritm with IteratorWeighted failed" << std::endl;
148    suite.add(false);
149  }
150  if (aw.begin()!=mw.begin_row(0))
151    suite.add(false);
152  if (aw.end()!=mw.end_row(0))
153    suite.add(false);
154  classifier::DataLookupWeighted1D aw2(mw,0,false);
155  if (aw2.begin()!=mw.begin_column(0))
156    suite.add(false);
157  if (aw2.end()!=mw.end_column(0))
158    suite.add(false);
159
160  utility::DataIterator<classifier::DataLookupWeighted1D::const_iterator> 
161    data_iter(aw2.begin());
162  suite.out() << "testing data_iter\n";
163  suite.test_random_access_iterator(data_iter);
164  suite.out() << "testing weight_iter\n";
165  suite.test_random_access_iterator(weight_iterator(aw2.begin()));
166  suite.add(*data_iter == 1.0);
167  suite.add(*data_iterator(aw2.begin()) == 1.0);
168  std::vector<double> stl_vec(1,0);
169  utility::DataIterator<std::vector<double>::iterator> 
170    data_iter2(stl_vec.begin());
171  suite.add(*data_iter2 == 0.0);
172  *data_iter2 = 3.14;
173  suite.add(*data_iter2 == 3.14);
174  utility::WeightIterator<std::vector<double>::iterator> 
175    data_iter3(stl_vec.begin());
176  suite.add(*data_iter3 == 1.0);
177
178  // testing constness conversion
179  suite.out() << "testing const conversion\n";
180  std::vector<double>::const_iterator c_iter(stl_vec.begin());
181  std::vector<double>::iterator iter(stl_vec.begin());
182  suite.add(iter==c_iter);
183  utility::DataIterator<std::vector<double>::const_iterator> 
184    data_iter4(c_iter);
185  utility::DataIterator<std::vector<double>::iterator> 
186    data_iter5(iter);
187  suite.add(data_iter2 == data_iter5);
188  suite.add(data_iter4 == data_iter5);
189  utility::StrideIterator<std::vector<double>::const_iterator> stride_ci(c_iter);
190  utility::StrideIterator<std::vector<double>::iterator> stride_i(iter);
191  suite.add(stride_ci==stride_i);
192  suite.add(stride_i==stride_ci);
193
194  utility::MatrixWeighted x_weighted(3,4);
195  x_weighted.begin();
196  *x_weighted.begin();
197  utility::DataWeight element = *x_weighted.begin();
198  *(x_weighted.begin()+1) = element;
199  double element_data = *data_iterator(x_weighted.begin());
200  suite.add(element_data==x_weighted.begin()->data());
201
202  utility::Matrix m(mw.rows(), mw.columns());
203  classifier::MatrixLookup ml(m);
204  classifier::DataLookup1D dl1(ml,0,true);
205  if (dl1.begin()!=ml.begin_row(0))
206    suite.add(false);
207  if (dl1.end()!=ml.end_row(0))
208    suite.add(false);
209  classifier::DataLookup1D dl2(ml,0,false);
210  if (dl2.begin()!=ml.begin_column(0))
211    suite.add(false);
212  if (dl2.end()!=ml.end_column(0))
213    suite.add(false);
214
215}
216
217void test_boost_util(test::Suite& suite)
218{
219  bool ok_cached=suite.ok();
220  utility::PairFirst<std::pair<std::string, int> > pf;
221  std::pair<std::string, int> p("July", 31);
222  std::string str=pf(p);
223  suite.add(str=="July");
224  pf(p)="juli";
225  suite.add(pf(p)=="juli");
226
227  typedef utility::PairFirst<std::pair<const std::string, int> > PF2;
228  PF2 pf2;
229  std::pair<const std::string, int> p2("July", 31);
230  suite.add(pf2(p2)=="July");
231
232  utility::PairFirst<const std::pair<std::string, int> > pf3;
233  std::pair<std::string, int> p3("July", 31);
234  suite.add(pf3(p3)=="July");
235
236  utility::PairFirst<std::pair<std::string, const int> > pf4;
237  std::pair<std::string, const int> p4("July", 31);
238  suite.add(pf4(p4)=="July");
239  pf4(p4)="juli";
240  suite.add(pf4(p4)=="juli");
241
242  utility::PairFirst<std::pair<const std::string, const int> > pf5;
243  std::pair<const std::string, const int> p5("July", 31);
244  suite.add(pf5(p5)=="July");
245
246  typedef std::map<std::string, int> Map;
247  Map m;
248  m["July"]=31;
249  m["September"]=30;
250  m["June"]=30;
251  m["April"]=30;
252
253  boost::transform_iterator<PF2, Map::iterator> first_iterator(m.begin(), pf2);
254  boost::transform_iterator<PF2, Map::iterator> first_iterator_end(m.end(), pf2);
255  std::vector<std::string> vec(m.size());
256  std::copy(first_iterator, first_iterator_end, vec.begin());
257  std::vector<std::string> correct;
258  correct.push_back("April");
259  correct.push_back("July");
260  correct.push_back("June");
261  correct.push_back("September");
262  for (size_t i=0; i<vec.size(); ++i)
263    if (!suite.add(vec[i]==correct[i]))
264      suite.err() << "Error: vec[" << i << "] = " << vec[i] 
265                  << " expected " << correct[i] << "\n";
266
267  std::vector<std::string> vec2(m.size());
268  std::copy(utility::pair_first_iterator(m.begin()), 
269            utility::pair_first_iterator(m.end()),
270            vec2.begin());
271  suite.add(vec2==vec);
272 
273  std::vector<int> days;
274  days.resize(m.size());
275  std::copy(utility::pair_second_iterator(m.begin()), 
276            utility::pair_second_iterator(m.end()),
277            days.begin());
278  std::vector<int> days_correct;
279  days_correct.push_back(30);
280  days_correct.push_back(31);
281  days_correct.push_back(30);
282  days_correct.push_back(30);
283  for (size_t i=0; i<days.size(); ++i)
284    if (!suite.add(days[i]==days_correct[i]))
285      suite.err() << "Error: days[" << i << "] = " << days[i] 
286                  << " expected " << days_correct[i] << "\n";
287  days = std::vector<int>(days.size(), 0);
288  std::copy(days.begin(), days.end(), utility::pair_second_iterator(m.begin()));
289  for (std::map<std::string, int>::const_iterator i=m.begin(); i!=m.end(); ++i)
290    if (!suite.add(i->second==0) )
291      suite.err() << "Error: m[" << i->first << "] = " << i->second
292                  << " expected 0\n";
293
294  if (ok_cached && !suite.ok())
295    suite.err() << "test_bool_util failed" << std::endl;
296}
297
298
299void test_data_iterator(test::Suite& suite)
300{
301  // do not run compile test
302  return;
303
304  using utility::DataIterator;
305  using boost::input_iterator_archetype;
306  input_iterator_archetype<double> input_it;
307  using boost::mutable_forward_iterator_archetype;
308  mutable_forward_iterator_archetype<double> forward_it;
309 
310  using utility::data_iterator;
311  std::copy(data_iterator(input_it),
312            data_iterator(input_it),
313            data_iterator(forward_it));
314
315  boost::input_iterator_archetype_no_proxy<utility::DataWeight> input_it_w;
316  mutable_forward_iterator_archetype<utility::DataWeight> forward_it_w;
317  std::copy(data_iterator(input_it_w),
318            data_iterator(input_it_w),
319            data_iterator(forward_it_w));
320
321}
322
323
324void test_weight_iterator(test::Suite& suite)
325{
326  // do not run compile test
327  return;
328
329  using utility::WeightIterator;
330  using boost::input_iterator_archetype;
331  input_iterator_archetype<double> input_it;
332  using boost::mutable_forward_iterator_archetype;
333 
334  // we are using weighted here because unweighted WeightIterator is
335  // always const (not mutable)
336  mutable_forward_iterator_archetype<utility::DataWeight> forward_it_w;
337
338  using utility::weight_iterator;
339  std::copy(weight_iterator(input_it),
340            weight_iterator(input_it),
341            weight_iterator(forward_it_w));
342
343  boost::input_iterator_archetype_no_proxy<utility::DataWeight> input_it_w;
344  std::copy(weight_iterator(input_it_w),
345            weight_iterator(input_it_w),
346            weight_iterator(forward_it_w));
347}
348
349
350void test_iterator_traits(test::Suite& suite)
351{
352  typedef std::vector<utility::DataWeight>::iterator Iter;
353  suite.add(utility::detail::iter_has_mutable_weight<Iter>::value);
354  typedef std::vector<utility::DataWeight>::const_iterator Iter2;
355  suite.add(!utility::detail::iter_has_mutable_weight<Iter2>::value);
356
357  typedef std::vector<utility::DataWeight> WeightVector;
358  WeightVector vec(1);
359  utility::iterator_traits<WeightVector::iterator> traits;
360  double w = traits.weight(vec.begin());
361  traits.weight(vec.begin()) = w;
362  suite.add(suite.equal(w, 1.0));
363
364  utility::iterator_traits<WeightVector::const_iterator> c_traits;
365  w = c_traits.weight(vec.begin());
366  suite.add(suite.equal(w, 1.0));
367
368  utility::iterator_traits<utility::DataWeight*>().weight(&vec[0]);
369
370  double* trivial_iter = new double(1.0);
371  utility::DataWeightProxy<double*, double*> dwp(trivial_iter,trivial_iter); 
372  typedef utility::DataWeightProxy<double*, double*> Proxy;
373  utility::iterator_traits<Proxy*> traits2;
374  w = traits2.weight(&dwp);
375  delete trivial_iter;
376
377  // do not run compile test
378  return;
379  using utility::DataWeight;
380  using utility::iterator_traits;
381  // iterator_traits does not work with a proxy that lacks member
382  // function data() so we test with no_proxy archetype instead.
383  typedef boost::input_iterator_archetype_no_proxy<DataWeight> input; 
384  utility::iterator_traits<input> traits3;
385  w = traits3.weight(input());
386  typedef boost::output_iterator_archetype<DataWeight> output; 
387  utility::iterator_traits<output> traits4;
388  w = traits4.weight(boost::detail::dummy_constructor());
389}
390
391
392void test_stride_iterator(test::Suite& suite)
393{
394  suite.err() << "testing StrideIterator" << std::endl;
395  using utility::Vector;
396  Vector a(10);
397  // stride 2
398  utility::VectorConstView b(a, 0, 5, 2);
399  if (!suite.add(b.end()-b.begin()==5))
400    suite.err() << "ERROR: StrideIterator::operator- returned: " 
401                << b.end()-b.begin() 
402                << " expected 5\n";
403  utility::VectorView c(a, 0, 3, 2);
404  Vector::iterator begin = c.begin();
405  Vector::iterator end = c.end();
406  Vector::const_iterator cbegin = begin;
407  Vector::const_iterator cend = end;
408
409  if (!suite.add(c.size()==3))
410    suite.err() << "c.size() incorrect" << std::endl;
411  if (!suite.add(cend-cbegin == 3))
412    suite.err() << "cend-cbegin failed\n"; 
413
414  typedef utility::Vector::iterator iterator;
415  typedef std::reverse_iterator<iterator> reverse_iterator;
416
417  reverse_iterator rbegin(c.end());
418  reverse_iterator rend(c.begin());
419  // some pointless usage of the iterators
420  std::copy(rbegin, rend, rbegin);
421
422  // do not run compile test
423  if (false) {
424    using utility::StrideIterator;
425    StrideIterator<boost::random_access_iterator_archetype<double> > iter;
426    suite.test_random_access_iterator(iter);
427    double x = *iter;
428    x *= 2; // avoid compiler warning
429  }
430}
431
432void test_weighted_iterator(test::Suite& suite)
433{
434  std::vector<double> vec(3,1);
435  typedef std::vector<double>::iterator Iter;
436  typedef utility::WeightedIterator<Iter, Iter> WIter;
437  WIter iter(vec.begin(), vec.begin());
438
439  utility::DataWeight tmp = *iter;
440
441  suite.test_bidirectional_iterator(iter);
442  suite.test_random_access_iterator(iter);
443  std::vector<double> data(vec.size());
444  std::vector<double> weight(vec.size());
445  WIter iter2(data.begin(), weight.begin());
446  utility::DataWeight tmp2(6.89, 0.79);
447  *iter2 = tmp2;
448  if (!suite.add(tmp2==*iter2))
449    suite.err() << "error: tmp2==*iter2" << std::endl;
450  utility::DataWeight tmp3(*iter2);
451  suite.add(suite.equal(tmp3.data(), tmp2.data()));
452  suite.add(suite.equal(tmp3.weight(), tmp2.weight()));
453  *iter2 = *iter;
454  if (!suite.add(*iter2 == *iter))
455    suite.err() << "error: *iter2 == *iter\n";
456  tmp = *iter2;
457  suite.add(suite.equal(tmp.data(), 1));
458  std::copy(iter, iter+3, iter2);
459  suite.add(suite.equal(vec.front(), 1));
460  suite.add(suite.equal(data.front(), 1));
461
462  suite.err() << "  testing const conversion\n";
463  typedef std::vector<double>::const_iterator const_Iter;
464  typedef utility::WeightedIterator<const_Iter, const_Iter> const_WIter;
465  const_WIter const_iter(vec.begin(), vec.begin());
466  const_iter = iter;
467 
468  suite.err() << "  testing assignment between different iterators\n";
469  const std::vector<double> const_vec(10, 10.7);
470  const_WIter const_iter2(const_vec.begin(), const_vec.begin());
471  utility::DataWeight tmp4;
472  tmp4 = *const_iter2;
473  *iter = *const_iter2;
474  suite.add(*iter==*const_iter2);
475  *iter = *const_iter;
476  suite.add(*iter==*const_iter);
477
478  double x=101;
479  utility::WeightedIterator<double*, double*> iter_p(&x, &x);
480  *iter_p = *iter;
481  suite.add(*iter_p==*iter); 
482}
483
484void test_matrix_lookup_iterator(test::Suite& suite)
485{
486  classifier::MatrixLookup ml(10, 10);
487  suite.test_random_access_iterator(ml.begin());
488  std::vector<double> vec(ml.rows()*ml.columns());
489  std::copy(ml.begin(), ml.end(), vec.begin());
490}
491
492void test_pair_second_iterator(test::Suite& suite)
493{
494  typedef std::map<std::string, std::string> C;
495  C person2color;
496  person2color["me"] = "yellow";
497  person2color["you"] = "orange";
498
499  C::const_iterator cbegin = person2color.begin();
500  C::const_iterator cend = person2color.end();
501
502  std::set<std::string> colors;
503  colors.insert(utility::pair_second_iterator(cbegin), 
504               utility::pair_second_iterator(cend));
505
506  suite.test_bidirectional_iterator(utility::pair_second_iterator(cbegin));
507  suite.test_bidirectional_iterator(utility::pair_first_iterator(cbegin));
508}
Note: See TracBrowser for help on using the repository browser.