00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
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)
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
clear();
00080 }
00081
00082
template <
class T>
00083 void DoubleAccessSparseMatrix<T>::clear()
00084 {
00085
if (
mode ==
ROW_WISE ||
double_access)
00086 {
00087
00088
int rs = (
int)
rows.size();
00089
for (
int i = 0; i < rs; i++)
00090
rows[i].clear();
00091 }
00092
if (
mode ==
COLUMN_WISE ||
double_access)
00093 {
00094
00095
int cs = (
int)
cols.size();
00096
for (
int i = 0; i < cs; i++)
00097
cols[i].clear();
00098 }
00099 }
00100
00101
template <
class T>
00102 void DoubleAccessSparseMatrix<T>::clearRow(
int i,
bool force_synchro_if_double_accessible)
00103 {
00104
if (!
double_access)
00105 {
00106
if (
mode ==
COLUMN_WISE)
00107
PLERROR(
"cannot access rows in the column-wise matrix");
00108
else
00109
rows[i].clear();
00110 }
else
00111 {
00112
if (force_synchro_if_double_accessible)
00113 {
00114
for (
int j = 0; j <
width; j++)
00115 {
00116 map<int, T>& col_j =
cols[j];
00117
if (col_j.find(i) != col_j.end())
00118 col_j.erase(i);
00119 }
00120 }
else
00121 {
00122
PLWARNING(
"can only clear rows in the row-wise matrix (internal matrices are now out of sync)");
00123
rows[i].clear();
00124 }
00125 }
00126 }
00127
00128
template <
class T>
00129 void DoubleAccessSparseMatrix<T>::clearCol(
int j,
bool force_synchro_if_double_accessible)
00130 {
00131
if (!
double_access)
00132 {
00133
if (
mode ==
ROW_WISE)
00134
PLERROR(
"cannot access columns in the row-wise matrix");
00135
else if (
mode ==
COLUMN_WISE)
00136
cols[j].clear();
00137 }
else
00138 {
00139
if (force_synchro_if_double_accessible)
00140 {
00141
for (
int i = 0; i <
height; j++)
00142 {
00143 map<int, T>& row_i =
rows[i];
00144
if (row_i.find(j) != row_i.end())
00145 row_i.erase(j);
00146 }
00147 }
else
00148 {
00149
PLWARNING(
"can only clear columns in the column-wise matrix (internal matrices are now out of sync)");
00150
cols[j].clear();
00151 }
00152 }
00153 }
00154
00155
template <
class T>
00156 void DoubleAccessSparseMatrix<T>::clearElem(
int i,
int j)
00157 {
00158
if (
mode ==
ROW_WISE ||
double_access)
00159 {
00160 map<int, T>& row_i =
rows[i];
00161
if (row_i.find(j) != row_i.end())
00162 row_i.erase(j);
00163 }
00164
if (
mode ==
COLUMN_WISE ||
double_access)
00165 {
00166 map<int, T>& col_j =
cols[j];
00167
if (col_j.find(i) != col_j.end())
00168 col_j.erase(i);
00169 }
00170 }
00171
00172
template <
class T>
00173 T
DoubleAccessSparseMatrix<T>::get(
int i,
int j)
00174 {
00175
#ifdef BOUNDCHECK
00176
if (i < 0 || i >=
height || j < 0 || j >=
width)
00177
PLERROR(
"out-of-bound access to (%d, %d), dims = (%d, %d)", i, j,
height,
width);
00178
#endif
00179
if (
mode ==
ROW_WISE)
00180 {
00181 map<int, T>& row_i =
rows[i];
00182
typename map<int, T>::iterator it = row_i.find(j);
00183
if (it == row_i.end())
00184
return null_elem;
00185
return it->second;
00186 }
else
00187 {
00188 map<int, T>& col_j =
cols[j];
00189
typename map<int, T>::iterator it = col_j.find(i);
00190
if (it == col_j.end())
00191
return null_elem;
00192
return it->second;
00193 }
00194 }
00195
00196
template <
class T>
00197 bool DoubleAccessSparseMatrix<T>::exists(
int i,
int j)
00198 {
00199
#ifdef BOUNDCHECK
00200
if (i < 0 || i >=
height || j < 0 || j >=
width)
00201
PLERROR(
"out-of-bound access to (%d, %d), dims = (%d, %d)", i, j,
height,
width);
00202
#endif
00203
if (
mode ==
ROW_WISE)
00204 {
00205 map<int, T>& row_i =
rows[i];
00206
return (row_i.find(j) != row_i.end());
00207 }
else
00208 {
00209 map<int, T>& col_j =
cols[j];
00210
return (col_j.find(i) != col_j.end());
00211 }
00212 }
00213
00214
template <
class T>
00215 void DoubleAccessSparseMatrix<T>::set(
int i,
int j, T value)
00216 {
00217
#ifdef BOUNDCHECK
00218
if (i < 0 || i >=
height || j < 0 || j >=
width)
00219
PLERROR(
"out-of-bound access to (%d, %d), dims = (%d, %d)", i, j,
height,
width);
00220
#endif
00221
if (value !=
null_elem)
00222 {
00223
if (
mode ==
ROW_WISE ||
double_access)
00224
rows[i][j] = value;
00225
if (
mode ==
COLUMN_WISE ||
double_access)
00226
cols[j][i] = value;
00227 }
else
00228 {
00229
clearElem(i, j);
00230 }
00231 }
00232
00233
template <
class T>
00234 void DoubleAccessSparseMatrix<T>::incr(
int i,
int j, T inc)
00235 {
00236
if (inc !=
null_elem)
00237
set(i, j,
get(i, j) + inc);
00238 }
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
template <
class T>
00279 map<int, T>&
DoubleAccessSparseMatrix<T>::getRow(
int i)
00280 {
00281
if (
mode ==
ROW_WISE ||
double_access)
00282 {
00283
#ifdef BOUNDCHECK
00284
if (i < 0 || i >
height)
00285
PLERROR(
"out-of-bound access to row %d, dims = (%d, %d)", i,
height,
width);
00286
#endif
00287
return rows[i];
00288 }
else
00289 {
00290
PLERROR(
"cannot access rows in the column-wise matrix");
00291
return rows[0];
00292 }
00293 }
00294
00295
template <
class T>
00296 map<int, T>&
DoubleAccessSparseMatrix<T>::getCol(
int j)
00297 {
00298
if (
mode ==
COLUMN_WISE ||
double_access)
00299 {
00300
#ifdef BOUNDCHECK
00301
if (j < 0 || j >
width)
00302
PLERROR(
"out-of-bound access to column %d, dims = (%d, %d)", j,
height,
width);
00303
#endif
00304
return cols[j];
00305 }
else
00306 {
00307
PLERROR(
"cannot access columns in the row-wise matrix");
00308
return cols[0];
00309 }
00310 }
00311
00312
template <
class T>
00313 void DoubleAccessSparseMatrix<T>::addRow(map<int, T>& row)
00314 {
00315
if (
mode ==
COLUMN_WISE ||
double_access)
00316 {
00317
PLERROR(
"cannot add row in the column-wise matrix");
00318 }
else
00319 {
00320
rows.push_back(row);
00321
height++;
00322 }
00323 }
00324
00325
template <
class T>
00326 void DoubleAccessSparseMatrix<T>::addCol(map<int, T>& col)
00327 {
00328
if (
mode ==
ROW_WISE ||
double_access)
00329 {
00330
PLERROR(
"cannot add col in the row-wise matrix");
00331 }
else
00332 {
00333
cols.push_back(col);
00334
width++;
00335 }
00336 }
00337
00338
template <
class T>
00339 int DoubleAccessSparseMatrix<T>::size()
00340 {
00341
int s = 0;
00342
if (
mode ==
ROW_WISE)
00343 {
00344
for (
unsigned int i = 0; i <
rows.size(); i++)
00345
00346 s += (
int)
rows[i].size();
00347 }
else
00348 {
00349
for (
unsigned int j = 0; j <
cols.size(); j++)
00350
00351 s += (
int)
cols[j].size();
00352 }
00353
return s;
00354 }
00355
00356
template <
class T>
00357 T
DoubleAccessSparseMatrix<T>::sumRow(
int i)
00358 {
00359
if (
mode ==
ROW_WISE ||
double_access)
00360 {
00361 T
sum = 0;
00362 map<int, T>& row_i =
rows[i];
00363
for (
typename map<int, T>::iterator it = row_i.begin(); it != row_i.end(); ++it)
00364
sum += it->second;
00365
return sum;
00366 }
else
00367 {
00368
PLERROR(
"cannot access rows in the column-wise matrix");
00369
return 0;
00370 }
00371 }
00372
00373
template <
class T>
00374 T
DoubleAccessSparseMatrix<T>::sumCol(
int j)
00375 {
00376
if (
mode ==
COLUMN_WISE ||
double_access)
00377 {
00378 T
sum = 0;
00379 map<int, T>& col_j =
cols[j];
00380
for (
typename map<int, T>::iterator it = col_j.begin(); it != col_j.end(); ++it)
00381
sum += it->second;
00382
return sum;
00383 }
else
00384 {
00385
PLERROR(
"cannot access columns in the row-wise matrix");
00386
return 0;
00387 }
00388 }
00389
00390
template <
class T>
00391 T*
DoubleAccessSparseMatrix<T>::getAsCompressedVec()
00392 {
00393
int vector_size =
size() * 3;
00394 T* compressed_vec = NULL;
00395
int pos = 0;
00396
if (
mode ==
ROW_WISE ||
double_access)
00397 {
00398 compressed_vec =
new T[vector_size];
00399
for (
int i = 0; i <
height; i++)
00400 {
00401 map<int, T>& row_i =
rows[i];
00402
for (
typename map<int, T>::iterator it = row_i.begin(); it != row_i.end(); ++it)
00403 {
00404
int j = it->first;
00405 T value = it->second;
00406 compressed_vec[pos++] = (T)i;
00407 compressed_vec[pos++] = (T)j;
00408 compressed_vec[pos++] = value;
00409 }
00410 }
00411
if (pos != vector_size)
00412
PLERROR(
"weird");
00413 }
else if (
mode ==
COLUMN_WISE)
00414 {
00415 compressed_vec =
new T[vector_size];
00416
for (
int j = 0; j <
width; j++)
00417 {
00418 map<int, T>& col_j =
cols[j];
00419
for (
typename map<int, T>::iterator it = col_j.begin(); it != col_j.end(); ++it)
00420 {
00421
int i = it->first;
00422 T value = it->second;
00423 compressed_vec[pos++] = (T)i;
00424 compressed_vec[pos++] = (T)j;
00425 compressed_vec[pos++] = value;
00426 }
00427 }
00428
if (pos != vector_size)
00429
PLERROR(
"weird");
00430 }
00431
return compressed_vec;
00432 }
00433
00434
template <
class T>
00435 void DoubleAccessSparseMatrix<T>::getAsMaxSizedCompressedVecs(
int max_size,
vector<pair<T*, int> >& vectors)
00436 {
00437
if ((max_size % 3) != 0)
PLWARNING(
"dangerous vector size (max_size mod 3 must equal 0)");
00438
00439
int n_elems =
size() * 3;
00440
int n_vecs = n_elems / max_size;
00441
int remaining = n_elems % max_size;
00442
int pos = 0;
00443
if (remaining > 0)
00444 {
00445 n_vecs += 1;
00446
int mod3 = remaining % 3;
00447
if (mod3 != 0)
00448 remaining += (3 - mod3);
00449 }
00450 vectors.resize(n_vecs);
00451
for (
int i = 0; i < n_vecs; i++)
00452 {
00453
if (i == (n_vecs - 1) && remaining > 0)
00454 {
00455 vectors[i].first =
new T[remaining];
00456 vectors[i].second = remaining;
00457 }
else
00458 {
00459 vectors[i].first =
new T[max_size];
00460 vectors[i].second = max_size;
00461 }
00462 }
00463
if (
mode ==
ROW_WISE)
00464 {
00465
for (
int i = 0; i <
height; i++)
00466 {
00467 map<int, T>& row_i =
rows[i];
00468
for (
typename map<int, T>::iterator it = row_i.begin(); it != row_i.end(); ++it)
00469 {
00470
int j = it->first;
00471 T value = it->second;
00472 vectors[pos / max_size].first[pos++ % max_size] = (T)i;
00473 vectors[pos / max_size].first[pos++ % max_size] = (T)j;
00474 vectors[pos / max_size].first[pos++ % max_size] = value;
00475 }
00476 }
00477 }
else if (
mode ==
COLUMN_WISE)
00478 {
00479
for (
int j = 0; j <
width; j++)
00480 {
00481 map<int, T>& col_j =
cols[j];
00482
for (
typename map<int, T>::iterator it = col_j.begin(); it != col_j.end(); ++it)
00483 {
00484
int i = it->first;
00485 T value = it->second;
00486 vectors[pos / max_size].first[pos++ % max_size] = (T)i;
00487 vectors[pos / max_size].first[pos++ % max_size] = (T)j;
00488 vectors[pos / max_size].first[pos++ % max_size] = value;
00489 }
00490 }
00491 }
00492
while (pos < n_elems)
00493 {
00494 vectors[pos / max_size].first[pos++ % max_size] =
null_elem;
00495 vectors[pos / max_size].first[pos++ % max_size] =
null_elem;
00496 vectors[pos / max_size].first[pos++ % max_size] =
null_elem;
00497 }
00498 }
00499
00500
template <
class T>
00501 void DoubleAccessSparseMatrix<T>::addCompressedVec(T* compressed_vec,
int n_elems)
00502 {
00503
if ((n_elems % 3) != 0)
PLERROR(
"n_elems mod 3 must = 0");
00504
for (
int i = 0; i < n_elems; i += 3)
00505
incr((
int)compressed_vec[i], (
int)compressed_vec[i + 1], compressed_vec[i + 2]);
00506 }
00507
00508
template <
class T>
00509 void DoubleAccessSparseMatrix<T>::setCompressedVec(T* compressed_vec,
int n_elems)
00510 {
00511
if ((n_elems % 3) != 0)
PLERROR(
"n_elems mod 3 must = 0");
00512
clear();
00513
for (
int i = 0; i < n_elems; i += 3)
00514
set((
int)compressed_vec[i], (
int)compressed_vec[i + 1], compressed_vec[i + 2]);
00515 }
00516
00517
template <
class T>
00518 T
DoubleAccessSparseMatrix<T>::sumOfElements()
00519 {
00520 T
sum = 0;
00521
if (
mode ==
ROW_WISE)
00522 {
00523
for (
int i = 0; i <
height; i++)
00524 {
00525 map<int, T>& row_i =
rows[i];
00526
for (
typename map<int, T>::iterator it = row_i.begin(); it != row_i.end(); ++it)
00527
sum += it->second;
00528 }
00529 }
else if (
mode ==
COLUMN_WISE)
00530 {
00531
for (
int j = 0; j <
width; j++)
00532 {
00533 map<int, T>& col_j =
cols[j];
00534
for (
typename map<int, T>::iterator it = col_j.begin(); it != col_j.end(); ++it)
00535
sum += it->second;
00536 }
00537 }
00538
return sum;
00539 }
00540
00541
template <
class T>
00542 void DoubleAccessSparseMatrix<T>::setDoubleAccessible(
bool da)
00543 {
00544
if (
double_access != da)
00545 {
00546
double_access = da;
00547
if (!
double_access)
00548 {
00549
if (
mode ==
ROW_WISE)
00550
cols.clear();
00551
else if (
mode ==
COLUMN_WISE)
00552
rows.clear();
00553 }
else
00554 {
00555
if (
mode ==
ROW_WISE)
00556 {
00557
cols.resize(
width);
00558
for (
int i = 0; i <
height; i++)
00559 {
00560 map<int, T>& row_i =
rows[i];
00561
for (
typename map<int, T>::iterator it = row_i.begin(); it != row_i.end(); ++it)
00562 {
00563
int j = it->first;
00564 T value = it->second;
00565
set(i, j, value);
00566 }
00567 }
00568 }
else if (
mode ==
COLUMN_WISE)
00569 {
00570
rows.resize(
height);
00571
for (
int j = 0; j <
width; j++)
00572 {
00573 map<int, T>& col_j =
cols[j];
00574
for (
typename map<int, T>::iterator it = col_j.begin(); it != col_j.end(); ++it)
00575 {
00576
int i = it->first;
00577 T value = it->second;
00578
set(i, j, value);
00579 }
00580 }
00581 }
00582 }
00583 }
00584 }
00585
00586
template <
class T>
00587 void DoubleAccessSparseMatrix<T>::setMode(
int new_mode)
00588 {
00589
if (
mode !=
ROW_WISE &&
mode !=
COLUMN_WISE)
PLERROR(
"mode must be either row-wise or column-wise");
00590
00591
if (
mode != new_mode)
00592 {
00593
mode = new_mode;
00594
if (
mode ==
ROW_WISE && !
double_access)
00595 {
00596
rows.resize(
height);
00597
for (
int j = 0; j <
width; j++)
00598 {
00599 map<int, T>& col_j =
cols[j];
00600
for (
typename map<int, T>::iterator it = col_j.begin(); it != col_j.end(); ++it)
00601 {
00602
int i = it->first;
00603 T value = it->second;
00604
set(i, j, value);
00605 }
00606 }
00607
cols.clear();
00608 }
else if (
mode ==
COLUMN_WISE && !
double_access)
00609 {
00610
cols.resize(
width);
00611
for (
int i = 0; i <
height; i++)
00612 {
00613 map<int, T>& row_i =
rows[i];
00614
for (
typename map<int, T>::iterator it = row_i.begin(); it != row_i.end(); ++it)
00615 {
00616
int j = it->first;
00617 T value = it->second;
00618
set(i, j, value);
00619 }
00620 }
00621
rows.clear();
00622 }
00623 }
00624 }
00625
00626
template <
class T>
00627 void DoubleAccessSparseMatrix<T>::write(
PStream& out)
const
00628
{
00629
string class_name =
getClassName();
00630
switch(out.
outmode)
00631 {
00632
case PStream::raw_ascii :
00633
case PStream::pretty_ascii :
00634
PLERROR(
"raw/pretty_ascii write not implemented in %s", class_name.c_str());
00635
break;
00636
case PStream::raw_binary :
00637
PLERROR(
"raw_binary write not implemented in %s", class_name.c_str());
00638
break;
00639
case PStream::plearn_binary :
00640
case PStream::plearn_ascii :
00641 out.
write(class_name +
"(");
00642 out <<
rows;
00643 out <<
cols;
00644 out <<
name;
00645 out <<
mode;
00646 out <<
double_access;
00647 out <<
height;
00648 out <<
width;
00649 out <<
null_elem;
00650 out.
write(
")\n");
00651
break;
00652
default:
00653
PLERROR(
"unknown outmode in %s::write(PStream& out)", class_name.c_str());
00654
break;
00655 }
00656 }
00657
00658
template <
class T>
00659 void DoubleAccessSparseMatrix<T>::read(
PStream& in)
00660 {
00661
string class_name =
getClassName();
00662
switch (in.
inmode)
00663 {
00664
case PStream::raw_ascii :
00665
PLERROR(
"raw_ascii read not implemented in %s", class_name.c_str());
00666
break;
00667
case PStream::raw_binary :
00668
PLERROR(
"raw_binary read not implemented in %s", class_name.c_str());
00669
break;
00670
case PStream::plearn_ascii :
00671
case PStream::plearn_binary :
00672 {
00673 in.
skipBlanksAndCommentsAndSeparators();
00674
string word(class_name.size() + 1,
' ');
00675
for (
unsigned int i = 0; i < class_name.size() + 1; i++)
00676 in.
get(word[i]);
00677
if (word != class_name +
"(")
00678
PLERROR(
"in %s::(PStream& in), '%s' is not a proper header", class_name.c_str(), word.c_str());
00679 in.
skipBlanksAndCommentsAndSeparators();
00680 in >>
rows;
00681 in.
skipBlanksAndCommentsAndSeparators();
00682 in >>
cols;
00683 in.
skipBlanksAndCommentsAndSeparators();
00684 in >>
name;
00685 in.
skipBlanksAndCommentsAndSeparators();
00686 in >>
mode;
00687 in.
skipBlanksAndCommentsAndSeparators();
00688 in >>
double_access;
00689 in.
skipBlanksAndCommentsAndSeparators();
00690 in >>
height;
00691 in.
skipBlanksAndCommentsAndSeparators();
00692 in >>
width;
00693 in.
skipBlanksAndCommentsAndSeparators();
00694 in >>
null_elem;
00695 in.
skipBlanksAndCommentsAndSeparators();
00696
int c = in.
get();
00697
if(c !=
')')
00698
PLERROR(
"in %s::(PStream& in), expected a closing parenthesis, found '%c'", class_name.c_str(), c);
00699 }
00700
break;
00701
default:
00702
PLERROR(
"unknown inmode in %s::write(PStream& out)", class_name.c_str());
00703
break;
00704 }
00705 }
00706
00707 }