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
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 namespace CIMPL
00060 {
00061
00062
00063
00064 template< class T >
00065 SparseMatrix<T>::SparseMatrix()
00066 : ndims(2), count(0)
00067 {
00068 xDimStarts = 0;
00069 yDimStarts = 0;
00070
00071 dims = new (std::nothrow) int[ndims];
00072 Utility::CheckPointer(dims);
00073 for(int j=0;j<ndims;j++)
00074 {
00075 dims[j] = 0;
00076 }
00077
00078 }
00079
00080
00081
00082
00083 template< class T >
00084 SparseMatrix<T>::SparseMatrix(const int xdim, const int ydim)
00085 {
00086 if(xdim < 1 || ydim < 1)
00087 {
00088 cerr << "Line: " << __LINE__ << " File: " << __FILE__ << endl;
00089 Utility::RunTimeError("All array dimensions should be larger than 1!");
00090 }
00091
00092 ndims = 2;
00093 count = 0;
00094 dims = new (std::nothrow) int[ndims];
00095 Utility::CheckPointer(dims);
00096 dims[0] = xdim;
00097 dims[1] = ydim;
00098
00099 xDimStarts = new (std::nothrow) matrixCellStart<T>[xdim];
00100 Utility::CheckPointer(xDimStarts);
00101 for(int i=0; i<xdim; i++)
00102 {
00103 xDimStarts[i].listCount = 0;
00104 xDimStarts[i].first = new (std::nothrow) matrixCell<T>;
00105 Utility::CheckPointer(xDimStarts[i].first);
00106 xDimStarts[i].first->xNext = 0;
00107 xDimStarts[i].first->yNext = 0;
00108 }
00109
00110 yDimStarts = new (std::nothrow) matrixCellStart<T>[ydim];
00111 Utility::CheckPointer(yDimStarts);
00112 for(int i=0; i<ydim; i++)
00113 {
00114 yDimStarts[i].listCount = 0;
00115 yDimStarts[i].first = new (std::nothrow) matrixCell<T>;
00116 Utility::CheckPointer(yDimStarts[i].first);
00117 yDimStarts[i].first->xNext = 0;
00118 yDimStarts[i].first->yNext = 0;
00119 }
00120
00121
00122 }
00123
00124
00125
00126
00127
00128
00129 template< class T >
00130 SparseMatrix<T>::~SparseMatrix()
00131 {
00132
00133
00134
00135 for(int i=0; i<XDim(); i++)
00136 {
00137 matrixCell<T> *temp = xDimStarts[i].first;
00138 while(temp != 0)
00139 {
00140 matrixCell<T> *c = temp->yNext;
00141 delete temp;
00142 temp = c;
00143 }
00144 }
00145 delete [] xDimStarts;
00146
00147 for(int i=0; i<YDim(); i++)
00148 {
00149 delete yDimStarts[i].first;
00150 }
00151 delete [] yDimStarts;
00152 delete [] dims;
00153
00154
00155 }
00156
00157
00158
00159
00160
00161 template< class T >
00162 inline const int SparseMatrix<T>::Columns() const
00163 {
00164 return dims[0];
00165 }
00166
00167 template< class T >
00168 inline const int SparseMatrix<T>::Rows() const
00169 {
00170 return dims[1];
00171 }
00172
00173
00174 template< class T >
00175 inline const int SparseMatrix<T>::XDim() const
00176 {
00177 return dims[0];
00178 }
00179
00180 template< class T >
00181 inline const int SparseMatrix<T>::YDim() const
00182 {
00183 if(ndims < 2)
00184 {
00185 cerr << "Line: " << __LINE__ << " File: " << __FILE__ << endl;
00186 Utility::RunTimeError("YDim(): Number of dimensions is less than 2!");
00187 }
00188 return dims[1];
00189 }
00190
00191
00192
00193 template< class T >
00194 inline const int SparseMatrix<T>::NNZ(void) const
00195 {
00196 return count;
00197 }
00198
00199
00200 template< class T >
00201 inline void SparseMatrix<T>::SetValue(const int x, const int y, const T value)
00202 {
00203 if(x<0 || x>=dims[0] || y<0 || y>=dims[1])
00204 {
00205 cerr << "Line: " << __LINE__ << " File: " << __FILE__ << endl;
00206 Utility::RunTimeError("Index outside bounds!");
00207 }
00208
00209 if(value == 0)
00210 {
00211 bool deleted = DeleteCell(x, y);
00212 if(deleted)
00213 {
00214 xDimStarts[x].listCount--;
00215 yDimStarts[y].listCount--;
00216 count--;
00217 }
00218 return;
00219 }
00220
00221
00222 matrixCell<T> *c = new (std::nothrow) matrixCell<T>;
00223 Utility::CheckPointer(c);
00224 c->value = value;
00225 c->x = x;
00226 c->y = y;
00227 c->xNext = 0;
00228 c->yNext = 0;
00229
00230 if( xDimStarts[x].listCount > yDimStarts[y].listCount )
00231 {
00232 bool exists = AddCellYStart(c);
00233 if(!exists)
00234 {
00235 AddCellXStart(c);
00236 xDimStarts[x].listCount++;
00237 yDimStarts[y].listCount++;
00238 count++;
00239 }
00240 }
00241 else
00242 {
00243 bool exists = AddCellXStart(c);
00244 if(!exists)
00245 {
00246 AddCellYStart(c);
00247 xDimStarts[x].listCount++;
00248 yDimStarts[y].listCount++;
00249 count++;
00250 }
00251 }
00252 }
00253
00254 template< class T >
00255 inline T SparseMatrix<T>::GetValue(const int x, const int y)
00256 {
00257 if(x<0 || x>=dims[0] || y<0 || y>=dims[1])
00258 {
00259 cerr << "Line: " << __LINE__ << " File: " << __FILE__ << endl;
00260 Utility::RunTimeError("Index outside bounds!");
00261 }
00262
00263 if( xDimStarts[x].listCount > yDimStarts[y].listCount )
00264 {
00265 return GetCellYStart(x, y);
00266 }
00267 else
00268 {
00269 return GetCellXStart(x, y);
00270 }
00271 }
00272
00273
00274
00275
00276
00277
00278
00279 template< class T >
00280 inline T SparseMatrix<T>::operator() (const int i, const int j)
00281 {
00282 return GetValue(i, j);
00283 }
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00300
00302
00303
00304
00305
00306 template< class T >
00307 bool SparseMatrix<T>::AddCellYStart(matrixCell<T> *c)
00308 {
00309 matrixCell<T> *temp = yDimStarts[c->y].first;
00310 while(temp->xNext != 0)
00311 {
00312 if(temp->xNext->x == c->x)
00313 {
00314 temp->xNext->value = c->value;
00315 delete c;
00316 return true;
00317 }
00318 else if(temp->xNext->x > c->x)
00319 {
00320 c->xNext = temp->xNext;
00321 temp->xNext = c;
00322 return false;
00323 }
00324
00325 temp = temp->xNext;
00326 }
00327
00328 c->xNext = 0;
00329 temp->xNext = c;
00330 return false;
00331 }
00332
00333
00334
00335 template< class T >
00336 bool SparseMatrix<T>::AddCellXStart(matrixCell<T> *c)
00337 {
00338 matrixCell<T> *temp = xDimStarts[c->x].first;
00339 while(temp->yNext != 0)
00340 {
00341 if(temp->yNext->y == c->y)
00342 {
00343 temp->yNext->value = c->value;
00344 delete c;
00345 return true;
00346 }
00347 else if(temp->yNext->y > c->y)
00348 {
00349 c->yNext = temp->yNext;
00350 temp->yNext = c;
00351 return false;
00352 }
00353
00354 temp = temp->yNext;
00355 }
00356
00357 c->yNext = 0;
00358 temp->yNext = c;
00359 return false;
00360 }
00361
00362
00363 template< class T >
00364 T SparseMatrix<T>::GetCellYStart(const int x, const int y)
00365 {
00366 matrixCell<T> *temp = yDimStarts[y].first;
00367 while(temp->xNext != 0)
00368 {
00369 if(temp->xNext->x == x)
00370 {
00371 return temp->xNext->value;
00372 }
00373 else if(temp->xNext->x > x)
00374 {
00375 return 0;
00376 }
00377
00378 temp = temp->xNext;
00379 }
00380
00381 return 0;
00382 }
00383
00384 template< class T >
00385 T SparseMatrix<T>::GetCellXStart(const int x, const int y)
00386 {
00387 matrixCell<T> *temp = xDimStarts[x].first;
00388 while(temp->yNext != 0)
00389 {
00390 if(temp->yNext->y == y)
00391 {
00392 return temp->yNext->value;
00393 }
00394 else if(temp->yNext->y > y)
00395 {
00396 return 0;
00397 }
00398
00399 temp = temp->yNext;
00400 }
00401
00402 return 0;
00403 }
00404
00405
00406 template< class T >
00407 bool SparseMatrix<T>::DeleteCell(const int x, const int y)
00408 {
00409 matrixCell<T> *c = 0;
00410 bool deleted = false;
00411
00412 matrixCell<T> *temp = yDimStarts[y].first;
00413 while(temp->xNext != 0)
00414 {
00415 if(temp->xNext->x == x)
00416 {
00417 c = temp->xNext;
00418 temp->xNext = c->xNext;
00419 deleted = true;
00420 break;
00421 }
00422 else if(temp->xNext->x > c->x)
00423 {
00424 return false;
00425 }
00426
00427 temp = temp->xNext;
00428 }
00429
00430 if(deleted == false)
00431 {
00432 return false;
00433 }
00434
00435 temp = xDimStarts[x].first;
00436 while(temp->yNext != 0)
00437 {
00438 if(temp->yNext->y == y)
00439 {
00440 c = temp->yNext;
00441 temp->yNext = c->yNext;
00442 deleted = true;
00443 break;
00444 }
00445 else if(temp->yNext->y > c->y)
00446 {
00447 return false;
00448 }
00449
00450 temp = temp->yNext;
00451 }
00452 if(deleted == false)
00453 {
00454 return false;
00455 }
00456
00457 delete c;
00458 return true;
00459 }
00460
00461
00462
00463
00464 };
00465
00466
00467
00468
00469
00470
00471