source: trunk/test/iterator_test.cc @ 2289

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

adding test, refs #623

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