ivl 679
ivl/details/array/impl/index_array.hpp
00001 /* This file is part of the ivl C++ library <http://image.ntua.gr/ivl>.
00002    A C++ template library extending syntax towards mathematical notation.
00003 
00004    Copyright (C) 2012 Yannis Avrithis <iavr@image.ntua.gr>
00005    Copyright (C) 2012 Kimon Kontosis <kimonas@image.ntua.gr>
00006 
00007    ivl is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU Lesser General Public License 
00009    version 3 as published by the Free Software Foundation.
00010 
00011    Alternatively, you can redistribute it and/or modify it under the terms 
00012    of the GNU General Public License version 2 as published by the Free 
00013    Software Foundation.
00014 
00015    ivl is distributed in the hope that it will be useful,
00016    but WITHOUT ANY WARRANTY; without even the implied warranty of
00017    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
00018    See the GNU General Public License for more details.
00019 
00020    You should have received a copy of the GNU General Public License 
00021    and a copy of the GNU Lesser General Public License along 
00022    with ivl. If not, see <http://www.gnu.org/licenses/>. */
00023 
00024 #ifndef IVL_ARRAY_DETAILS_INDEX_ARRAY_HPP
00025 #define IVL_ARRAY_DETAILS_INDEX_ARRAY_HPP
00026 
00027 namespace ivl {
00028 
00029 struct index_array_all_type
00030 {
00031 };
00032 
00035 class index_array
00036 : public array<size_t, data::stack<4, true> >
00037 , public size_range
00038 {
00039 protected:
00040 
00041 public:
00042         typedef array<size_t, data::stack<4, true> > size_array;
00043 
00044         using size_array::operator[];
00045         using size_array::operator=;
00046 
00047         enum index_array_type {
00048                 ARRAY,
00049                 RANGE,
00050                 ALL
00051         };
00052 
00053         index_array_type indtype;
00054 
00055         // Constructors
00056         index_array() : size_array(1,(size_t)(0)), indtype(ALL) { }
00057 
00058         index_array(const size_array& sa) : size_array(sa), indtype(ARRAY) { }
00059 
00060         template <class S>
00061         index_array(const array<size_t, S>& sa) : size_array(sa), indtype(ARRAY) { }
00062 
00063         index_array(size_t s) : size_array(1,s), indtype(ARRAY) { }
00064 
00065         index_array(const size_range& sr) : size_range(sr), indtype(RANGE) { }
00066 
00067         index_array(const range<int>& sr) : size_range(sr), indtype(RANGE) { }
00068 
00069         index_array(const index_array_all_type& sa) : indtype(ALL) { }
00070 
00071         index_array(const index_array& ia)
00072                 : size_array(ia), size_range(ia), indtype(ia.indtype) { }
00073 
00074 
00075         // Operator=
00076         index_array& operator= (const size_array& sa)
00077         {
00078                 size_array::operator=(sa);
00079                 indtype = ARRAY;
00080                 return *this;
00081         }
00082 
00083         template <class S>
00084         index_array& operator= (const array<size_t, S>& sa)
00085         {
00086                 size_array::operator=(sa);
00087                 indtype = ARRAY;
00088                 return *this;
00089         }
00090 
00091         template <class S>
00092         index_array& operator= (size_t s)
00093         {
00094                 size_array::resize(1, s);
00095                 indtype = ARRAY;
00096                 return *this;
00097         }
00098 
00099         index_array& operator =(const size_range &a)
00100         {
00101                 size_range::operator=(a);
00102                 indtype = RANGE;
00103                 return *this;
00104         }
00105         index_array& operator =(const range<int> &a)
00106         {
00107                 size_range::operator=(a);
00108                 indtype = RANGE;
00109                 return *this;
00110         }
00111 
00112         index_array& operator =(const index_array_all_type& sa)
00113         {
00114                 indtype = ALL;
00115                 return *this;
00116         }
00117 
00118         index_array& operator =(const index_array &a)
00119         {
00120                 const size_array &tmp = a;
00121                 size_array::operator=(tmp);
00122                 size_range::operator=(a);
00123                 indtype = a.indtype;
00124                 return *this;
00125         }
00126 
00127 
00128 
00129         inline bool is_all() const;
00130         inline bool is_array() const;
00131         inline bool is_range() const;
00132         inline size_t length() const;
00133         inline size_t length(const size_array& sizes, size_t dim = 0) const;
00134         inline size_t starts() const;
00135         inline size_t ends() const;
00136         inline size_t steps() const;
00137         inline size_array cast() const; 
00138 
00139         inline size_array& as_array()
00140         {
00141                 return static_cast<size_array&>(*this);
00142         }
00143         inline const size_array& as_array() const
00144         {
00145                 return static_cast<const size_array&>(*this);
00146         }
00147         inline size_range& as_range()
00148         {
00149                 return static_cast<size_range&>(*this);
00150         }
00151         inline const size_range& as_range() const
00152         {
00153                 return static_cast<const size_range&>(*this);
00154         }
00155 };
00156 
00157 inline
00158 size_t index_array::length() const
00159 {
00160         switch (indtype) {
00161         case ARRAY:
00162                 return size_array::length();
00163         case RANGE:
00164                 return size_range::length();
00165         default:
00166         // In case we have ALL, the length is not known.
00167         // We need the array this index is applied to to compute it.
00168                 return 0;
00169         }
00170 }
00171 
00172 inline
00173 size_t index_array::length(const size_array& sizes, size_t dim) const
00174 {
00175         switch (indtype) {
00176         case ARRAY:
00177                 return size_array::length();
00178         case RANGE:
00179                 return size_range::length();
00180         case ALL:
00181                 return sizes[dim];
00182         default:
00183                 return 0;
00184         }
00185 }
00186 
00187 inline
00188 size_t index_array::starts() const
00189 {
00190         switch (indtype) {
00191         case ARRAY:
00192                 return size_array::operator[](0);
00193         case RANGE:
00194                 return size_range::first;
00195         case ALL:
00196         default:
00197                 return 0;
00198         }
00199 }
00200 
00201 inline
00202 size_t index_array::ends() const
00203 {
00204         switch (indtype) {
00205         case ARRAY:
00206                 return size_array::operator[](length() - 1);
00207         case RANGE:
00208                 return size_range::last;
00209         case ALL:
00210         default:
00211                 return 0;
00212         }
00213 }
00214 
00215 inline
00216 size_t index_array::steps() const
00217 {
00218         switch (indtype) {
00219         case RANGE:
00220                 return size_range::step;
00221         case ALL:
00222                 return 1;
00223         case ARRAY:
00224                 return 1; // steps() is meaningless in case of array.
00225                                   // however the minimum step is 1 and has to be returned
00226                                   // because it is used in subarray.
00227         default:
00228                 return 0;
00229         }
00230 }
00231 
00232 inline
00233 index_array::size_array index_array::cast() const
00234 {
00235         size_array a;
00236         const size_array& myself = *this;
00237 
00238         switch (indtype) {
00239         case RANGE:
00240                 a = size_array(size_range::length());
00241                 for (size_t i = 0; i < a.length(); i++)
00242                         a[i] = first + i * step;
00243                 return a;
00244         case ALL:
00245                 return size_array(0);
00246         case ARRAY:
00247                 return myself;
00248         default:
00249                 return size_array(0);
00250         }
00251 }
00252 
00253 /*
00254 inline index_array::type index_array::index_type() const
00255 {
00256         return indtype;
00257 }
00258 */
00259 
00260 inline
00261 bool index_array::is_all() const
00262 {
00263         return (indtype == ALL);
00264 }
00265 
00266 inline
00267 bool index_array::is_array() const
00268 {
00269         return (indtype == ARRAY);
00270 }
00271 
00272 inline
00273 bool index_array::is_range() const
00274 {
00275         return (indtype == RANGE);
00276 }
00277 
00279 inline
00280 std::ostream& operator<<(std::ostream& os, const index_array& a)
00281 {
00282         if (a.is_all())
00283                 os << ":";
00284         else if(a.is_range())
00285                 os << a.as_range();
00286         else if(a.is_array())
00287                 os << a.as_array();
00288 
00289         return os;
00290 }
00291 
00292 // index_array NON_MEMBER FUNCTIONS
00293 
00294 inline
00295 index_array_all_type all()
00296 {
00297         return index_array_all_type();
00298 }
00299 
00300 } // namespace ivl
00301 
00302 #endif // IVL_ARRAY_DETAILS_INDEX_ARRAY_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations