libidx
|
00001 /*************************************************************************** 00002 * Copyright (C) 2011 by Yann LeCun and Pierre Sermanet * 00003 * yann@cs.nyu.edu, pierre.sermanet@gmail.com * 00004 * All rights reserved. 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions are met: 00008 * * Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * * Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * * Redistribution under a license not approved by the Open Source 00014 * Initiative (http://www.opensource.org) must display the 00015 * following acknowledgement in all advertising material: 00016 * This product includes software developed at the Courant 00017 * Institute of Mathematical Sciences (http://cims.nyu.edu). 00018 * * The names of the authors may not be used to endorse or promote products 00019 * derived from this software without specific prior written permission. 00020 * 00021 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 00022 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00023 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00024 * DISCLAIMED. IN NO EVENT SHALL ThE AUTHORS BE LIABLE FOR ANY 00025 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00026 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00027 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00028 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00029 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00030 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00031 ***************************************************************************/ 00032 00033 #ifndef IDXITER_H_ 00034 #define IDXITER_H_ 00035 00036 namespace ebl { 00037 00038 // forward declarations 00039 template <typename T> class idx; 00040 00042 // idx Iterators are a subclass of idx 00043 00048 template <class T> class idxlooper : public idx<T> { 00049 public: 00051 idxlooper(idx<T> &m, int ld); 00053 bool notdone(); 00055 T *next(); 00056 void operator++(); 00057 protected: 00058 intg i; // loop index 00059 intg dimd; // number of elements to iterated upon 00060 intg modd; // stride in dimension being iterated upon 00061 }; 00062 00064 // idx Iterators: gives you a pointer to the actual data, 00065 // unlike idxlooper which gives you another idx. 00066 00081 template <class T> class idxiter { 00082 public: 00084 idxiter(); 00087 T *init(const idx<T> &m); 00089 bool notdone(); 00091 T *next(); 00093 T& operator*() { return *data; } 00094 protected: 00095 T *data; 00096 intg i; 00097 intg n; 00098 int j; 00099 intg d[MAXDIMS]; 00100 const idx<T> *iterand; 00101 }; 00102 00103 template <class T> class contiguous_idxiter { 00104 public: 00105 inline contiguous_idxiter() {} 00106 inline contiguous_idxiter(idx<T> & m) 00107 :current(m.storage->data + m.spec.offset), end(NULL) { 00108 #ifdef __DEBUG__ 00109 if (!m.contiguousp()) 00110 eblerror("this idx should be contiguous"); 00111 #endif 00112 end = current + (unsigned)m.nelements(); 00113 } 00114 //inline intg i (); 00115 inline bool notdone () const {return current < end;} 00116 inline void next() {++current;} 00117 inline T& operator * () {return *current;} 00118 inline void operator += (intg i) {current += i;} 00119 protected: // members 00120 T *current, *end; 00121 }; 00122 00123 template <class T> class noncontiguous_idxiter { 00124 public: 00125 T* data; 00126 intg d[MAXDIMS]; 00127 intg i, n; 00128 int j, jmax; 00129 idx<T>* iterand; 00130 inline noncontiguous_idxiter() {} 00131 inline noncontiguous_idxiter(idx<T> & m) 00132 :data(m.storage->data + m.spec.offset), i(0), n(m.spec.nelements()), 00133 j(m.spec.ndim - 1), jmax(m.spec.ndim - 1), iterand(&m) { 00134 memset(d, 0, MAXDIMS * sizeof(intg)); 00135 } 00136 inline bool notdone () const {return i < n;} 00137 inline void next () { 00138 ++i; 00139 while (j >= 0) { 00140 if (++d[j] >= iterand->spec.dim[j]) { 00141 data -= iterand->spec.dim[j] * iterand->spec.mod[j]; //TODO precalculate? 00142 d[j--] = -1; 00143 continue; 00144 } 00145 data += iterand->spec.mod[j]; 00146 if (j != jmax) 00147 j++; 00148 else 00149 return; 00150 } 00151 } 00152 inline T& operator * () {return *data;} 00153 inline void operator += (intg k) { 00154 if (k + i >= n) { 00155 i = n; 00156 return; 00157 } 00158 i += k; 00159 intg m = 1; 00160 intg t; 00161 while ((t = (iterand->spec.dim[j] - d[j]) * m) < k) { 00162 k += d[j]; 00163 d[j] = 0; 00164 data -= d[j] * iterand->spec.mod[j]; 00165 m *= iterand->spec.dim[j]; 00166 --j; 00167 } 00168 for(;;) { 00169 t = k/m; 00170 d[j] += t; 00171 data += iterand->spec.mod[j] * t; 00172 if (j == jmax) 00173 return; 00174 ++j; 00175 k -= t*m; 00176 m /= iterand->spec.dim[j]; 00177 } 00178 } 00179 }; 00180 00181 #define new_fast_idxiter(itr, src, type, code) \ 00182 if (src.contiguousp()) { \ 00183 contiguous_idxiter<type> itr (src); \ 00184 code \ 00185 } else { \ 00186 noncontiguous_idxiter<type> itr (src); \ 00187 code \ 00188 } 00189 00190 #define idx_aloopf1(itr0, src0, type0, code) \ 00191 if (src0.contiguousp()) { \ 00192 for (contiguous_idxiter<type0> itr0 (src0); itr0.notdone(); \ 00193 itr0.next()) \ 00194 code \ 00195 } else { \ 00196 for (noncontiguous_idxiter<type0> itr0 (src0); itr0.notdone(); \ 00197 itr0.next()) \ 00198 code \ 00199 } 00200 00201 #define idx_aloopf2(itr0, src0, type0, itr1, src1, type1, code) \ 00202 if (src0.contiguousp()) { \ 00203 if (src1.contiguousp()) { \ 00204 contiguous_idxiter<type0> itr0 (src0); \ 00205 contiguous_idxiter<type1> itr1 (src1); \ 00206 for (; itr0.notdone(); itr0.next(), itr1.next()) \ 00207 code \ 00208 } else { \ 00209 contiguous_idxiter<type0> itr0 (src0); \ 00210 noncontiguous_idxiter<type1> itr1 (src1); \ 00211 for (; itr0.notdone(); itr0.next(), itr1.next()) \ 00212 code \ 00213 } \ 00214 } else { \ 00215 if (src1.contiguousp()) { \ 00216 noncontiguous_idxiter<type0> itr0 (src0); \ 00217 contiguous_idxiter<type1> itr1 (src1); \ 00218 for (; itr0.notdone(); itr0.next(), itr1.next()) \ 00219 code \ 00220 } else { \ 00221 noncontiguous_idxiter<type0> itr0 (src0); \ 00222 noncontiguous_idxiter<type1> itr1 (src1); \ 00223 for (; itr0.notdone(); itr0.next(), itr1.next()) \ 00224 code \ 00225 } \ 00226 } 00227 00228 #define idx_aloopf3(itr0, src0, type0, itr1, src1, type1, itr2, src2, \ 00229 type2, code) \ 00230 new_fast_idxiter(itr0, src0, type0, { \ 00231 new_fast_idxiter(itr1, src1, type1, { \ 00232 new_fast_idxiter(itr2, src2, type1, { \ 00233 for (; itr0.notdone(); itr0.next(), itr1.next(), itr2.next()) \ 00234 code \ 00235 }) \ 00236 }) \ 00237 }) 00238 00239 } // end namespace ebl 00240 00241 #include "idxiter.hpp" 00242 00243 #endif /* IDXITER_H_ */