source: trunk/test/vector.cc @ 3550

Last change on this file since 3550 was 3550, checked in by Peter, 6 years ago

Update copyright years. Happy New Year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.2 KB
Line 
1// $Id: vector.cc 3550 2017-01-03 05:41:02Z peter $
2
3/*
4  Copyright (C) 2004 Peter Johansson
5  Copyright (C) 2005 Jari Häkkinen, Peter Johansson, Markus Ringnér
6  Copyright (C) 2006 Jari Häkkinen
7  Copyright (C) 2007 Jari Häkkinen, Peter Johansson, Markus Ringnér
8  Copyright (C) 2008, 2009 Jari Häkkinen, Peter Johansson
9  Copyright (C) 2012, 2016 Peter Johansson
10
11  This file is part of the yat library, http://dev.thep.lu.se/yat
12
13  The yat library is free software; you can redistribute it and/or
14  modify it under the terms of the GNU General Public License as
15  published by the Free Software Foundation; either version 3 of the
16  License, or (at your option) any later version.
17
18  The yat library is distributed in the hope that it will be useful,
19  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21  General Public License for more details.
22
23  You should have received a copy of the GNU General Public License
24  along with yat. If not, see <http://www.gnu.org/licenses/>.
25*/
26
27#include <config.h>
28
29#include "Suite.h"
30
31#include "yat/utility/Exception.h"
32#include "yat/utility/FileUtil.h"
33#include "yat/utility/utility.h"
34#include "yat/utility/Vector.h"
35#include "yat/utility/VectorConstView.h"
36#include "yat/utility/VectorView.h"
37
38#include <cstddef>
39#include <fstream>
40#include <iostream>
41#include <sstream>
42
43using namespace theplu::yat;
44
45void check_file_access(std::string& str)
46{
47 
48  if (utility::FileUtil(str).permissions("r")) {
49    std::cerr << "test_nni: Cannot access file " << str << std::endl;
50    exit(-1);
51  }
52}
53
54void test_sort(test::Suite&);
55void test_vector_mutable_assignment(test::Suite&);
56
57int main(int argc,char* argv[])
58{ 
59  test::Suite suite(argc, argv);
60  suite.err() << "testing vector" << std::endl;
61
62  utility::Vector vec(12);
63  for (size_t i=0; i<vec.size(); i++) 
64    vec(i)=i;
65
66  suite.add(suite.test_stream(vec));
67
68  // checking that shuffle works
69  suite.err() << "shuffle" << std::endl;
70  double sum_before = utility::sum(vec);
71  shuffle(vec);
72  double sum_after = utility::sum(vec);
73  if (sum_after!=sum_before){
74    suite.err() << "shuffle failed" << std::endl;
75    suite.add(false);
76  }
77
78  // checking that view works
79  suite.err() << "view" << std::endl;
80  sum_before=0;
81  for (size_t i=0; i<vec.size(); i+=2) 
82    sum_before+=vec(i);
83  utility::VectorView vec_view(vec,0,6,2);
84  sum_after=utility::sum(vec_view);
85  suite.add(suite.equal(sum_after, sum_before));
86  vec(0)=0;
87  vec_view(0)=24;
88  suite.add(suite.equal(vec(0), vec_view(0)));
89
90  // Test of const view implementation (make sure no zero pointer is
91  // used). Here we use the bad style of not making the view const!
92  // If test fails with a null pointer exception it is an uncatchable
93  // core dump!
94  {
95    suite.err() << "const view implementation" << std::endl;
96    const utility::Vector vv(10,3.0);
97    utility::VectorConstView vview(vv,0,5,1);
98    // const utility::Vector vview(vv,0,5,1); // this is the proper line
99    utility::Vector vv2(5,2.0);
100    vv2.mul(vview); // should work even without const since const arg passing
101    vv2.div(vview); // should work even without const since const arg passing
102    suite.add(suite.equal(vview*vview, 3.0*3.0*vview.size()));
103  }
104
105  // checking that copy constructor creates an independent object when
106  // a non-view vector is copied
107  {
108    suite.err() << "copy constructor" << std::endl;
109    utility::Vector vec2(vec);
110    suite.add(vec.size()==vec2.size());
111    suite.add(suite.equal_range(vec2.begin(), vec2.end(), vec.begin()));
112    suite.add(&vec2 != &vec);
113    suite.add(!vec2.isview());
114  }
115
116  // checking that copy constructor creates an independent object when
117  // a view vector is copied
118  {
119    suite.err() << "copy contructor on view" << std::endl;
120    utility::Vector vec3(vec_view);
121    suite.add(vec_view.size()==vec3.size());
122    suite.add(suite.equal_range(vec3.begin(), vec3.end(), vec_view.begin()));
123    suite.add(!vec3.isview());
124  }
125
126  // checking that assignment operator throws an exception if vectors
127  // differ in size
128  {
129    suite.err() << "assignment operator" << std::endl;
130    // GSL will catch the error in this test there for the GSL error
131    // handling must be disabled until after the exception is
132    // catched. The GSL error handler is reinstated after the
133    // try-catch construct.
134    gsl_error_handler_t* err_handler=gsl_set_error_handler_off();
135    bool exception_happens=false;
136    try {
137      utility::Vector v(vec_view.size()+1,0.0);
138      vec_view=v;
139    } catch (utility::GSL_error& err) {
140      exception_happens=true;
141    }
142    if (!exception_happens) {
143      suite.err() << "Vector assignment operator did not throw expected exception"
144               << std::endl;
145      suite.add(false);
146    }
147    gsl_set_error_handler(err_handler);
148  }
149
150  // checking that assignment operator changes the underlying object when
151  // a view is changed.
152  {
153    suite.err() << "assignment operator on view" << std::endl;
154    vec(3)=vec(4)=vec(5)=13;
155    utility::VectorView vec_view(vec,3,3,1);
156    utility::Vector vec2(3,123.0);
157    vec_view=vec2;
158    if (vec(3)!=vec_view(0) || vec(4)!=vec_view(1) || vec(5)!=vec_view(2)){
159      suite.err() << " failed\n";
160      suite.add(false);
161    }
162  }
163
164  // checking clone functionality
165  {
166    suite.err() << "clone functionality" << std::endl;
167    bool this_ok=true;
168    suite.err() << "\tcloning normal vector" << std::endl;
169    utility::Vector vec2(3,123.0);
170    vec2 = vec;
171    if (vec.size()!=vec2.size())
172      this_ok=false;
173    else
174      for (size_t i=0; i<vec.size(); ++i)
175        if (vec(i)!=vec2(i))
176          this_ok=false;
177    if (vec.gsl_vector_p()==vec2.gsl_vector_p())
178      this_ok=false;
179    suite.err() << "\tcloning vector view" << std::endl;
180    utility::VectorView* vec_view=new utility::VectorView(vec,3,3,1);
181    utility::VectorView vec_view2(*vec_view);
182    if (!vec_view2.isview())
183      this_ok=false;
184    if (vec_view->size()!=vec_view2.size())
185      this_ok=false;
186    else
187      for (size_t i=0; i<vec_view2.size(); ++i)
188        if ((*vec_view)(i)!=vec_view2(i))
189          this_ok=false;
190    suite.err() << "\tcloned vector view independence" << std::endl;
191    delete vec_view;
192    if (vec(3)!=vec_view2(0) || vec(4)!=vec_view2(1) || vec(5)!=vec_view2(2))
193      this_ok=false;
194
195    if (!this_ok) {
196      suite.err() << "FAIL: clone test" << std::endl;
197      suite.add(false);
198    }
199  }
200
201  // checking that reading vectors from properly formatted files works
202  try {
203    suite.err() << "stream" << std::endl;
204    std::string data1(test::filename("data/vector1.data"));
205    std::string data2(test::filename("data/vector2.data"));
206    std::string data3(test::filename("data/vector3.data"));
207    std::string data4(test::filename("data/vector4.data"));
208    check_file_access(data1);
209    check_file_access(data2);
210    check_file_access(data3);
211    check_file_access(data4);
212    std::ifstream data_stream1(data1.c_str());
213    std::ifstream data_stream2(data2.c_str());
214    std::ifstream data_stream3(data3.c_str());
215    std::ifstream data_stream4(data4.c_str());
216    utility::Vector vec1(data_stream1);
217    suite.add(vec1.size()==9);
218    vec1=utility::Vector(data_stream2);
219    suite.add(vec1.size()==9);
220    utility::Vector vec2(data_stream3);
221    suite.add(vec2.size()==12);
222    vec2=utility::Vector(data_stream4);
223    suite.add(vec2.size()==12);
224  } catch (utility::IO_error& err) {
225    suite.err() << err.what() << std::endl;
226    suite.add(false);
227  }
228
229  // Checking that vector stream input operator can read whatever
230  // vector stream output operator produces.
231  {
232    suite.err() << "checking that output stream is valid as an input stream"
233             << std::endl;
234    std::stringstream s;
235    s << vec;
236    utility::Vector vec2(s);
237    suite.add(suite.equal_range(vec.begin(), vec.end(), vec2.begin()));
238  }
239
240  // Checking that badly formatted files are not accepted, or at least
241  // throws an exception for the programmer to catch.
242  suite.err() << "checking that bad stream are rejected" << std::endl;
243  bool this_ok=false;
244  // Checking that unexpected characters in a stream gives error.
245  try {
246    std::string data5(test::filename("data/vector5.data"));
247    check_file_access(data5);
248    std::ifstream data_stream5(data5.c_str());
249    utility::Vector dummy(data_stream5); // this will give an exception
250  } catch (utility::IO_error& err) {
251    suite.err() << err.what() << std::endl;
252    this_ok=true; // good, exception thrown, test passed
253  }
254  try {
255    std::string data(test::filename("data/vector6.data"));
256    check_file_access(data);
257    std::ifstream data_stream(data.c_str());
258    utility::Vector dummy(data_stream); // this will give an exception
259  } catch (utility::IO_error& err) {
260    suite.err() << err.what() << std::endl;
261    this_ok=true; // good, exceoption thrown, test passed
262  }
263  suite.add(this_ok);
264
265  this_ok=false;
266  try {
267    std::string data(test::filename("data/vector7.data"));
268    check_file_access(data);
269    std::ifstream data_stream(data.c_str());
270    vec=utility::Vector(data_stream); // this will give an exception
271  } catch (utility::IO_error& err) {
272    suite.err() << err.what() << std::endl;
273    this_ok=true; // good, exceoption thrown, test passed
274  }
275  suite.add(this_ok);
276
277
278  // Test sort algorithms
279  {
280    std::string data3(test::filename("data/vector3.data"));
281    std::ifstream data_stream3(data3.c_str());
282    utility::Vector vec3(data_stream3);
283    std::vector<size_t> dummy;
284    dummy.push_back(100); // To make sure it works starting with a non-empty vector
285
286    utility::sort_index(dummy,vec3);
287    if(dummy.size()!=vec3.size()) {
288      suite.add(false);
289      suite.err() << "Vector of sorted indices has incorrect size" << std::endl;
290    }
291    if(dummy[0]!=11 || dummy[dummy.size()-1]!=8) {
292      suite.add(false);
293      suite.err() << "Vector of sorted indices incorrect" << std::endl;
294    }
295    size_t k=3;
296
297    utility::sort_smallest_index(dummy,k,vec3);
298    if(dummy.size()!=k) {
299      suite.add(false);
300      suite.err() << "Vector of sorted smallest indices has incorrect size" << std::endl;
301    }
302    if(dummy[0]!=11 || dummy[dummy.size()-1]!=9) {
303      suite.add(false);
304      suite.err() << "Vector of sorted smallest indices incorrect" << std::endl;
305    }
306
307    k=4;
308    utility::sort_largest_index(dummy,k,vec3);
309    if(dummy.size()!=k) {
310      suite.add(false);
311      suite.err() << "Vector of sorted largest indices has incorrect size" << std::endl;
312    }
313    if(dummy[0]!=8 || dummy[dummy.size()-1]!=5) {
314      suite.add(false);
315      suite.err() << "Vector of sorted largest indices incorrect" << std::endl;
316    }
317  }
318
319  {
320    utility::Vector vec(10, 2.3);
321    utility::VectorView vv(vec);
322    vec = vv;
323    if (vec.size()!=10){
324      suite.err() << "indirect self-assignment failed - size should be 10\n";
325      suite.add(false);
326    }
327    if (vec(0)!=2.3){
328      suite.err() << "indirect self-assignment failed - vec(0) should be 2.3\n";
329      suite.add(false);
330    }
331    utility::VectorView vv2(vec, 0, 5);
332    vec = vv2;
333    if (vec.size()!=5){
334      suite.err() << "indirect self-assignment failed - size should be 5\n";
335      suite.add(false);
336    }
337    if (vec(0)!=2.3){
338      suite.err() << "indirect self-assignment failed - vec(0) should be 2.3\n";
339      suite.add(false);
340    }
341  }
342
343  // test for ticket:285
344  {
345    theplu::yat::utility::Vector vec(10);
346    theplu::yat::utility::Vector vec2;
347    vec2 = vec;
348  }
349
350  // test for zero size constructor
351  {
352    theplu::yat::utility::Vector vec(0, 1.2);
353    theplu::yat::utility::Vector vec2(vec);
354  }
355
356  // test that sort can handle NaN properly
357  test_sort(suite);
358  // test for ticket 840
359  test_vector_mutable_assignment(suite);
360
361  return suite.return_value();
362}
363
364void test_sort(test::Suite& suite)
365{
366  utility::Vector vec(5);
367  vec(0) = 0;
368  vec(1) = 10;
369  vec(2) = std::numeric_limits<double>::quiet_NaN();
370  vec(3) = 2;
371  vec(4) = 5;
372
373  sort(vec);
374  for (size_t i=0; i<vec.size(); ++i)
375    for (size_t j=i+1; j<vec.size(); ++j) {
376      if (vec(j)<vec(i)) {
377        suite.err() << "Vector: '" << vec << "' is not sorted because '" 
378                    << vec(j) << "' is less than '" << vec(i) << "'\n";
379        suite.add(false);
380      }
381    }
382}
383
384
385void test_assign(utility::VectorMutable& lhs, const utility::Vector& rhs)
386{
387  lhs = rhs;
388}
389
390
391void test_assign2(utility::VectorMutable& lhs, const utility::VectorView& rhs)
392{
393  lhs = rhs;
394}
395
396
397void test_assign3(utility::VectorMutable& lhs, const utility::VectorBase& rhs)
398{
399  lhs = rhs;
400}
401
402
403void test_assign4(utility::VectorMutable& lhs, const utility::VectorMutable& rhs)
404{
405  lhs = rhs;
406}
407
408
409void test_vector_mutable_assignment(test::Suite&)
410{
411  utility::Vector vec(10, 1);
412  utility::Vector vec2(10, 2);
413  utility::VectorView view(vec2);
414  utility::VectorConstView const_view(vec2);
415  test_assign(vec2, vec);
416  test_assign(view, vec);
417
418  test_assign2(view, view);
419  test_assign2(vec, view);
420
421  test_assign3(view, view);
422  test_assign3(vec, view);
423  test_assign3(vec2, vec);
424  test_assign3(view, vec);
425  test_assign3(vec, const_view);
426
427  test_assign4(view, view);
428  test_assign4(vec, view);
429  test_assign4(vec2, vec);
430  test_assign4(view, vec);
431}
Note: See TracBrowser for help on using the repository browser.