Diana  0.8.3
DianaArray.hpp
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