source: trunk/test/iterator.cc @ 3374

Last change on this file since 3374 was 3374, checked in by Peter, 9 years ago

improve test diagnosis

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