source: trunk/test/vector_test.cc @ 1659

Last change on this file since 1659 was 1506, checked in by Peter, 13 years ago

fixes #434

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