libidx
|
00001 /*************************************************************************** 00002 * Copyright (C) 2008 by Pierre Sermanet * 00003 * 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 IDXIO_HPP_ 00034 #define IDXIO_HPP_ 00035 00036 #include "idxops.h" 00037 00038 namespace ebl { 00039 00041 // helper functions 00042 00043 // template functions returning the magic number associated with a 00044 // particular type 00045 template <class T> inline int get_magic() { 00046 eblerror("matrix type not implemented."); return 0; } 00047 template <> inline int get_magic<ubyte>() {return MAGIC_BYTE_MATRIX; } 00048 template <> inline int get_magic<int>() {return MAGIC_INTEGER_MATRIX;} 00049 template <> inline int get_magic<float>() {return MAGIC_FLOAT_MATRIX; } 00050 template <> inline int get_magic<double>() {return MAGIC_DOUBLE_MATRIX; } 00051 template <> inline int get_magic<long>() {return MAGIC_LONG_MATRIX; } 00052 template <> inline int get_magic<uint>() {return MAGIC_UINT_MATRIX; } 00053 template <> inline int get_magic<uint64>() {return MAGIC_UINT64_MATRIX; } 00054 00055 // Pascal Vincent type 00056 template <class T> inline int get_magic_vincent() { 00057 eblerror("matrix type not implemented"); return 0; } 00058 template <> inline int get_magic_vincent<ubyte>(){return MAGIC_UBYTE_VINCENT;} 00059 template <> inline int get_magic_vincent<int>() {return MAGIC_INT_VINCENT;} 00060 template <> inline int get_magic_vincent<float>(){return MAGIC_FLOAT_VINCENT;} 00061 template <> inline int get_magic_vincent<double>() { 00062 return MAGIC_DOUBLE_VINCENT; } 00063 template <> inline int get_magic_vincent<long>() {return 0x0000; } 00064 00065 // type to string function for debug message. 00066 inline std::string get_magic_str(int magic) { 00067 switch (magic) { 00068 // standard format 00069 case MAGIC_BYTE_MATRIX: return "ubyte"; 00070 case MAGIC_PACKED_MATRIX: return "packed"; 00071 case MAGIC_SHORT_MATRIX: return "short"; 00072 case MAGIC_SHORT8_MATRIX: return "short8"; 00073 case MAGIC_ASCII_MATRIX: return "ascii"; 00074 case MAGIC_INTEGER_MATRIX: return "int"; 00075 case MAGIC_FLOAT_MATRIX: return "float"; 00076 case MAGIC_DOUBLE_MATRIX: return "double"; 00077 case MAGIC_LONG_MATRIX: return "long"; 00078 // non standard 00079 case MAGIC_UINT_MATRIX: return "uint"; 00080 case MAGIC_UINT64_MATRIX: return "uint64"; 00081 case MAGIC_INT64_MATRIX: return "int64"; 00082 // pascal vincent format 00083 case MAGIC_BYTE_VINCENT: return "byte (pascal vincent)"; 00084 case MAGIC_UBYTE_VINCENT: return "ubyte (pascal vincent)"; 00085 case MAGIC_SHORT_VINCENT: return "short (pascal vincent)"; 00086 case MAGIC_INT_VINCENT: return "int (pascal vincent)"; 00087 case MAGIC_FLOAT_VINCENT: return "float (pascal vincent)"; 00088 case MAGIC_DOUBLE_VINCENT: return "double (pascal vincent)"; 00089 default: 00090 string s; 00091 s << "unknown type (magic: " << reinterpret_cast<void*>(magic) << ")"; 00092 return s; 00093 } 00094 } 00095 00105 template <class T> inline void reverse_n(T *ptr, int n) { 00106 char *mptr = (char *) ptr; 00107 while(n--) 00108 { 00109 char tmp; 00110 char *uptr = mptr + sizeof (T); 00111 if (sizeof (T) >= 2) 00112 { tmp = mptr[0]; mptr[0]=uptr[-1]; uptr[-1]=tmp; } 00113 if (sizeof (T) >= 4) 00114 { tmp = mptr[1]; mptr[1]=uptr[-2]; uptr[-2]=tmp; } 00115 if (sizeof (T) >= 6) 00116 { tmp = mptr[2]; mptr[2]=uptr[-3]; uptr[-3]=tmp; } 00117 if (sizeof (T) >= 8) 00118 { tmp = mptr[3]; mptr[3]=uptr[-4]; uptr[-4]=tmp; } 00119 mptr = uptr; 00120 } 00121 } 00122 00123 template <class T> inline T endian(T ptr) { 00124 T v = ptr; 00125 // endianess test 00126 int endiantest = 1; 00127 if (*(char*)&endiantest) reverse_n(&v, 1); 00128 return v; 00129 } 00130 00131 template <typename T, typename T2> 00132 void read_cast_matrix(FILE *fp, idx<T2> &out) { 00133 idx<T> m(out.get_idxdim()); 00134 read_matrix_body(fp, m); 00135 idx_copy(m, out); 00136 } 00137 00138 template <typename T> 00139 void read_matrix_body(FILE *fp, idx<T> &m) { 00140 int res; 00141 idx_aloop1(i, m, T) { 00142 res = fread(&(*i), sizeof (T), 1, fp); 00143 } 00144 res = 0; // just to avoid warning 00145 } 00146 00148 // loading 00149 00150 template <typename T> idx<T> load_matrix(const std::string &filename) { 00151 return load_matrix<T>(filename.c_str()); 00152 } 00153 00154 template <typename T> idx<T> load_matrix(const char *filename) { 00155 // open file 00156 FILE *fp = fopen(filename, "rb"); 00157 if (!fp) 00158 eblthrow("load_matrix failed to open " << filename); 00159 // read it 00160 idx<T> m; 00161 try { 00162 m = load_matrix<T>(fp); 00163 fclose(fp); 00164 } catch(eblexception &e) { 00165 e << " while loading " << filename; 00166 throw e; 00167 } 00168 return m; 00169 } 00170 00171 template <typename T> 00172 void load_matrix(idx<T>& m, const std::string &filename) { 00173 load_matrix(m, filename.c_str()); 00174 } 00175 00176 template <typename T> void load_matrix(idx<T>& m, const char *filename) { 00177 // open file 00178 FILE *fp = fopen(filename, "rb"); 00179 if (!fp) 00180 eblthrow("load_matrix failed to open " << filename); 00181 // read it 00182 m = load_matrix<T>(fp, &m); 00183 fclose(fp); 00184 } 00185 00186 template <typename T> 00187 idx<T> load_matrix(FILE *fp, idx<T> *out_) { 00188 int magic; 00189 idxdim dims = read_matrix_header(fp, magic); 00190 idx<T> out; 00191 idx<T> *pout = &out; 00192 if (!out_) // if no input matrix, allocate new one 00193 out = idx<T>(dims); 00194 else // otherwise use given one 00195 pout = out_; 00196 00197 // resize out if necessary 00198 if (pout->get_idxdim() != dims) { // different order/dimensions 00199 // if order is different, it's from the input matrix, error 00200 if (pout->order() != dims.order()) 00201 eblerror("error: different orders: " << *pout << " " << dims); 00202 // resize output idx 00203 pout->resize(dims); 00204 } 00206 if ((magic == get_magic<T>()) || (magic == get_magic_vincent<T>())) { 00207 // read 00208 read_matrix_body(fp, *pout); 00209 } else { // different type, read original type, then copy/cast into out 00210 switch (magic) { 00211 case MAGIC_BYTE_MATRIX: 00212 case MAGIC_UBYTE_VINCENT: 00213 read_cast_matrix<ubyte>(fp, *pout); 00214 break ; 00215 case MAGIC_INTEGER_MATRIX: 00216 case MAGIC_INT_VINCENT: 00217 read_cast_matrix<int>(fp, *pout); 00218 break ; 00219 case MAGIC_FLOAT_MATRIX: 00220 case MAGIC_FLOAT_VINCENT: 00221 read_cast_matrix<float>(fp, *pout); 00222 break ; 00223 case MAGIC_DOUBLE_MATRIX: 00224 case MAGIC_DOUBLE_VINCENT: 00225 read_cast_matrix<double>(fp, *pout); 00226 break ; 00227 case MAGIC_LONG_MATRIX: 00228 read_cast_matrix<long>(fp, *pout); 00229 break ; 00230 case MAGIC_UINT_MATRIX: 00231 read_cast_matrix<uint>(fp, *pout); 00232 break ; 00233 case MAGIC_UINT64_MATRIX: 00234 read_cast_matrix<uint64>(fp, *pout); 00235 break ; 00236 case MAGIC_INT64_MATRIX: 00237 read_cast_matrix<int64>(fp, *pout); 00238 break ; 00239 default: 00240 eblerror("unknown magic number"); 00241 } 00242 } 00243 return *pout; 00244 } 00245 00246 template <typename T> 00247 midx<T> load_matrices(const std::string &filename, bool ondemand){ 00248 // open file 00249 file *f = new file(filename.c_str(), "rb"); 00250 FILE *fp = f->get_fp(); 00251 // first read offsets matrix 00252 idx<int64> p = load_matrix<int64>(fp); 00253 // switch loading mode 00254 if (ondemand) { // do not load data now 00255 fseek(fp, 0, SEEK_SET); // reset fp to beginning 00256 midx<T> all(p.get_idxdim(), f, &p); 00257 return all; 00258 } else { // load all data now 00259 cout << "Loading the whole dataset into memory" <<endl; 00260 // read all present matrices 00261 midx<T> all(p.dim(0)); 00262 for (uint i = 0; i < p.dim(0); ++i) { 00263 if (p.get(i) > 0) { // matrix is present, get it 00264 if (fseek(fp, p.get(i), SEEK_SET)) { 00265 fseek(fp, 0, SEEK_END); 00266 fpos_t fppos; 00267 fgetpos(fp, &fppos); 00268 #if defined(__WINDOWS__) || defined(__MAC__) 00269 eblerror("fseek to position " << p.get(i) << " failed, " 00270 << "file is " << (intg) fppos << " big"); 00271 #else 00272 eblerror("fseek to position " << p.get(i) << " failed, " 00273 << "file is " << (intg) fppos.__pos << " big"); 00274 #endif 00275 } 00276 // move fp to matrix beginning 00277 idx<T> m = load_matrix<T>(fp); 00278 all.set(m, i); 00279 } 00280 } 00281 delete f; 00282 return all; 00283 } 00284 } 00285 00287 // saving 00288 00289 template <typename T> 00290 bool save_matrix(idx<T>& m, const std::string &filename) { 00291 return save_matrix(m, filename.c_str()); 00292 } 00293 00294 template <typename T2, typename T> 00295 bool save_matrix(idx<T>& m, const std::string &filename) { 00296 idx<T2> m2(m.get_idxdim()); 00297 idx_copy(m, m2); 00298 return save_matrix(m2, filename.c_str()); 00299 } 00300 00301 // TODO: intg support 00302 template <typename T> bool save_matrix(idx<T>& m, const char *filename) { 00303 FILE *fp = fopen(filename, "wb"); 00304 if (!fp) { 00305 cerr << "save_matrix failed (" << filename << "): "; 00306 perror(""); 00307 return false; 00308 } 00309 bool ret = save_matrix(m, fp); 00310 if (!ret) 00311 cerr << "failed to write matrix " << m << " to " << filename << "." 00312 << endl; 00313 fclose(fp); 00314 return ret; 00315 } 00316 00317 // TODO: intg support 00318 template <typename T> bool save_matrix(idx<T>& m, FILE *fp) { 00319 int v, i; 00320 // write header 00321 v = get_magic<T>(); 00322 if (fwrite(&v, sizeof (int), 1, fp) != 1) return false; 00323 v = m.order(); 00324 if (fwrite(&v, sizeof (int), 1, fp) != 1) return false; 00325 for (i = 0; (i < m.order()) || (i < 3); ++i) { 00326 if (i < m.order()) 00327 v = m.dim(i); 00328 else 00329 v = 1; 00330 if (fwrite(&v, sizeof (int), 1, fp) != 1) return false; 00331 } 00332 // write body 00333 int res; 00334 idx_aloop1(k, m, T) 00335 res = fwrite(&(*k), sizeof (T), 1, fp); 00336 res = 0; // just to avoid compilation warning 00337 return true; 00338 } 00339 00340 template <typename T> 00341 bool save_matrices(midx<T>& m, const std::string &filename) { 00342 FILE *fp = fopen(filename.c_str(), "wb+"); 00343 if (!fp) { 00344 cerr << "save_matrix failed (" << filename << "): "; 00345 perror(""); 00346 return false; 00347 } 00348 // allocate offset matrix 00349 idx<int64> offsets(m.get_idxdim()); 00350 idx_clear(offsets); 00351 // save offsets matrix first 00352 bool ret = save_matrix(offsets, fp); 00353 if (!ret) { 00354 cerr << "failed to write matrix " << offsets << " to " << filename << "." 00355 << endl; 00356 fclose(fp); 00357 return false; 00358 } 00359 // then save all matrices contained in m 00360 fpos_t pos; 00361 // TODO: implement generic looping for midx 00362 if (m.order() == 1) { 00363 for (uint i = 0; i < m.dim(0); ++i) { 00364 if (m.exists(i)) { 00365 // save offset of matrix 00366 fgetpos(fp, &pos); 00367 #if defined(__WINDOWS__) || defined(__MAC__) 00368 offsets.set((int64) pos, i); 00369 #else 00370 offsets.set((int64) pos.__pos, i); 00371 #endif 00372 // save matrix to file 00373 idx<T> e = m.get(i); 00374 ret = save_matrix(e, fp); 00375 if (!ret) { 00376 cerr << "failed to write matrix " << e << " to " << filename << "." 00377 << endl; 00378 fclose(fp); 00379 return false; 00380 } 00381 } 00382 } 00383 } else if (m.order() == 2) { 00384 for (uint i = 0; i < m.dim(0); ++i) { 00385 for (uint j = 0; j < m.dim(1); ++j) { 00386 if (m.exists(i, j)) { 00387 // save offset of matrix 00388 fgetpos(fp, &pos); 00389 #if defined(__WINDOWS__) || defined(__MAC__) 00390 offsets.set((int64) pos, i, j); 00391 #else 00392 offsets.set((int64) pos.__pos, i, j); 00393 #endif 00394 // save matrix to file 00395 idx<T> e = m.get(i, j); 00396 ret = save_matrix(e, fp); 00397 if (!ret) { 00398 cerr << "failed to write matrix " << e << " to " 00399 << filename << "." << endl; 00400 fclose(fp); 00401 return false; 00402 } 00403 } 00404 } 00405 } 00406 } 00407 fclose(fp); 00408 // finally rewrite offset matrix at beginning of file 00409 fp = fopen(filename.c_str(), "rb+"); 00410 if (!fp) { 00411 cerr << "save_matrix failed (" << filename << "): "; 00412 perror(""); 00413 return false; 00414 } 00415 ret = save_matrix(offsets, fp); 00416 if (!ret) { 00417 cerr << "failed to write matrix " << offsets << " to " << filename << "." 00418 << endl; 00419 fclose(fp); 00420 return false; 00421 } 00422 fclose(fp); 00423 return ret; 00424 } 00425 00426 template <typename T> 00427 bool save_matrices_individually(midx<T>& m, const std::string &root, 00428 bool print) { 00429 intg id = 0; 00430 // TODO: implement generic looping for midx 00431 if (m.order() == 1) { 00432 for (uint i = 0; i < m.dim(0); ++i) { 00433 if (m.exists(i)) { 00434 // save matrix to file 00435 string fname; fname << root << "_" << id++ << ".mat"; 00436 idx<T> e = m.get(i); 00437 if (!save_matrix(e, fname)) return false; 00438 if (print) std::cout << "saved " << fname << std::endl; 00439 } 00440 } 00441 } else if (m.order() == 2) { 00442 for (uint i = 0; i < m.dim(0); ++i) { 00443 for (uint j = 0; j < m.dim(1); ++j) { 00444 if (m.exists(i, j)) { 00445 // save matrix to file 00446 string fname; fname << root << "_" << id++ << ".mat"; 00447 idx<T> e = m.get(i, j); 00448 if (!save_matrix(e, fname)) return false; 00449 if (print) std::cout << "saved " << fname << std::endl; 00450 } 00451 } 00452 } 00453 } 00454 return true; 00455 } 00456 00457 template <typename T> 00458 bool save_matrices(midx<T>& m1, midx<T> &m2, const std::string &filename) { 00459 FILE *fp = fopen(filename.c_str(), "wb+"); 00460 if (!fp) { 00461 cerr << "save_matrix failed (" << filename << "): "; 00462 perror(""); 00463 return false; 00464 } 00465 // target dimensions 00466 idxdim d1 = m1, d2 = m2, dd1 = m1, dd2 = m2; 00467 dd1.remove_dim(0); dd2.remove_dim(0); 00468 if (dd1 != dd2) 00469 eblerror("expected same dimensions but got " << dd1 << " and " << dd2); 00470 idxdim dall(d1); 00471 dall.setdim(0, d1.dim(0) + d2.dim(0)); 00472 // allocate offset matrix 00473 idx<int64> offsets(dall); 00474 idx_clear(offsets); 00475 // save offsets matrix first 00476 bool ret = save_matrix(offsets, fp); 00477 if (!ret) { 00478 cerr << "failed to write matrix " << offsets << " to " << filename << "." 00479 << endl; 00480 fclose(fp); 00481 return false; 00482 } 00483 // then save all matrices contained in m 00484 fpos_t pos; 00485 // TODO: implement generic looping for midx 00486 midx<T> *m = &m1; 00487 if (dall.order() == 1) { 00488 for (uint i = 0, k = 0; i < dall.dim(0); ++i, ++k) { 00489 // switch to second matrix 00490 if (i == m1.dim(0)) { 00491 m = &m2; 00492 k = 0; // reset iterator 00493 } 00494 if (m->exists(k)) { 00495 // save offset of matrix 00496 fgetpos(fp, &pos); 00497 #if defined(__WINDOWS__) || defined(__MAC__) 00498 offsets.set((int64) pos, i); 00499 #else 00500 offsets.set((int64) pos.__pos, i); 00501 #endif 00502 // save matrix to file 00503 idx<T> e = m->get(k); 00504 ret = save_matrix(e, fp); 00505 if (!ret) { 00506 cerr << "failed to write matrix " << e << " to " << filename << "." 00507 << endl; 00508 fclose(fp); 00509 return false; 00510 } 00511 } 00512 } 00513 } else if (m->order() == 2) { 00514 for (uint i = 0, k = 0; i < dall.dim(0); ++i, ++k) { 00515 // switch to second matrix 00516 if (i == m1.dim(0)) { 00517 m = &m2; 00518 k = 0; // reset iterator 00519 } 00520 for (uint j = 0; j < m->dim(1); ++j) { 00521 if (m->exists(k, j)) { 00522 // save offset of matrix 00523 fgetpos(fp, &pos); 00524 #if defined(__WINDOWS__) || defined(__MAC__) 00525 offsets.set((int64) pos, i, j); 00526 #else 00527 offsets.set((int64) pos.__pos, i, j); 00528 #endif 00529 // save matrix to file 00530 idx<T> e = m->get(k, j); 00531 ret = save_matrix(e, fp); 00532 if (!ret) { 00533 cerr << "failed to write matrix " << e << " to " 00534 << filename << "." << endl; 00535 fclose(fp); 00536 return false; 00537 } 00538 } 00539 } 00540 } 00541 } 00542 fclose(fp); 00543 // finally rewrite offset matrix at beginning of file 00544 fp = fopen(filename.c_str(), "rb+"); 00545 if (!fp) { 00546 cerr << "save_matrix failed (" << filename << "): "; 00547 perror(""); 00548 return false; 00549 } 00550 ret = save_matrix(offsets, fp); 00551 if (!ret) { 00552 cerr << "failed to write matrix " << offsets << " to " << filename << "." 00553 << endl; 00554 fclose(fp); 00555 return false; 00556 } 00557 fclose(fp); 00558 return ret; 00559 } 00560 00561 template <typename T> 00562 bool save_matrices(std::list<std::string> &filenames, 00563 const std::string &filename) { 00564 if (filenames.size() == 0) eblerror("expected a non-empty list"); 00565 FILE *fp = fopen(filename.c_str(), "wb+"); 00566 if (!fp) { 00567 cerr << "save_matrix failed (" << filename << "): "; 00568 perror(""); 00569 return false; 00570 } 00571 // determine matrices dims 00572 idxdim alld(filenames.size()); 00573 std::string s = filenames.front(); 00574 bool multi = has_multiple_matrices(s.c_str()); 00575 if (multi) { 00576 midx<T> e = load_matrices<T>(s); 00577 idxdim d = e.get_idxdim(); 00578 for (uint i = 0; i < d.order(); ++i) 00579 alld.insert_dim(d.order(), d.dim(i)); 00580 } 00581 // allocate offsets matrix 00582 idx<int64> offsets(alld); 00583 idx_clear(offsets); 00584 // put this matrix first in the file 00585 bool ret = save_matrix(offsets, fp); 00586 if (!ret) { 00587 cerr << "failed to write matrix " << offsets << " to " << filename << "." 00588 << endl; 00589 fclose(fp); 00590 return false; 00591 } 00592 // then save all matrices 00593 fpos_t pos; 00594 intg j = 0; 00595 for (std::list<std::string>::iterator i = filenames.begin(); 00596 i != filenames.end(); ++i, ++j) { 00597 if (multi) { // each matrix is composed of multiple matrices 00598 midx<T> e = load_matrices<T>(*i, false); 00599 for (uint k = 0; k < e.dim(0); ++k) { 00600 // save offset of matrix 00601 fgetpos(fp, &pos); 00602 #if defined(__WINDOWS__) || defined(__MAC__) 00603 offsets.set((int64) pos, j, k); 00604 #else 00605 offsets.set((int64) pos.__pos, j, k); 00606 #endif 00607 // save matrix into file 00608 idx<T> ee = e.get(k); 00609 ret = save_matrix(ee, fp); 00610 if (!ret) { 00611 cerr << "failed to write matrix " << k << " to " << filename << "." 00612 << endl; 00613 fclose(fp); 00614 return false; 00615 } 00616 } 00617 } else { 00618 idx<T> e = load_matrix<T>(*i); 00619 // save offset of matrix 00620 fgetpos(fp, &pos); 00621 #if defined(__WINDOWS__) || defined(__MAC__) 00622 offsets.set((int64) pos, j); 00623 #else 00624 offsets.set((int64) pos.__pos, j); 00625 #endif 00626 // save matrix into file 00627 ret = save_matrix(e, fp); 00628 if (!ret) { 00629 cerr << "failed to write matrix " << e << " to " << filename << "." 00630 << endl; 00631 fclose(fp); 00632 return false; 00633 } 00634 } 00635 } 00636 fclose(fp); 00637 // finally rewrite offset matrix at beginning of file 00638 fp = fopen(filename.c_str(), "rb+"); 00639 if (!fp) { 00640 cerr << "save_matrix failed (" << filename << "): "; 00641 perror(""); 00642 return false; 00643 } 00644 ret = save_matrix(offsets, fp); 00645 if (!ret) { 00646 cerr << "failed to write matrix " << offsets << " to " << filename << "." 00647 << endl; 00648 fclose(fp); 00649 return false; 00650 } 00651 fclose(fp); 00652 return ret; 00653 } 00654 00655 template <typename T> 00656 bool save_matrix(std::list<std::string> &filenames, 00657 const std::string &filename) { 00658 if (filenames.size() == 0) eblerror("expected a non-empty list"); 00659 FILE *fp = fopen(filename.c_str(), "wb+"); 00660 if (!fp) { 00661 cerr << "save_matrix failed (" << filename << "): "; 00662 perror(""); 00663 return false; 00664 } 00665 // determine matrices dims 00666 idxdim alld(filenames.size()); 00667 std::string s = filenames.front(); 00668 bool multi = has_multiple_matrices(s.c_str()); 00669 if (multi) 00670 eblerror("expected a single-matrix file in " << s.c_str()); 00671 idx<T> e = load_matrix<T>(s); 00672 idxdim d = e.get_idxdim(); 00673 for (uint i = 0; i < d.order(); ++i) 00674 alld.insert_dim(alld.order(), d.dim(i)); 00675 // allocate matrix 00676 idx<T> all(alld); 00677 idx_clear(all); 00678 // add all matrices 00679 intg j = 0; 00680 for (std::list<std::string>::iterator i = filenames.begin(); 00681 i != filenames.end(); ++i, ++j) { 00682 if (multi) 00683 eblerror("expected a single-matrix file in " << s.c_str()); 00684 idx<T> e = all.select(0, j); 00685 load_matrix<T>(e, *i); 00686 } 00687 // save matrix 00688 return save_matrix(all, filename); 00689 } 00690 00691 } // end namespace ebl 00692 00693 #endif /* IDXIO_HPP_ */