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
#include "SparseMatrix.h"
00037
00038
namespace PLearn {
00039
using namespace std;
00040
00041 void SparseMatrix::resize(
int nbrows,
int n_columns,
int n_non_zero)
00042 {
00043
n_rows=nbrows;
00044
beginRow.
resize(n_columns);
00045
endRow.
resize(n_columns);
00046
row.
resize(n_non_zero);
00047
values.
resize(n_non_zero);
00048 }
00049
00050
00051
00052 void SparseMatrix::loadFortran(
const char* filename)
00053 {
00054 FILE* fp=fopen(filename,
"r");
00055
if (!fp)
00056
PLERROR(
"SparseMatrix::loadFortran, can't open file %s\n",filename);
00057
int n_cols,n_nonzero;
00058 fscanf(fp,
"%*72c%*s%*s%*s%d%d%d%*d",&
n_rows, &n_cols, &n_nonzero);
00059 fscanf(fp,
"%*s %*s %*s %*s");
00060
beginRow.
resize(n_cols);
00061
endRow.
resize(n_cols);
00062
values.
resize(n_nonzero);
00063
row.
resize(n_nonzero);
00064
real *brow =
beginRow.
data();
00065
real *erow =
endRow.
data();
00066
real *v =
values.
data();
00067
real *r =
row.
data();
00068
int i;
00069
for (i = 0; i < n_cols; i++)
00070 {
00071
#ifdef USEFLOAT
00072
fscanf(fp,
"%f", &brow[i]);
00073
#endif
00074
#ifdef USEDOUBLE
00075
fscanf(fp,
"%lf", &brow[i]);
00076
#endif
00077
brow[i]--;
00078
if (i>0) erow[i-1]=brow[i]-1;
00079 }
00080 erow[n_cols-1]=n_nonzero-1;
00081 fscanf(fp,
"%d",&i);
00082
if (i-1!=n_nonzero)
00083
PLERROR(
"SparseMatrix::loadFortran, inconsistent nnz %d vs %d",
00084 n_nonzero,i);
00085
for (i=0;i<n_nonzero;i++)
00086 {
00087
#ifdef USEFLOAT
00088
fscanf(fp,
"%f", &r[i]);
00089
#endif
00090
#ifdef USEDOUBLE
00091
fscanf(fp,
"%lf", &r[i]);
00092
#endif
00093
r[i]--;
00094 }
00095
for (i=0;i<n_nonzero;i++)
00096
#ifdef USEFLOAT
00097
fscanf(fp,
"%f", &v[i]);
00098
#endif
00099
#ifdef USEDOUBLE
00100
fscanf(fp,
"%lf", &v[i]);
00101
#endif
00102
}
00103
00104
00105 void SparseMatrix::saveFortran(
const char* filename)
00106 {
00107 FILE* fp=fopen(filename,
"w");
00108
if (!fp)
00109
PLERROR(
"SparseMatrix::saveFortran, can't open file %s\n",filename);
00110
int n_nonzero=
values.
length(), n_cols =
endRow.
length();
00111 fprintf(fp,
"%72s%8s\n#\nrra %d %d %d 0\n",
"SparseMatrix ",
00112 filename,
00113
n_rows, n_cols , n_nonzero);
00114 fprintf(fp,
" (10i8) (10i8) (8f10.3) (8f10.3)\n");
00115
real *brow =
beginRow.
data();
00116
real *v =
values.
data();
00117
real *r =
row.
data();
00118
int i;
00119
for (i = 0; i < n_cols; i++)
00120
00121 fprintf(fp,
"%7d ", (
int)(brow[i]+1));
00122 fprintf(fp,
"%8d\n",
values.
length()+1);
00123
for (i=0;i<n_nonzero;i++)
00124 fprintf(fp,
"%7d ",(
int)(r[i]+1));
00125 fprintf(fp,
"\n");
00126
for (i=0;i<n_nonzero;i++)
00127 fprintf(fp,
"%9f ",v[i]);
00128 fprintf(fp,
"\n");
00129 fclose(fp);
00130 }
00131
00132
00133 Mat SparseMatrix::toMat()
00134 {
00135
int n_cols =
beginRow.
length();
00136
Mat A(
n_rows,n_cols);
00137
real* r=
row.
data();
00138
real* v=
values.
data();
00139
for (
int c=0;c<n_cols;c++)
00140 {
00141
real* Ac = &A(0,c);
00142
int e = (
int)
endRow[c];
00143
for (
int k=(
int)
beginRow[c];
k<=e;
k++)
00144 Ac[n_cols*(
int)r[
k]]=v[
k];
00145 }
00146
return A;
00147 }
00148
00149 SparseMatrix::SparseMatrix(
Mat A)
00150 : n_rows(A.length()), beginRow(A.width()), endRow(A.width())
00151 {
00152
int n_nonzero=0;
00153
for (
int i=0;i<
n_rows;i++)
00154 {
00155
real* Ai=A[i];
00156
for (
int j=0;j<A.width();j++)
00157
if (Ai[j]!=0) n_nonzero++;
00158 }
00159
row.
resize(n_nonzero);
00160
values.
resize(n_nonzero);
00161
int mod = A.
mod();
00162
int k=0;
00163
real* v=
values.
data();
00164
real* r=
row.
data();
00165
real* b=
beginRow.
data();
00166
real* e=
endRow.
data();
00167
for (
int j=0;j<A.
width();j++)
00168 {
00169
real* Aij = &A(0,j);
00170 b[j] =
k;
00171
for (
int i=0;i<n_rows;i++,Aij+=mod)
00172
if (*Aij!=0)
00173 {
00174 r[
k] = i;
00175 v[
k] = *Aij;
00176
k++;
00177 }
00178 e[j] =
k-1;
00179 }
00180 }
00181
00182 void SparseMatrix::product(
const Vec& x,
Vec& y)
00183 {
00184
00185
if (y.
length()!=
n_rows ||
x.length()!=
beginRow.
length())
00186
PLERROR(
"SparseMatrix(%d,%d)::product(x(%d) -> y(%d)): dimensions don't match",
00187
n_rows,
beginRow.
length(),
x.length(),y.
length());
00188 y.
clear();
00189
real* y_=y.
data();
00190
real* x_=
x.data();
00191
real* A_=
values.
data();
00192
00193
for (
int j=0;j<
beginRow.
length();j++)
00194 {
00195
real xj = x_[j];
00196
for (
int k=(
int)
beginRow[j];
k<=
endRow[j];
k++)
00197 {
00198
int i=(
int)
row[
k];
00199 y_[i] += A_[
k] * xj;
00200 }
00201 }
00202 }
00203
00204 void SparseMatrix::diag(
Vec& d)
00205 {
00206
real* d_ = d.
data();
00207
real* A_ =
values.
data();
00208
int k;
00209
for (
int j=0;j<
beginRow.
length();j++)
00210 {
00211
int end=
int(
endRow[j]);
00212
for (
k=(
int)
beginRow[j];
k<=end && int(
row[
k])!=j;
k++);
00213
if (
k<=end)
00214 d_[j]=A_[
k];
00215
else
00216 d_[j]=0;
00217 }
00218 }
00219
00220 void SparseMatrix::diagonalOfSquare(
Vec& d)
00221 {
00222
real* d_ = d.
data();
00223
real* A_ =
values.
data();
00224
int k;
00225
for (
int j=0;j<
beginRow.
length();j++)
00226 {
00227
int end=
int(
endRow[j]);
00228
real sum2=0;
00229
for (
k=(
int)
beginRow[j];
k<=end;
k++)
00230 sum2 += A_[
k]*A_[
k];
00231 d_[j]=sum2;
00232 }
00233 }
00234
00235
00236 real SparseMatrix::dotRow(
int i,
Vec v)
00237 {
00238
PLERROR(
"SparseMatrix is not appropriate to perform dotRow operations");
00239
return 0;
00240 }
00241
00242
00243 real SparseMatrix::dotColumn(
int j,
Vec v)
00244 {
00245
#ifdef BOUNDCHECK
00246
if (v.
length()!=
length())
00247
PLERROR(
"SparseMatrix::dotColumn(%d,v), v.length_=%d != matrix length=%d",
00248 j,v.
length(),
length());
00249
#endif
00250
real s=0;
00251
real* v_=v.
data();
00252
real* A_=
values.
data();
00253
for (
int k=
int(
beginRow[j]);
k<=int(
endRow[j]);
k++)
00254 s += A_[
k] * v_[int(
row[
k])];
00255
return s;
00256 }
00257
00258
00259 SparseMatrix operator+(
const SparseMatrix& A,
const SparseMatrix& B)
00260 {
00261
int n_rows = A.
n_rows;
00262
int n_columns = A.
beginRow.
length();
00263
if (n_rows != B.
n_rows)
00264
PLERROR(
"SparseMatrix(%d,%d)+SparseMatrix(%d,%d): both should have same dimensions",
00265 n_rows,A.
beginRow.
length(),B.
n_rows,B.
beginRow.
length());
00266
int n_non_zero = A.
row.
length()+B.
row.
length();
00267
SparseMatrix C(n_rows,n_columns,n_non_zero);
00268
00269
int n_actual_non_zero=0;
00270
00271
Vec column(n_rows);
00272
real* v=column.
data();
00273
for (
int j=0;j<n_columns;j++)
00274 {
00275 column.
clear();
00276
for (
int i=(
int)A.
beginRow[j];i<=A.
endRow[j];i++)
00277 v[(
int)A.
row[i]]=A.
values[i];
00278
for (
int i=(
int)B.
beginRow[j];i<=B.
endRow[j];i++)
00279 v[(
int)B.
row[i]]+=B.
values[i];
00280 C.
beginRow[j]=n_actual_non_zero;
00281
for (
int i=0;i<n_rows;i++)
00282
if (v[i]!=0)
00283 {
00284 C.
row[n_actual_non_zero]=i;
00285 C.
values[n_actual_non_zero]=v[i];
00286 n_actual_non_zero++;
00287 }
00288 C.
endRow[j]=n_actual_non_zero-1;
00289
00290 }
00291 C.
row.
resize(n_actual_non_zero);
00292 C.
values.
resize(n_actual_non_zero);
00293
return C;
00294 }
00295
00296
00297 SparseMatrix add(
Array<SparseMatrix>& matrices)
00298 {
00299
int n_mat = matrices.
size();
00300
if (n_mat<1)
PLERROR(
"add(Array<SparseMatrix>) argument is empty!");
00301
int n_rows = matrices[0].n_rows;
00302
int n_columns = matrices[0].beginRow.length();
00303
for (
int i=1;i<n_mat;i++)
00304
if (n_rows != matrices[i].n_rows)
00305
PLERROR(
"add(SparseMatrix(%d,%d)+SparseMatrix(%d,%d): both should have same dimensions",
00306 n_rows,n_columns,matrices[i].n_rows,matrices[i].beginRow.length());
00307
int n_non_zero = 0;
00308
for (
int i=0;i<n_mat;i++)
00309 n_non_zero+=matrices[i].row.length();
00310
00311
SparseMatrix C(n_rows,n_columns,n_non_zero);
00312
00313
int n_actual_non_zero=0;
00314
00315
Vec column(n_rows);
00316
real* v=column.
data();
00317
for (
int j=0;j<n_columns;j++)
00318 {
00319 column.
clear();
00320
for (
int k=0;
k<n_mat;
k++)
00321
for (
int i=(
int)matrices[
k].beginRow[j];i<=(
int)matrices[
k].endRow[j];i++)
00322 v[(
int)matrices[
k].row[i]]+=matrices[
k].values[i];
00323 C.
beginRow[j]=n_actual_non_zero;
00324
for (
int i=0;i<n_rows;i++)
00325
if (v[i]!=0)
00326 {
00327 C.
row[n_actual_non_zero]=i;
00328 C.
values[n_actual_non_zero]=v[i];
00329 n_actual_non_zero++;
00330 }
00331 C.
endRow[j]=n_actual_non_zero-1;
00332
00333 }
00334 C.
row.
resize(n_actual_non_zero);
00335 C.
values.
resize(n_actual_non_zero);
00336
return C;
00337 }
00338
00339 }