00001
00018 #include <vector>
00019 #include <sstream>
00020 #include <string>
00021 #include <iostream>
00022 #include <iomanip>
00023 #include <math.h>
00024 #include "comun.hpp"
00025 #include "Elias.hpp"
00026
00027 using namespace std;
00028
00029 unsigned int techo_logb2(unsigned long x)
00030 {
00031 ASSERT(x>=1);
00032
00033 int r = 0;
00034 int u = 0;
00035 while (x>1) {
00036 r++;
00037 if (x % 2 == 1) {
00038 u = 1;
00039 }
00040 x = x / 2;
00041 }
00042 return r + u;
00043 }
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00060 unsigned int piso_logb2(unsigned int n)
00061 {
00062 ASSERT(n>=1);
00063 int pos = 0;
00064 if (n >= 1<<16) {
00065 n >>= 16;
00066 pos += 16;
00067 }
00068 if (n >= 1<< 8) {
00069 n >>= 8;
00070 pos += 8;
00071 }
00072 if (n >= 1<< 4) {
00073 n >>= 4;
00074 pos += 4;
00075 }
00076 if (n >= 1<< 2) {
00077 n >>= 2;
00078 pos += 2;
00079 }
00080 if (n >= 1<< 1) {
00081 pos += 1;
00082 }
00083 return ((n == 0) ? (-1) : pos);
00084 }
00085
00086 unsigned long pot2(unsigned int e)
00087 {
00088 ASSERT(e>=0);
00089
00090 long r=1;
00091 while (e>0) {
00092 r = r * 2;
00093 e--;
00094 }
00095 return r;
00096 }
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177 string vb2str(vector<bool> &vb)
00178 {
00179 unsigned int i;
00180 stringstream ss;
00181 ss.clear();
00182 ss.str("");
00183 for(i = 0; i < vb.size(); i++) {
00184 ss << (char)(vb[i] + '0');
00185 }
00186 return ss.str();
00187 }
00188
00189
00190 vector<bool> str2vb(string s)
00191 {
00192 vector<bool> vb(0);
00193 stringstream ss(s);
00194 do {
00195 char c;
00196 ss >> c;
00197 if (ss.good()) {
00198 vb.push_back(c-'0');
00199 }
00200 } while (!ss.eof());
00201
00202 return vb;
00203 }
00204
00205
00206 void codifica_unario(unsigned long x, vector<bool> &vb)
00207 {
00208 ASSERT(x >= 1);
00209
00210 while (x > 1) {
00211 vb.push_back(1);
00212 x--;
00213 }
00214 vb.push_back(0);
00215 }
00216
00217
00218 unsigned long decodifica_unario(vector<bool> &vb)
00219 {
00220 ASSERT(vb.size() > 0);
00221
00222 long x = 1;
00223 vector<bool>::iterator cv = vb.begin();
00224 short int c = *cv;
00225 vb.erase(cv);
00226
00227 while (c == 1) {
00228 x++;
00229 cv = vb.begin();
00230 c = *cv;
00231 vb.erase(cv);
00232 }
00233 return x;
00234 }
00235
00236
00237 void pone_un_entero(unsigned long x, unsigned int nbits, vector<bool> &vb)
00238 {
00239 ASSERT(x >= 0);
00240 ASSERT(nbits >= 0);
00241
00242 int i;
00243 long p2 = 0;
00244 if (nbits>0) {
00245 p2 = pot2(nbits-1);
00246 }
00247 for(i = nbits - 1; i >= 0; i--) {
00248 int b = (x / p2) % 2;
00249 vb.push_back(b);
00250 p2 = p2 / 2;
00251 }
00252 }
00253
00254
00255 unsigned long toma_un_entero(unsigned int nbits, vector<bool> &vb)
00256 {
00257 ASSERT(nbits >= 0);
00258 ASSERT(vb.size() >= nbits);
00259
00260 long x = 0;
00261 int i;
00262 vector<bool>::iterator cv;
00263 for(i = nbits-1; i >= 0; i--) {
00264 cv = vb.begin();
00265 short int b = *cv;
00266 vb.erase(cv);
00267 x = 2 * x + b;
00268 }
00269 return x;
00270 }
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283 void codifica_elias_gama(unsigned int x, vector<bool> &vb)
00284 {
00285 ASSERT(x >= 1);
00286
00287 int b = 1 + piso_logb2(x);
00288 codifica_unario(b, vb);
00289 pone_un_entero(x - pot2(b - 1), b - 1, vb);
00290 }
00291
00292
00293 unsigned long decodifica_elias_gama(vector<bool> &vb)
00294 {
00295 ASSERT(vb.size() > 0);
00296
00297 unsigned int b = decodifica_unario(vb);
00298 long x = toma_un_entero(b - 1, vb);
00299 return pot2(b - 1) + x;
00300 }
00301
00309 unsigned long
00310 lee_elias_gama(std::istream &is) throw (string)
00311 {
00312 vector<bool> vb(0);
00313 vb.clear();
00314
00315
00316 unsigned int p2;
00317 int c;
00318 short bit;
00319 do {
00320 c = is.get();
00321
00322 if (c == EOF) {
00323 throw errorFormato(is,
00324 "Fin de archivo mientras esperaba unario");
00325 } else if (c == 255) {
00326 vb.push_back(1);
00327 vb.push_back(1);
00328 vb.push_back(1);
00329 vb.push_back(1);
00330 vb.push_back(1);
00331 vb.push_back(1);
00332 vb.push_back(1);
00333 vb.push_back(1);
00334 }
00335 } while (c == 255);
00336 p2 = 256;
00337 do {
00338 p2 >>= 1;
00339
00340 bit = (c & (short)p2) > 0 ? 1 : 0;
00341 vb.push_back(bit);
00342
00343 } while (bit == 1 && p2 > 1);
00344
00345 unsigned int nb = vb.size();
00346
00347 do {
00348
00349 while (p2 > 1 && vb.size() < 1+ 2 * (nb-1)) {
00350 p2 >>= 1;
00351
00352 bit = (c & (short)p2) > 0 ? 1 : 0;
00353 vb.push_back(bit);
00354
00355 }
00356 if (vb.size() < 1 + 2 * (nb-1)) {
00357 c = is.get();
00358
00359 if (c == EOF) {
00360 stringstream ss("");
00361 ss << "Fin de archivo, se esperaba binario ("
00362 << vb.size() << " < " <<
00363 1+ 2*(nb-1)<< ")";
00364 throw errorFormato(is, ss.str());
00365 }
00366 p2 = 256;
00367 }
00368
00369 } while (vb.size() < 1+ 2 * (nb-1));
00370
00371
00372 unsigned long lr = decodifica_elias_gama(vb);
00373
00374 return lr;
00375 }
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436 unsigned long
00437 lee_elias_gama2(std::istream &is) throw (string)
00438 {
00439
00440 unsigned int p2;
00441 int c;
00442 short bit;
00443 unsigned int nbits = 0;
00444 unsigned long p2f = 1;
00445
00446
00447
00448
00449 do {
00450 c = is.get();
00451
00452
00453
00454 if (c == EOF) {
00455 throw errorFormato(is,
00456 "Fin de archivo mientras esperaba unario");
00457 } else if (c == 255) {
00458 nbits += 8;
00459 p2f <<= 8;
00460
00461 }
00462 } while (c == 255);
00463
00464 p2 = 256;
00465 do {
00466 p2 >>= 1;
00467 bit = (c & (short)p2) > 0 ? 1 : 0;
00468
00469 if (bit == 1) {
00470 nbits++;
00471 p2f <<= 1;
00472 }
00473 } while (bit == 1 && p2 > 1);
00474
00475
00476 ASSERT(nbits<=31);
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486 unsigned int bl;
00487 if (nbits <= 3) {
00488 bl = nbits;
00489
00490
00491 } else {
00492 bl = 7 - (nbits % 8);
00493 }
00494
00495 unsigned int ui = 0;
00496
00497
00498 ui = (unsigned char)(c << ((nbits % 8) + 1));
00499
00500 if (bl == nbits) {
00501
00502 ui >>= 8 - bl;
00503 } else {
00504
00505 ui >>= (nbits % 8) + 1;
00506 }
00507
00508
00509 while (bl < nbits) {
00510 c = is.get();
00511
00512 if ((nbits > 8) && (bl < nbits - 8)) {
00513
00514 ui <<= 8;
00515 ui |= c;
00516 bl += 8;
00517
00518 } else {
00519
00520 ui <<= nbits - bl;
00521 unsigned char cui = ((unsigned char)c) >> 8 - nbits + bl;
00522
00523 ui |= cui;
00524 bl = nbits;
00525
00526 }
00527 }
00528
00529 unsigned int lr = p2f | ui;
00530
00531 return lr;
00532 }
00533
00540 void
00541 escribe_elias_gama(std::ostream &os, unsigned int n)
00542 {
00543 ASSERT(n >= 1);
00544
00545
00546 vector<bool> vb(0);
00547 codifica_elias_gama(n, vb);
00548
00549 unsigned int i, p2 = 128;
00550 unsigned char c = 0;
00551
00552 unsigned int t = vb.size();
00553 for(i = 0; i < t; i++) {
00554 if (vb[i]) {
00555 c = c | p2;
00556 }
00557
00558 p2 >>= 1;
00559 if (p2 == 0) {
00560 os << c ;
00561
00562 p2 = 128;
00563 c = 0;
00564 }
00565 }
00566 if (p2 != 128) {
00567
00568 os << c ;
00569
00570 }
00571 }
00572
00573
00574 void
00575 escribe_elias_gama2(std::ostream &os, unsigned int n)
00576 {
00577 ASSERT(n >= 1);
00578
00579 unsigned long r = 0;
00580
00581 int b = piso_logb2(n);
00582
00583
00584 ASSERT(b <= 31);
00585
00586 for (int i = 0; i < b; i++) {
00587 r |= 1;
00588 r <<= 1;
00589
00590 }
00591 r <<= b;
00592
00593
00594
00595 unsigned long m = 0;
00596 for (int i = 0; i < b; i++) {
00597 m <<= 1;
00598 m |= 1;
00599 }
00600
00601 r |= n & m;
00602
00603
00604 int nb = 1+b/4;
00605 r <<= (nb*8) - (2*b + 1);
00606
00607 m = (unsigned long)0xFF00000000000000;
00608 unsigned char c = 0;
00609 for (int i=0; i < 8; i++) {
00610 if (8-i <= nb) {
00611 unsigned long ct = (unsigned long)r & (unsigned long)m;
00612
00613 ct >>= 8*(7-i);
00614
00615 c = (unsigned char)ct;
00616
00617 os.write((char *)&c, 1);
00618
00619 } else {
00620
00621 }
00622 m >>= 8;
00623 }
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640 }
00641
00642
00643
00651 unsigned int
00652 long_elias_gama(unsigned long n)
00653 {
00654 ASSERT(n >= 1);
00655
00656 int b = 1 + piso_logb2(n);
00657 int nb = (b-1)*2 + 1;
00658
00659 return (unsigned long)ceil((double)nb/(double)8);
00660 }
00661
00662
00663 void codifica_binaria_minima(unsigned long x, unsigned int n, vector<bool> &vb)
00664 {
00665 ASSERT(x >= 0);
00666 ASSERT(n >= 1);
00667
00668 int b = techo_logb2(n);
00669 unsigned long d = pot2(b) - n;
00670 if (x > d) {
00671 pone_un_entero(x - 1 + d, b, vb);
00672 } else {
00673 pone_un_entero(x - 1 , b - 1, vb);
00674 }
00675 }
00676
00677
00678 unsigned long decodifica_binaria_minima(unsigned int n, vector<bool> &vb)
00679 {
00680 ASSERT(n >= 1);
00681
00682
00683 unsigned int b = techo_logb2(n);
00684
00685 ASSERT(vb.size() >= b - 1);
00686
00687 long d = pot2(b) - n;
00688 long x = toma_un_entero(b - 1, vb);
00689 if ((x + 1) > d) {
00690 vector<bool>::iterator cv = vb.begin();
00691 char c = *cv;
00692 vb.erase(cv);
00693 x = 2 * x + c;
00694 x = x - d;
00695 }
00696 return x + 1;
00697 }