source: trunk/test/iterator.cc @ 3375

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

extend test

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