source: branches/0.14-stable/test/vector.cc @ 3616

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

merge r3612 to 0.14.x branch. refs #884

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