PLearn 0.1
|
00001 // -*- C++ -*- 00002 00003 // DoubleAccessSparseMatrix.cc 00004 // 00005 // PLearn (A C++ Machine Learning Library) 00006 // Copyright (C) 2002 Christian Jauvin 00007 // 00008 // Redistribution and use in source and binary forms, with or without 00009 // modification, are permitted provided that the following conditions are met: 00010 // 00011 // 1. Redistributions of source code must retain the above copyright 00012 // notice, this list of conditions and the following disclaimer. 00013 // 00014 // 2. Redistributions in binary form must reproduce the above copyright 00015 // notice, this list of conditions and the following disclaimer in the 00016 // documentation and/or other materials provided with the distribution. 00017 // 00018 // 3. The name of the authors may not be used to endorse or promote 00019 // products derived from this software without specific prior written 00020 // permission. 00021 // 00022 // THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 00023 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00024 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 00025 // NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00026 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 00027 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00028 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00029 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00030 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00031 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00032 // 00033 // This file is part of the PLearn library. For more information on the PLearn 00034 // library, go to the PLearn Web site at www.plearn.org 00035 00036 /* ******************************************************* 00037 * $Id: DoubleAccessSparseMatrix_impl.h 3994 2005-08-25 13:35:03Z chapados $ 00038 ******************************************************* */ 00039 00042 namespace PLearn { 00043 using namespace std; 00044 00045 template<class T> 00046 DoubleAccessSparseMatrix<T>::DoubleAccessSparseMatrix(int n_rows, int n_cols, string _name, int _mode, bool _double_access, T _null_elem) : name(_name), mode(_mode), double_access(_double_access), height(n_rows), width(n_cols), null_elem(_null_elem) 00047 { 00048 if (mode != ROW_WISE && mode != COLUMN_WISE) PLERROR("mode must be either row-wise or column-wise"); 00049 00050 if (double_access) 00051 { 00052 rows.resize(height); 00053 cols.resize(width); 00054 } else if (mode == ROW_WISE) 00055 { 00056 rows.resize(height); 00057 } else 00058 { 00059 cols.resize(width); 00060 } 00061 } 00062 00063 template <class T> 00064 void DoubleAccessSparseMatrix<T>::resize(int n_rows, int n_cols, bool clear_data) 00065 { 00066 height = n_rows; 00067 width = n_cols; 00068 if (double_access) 00069 { 00070 rows.resize(n_rows); 00071 cols.resize(n_cols); 00072 } else if (mode == ROW_WISE) 00073 { 00074 rows.resize(n_rows); 00075 } else 00076 { 00077 cols.resize(n_cols); 00078 } 00079 if (clear_data) 00080 clear(); 00081 } 00082 00083 template <class T> 00084 void DoubleAccessSparseMatrix<T>::clear() 00085 { 00086 if (mode == ROW_WISE || double_access) 00087 { 00088 // norman: added explicit cast 00089 int rs = (int)rows.size(); 00090 for (int i = 0; i < rs; i++) 00091 rows[i].clear(); 00092 } 00093 if (mode == COLUMN_WISE || double_access) 00094 { 00095 // norman: added explicit cast 00096 int cs = (int)cols.size(); 00097 for (int i = 0; i < cs; i++) 00098 cols[i].clear(); 00099 } 00100 } 00101 00102 template <class T> 00103 void DoubleAccessSparseMatrix<T>::clearRow(int i, bool force_synchro_if_double_accessible) 00104 { 00105 if (!double_access) 00106 { 00107 if (mode == COLUMN_WISE) 00108 PLERROR("cannot access rows in the column-wise matrix"); 00109 else 00110 rows[i].clear(); 00111 } else 00112 { 00113 if (force_synchro_if_double_accessible) 00114 { 00115 for (int j = 0; j < width; j++) 00116 { 00117 map<int, T>& col_j = cols[j]; 00118 if (col_j.find(i) != col_j.end()) 00119 col_j.erase(i); 00120 } 00121 } else 00122 { 00123 PLWARNING("can only clear rows in the row-wise matrix (internal matrices are now out of sync)"); 00124 rows[i].clear(); 00125 } 00126 } 00127 } 00128 00129 template <class T> 00130 void DoubleAccessSparseMatrix<T>::clearCol(int j, bool force_synchro_if_double_accessible) 00131 { 00132 if (!double_access) 00133 { 00134 if (mode == ROW_WISE) 00135 PLERROR("cannot access columns in the row-wise matrix"); 00136 else if (mode == COLUMN_WISE) 00137 cols[j].clear(); 00138 } else 00139 { 00140 if (force_synchro_if_double_accessible) 00141 { 00142 for (int i = 0; i < height; j++) 00143 { 00144 map<int, T>& row_i = rows[i]; 00145 if (row_i.find(j) != row_i.end()) 00146 row_i.erase(j); 00147 } 00148 } else 00149 { 00150 PLWARNING("can only clear columns in the column-wise matrix (internal matrices are now out of sync)"); 00151 cols[j].clear(); 00152 } 00153 } 00154 } 00155 00156 template <class T> 00157 void DoubleAccessSparseMatrix<T>::clearElem(int i, int j) 00158 { 00159 if (mode == ROW_WISE || double_access) 00160 { 00161 map<int, T>& row_i = rows[i]; 00162 if (row_i.find(j) != row_i.end()) 00163 row_i.erase(j); 00164 } 00165 if (mode == COLUMN_WISE || double_access) 00166 { 00167 map<int, T>& col_j = cols[j]; 00168 if (col_j.find(i) != col_j.end()) 00169 col_j.erase(i); 00170 } 00171 } 00172 00173 template <class T> 00174 T DoubleAccessSparseMatrix<T>::get(int i, int j) const 00175 { 00176 #ifdef BOUNDCHECK 00177 if (i < 0 || i >= height || j < 0 || j >= width) 00178 PLERROR("out-of-bound access to (%d, %d), dims = (%d, %d)", i, j, height, width); 00179 #endif 00180 if (mode == ROW_WISE) 00181 { 00182 const map<int, T>& row_i = rows[i]; 00183 typename map<int, T>::const_iterator it = row_i.find(j); 00184 if (it == row_i.end()) 00185 return null_elem; 00186 return it->second; 00187 } else 00188 { 00189 const map<int, T>& col_j = cols[j]; 00190 typename map<int, T>::const_iterator it = col_j.find(i); 00191 if (it == col_j.end()) 00192 return null_elem; 00193 return it->second; 00194 } 00195 } 00196 00197 template <class T> 00198 bool DoubleAccessSparseMatrix<T>::exists(int i, int j) const 00199 { 00200 #ifdef BOUNDCHECK 00201 if (i < 0 || i >= height || j < 0 || j >= width) 00202 PLERROR("out-of-bound access to (%d, %d), dims = (%d, %d)", i, j, height, width); 00203 #endif 00204 if (mode == ROW_WISE) 00205 { 00206 const map<int, T>& row_i = rows[i]; 00207 return (row_i.find(j) != row_i.end()); 00208 } else 00209 { 00210 const map<int, T>& col_j = cols[j]; 00211 return (col_j.find(i) != col_j.end()); 00212 } 00213 } 00214 00215 template <class T> 00216 void DoubleAccessSparseMatrix<T>::set(int i, int j, T value) 00217 { 00218 #ifdef BOUNDCHECK 00219 if (i < 0 || i >= height || j < 0 || j >= width) 00220 PLERROR("out-of-bound access to (%d, %d), dims = (%d, %d)", i, j, height, width); 00221 #endif 00222 if (value != null_elem) 00223 { 00224 if (mode == ROW_WISE || double_access) 00225 rows[i][j] = value; 00226 if (mode == COLUMN_WISE || double_access) 00227 cols[j][i] = value; 00228 } else 00229 { 00230 clearElem(i, j); 00231 } 00232 } 00233 00234 template <class T> 00235 void DoubleAccessSparseMatrix<T>::incr(int i, int j, T inc) 00236 { 00237 if (inc != null_elem) 00238 set(i, j, get(i, j) + inc); 00239 } 00240 00241 /* 00242 template <class T> 00243 void DoubleAccessSparseMatrix<T>::operator=(SMat<T> m) 00244 { 00245 name = m->getName(); 00246 mode = m->getMode(); 00247 null_elem = m->getNullElem(); 00248 double_access = m->isDoubleAccessible(); 00249 clear(); 00250 resize(m->getHeight(), m->getWidth()); 00251 if (mode == ROW_WISE) 00252 { 00253 for (int i = 0; i < height; i++) 00254 { 00255 map<int, T>& row_i = m->getRow(i); 00256 for (typename map<int, T>::iterator it = row_i.begin(); it != row_i.end(); ++it) 00257 { 00258 int j = it->first; 00259 T val = it->second; 00260 set(i, j, val); 00261 } 00262 } 00263 } else 00264 { 00265 for (int j = 0; j < width; j++) 00266 { 00267 map<int, T>& col_j = m->getCol(j); 00268 for (typename map<int, T>::iterator it = col_j.begin(); it != col_j.end(); ++it) 00269 { 00270 int i = it->first; 00271 T val = it->second; 00272 set(i, j, val); 00273 } 00274 } 00275 } 00276 } 00277 */ 00278 00279 template <class T> 00280 map<int, T>& DoubleAccessSparseMatrix<T>::getRow(int i) 00281 { 00282 if (mode == ROW_WISE || double_access) 00283 { 00284 #ifdef BOUNDCHECK 00285 if (i < 0 || i > height) 00286 PLERROR("out-of-bound access to row %d, dims = (%d, %d)", i, height, width); 00287 #endif 00288 return rows[i]; 00289 } else 00290 { 00291 PLERROR("cannot access rows in the column-wise matrix"); 00292 return rows[0]; 00293 } 00294 } 00295 00296 template <class T> 00297 const map<int, T>& DoubleAccessSparseMatrix<T>::getCol(int j)const 00298 { 00299 if (mode == COLUMN_WISE || double_access) 00300 { 00301 #ifdef BOUNDCHECK 00302 if (j < 0 || j > width) 00303 PLERROR("out-of-bound access to column %d, dims = (%d, %d)", j, height, width); 00304 #endif 00305 return cols[j]; 00306 } else 00307 { 00308 PLERROR("cannot access columns in the row-wise matrix"); 00309 return cols[0]; 00310 } 00311 } 00312 00313 template <class T> 00314 void DoubleAccessSparseMatrix<T>::addRow(map<int, T>& row) 00315 { 00316 if (mode == COLUMN_WISE || double_access) 00317 { 00318 PLERROR("cannot add row in the column-wise matrix"); 00319 } else 00320 { 00321 rows.push_back(row); 00322 height++; 00323 } 00324 } 00325 00326 template <class T> 00327 void DoubleAccessSparseMatrix<T>::addCol(map<int, T>& col) 00328 { 00329 if (mode == ROW_WISE || double_access) 00330 { 00331 PLERROR("cannot add col in the row-wise matrix"); 00332 } else 00333 { 00334 cols.push_back(col); 00335 width++; 00336 } 00337 } 00338 00339 template <class T> 00340 int DoubleAccessSparseMatrix<T>::size() 00341 { 00342 int s = 0; 00343 if (mode == ROW_WISE) 00344 { 00345 for (unsigned int i = 0; i < rows.size(); i++) 00346 // norman: added explicit cast 00347 s += (int)rows[i].size(); 00348 } else 00349 { 00350 for (unsigned int j = 0; j < cols.size(); j++) 00351 // norman: added explicit cast 00352 s += (int)cols[j].size(); 00353 } 00354 return s; 00355 } 00356 00357 template <class T> 00358 T DoubleAccessSparseMatrix<T>::sumRow(int i) 00359 { 00360 if (mode == ROW_WISE || double_access) 00361 { 00362 T sum = 0; 00363 map<int, T>& row_i = rows[i]; 00364 for (typename map<int, T>::iterator it = row_i.begin(); it != row_i.end(); ++it) 00365 sum += it->second; 00366 return sum; 00367 } else 00368 { 00369 PLERROR("cannot access rows in the column-wise matrix"); 00370 return 0; 00371 } 00372 } 00373 00374 template <class T> 00375 T DoubleAccessSparseMatrix<T>::sumCol(int j) 00376 { 00377 if (mode == COLUMN_WISE || double_access) 00378 { 00379 T sum = 0; 00380 map<int, T>& col_j = cols[j]; 00381 for (typename map<int, T>::iterator it = col_j.begin(); it != col_j.end(); ++it) 00382 sum += it->second; 00383 return sum; 00384 } else 00385 { 00386 PLERROR("cannot access columns in the row-wise matrix"); 00387 return 0; 00388 } 00389 } 00390 00391 template <class T> 00392 T* DoubleAccessSparseMatrix<T>::getAsCompressedVec() 00393 { 00394 int vector_size = size() * 3; 00395 T* compressed_vec = NULL; 00396 int pos = 0; 00397 if (mode == ROW_WISE || double_access) 00398 { 00399 compressed_vec = new T[vector_size]; 00400 for (int i = 0; i < height; i++) 00401 { 00402 map<int, T>& row_i = rows[i]; 00403 for (typename map<int, T>::iterator it = row_i.begin(); it != row_i.end(); ++it) 00404 { 00405 int j = it->first; 00406 T value = it->second; 00407 compressed_vec[pos++] = (T)i; 00408 compressed_vec[pos++] = (T)j; 00409 compressed_vec[pos++] = value; 00410 } 00411 } 00412 if (pos != vector_size) 00413 PLERROR("weird"); 00414 } else if (mode == COLUMN_WISE) 00415 { 00416 compressed_vec = new T[vector_size]; 00417 for (int j = 0; j < width; j++) 00418 { 00419 map<int, T>& col_j = cols[j]; 00420 for (typename map<int, T>::iterator it = col_j.begin(); it != col_j.end(); ++it) 00421 { 00422 int i = it->first; 00423 T value = it->second; 00424 compressed_vec[pos++] = (T)i; 00425 compressed_vec[pos++] = (T)j; 00426 compressed_vec[pos++] = value; 00427 } 00428 } 00429 if (pos != vector_size) 00430 PLERROR("weird"); 00431 } 00432 return compressed_vec; 00433 } 00434 00435 template <class T> 00436 void DoubleAccessSparseMatrix<T>::getAsMaxSizedCompressedVecs(int max_size, vector<pair<T*, int> >& vectors) 00437 { 00438 if ((max_size % 3) != 0) PLWARNING("dangerous vector size (max_size mod 3 must equal 0)"); 00439 00440 int n_elems = size() * 3; 00441 int n_vecs = n_elems / max_size; 00442 int remaining = n_elems % max_size; 00443 int pos = 0; 00444 if (remaining > 0) // padding to get sure that last block size (= remaining) is moddable by 3 00445 { 00446 n_vecs += 1; 00447 int mod3 = remaining % 3; 00448 if (mod3 != 0) 00449 remaining += (3 - mod3); 00450 } 00451 vectors.resize(n_vecs); 00452 for (int i = 0; i < n_vecs; i++) 00453 { 00454 if (i == (n_vecs - 1) && remaining > 0) 00455 { 00456 vectors[i].first = new T[remaining]; 00457 vectors[i].second = remaining; 00458 } else 00459 { 00460 vectors[i].first = new T[max_size]; 00461 vectors[i].second = max_size; 00462 } 00463 } 00464 if (mode == ROW_WISE) 00465 { 00466 for (int i = 0; i < height; i++) 00467 { 00468 map<int, T>& row_i = rows[i]; 00469 for (typename map<int, T>::iterator it = row_i.begin(); it != row_i.end(); ++it) 00470 { 00471 int j = it->first; 00472 T value = it->second; 00473 vectors[pos / max_size].first[pos++ % max_size] = (T)i; 00474 vectors[pos / max_size].first[pos++ % max_size] = (T)j; 00475 vectors[pos / max_size].first[pos++ % max_size] = value; 00476 } 00477 } 00478 } else if (mode == COLUMN_WISE) 00479 { 00480 for (int j = 0; j < width; j++) 00481 { 00482 map<int, T>& col_j = cols[j]; 00483 for (typename map<int, T>::iterator it = col_j.begin(); it != col_j.end(); ++it) 00484 { 00485 int i = it->first; 00486 T value = it->second; 00487 vectors[pos / max_size].first[pos++ % max_size] = (T)i; 00488 vectors[pos / max_size].first[pos++ % max_size] = (T)j; 00489 vectors[pos / max_size].first[pos++ % max_size] = value; 00490 } 00491 } 00492 } 00493 while (pos < n_elems) // pad with (null_elem, null_elem, null_elem) 00494 { 00495 vectors[pos / max_size].first[pos++ % max_size] = null_elem; 00496 vectors[pos / max_size].first[pos++ % max_size] = null_elem; 00497 vectors[pos / max_size].first[pos++ % max_size] = null_elem; 00498 } 00499 } 00500 00501 template <class T> 00502 void DoubleAccessSparseMatrix<T>::addCompressedVec(T* compressed_vec, int n_elems) 00503 { 00504 if ((n_elems % 3) != 0) PLERROR("n_elems mod 3 must = 0"); 00505 for (int i = 0; i < n_elems; i += 3) 00506 incr((int)compressed_vec[i], (int)compressed_vec[i + 1], compressed_vec[i + 2]); 00507 } 00508 00509 template <class T> 00510 void DoubleAccessSparseMatrix<T>::setCompressedVec(T* compressed_vec, int n_elems) 00511 { 00512 if ((n_elems % 3) != 0) PLERROR("n_elems mod 3 must = 0"); 00513 clear(); 00514 for (int i = 0; i < n_elems; i += 3) 00515 set((int)compressed_vec[i], (int)compressed_vec[i + 1], compressed_vec[i + 2]); 00516 } 00517 00518 template <class T> 00519 T DoubleAccessSparseMatrix<T>::sumOfElements() 00520 { 00521 T sum = 0; 00522 if (mode == ROW_WISE) 00523 { 00524 for (int i = 0; i < height; i++) 00525 { 00526 map<int, T>& row_i = rows[i]; 00527 for (typename map<int, T>::iterator it = row_i.begin(); it != row_i.end(); ++it) 00528 sum += it->second; 00529 } 00530 } else if (mode == COLUMN_WISE) 00531 { 00532 for (int j = 0; j < width; j++) 00533 { 00534 map<int, T>& col_j = cols[j]; 00535 for (typename map<int, T>::iterator it = col_j.begin(); it != col_j.end(); ++it) 00536 sum += it->second; 00537 } 00538 } 00539 return sum; 00540 } 00541 00542 template <class T> 00543 void DoubleAccessSparseMatrix<T>::setDoubleAccessible(bool da) 00544 { 00545 if (double_access != da) 00546 { 00547 double_access = da; 00548 if (!double_access) 00549 { 00550 if (mode == ROW_WISE) 00551 cols.clear(); 00552 else if (mode == COLUMN_WISE) 00553 rows.clear(); 00554 } else 00555 { 00556 if (mode == ROW_WISE) 00557 { 00558 cols.resize(width); 00559 for (int i = 0; i < height; i++) 00560 { 00561 map<int, T>& row_i = rows[i]; 00562 for (typename map<int, T>::iterator it = row_i.begin(); it != row_i.end(); ++it) 00563 { 00564 int j = it->first; 00565 T value = it->second; 00566 set(i, j, value); 00567 } 00568 } 00569 } else if (mode == COLUMN_WISE) 00570 { 00571 rows.resize(height); 00572 for (int j = 0; j < width; j++) 00573 { 00574 map<int, T>& col_j = cols[j]; 00575 for (typename map<int, T>::iterator it = col_j.begin(); it != col_j.end(); ++it) 00576 { 00577 int i = it->first; 00578 T value = it->second; 00579 set(i, j, value); 00580 } 00581 } 00582 } 00583 } 00584 } 00585 } 00586 00587 template <class T> 00588 void DoubleAccessSparseMatrix<T>::setMode(int new_mode) 00589 { 00590 if (mode != ROW_WISE && mode != COLUMN_WISE) PLERROR("mode must be either row-wise or column-wise"); 00591 00592 if (mode != new_mode) 00593 { 00594 mode = new_mode; 00595 if (mode == ROW_WISE && !double_access) 00596 { 00597 rows.resize(height); 00598 for (int j = 0; j < width; j++) 00599 { 00600 map<int, T>& col_j = cols[j]; 00601 for (typename map<int, T>::iterator it = col_j.begin(); it != col_j.end(); ++it) 00602 { 00603 int i = it->first; 00604 T value = it->second; 00605 set(i, j, value); 00606 } 00607 } 00608 cols.clear(); 00609 } else if (mode == COLUMN_WISE && !double_access) 00610 { 00611 cols.resize(width); 00612 for (int i = 0; i < height; i++) 00613 { 00614 map<int, T>& row_i = rows[i]; 00615 for (typename map<int, T>::iterator it = row_i.begin(); it != row_i.end(); ++it) 00616 { 00617 int j = it->first; 00618 T value = it->second; 00619 set(i, j, value); 00620 } 00621 } 00622 rows.clear(); 00623 } 00624 } 00625 } 00626 00627 template <class T> 00628 void DoubleAccessSparseMatrix<T>::write(PStream& out) const 00629 { 00630 string class_name = getClassName(); 00631 switch(out.outmode) 00632 { 00633 case PStream::raw_ascii : 00634 case PStream::pretty_ascii : 00635 PLERROR("raw/pretty_ascii write not implemented in %s", class_name.c_str()); 00636 break; 00637 case PStream::raw_binary : 00638 PLERROR("raw_binary write not implemented in %s", class_name.c_str()); 00639 break; 00640 case PStream::plearn_binary : 00641 case PStream::plearn_ascii : 00642 out.write(class_name + "("); 00643 out << rows; 00644 out << cols; 00645 out << name; 00646 out << mode; 00647 out << double_access; 00648 out << height; 00649 out << width; 00650 out << null_elem; 00651 out.write(")\n"); 00652 break; 00653 default: 00654 PLERROR("unknown outmode in %s::write(PStream& out)", class_name.c_str()); 00655 break; 00656 } 00657 } 00658 00659 template <class T> 00660 void DoubleAccessSparseMatrix<T>::read(PStream& in) 00661 { 00662 string class_name = getClassName(); 00663 switch (in.inmode) 00664 { 00665 case PStream::raw_ascii : 00666 PLERROR("raw_ascii read not implemented in %s", class_name.c_str()); 00667 break; 00668 case PStream::raw_binary : 00669 PLERROR("raw_binary read not implemented in %s", class_name.c_str()); 00670 break; 00671 case PStream::plearn_ascii : 00672 case PStream::plearn_binary : 00673 { 00674 in.skipBlanksAndCommentsAndSeparators(); 00675 string word(class_name.size() + 1, ' '); 00676 for (unsigned int i = 0; i < class_name.size() + 1; i++) 00677 in.get(word[i]); 00678 if (word != class_name + "(") 00679 PLERROR("in %s::(PStream& in), '%s' is not a proper header", class_name.c_str(), word.c_str()); 00680 in.skipBlanksAndCommentsAndSeparators(); 00681 in >> rows; 00682 in.skipBlanksAndCommentsAndSeparators(); 00683 in >> cols; 00684 in.skipBlanksAndCommentsAndSeparators(); 00685 in >> name; 00686 in.skipBlanksAndCommentsAndSeparators(); 00687 in >> mode; 00688 in.skipBlanksAndCommentsAndSeparators(); 00689 in >> double_access; 00690 in.skipBlanksAndCommentsAndSeparators(); 00691 in >> height; 00692 in.skipBlanksAndCommentsAndSeparators(); 00693 in >> width; 00694 in.skipBlanksAndCommentsAndSeparators(); 00695 in >> null_elem; 00696 in.skipBlanksAndCommentsAndSeparators(); 00697 int c = in.get(); 00698 if(c != ')') 00699 PLERROR("in %s::(PStream& in), expected a closing parenthesis, found '%c'", class_name.c_str(), c); 00700 } 00701 break; 00702 default: 00703 PLERROR("unknown inmode in %s::write(PStream& out)", class_name.c_str()); 00704 break; 00705 } 00706 } 00707 00708 } // end of namespace PLearn 00709 00710 00711 /* 00712 Local Variables: 00713 mode:c++ 00714 c-basic-offset:4 00715 c-file-style:"stroustrup" 00716 c-file-offsets:((innamespace . 0)(inline-open . 0)) 00717 indent-tabs-mode:nil 00718 fill-column:79 00719 End: 00720 */ 00721 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :