00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef __REEDSOLOMON_H__
00021 #define __REEDSOLOMON_H__
00022
00023
00024
00025
00026
00027
00028
00029
00030 class RSOutputRow
00031 {
00032 public:
00033 RSOutputRow(void) {};
00034 RSOutputRow(bool _present, u16 _exponent) : present(_present), exponent(_exponent) {}
00035
00036 public:
00037 bool present;
00038 u16 exponent;
00039 };
00040
00041 templateclass g>
00042 class ReedSolomon
00043 {
00044 public:
00045 typedef g G;
00046
00047 ReedSolomon(void);
00048 ~ReedSolomon(void);
00049
00050
00051 bool SetInput(const vector &present);
00052 bool SetInput(u32 count);
00053
00054
00055 bool SetOutput(bool present, u16 exponent);
00056 bool SetOutput(bool present, u16 lowexponent, u16 highexponent);
00057
00058
00059 bool Compute(CommandLine::NoiseLevel noiselevel);
00060
00061
00062 bool Process(size_t size,
00063 u32 inputindex,
00064 const void *inputbuffer,
00065 u32 outputindex,
00066 void *outputbuffer);
00067
00068 private:
00069 bool InternalProcess(const g &factor, size_t size, const void *inputbuffer, void *outputbuffer);
00070
00071 protected:
00072
00073 bool GaussElim(CommandLine::NoiseLevel noiselevel,
00074 unsigned int rows,
00075 unsigned int leftcols,
00076 G *leftmatrix,
00077 G *rightmatrix,
00078 unsigned int datamissing);
00079
00080 protected:
00081 u32 inputcount;
00082
00083 u32 datapresent;
00084 u32 datamissing;
00085 u32 *datapresentindex;
00086 u32 *datamissingindex;
00087
00088 typename G::ValueType *database;
00089
00090 u32 outputcount;
00091
00092 u32 parpresent;
00093 u32 parmissing;
00094 u32 *parpresentindex;
00095 u32 *parmissingindex;
00096
00097 vector outputrows;
00098
00099 G *leftmatrix;
00100
00101
00102
00103
00104
00105 #ifdef LONGMULTIPLY
00106 GaloisLongMultiplyTable *glmt;
00107 #endif
00108 };
00109
00110 templateclass g>
00111 inline ReedSolomon::ReedSolomon(void)
00112 {
00113 inputcount = 0;
00114
00115 datapresent = 0;
00116 datamissing = 0;
00117 datapresentindex = 0;
00118 datamissingindex = 0;
00119 database = 0;
00120
00121 outputrows.empty();
00122
00123 outputcount = 0;
00124
00125 parpresent = 0;
00126 parmissing = 0;
00127 parpresentindex = 0;
00128 parmissingindex = 0;
00129
00130 leftmatrix = 0;
00131
00132 #ifdef LONGMULTIPLY
00133 glmt = new GaloisLongMultiplyTable;
00134 #endif
00135 }
00136
00137 templateclass g>
00138 inline ReedSolomon::~ReedSolomon(void)
00139 {
00140 delete [] datapresentindex;
00141 delete [] datamissingindex;
00142 delete [] database;
00143 delete [] parpresentindex;
00144 delete [] parmissingindex;
00145 delete [] leftmatrix;
00146
00147 #ifdef LONGMULTIPLY
00148 delete glmt;
00149 #endif
00150 }
00151
00152 templateclass g>
00153 inline bool ReedSolomon::Process(size_t size, u32 inputindex, const void *inputbuffer, u32 outputindex, void *outputbuffer)
00154 {
00155
00156
00157
00158
00159 g factor = leftmatrix[outputindex * (datapresent + datamissing) + inputindex];
00160
00161 if (factor == 0 || 0 == size)
00162 return eSuccess;
00163 return this->InternalProcess (factor, size, inputbuffer, outputbuffer);
00164 }
00165
00166 u32 gcd(u32 a, u32 b);
00167
00168
00169
00170 templateclass g>
00171 inline bool ReedSolomon::SetOutput(bool present, u16 exponent)
00172 {
00173
00174 outputrows.push_back(RSOutputRow(present, exponent));
00175
00176 outputcount++;
00177
00178
00179 if (present)
00180 {
00181 parpresent++;
00182 }
00183 else
00184 {
00185 parmissing++;
00186 }
00187
00188 return true;
00189 }
00190
00191
00192
00193 templateclass g>
00194 inline bool ReedSolomon::SetOutput(bool present, u16 lowexponent, u16 highexponent)
00195 {
00196 for (unsigned int exponent=lowexponent; exponent00197 {
00198 if (!SetOutput(present, exponent))
00199 return false;
00200 }
00201
00202 return true;
00203 }
00204
00205
00206 templateclass g>
00207 inline bool ReedSolomon::Compute(CommandLine::NoiseLevel noiselevel)
00208 {
00209 u32 outcount = datamissing + parmissing;
00210 u32 incount = datapresent + datamissing;
00211
00212 if (datamissing > parpresent)
00213 {
00214 cerr "Not enough recovery blocks." 00215 return false;
00216 }
00217 else if (outcount == 0)
00218 {
00219 cerr "No output blocks." 00220 return false;
00221 }
00222
00223 if (noiselevel > CommandLine::nlQuiet)
00224 cout "Computing Reed Solomon matrix." 00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243 leftmatrix = new G[outcount * incount];
00244 memset(leftmatrix, 0, outcount * incount * sizeof(G));
00245
00246
00247
00248 G *rightmatrix = 0;
00249 if (datamissing > 0)
00250 {
00251 rightmatrix = new G[outcount * outcount];
00252 memset(rightmatrix, 0, outcount *outcount * sizeof(G));
00253 }
00254
00255
00256
00257 vector::const_iterator outputrow = outputrows.begin();
00258
00259
00260 for (unsigned int row=0; row00261 {
00262 if (noiselevel > CommandLine::nlQuiet)
00263 {
00264 int progress = row * 1000 / (datamissing+parmissing);
00265 cout "Constructing: " '.' "%\r" 00266 }
00267
00268
00269 while (!outputrow->present)
00270 {
00271 outputrow++;
00272 }
00273 u16 exponent = outputrow->exponent;
00274
00275
00276 for (unsigned int col=0; coldatapresent; col++)
00277 {
00278 leftmatrix[row * incount + col] = G(database[datapresentindex[col]]).pow(exponent);
00279 }
00280
00281 for (unsigned int col=0; col00282 {
00283 leftmatrix[row * incount + col + datapresent] = (row == col) ? 1 : 0;
00284 }
00285
00286 if (datamissing > 0)
00287 {
00288
00289 for (unsigned int col=0; col00290 {
00291 rightmatrix[row * outcount + col] = G(database[datamissingindex[col]]).pow(exponent);
00292 }
00293
00294 for (unsigned int col=0; col00295 {
00296 rightmatrix[row * outcount + col + datamissing] = 0;
00297 }
00298 }
00299
00300 outputrow++;
00301 }
00302
00303 outputrow = outputrows.begin();
00304 for (unsigned int row=0; row00305 {
00306 if (noiselevel > CommandLine::nlQuiet)
00307 {
00308 int progress = (row+datamissing) * 1000 / (datamissing+parmissing);
00309 cout "Constructing: " '.' "%\r" 00310 }
00311
00312
00313 while (outputrow->present)
00314 {
00315 outputrow++;
00316 }
00317 u16 exponent = outputrow->exponent;
00318
00319
00320 for (unsigned int col=0; coldatapresent; col++)
00321 {
00322 leftmatrix[(row+datamissing) * incount + col] = G(database[datapresentindex[col]]).pow(exponent);
00323 }
00324
00325 for (unsigned int col=0; col00326 {
00327 leftmatrix[(row+datamissing) * incount + col + datapresent] = 0;
00328 }
00329
00330 if (datamissing > 0)
00331 {
00332
00333 for (unsigned int col=0; col00334 {
00335 rightmatrix[(row+datamissing) * outcount + col] = G(database[datamissingindex[col]]).pow(exponent);
00336 }
00337
00338 for (unsigned int col=0; col00339 {
00340 rightmatrix[(row+datamissing) * outcount + col + datamissing] = (row == col) ? 1 : 0;
00341 }
00342 }
00343
00344 outputrow++;
00345 }
00346 if (noiselevel > CommandLine::nlQuiet)
00347 cout "Constructing: done." 00348
00349
00350 if (datamissing > 0)
00351 {
00352
00353
00354 bool success = GaussElim(noiselevel, outcount, incount, leftmatrix, rightmatrix, datamissing);
00355 delete [] rightmatrix;
00356 return success;
00357 }
00358
00359 return true;
00360 }
00361
00362
00363 templateclass g>
00364 inline bool ReedSolomon::GaussElim(CommandLine::NoiseLevel noiselevel, unsigned int rows, unsigned int leftcols, G *leftmatrix, G *rightmatrix, unsigned int datamissing)
00365 {
00366 if (noiselevel == CommandLine::nlDebug)
00367 {
00368 for (unsigned int row=0; row00369 {
00370 cout "/" : (row==rows-1) ? "\\" : "|");
00371 for (unsigned int col=0; col00372 {
00373 cout " "
00374 8?4:2) '0')
00375 unsigned int)leftmatrix[row*leftcols+col];
00376 }
00377 cout " \\ /" : (row==rows-1) ? " / \\" : " | |");
00378 for (unsigned int col=0; col00379 {
00380 cout " "
00381 8?4:2) '0')
00382 unsigned int)rightmatrix[row*rows+col];
00383 }
00384 cout " \\" : (row==rows-1) ? " /" : " | |");
00385 cout 00386
00387 cout ' ');
00388 }
00389 }
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400 int progress = 0;
00401
00402
00403 for (unsigned int row=0; row00404 {
00405
00406
00407
00408
00409 G pivotvalue = rightmatrix[row * rows + row];
00410 assert(pivotvalue != 0);
00411 if (pivotvalue == 0)
00412 {
00413 cerr "RS computation error." 00414 return false;
00415 }
00416
00417
00418 if (pivotvalue != 1)
00419 {
00420 for (unsigned int col=0; col00421 {
00422 if (leftmatrix[row * leftcols + col] != 0)
00423 {
00424 leftmatrix[row * leftcols + col] /= pivotvalue;
00425 }
00426 }
00427 rightmatrix[row * rows + row] = 1;
00428 for (unsigned int col=row+1; col00429 {
00430 if (rightmatrix[row * rows + col] != 0)
00431 {
00432 rightmatrix[row * rows + col] /= pivotvalue;
00433 }
00434 }
00435 }
00436
00437
00438 for (unsigned int row2=0; row200439 {
00440 if (noiselevel > CommandLine::nlQuiet)
00441 {
00442 int newprogress = (row*rows+row2) * 1000 / (datamissing*rows);
00443 if (progress != newprogress)
00444 {
00445 progress = newprogress;
00446 cout "Solving: " '.' "%\r" 00447 }
00448 }
00449
00450 if (row != row2)
00451 {
00452
00453 G scalevalue = rightmatrix[row2 * rows + row];
00454
00455 if (scalevalue == 1)
00456 {
00457
00458 for (unsigned int col=0; col00459 {
00460 if (leftmatrix[row * leftcols + col] != 0)
00461 {
00462 leftmatrix[row2 * leftcols + col] -= leftmatrix[row * leftcols + col];
00463 }
00464 }
00465
00466 for (unsigned int col=row; col00467 {
00468 if (rightmatrix[row * rows + col] != 0)
00469 {
00470 rightmatrix[row2 * rows + col] -= rightmatrix[row * rows + col];
00471 }
00472 }
00473 }
00474 else if (scalevalue != 0)
00475 {
00476
00477 for (unsigned int col=0; col00478 {
00479 if (leftmatrix[row * leftcols + col] != 0)
00480 {
00481 leftmatrix[row2 * leftcols + col] -= leftmatrix[row * leftcols + col] * scalevalue;
00482 }
00483 }
00484
00485 for (unsigned int col=row; col00486 {
00487 if (rightmatrix[row * rows + col] != 0)
00488 {
00489 rightmatrix[row2 * rows + col] -= rightmatrix[row * rows + col] * scalevalue;
00490 }
00491 }
00492 }
00493 }
00494 }
00495 }
00496 if (noiselevel > CommandLine::nlQuiet)
00497 cout "Solving: done." 00498 if (noiselevel == CommandLine::nlDebug)
00499 {
00500 for (unsigned int row=0; row00501 {
00502 cout "/" : (row==rows-1) ? "\\" : "|");
00503 for (unsigned int col=0; col00504 {
00505 cout " "
00506 8?4:2) '0')
00507 unsigned int)leftmatrix[row*leftcols+col];
00508 }
00509 cout " \\ /" : (row==rows-1) ? " / \\" : " | |");
00510 for (unsigned int col=0; col00511 {
00512 cout " "
00513 8?4:2) '0')
00514 unsigned int)rightmatrix[row*rows+col];
00515 }
00516 cout " \\" : (row==rows-1) ? " /" : " | |");
00517 cout 00518
00519 cout ' ');
00520 }
00521 }
00522
00523 return true;
00524 }
00525
00526
00527 #endif // __REEDSOLOMON_H__