libidx
|
00001 /*************************************************************************** 00002 * Copyright (C) 2008 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 IDXSPEC_HPP_ 00034 #define IDXSPEC_HPP_ 00035 00036 namespace ebl { 00037 00039 // idxdim: constructors 00040 00041 template <typename T> 00042 idxd<T>::~idxd() { 00043 if (offsets) { 00044 delete[] offsets; 00045 } 00046 } 00047 00048 template <typename T> 00049 idxd<T>::idxd() : offsets(NULL) { 00050 ndim = -1; 00051 memset(dims, -1, MAXDIMS * sizeof (T)); 00052 } 00053 00054 template <typename T> template <class T2> 00055 idxd<T>::idxd(const idx<T2> &i) : offsets(NULL) { 00056 setdims(i.spec); 00057 } 00058 00059 template <typename T> template <class T2> 00060 idxd<T>::idxd(const idxd<T2> &i) : offsets(NULL) { 00061 *this = i; 00062 } 00063 00064 template <typename T> 00065 idxd<T>::idxd(const idxspec &s) : offsets(NULL) { 00066 setdims(s); 00067 } 00068 00069 template <typename T> 00070 idxd<T>::idxd(const idxd<T> &s) : offsets(NULL) { 00071 setdims(s); 00072 } 00073 00074 template <typename T> 00075 idxd<T>::idxd(T s0, T s1, T s2, T s3, T s4, T s5, T s6, T s7) 00076 : offsets(NULL) { 00077 dims[0] = s0; dims[1] = s1; dims[2] = s2; dims[3] = s3; 00078 dims[4] = s4; dims[5] = s5; dims[6] = s6; dims[7] = s7; 00079 ndim = 0; 00080 for (int i = 0; i < MAXDIMS; i++) 00081 if (dims[i] >= 0) ndim++; 00082 else break; 00083 } 00084 00086 // idxdim: set dimensions 00087 00088 template <typename T> template <class Tidx> 00089 void idxd<T>::setdims(const idx<Tidx> &i) { 00090 setdims(i.spec); 00091 } 00092 00093 template <typename T> 00094 void idxd<T>::setdims(const idxspec &s) { 00095 ndim = s.ndim; 00096 // copy existing dimensions 00097 for (int i = 0; i < ndim; ++i) 00098 dims[i] = (T) s.dim[i]; 00099 // set remaining to -1 00100 int ord = std::max((int) 0, s.ndim); 00101 memset(dims + ord, -1, (MAXDIMS - ord) * sizeof (T)); 00102 } 00103 00104 template <typename T> 00105 void idxd<T>::setdims(const idxd<T> &s) { 00106 ndim = s.order(); 00107 // copy existing dimensions 00108 for (int i = 0; i < s.order(); ++i) 00109 dims[i] = s.dim(i); 00110 // set remaining to -1 00111 intg ord = std::max((intg) 0, s.order()); 00112 memset(dims + ord, -1, (MAXDIMS - ord) * sizeof (T)); 00113 // copy all offsets if exist 00114 if (s.offsets) { 00115 if (!offsets) 00116 offsets = new T[MAXDIMS]; 00117 memcpy(offsets, s.offsets, MAXDIMS * sizeof(T)); 00118 } else if (offsets) { // no offsets, delete existing 00119 delete[] offsets; 00120 offsets = NULL; 00121 } 00122 } 00123 00124 template <typename T> 00125 void idxd<T>::setdims(T n) { 00126 for (int i = 0; i < ndim; ++i) 00127 dims[i] = n; 00128 } 00129 00130 template <typename T> 00131 void idxd<T>::insert_dim(intg pos, T dim_size) { 00132 if (ndim + 1 > MAXDIMS) 00133 eblerror("error: cannot add another dimension to dim." 00134 << " Maximum number of dimensions (" << MAXDIMS << ") reached.") 00135 // check that dim_size is valid 00136 if (dim_size <= 0) 00137 eblerror("cannot set negative or zero dimension"); 00138 // check that all dimensions up to pos (excluded) are > 0. 00139 for (uint i = 0; i < pos; ++i) 00140 if (dims[i] <= 0) 00141 eblerror("error: cannot insert dimension " << pos 00142 << " after empty dimensions: " << *this); 00143 // add order of 1 00144 ndim++; 00145 if (ndim == 0) // one more if it was empty 00146 ndim++; 00147 // shift all dimensions until position pos 00148 for (uint i = ndim - 1; i > pos && i >= 1; i--) 00149 dims[i] = dims[i - 1]; 00150 if (offsets) 00151 for (uint i = ndim - 1; i > pos && i >= 1; i--) 00152 offsets[i] = offsets[i - 1]; 00153 // insert new dim 00154 dims[pos] = dim_size; 00155 if (offsets) 00156 offsets[pos] = 0; 00157 } 00158 00159 template <typename T> 00160 T idxd<T>::remove_dim(intg pos) { 00161 // check that dim_size is valid 00162 if (ndim == 0) 00163 eblerror("not enough dimensions for removing one in " << *this); 00164 T rdim = dim(pos); 00165 // shift all dimensions until position pos 00166 for (uint i = pos; i < ndim - 1; i++) 00167 dims[i] = dims[i + 1]; 00168 dims[ndim - 1] = -1; // empty last dimension 00169 if (offsets) { 00170 for (uint i = pos; i < ndim - 1; i++) 00171 offsets[i] = offsets[i + 1]; 00172 offsets[ndim - 1] = 0; // empty last offset 00173 } 00174 // decrease order by 1 00175 ndim--; 00176 return rdim; 00177 } 00178 00179 template <typename T> 00180 void idxd<T>::setdim(intg dimn, T size) { 00181 if (dimn >= ndim) 00182 eblerror("error: trying to set dimension " << dimn << " to size " 00183 << size << " but idxidm has only " << ndim 00184 << " dimension(s): " << *this); 00185 dims[dimn] = size; 00186 } 00187 00188 template <typename T> 00189 void idxd<T>::setoffset(intg dimn, T offset) { 00190 if (dimn >= ndim) 00191 eblerror("error: trying to set offset of dim " << dimn << " to " 00192 << offset << " but idxidm has only " << ndim 00193 << " dimension(s): " << *this); 00194 // allocate if not allocated 00195 if (!offsets) { 00196 offsets = new T[MAXDIMS]; 00197 memset(offsets, 0, MAXDIMS * sizeof (T)); 00198 } 00199 offsets[dimn] = offset; 00200 } 00201 00202 template <typename T> 00203 bool idxd<T>::has_offsets() const { 00204 return offsets != NULL; 00205 } 00206 00207 template <typename T> 00208 void idxd<T>::set_max(const idxd<T> &other) { 00209 if (other.order() != ndim) 00210 eblerror("expected same order in " << *this << " and " << other); 00211 for (uint i = 0; i < ndim; i++) 00212 dims[i] = std::max(dims[i], other.dim(i)); 00213 } 00214 00215 template <typename T> 00216 void idxd<T>::shift_dim(int d, int pos) { 00217 T dims2[MAXDIMS]; 00218 for (int i = 0, j = 0; i < MAXDIMS; ++i) { 00219 if (i == pos) 00220 dims2[i] = dims[d]; 00221 else { 00222 if (j == d) 00223 j++; 00224 dims2[i] = dims[j++]; 00225 } 00226 } 00227 memcpy(dims, dims2, MAXDIMS * sizeof (T)); 00228 if (offsets) 00229 eblerror("not implemented (TODO)"); 00230 } 00231 00233 // get dimensions 00234 00235 template <typename T> 00236 intg idxd<T>::order() const { 00237 return ndim; 00238 } 00239 00240 template <typename T> 00241 bool idxd<T>::empty() const { 00242 return ndim == -1; 00243 } 00244 00245 template <typename T> 00246 T idxd<T>::dim(intg dimn) const { 00247 if (dimn >= ndim) 00248 eblerror("trying to access size of dimension " << dimn 00249 << " but idxdim's maximum dimensions is " << ndim); 00250 return dims[dimn]; 00251 } 00252 00253 template <typename T> 00254 T idxd<T>::maxdim() const { 00255 T m = 0; 00256 for (intg i = 0; i < ndim; ++i) 00257 if (m < dims[i]) m = dims[i]; 00258 return m; 00259 } 00260 00261 template <typename T> 00262 T idxd<T>::offset(intg dimn) const { 00263 if (dimn >= ndim) 00264 eblerror("trying to access size of dimension " << dimn 00265 << " but idxdim's maximum dimensions is " << ndim); 00266 if (offsets) 00267 return offsets[dimn]; 00268 else 00269 return 0; 00270 } 00271 00272 template <typename T> 00273 bool idxd<T>::operator==(const idxd<T>& other) { 00274 if (other.ndim != ndim) 00275 return false; 00276 for (int i = 0; i < ndim; ++i) 00277 if (other.dim(i) != dim(i)) 00278 return false; 00279 return true; 00280 } 00281 00282 template <typename T> 00283 bool idxd<T>::operator!=(const idxd<T>& other) { 00284 return !(*this == other); 00285 } 00286 00288 // operators 00289 00290 // template <typename T> 00291 // idxd<T>& idxd<T>::operator=(const idxd<T> &d2) { 00292 // if ((void*)this != (void*)&d2) { // protect against invalid self-assignment 00293 // setdims(d2); 00294 // } 00295 // EDEBUG("this " << this << " " << *this << " <- d2 " << &d2 << " " << d2); 00296 // return *this; 00297 // } 00298 00299 template <typename T> 00300 idxd<T>& idxd<T>::operator=(idxd<T> d2) { 00301 setdims(d2); 00302 return *this; 00303 } 00304 00305 template <typename T> template <typename T2> 00306 idxd<T>& idxd<T>::operator=(const idxd<T2> &d2) { 00307 if ((void*)this != (void*)&d2) { // protect against invalid self-assignment 00308 ndim = d2.order(); 00309 for (intg i = 0; i < ndim; ++i) 00310 dims[i] = (T) d2.dim(i); 00311 if (offsets && !d2.has_offsets()) { 00312 delete[] offsets; 00313 offsets = NULL; 00314 } else if (d2.has_offsets()) { 00315 if (!offsets) 00316 offsets = new T[MAXDIMS]; 00317 for (intg i = 0; i < d2.order(); ++i) 00318 offsets[i] = (T) d2.offset(i); 00319 } 00320 } 00321 return *this; 00322 } 00323 00324 template <typename T> 00325 idxd<T> idxd<T>::operator*(const idxd<T> &d2) const { 00326 idxd<T> d = *this; 00327 if (d2.order() != d.order()) 00328 eblerror("expected same order idxd but got " << d << " and " << d2); 00329 for (int i = 0; i < d.order(); ++i) 00330 d.setdim(i, (T) (d.dim(i) * d2.dim(i))); 00331 if (offsets) 00332 for (int i = 0; i < d.order(); ++i) 00333 d.setoffset(i, (T) (d.offset(i) * d2.dim(i))); 00334 return d; 00335 } 00336 00337 template <typename T> template <typename T2> 00338 idxd<T> idxd<T>::operator*(const idxd<T2> &d2) const { 00339 idxd<T> d = *this; 00340 if (d2.order() != d.order()) 00341 eblerror("expected same order idxd but got " << d << " and " << d2); 00342 for (int i = 0; i < d.order(); ++i) 00343 d.setdim(i, (T) ((T2)(d.dim(i)) * d2.dim(i))); 00344 if (offsets) 00345 for (int i = 0; i < d.order(); ++i) 00346 d.setoffset(i, (T) ((T2)(d.offset(i)) * d2.dim(i))); 00347 return d; 00348 } 00349 00350 template <typename T> template <typename T2> 00351 idxd<T> idxd<T>::operator*(idxd<T2> &d2) { 00352 idxd<T> d = *this; 00353 if (d2.order() != d.order()) 00354 eblerror("expected same order idxd but got " << d << " and " << d2); 00355 for (int i = 0; i < d.order(); ++i) 00356 d.setdim(i, (T) ((T2)(d.dim(i)) * d2.dim(i))); 00357 if (offsets) 00358 for (int i = 0; i < d.order(); ++i) 00359 d.setoffset(i, (T) ((T2)(d.offset(i)) * d2.dim(i))); 00360 return d; 00361 } 00362 00363 template <typename T> template <typename T2> 00364 idxd<T> idxd<T>::operator*(T2 f) { 00365 idxd<T> d(*this); 00366 for (int i = 0; i < d.order(); ++i) 00367 d.setdim(i, (T) ((T2)(d.dim(i)) * f)); 00368 if (offsets) 00369 for (int i = 0; i < d.order(); ++i) 00370 d.setoffset(i, (T) ((T2)(d.offset(i)) * f)); 00371 return d; 00372 } 00373 00374 template <typename T> template <typename T2> 00375 idxd<T> idxd<T>::operator+(T2 f) { 00376 idxd<T> d = *this; 00377 for (int i = 0; i < d.order(); ++i) 00378 d.setdim(i, (T) ((T2)(d.dim(i)) + f)); 00379 return d; 00380 } 00381 00382 template <typename T> 00383 idxd<T> idxd<T>::operator+(idxd<T> &d2) { 00384 idxd<T> d = *this; 00385 if (d.order() != d2.order()) 00386 eblerror("cannot add two idxdim with different orders: " << d << " and " 00387 << d2); 00388 for (int i = 0; i < d.order(); ++i) 00389 d.setdim(i, d.dim(i) + d2.dim(i)); 00390 return d; 00391 } 00392 00393 template <typename T> 00394 bool idxd<T>::operator<=(idxd<T> &d2) { 00395 if (this->order() != d2.order()) 00396 eblerror("cannot add two idxdim with different orders: " << *this 00397 << " and " << d2); 00398 for (int i = 0; i < this->order(); ++i) 00399 if (this->dim(i) > d2.dim(i)) 00400 return false; 00401 return true; 00402 } 00403 00404 template <typename T> 00405 bool idxd<T>::operator>=(idxd<T> &d2) { 00406 if (this->order() != d2.order()) 00407 eblerror("cannot add two idxdim with different orders: " << *this 00408 << " and " << d2); 00409 for (int i = 0; i < this->order(); ++i) 00410 if (this->dim(i) < d2.dim(i)) 00411 return false; 00412 return true; 00413 } 00414 00416 00417 template <typename T> 00418 intg idxd<T>::nelements() { 00419 intg total = 1; 00420 for (int i = 0; i < ndim; ++i) 00421 total *= dim(i); 00422 return total; 00423 } 00424 00425 // midxdim /////////////////////////////////////////////////////////////////// 00426 00427 template <typename T> 00428 midxd<T>::midxd() { 00429 } 00430 00431 template <typename T> 00432 midxd<T>::midxd(uint n) : svector<idxd<T> >(n) { 00433 } 00434 00435 template <typename T> 00436 midxd<T>::~midxd() { 00437 } 00438 00439 template <typename T> 00440 midxd<T>::midxd(const idxd<T> &s) { 00441 push_back(s); 00442 } 00443 00444 template <typename T> template <typename T2> 00445 midxd<T>::midxd(const midxd<T2> &s) { 00446 *this = s; 00447 } 00448 00449 template <typename T> 00450 midxd<T> midxd<T>::narrow_copy(uint n, uint offset) { 00451 if (offset + n > this->size()) 00452 eblerror("out-of-bounds narrow of size " << n << " starting at offset " 00453 << offset << " in " << *this); 00454 midxd<T> m; 00455 for (typename midxd<T>::iterator i = this->begin() + offset; 00456 i != this->begin() + offset + n; ++i) 00457 if (i.exists()) m.push_back(*i); 00458 else m.push_back_empty(); 00459 return m; 00460 } 00461 00462 template <typename T> template <typename T2> 00463 void midxd<T>::push_back(const idxd<T2> &m) { 00464 svector<idxd<T> >::push_back(new idxd<T>(m)); 00465 } 00466 00467 template <typename T> 00468 void midxd<T>::push_back(const midxd<T> &m) { 00469 for (typename midxd<T>::const_iterator i = m.begin(); i != m.end(); ++i) { 00470 if (i.exists()) 00471 svector<idxd<T> >::push_back(new idxd<T>(*i)); 00472 else 00473 this->push_back_empty(); 00474 } 00475 } 00476 00477 // template <typename T> 00478 // void midxd<T>::push_back(midxd<T> &m) { 00479 // for (typename midxd<T>::iterator i = m.begin(); i != m.end(); ++i) 00480 // svector<idxd<T> >::push_back((*i); 00481 // } 00482 00483 template <typename T> 00484 midxd<T> midxd<T>::merge_all() { 00485 midxd<T> m; 00486 if (this->size() == 0) return m; 00487 // add first element 00488 idxd<T> &e0 = (*this)[0]; 00489 m.push_back(e0); 00490 // check that remaining ones are the same 00491 for (typename midxd<T>::iterator i = this->begin(1); i != this->end(); ++i){ 00492 if (((idxd<T>&)*i) != e0) 00493 eblerror("expected all elements to be the same in " << *this); 00494 } 00495 return m; 00496 } 00497 00498 template <typename T> template <typename T2> 00499 midxd<T>& midxd<T>::operator=(const midxd<T2> &other) { 00500 if ((void*) &other != (void*) this) { 00501 this->clear(); 00502 for (typename midxd<T2>::const_iterator i = other.begin(); 00503 i != other.end(); ++i) { 00504 if (i.exists()) this->push_back(*i); 00505 else this->push_back_empty(); 00506 } 00507 } 00508 return *this; 00509 } 00510 00511 // printing ////////////////////////////////////////////////////////////////// 00512 00513 template<class T> 00514 std::string& operator<<(std::string &o, const midxd<T> &v) { 00515 o << "[ "; 00516 for (typename midxd<T>::const_iterator i = v.begin(); 00517 i != v.end(); ++i) { 00518 if (i.exists()) 00519 o << *i << " "; 00520 else 00521 o << " null "; 00522 } 00523 o << "]"; 00524 return o; 00525 } 00526 00527 template<class T> 00528 std::ostream& operator<<(std::ostream &o, const midxd<T> &v) { 00529 o << "[ "; 00530 for (typename midxd<T>::const_iterator i = v.begin(); 00531 i != v.end(); ++i) { 00532 if (i.exists()) 00533 o << *i << " "; 00534 else 00535 o << " null "; 00536 } 00537 o << "]"; 00538 return o; 00539 } 00540 00541 } // namespace ebl 00542 00543 #endif /* IDXSPEC_HPP_ */