Diana
0.8.3
|
00001 /* ----------------------------------------------------------------------------- 00002 * Diana process modelling, simulation and analysis software 00003 * Copyright (c) 2005, Michael Krasnyk 00004 * All rights reserved. 00005 * 00006 * This file is a part of Diana process modelling, simulation and analysis software 00007 * 00008 * Diana is free software; you can redistribute it and/or modify it 00009 * under the terms of the GNU General Public License as published 00010 * by the Free Software Foundation (see accompanying file LICENSE) 00011 * ----------------------------------------------------------------------------- 00012 * $Id: DianaArray.hpp 8160 2009-03-16 18:36:30Z miha $ 00013 * ----------------------------------------------------------------------------- 00014 * Description: 00015 */ 00016 00017 #ifndef DIANA_ARRAY_HPP 00018 #define DIANA_ARRAY_HPP 00019 00020 #include "CapeTypes.hpp" 00021 #include "CapeException.hpp" 00022 #include <cstdarg> 00023 #include <sstream> 00024 00025 namespace Diana{ 00026 00027 00033 template<typename _T> 00034 class array { 00035 public: 00036 typedef _T tvalue; 00037 typedef Common::Types::CapeArrayLong tindices; 00038 typedef std::vector<tvalue> tvalues; 00039 typedef size_t size_type; 00040 00041 public: 00045 inline array() {}; 00046 00058 array(const tindices& _dims) : dims(_dims) { 00059 int nelems; 00060 if(dims.size()>0) { 00061 nelems=1; 00062 for(tindices::size_type i=0;i<dims.size();i++) { 00063 if(dims[i]<0) throw std::string("array::array: incorrect dimensions"); 00064 nelems*=dims[i]; 00065 } 00066 }else if (dims.size()==0) { 00067 nelems=1; 00068 dims.push_back(1); 00069 } 00070 values.resize(nelems); 00071 } 00072 00077 array(int nelems, tvalue* vals) : dims(1) { 00078 if(nelems<0) { 00079 throw std::string("array::array: incorrect dimension"); 00080 } 00081 dims[0]=nelems; 00082 values.resize(nelems); 00083 for(int i=0;i<nelems;i++) values[i]=vals[i]; 00084 } 00085 00090 array(std::vector<tvalue> vals) : dims(1) { 00091 dims[0]=vals.size(); 00092 values=vals; 00093 } 00094 00100 array(int nrows, int ncols) : dims(2) { 00101 if((nrows<0)||(ncols<0)) { 00102 throw std::string("array::array: incorrect dimensions"); 00103 } 00104 int nelems=nrows*ncols; 00105 dims[0]=nrows; 00106 dims[1]=ncols; 00107 values.resize(nelems, 0.0); 00108 } 00109 00110 00115 array(const array& ar) { 00116 dims=ar.dimensions(); 00117 values=ar.get_values(); 00118 } 00119 00120 00125 array& operator=(const array& ar) { 00126 if(this!=&ar) { 00127 dims=ar.dimensions(); 00128 values=ar.get_values(); 00129 } 00130 return *this; 00131 } 00132 00133 00135 virtual ~array() {}; 00136 00143 inline int rank() const { return dims.size(); } 00144 00146 inline size_type size() const { return values.size(); } 00147 00149 inline const tindices& dimensions() const { return dims; } 00150 00152 inline Common::Types::CapeBoolean empty() const { return values.empty(); } 00153 00165 inline tvalue& at(size_type __n) { check_range(__n, "at"); return (*this)[__n]; }; 00166 00178 inline const tvalue& at(size_type __n) const { check_range(__n, "at"); return (*this)[__n]; }; 00179 00190 inline tvalue& operator[] (size_type __n) { return values[__n]; }; 00191 00203 inline const tvalue& operator[] (size_type __n) const { return values[__n]; }; 00204 00206 inline tvalue front() const { return values.front(); }; 00208 inline tvalue back() const { return values.back(); }; 00214 int find(const tindices& idx) const { 00215 if(idx.size()!=dims.size()) throw std::string("array::find: incorrect indices"); 00216 if(dims.size()<=0) return -1; 00217 int pos=idx[0]; 00218 for(tindices::size_type i=1;i<dims.size();i++) { 00219 if((idx[i]<0)||(idx[i]>=dims[i])) return -1; 00220 pos=pos*dims[i]+idx[i]; 00221 } 00222 return pos; 00223 } 00224 00230 void set_value(const tindices& idx, tvalue value) { 00231 const int pos=find(idx); 00232 if((pos<0)||(static_cast<tindices::size_type>(pos)>values.size())) 00233 throw std::string("array::set_value: incorrect indices"); 00234 values[pos]=value; 00235 } 00236 00237 00242 void set_value(tvalue value) { 00243 for(tindices::size_type i=0;i<values.size();i++) { 00244 values[i]=value; 00245 } 00246 } 00247 00252 void set_values(const tvalues& _values) { 00253 if(values.size()!=_values.size()) throw std::string("array::set_values: incorrect values array"); 00254 values=_values; 00255 } 00256 00262 void add_value(const tindices& idx, tvalue value) { 00263 const int pos=find(idx); 00264 if((pos<0)||(static_cast<tindices::size_type>(pos)>values.size())) 00265 throw std::string("array::add_value: incorrect indices"); 00266 values[pos]+=value; 00267 } 00268 00273 tvalue get_value(const tindices& idx) const { 00274 const int pos=find(idx); 00275 if((pos<0)||(static_cast<tindices::size_type>(pos)>values.size())) return 0.0; 00276 return values[pos]; 00277 } 00278 00286 tvalue get_value(...) const { 00287 va_list lst; 00288 va_start(lst, this); 00289 tindices idx(rank()); 00290 for(int i=0;i<rank();i++) { 00291 idx[i]=va_arg(lst, int); 00292 } 00293 va_end(lst); 00294 return get_value(idx); 00295 } 00296 00300 const tvalues& get_values() const { 00301 return values; 00302 } 00303 00304 private: 00320 void check_range(size_type __n, const char* func_name=NULL) const { 00321 if(__n>=values.size()) { 00322 std::ostringstream ostr; 00323 if(func_name!=NULL) ostr<<"Diana::array::"<<func_name; else ostr<<"array"; 00324 ostr<<": argument "<<__n<<" not in range [0,"<<values.size()<<"]"; 00325 throw ostr.str(); 00326 } 00327 } 00328 00329 00330 private: 00331 tvalues values; 00332 tindices dims; 00333 }; 00334 00336 typedef array<Common::Types::CapeDouble> DianaArray; 00337 00345 std::ostream& print(std::ostream& ostr, const DianaArray& ar, int nentries=-1); 00346 00352 std::ostream& print_matlab(std::ostream& ostr, const DianaArray& ar); 00353 00355 std::ostream& operator<<(std::ostream& os, const DianaArray& ar); 00356 }; 00357 00358 #endif // DIANA_ARRAY_HPP