OverlayKey.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2006 Institut fuer Telematik, Universitaet Karlsruhe (TH)
00003 //
00004 // This program is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU General Public License
00006 // as published by the Free Software Foundation; either version 2
00007 // of the License, or (at your option) any later version.
00008 //
00009 // This program is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License
00015 // along with this program; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017 //
00018 
00024 #include <omnetpp.h>
00025 
00026 #include "OverlayKey.h"
00027 #include "Comparator.h"
00028 
00029 #include <BinaryValue.h>
00030 #include "SHA1.h"
00031 
00032 using namespace std;
00033 
00034 uint32_t OverlayKey::keyLength = MAX_KEYLENGTH;
00035 
00036 // TODO: replace both commands below with simpler macros without conditionals
00037 
00038 //#define ROUND_NEXT(n, div) (((n) + (div) - 1) / (div))
00039 //uint OverlayKey::aSize = ROUND_NEXT(OverlayKey::keyLength, 8*sizeof(mp_limb_t));
00040 
00041 uint32_t OverlayKey::aSize = OverlayKey::keyLength / (8*sizeof(mp_limb_t)) +
00042     (OverlayKey::keyLength % (8*sizeof(mp_limb_t))
00043      != 0 ? 1 : 0);
00044 
00045 mp_limb_t OverlayKey::GMP_MSB_MASK = (OverlayKey::keyLength % GMP_LIMB_BITS)
00046     != 0 ? (((mp_limb_t)1 << (OverlayKey::keyLength % GMP_LIMB_BITS))-1)
00047     : (mp_limb_t) - 1;
00048 
00049 //--------------------------------------------------------------------
00050 // constants
00051 //--------------------------------------------------------------------
00052 
00053 // predefined keys
00054 const OverlayKey OverlayKey::UNSPECIFIED_KEY;
00055 const OverlayKey OverlayKey::ZERO((uint32_t)0);
00056 const OverlayKey OverlayKey::ONE((uint32_t)1);
00057 
00058 
00059 // hex crap
00060 const char* HEX = "0123456789abcdef";
00061 
00062 //--------------------------------------------------------------------
00063 // construction and destruction
00064 //--------------------------------------------------------------------
00065 
00066 // default construction: create a unspecified node key
00067 OverlayKey::OverlayKey()
00068 {
00069     isUnspec = true;
00070 }
00071 
00072 // create a key out of an normal integer
00073 OverlayKey::OverlayKey(uint32_t num)
00074 {
00075     clear();
00076     key[0] = num;
00077     trim();
00078 }
00079 
00080 // create a key out of a buffer
00081 OverlayKey::OverlayKey(const unsigned char* buf, uint32_t size)
00082 {
00083     int trimSize, offset;
00084     clear();
00085     trimSize = (int)min((uint32_t) (aSize * sizeof(mp_limb_t)), size);
00086     offset = aSize * sizeof(mp_limb_t) - trimSize;
00087     memcpy( ((char*)key) + offset, buf, trimSize);
00088     trim();
00089 }
00090 
00091 // create a key out of an string with the given base
00092 OverlayKey::OverlayKey(const std::string& str, uint32_t base)
00093 {
00094     if ((base < 2) || (base > 16)) {
00095         throw cRuntimeError("OverlayKey::OverlayKey(): Invalid base!");
00096     }
00097 
00098     string s(str);
00099     clear();
00100 
00101     for (uint32_t i=0; i<s.size(); i++) {
00102         if ((s[i] >= '0') && (s[i] <= '9')) {
00103             s[i] -= '0';
00104         } else if ((s[i] >= 'a') && (s[i] <= 'f')) {
00105             s[i] -= ('a' - 10);
00106         } else if ((s[i] >= 'A') & (s[i] <= 'F')) {
00107             s[i] -= ('A' - 10);
00108         } else {
00109             throw cRuntimeError("OverlayKey::OverlayKey(): "
00110                                     "Invalid character in string!");
00111         }
00112     }
00113 
00114     mpn_set_str ((mp_limb_t*)this->key, (const unsigned char*)s.c_str(),
00115                  str.size(), base);
00116     trim();
00117 }
00118 
00119 // copy constructor
00120 OverlayKey::OverlayKey(const OverlayKey& rhs)
00121 {
00122     (*this) = rhs;
00123 }
00124 
00125 // default destructur
00126 OverlayKey::~OverlayKey()
00127 {}
00128 
00129 //--------------------------------------------------------------------
00130 // string representations & node key attributes
00131 //--------------------------------------------------------------------
00132 
00133 void OverlayKey::setKeyLength(uint32_t length)
00134 {
00135     if ((length < 1) || (length > OverlayKey::keyLength)) {
00136         opp_error("OverlayKey::setKeyLength(): length must be <= %i "
00137                   "and setKeyLength() must not be called twice "
00138                   "with different length!", MAX_KEYLENGTH);
00139     }
00140 
00141     keyLength = length;
00142 
00143     aSize = keyLength / (8*sizeof(mp_limb_t)) +
00144         (keyLength % (8*sizeof(mp_limb_t))!=0 ? 1 : 0);
00145 
00146     GMP_MSB_MASK = (keyLength % GMP_LIMB_BITS)
00147         != 0 ? (((mp_limb_t)1 << (keyLength % GMP_LIMB_BITS))-1)
00148         : (mp_limb_t)-1;
00149 }
00150 
00151 
00152 // returns the length in bits
00153 uint32_t OverlayKey::getLength()
00154 {
00155     return OverlayKey::keyLength;
00156 }
00157 
00158 bool OverlayKey::isUnspecified() const
00159 {
00160     return isUnspec;
00161 }
00162 
00163 std::string OverlayKey::toString(uint32_t base) const
00164 {
00165     if ((base != 2) && (base != 16)) {
00166         throw cRuntimeError("OverlayKey::OverlayKey(): Invalid base!");
00167     }
00168 
00169     if (isUnspec)
00170         return std::string("<unspec>");
00171     else {
00172         char temp[MAX_KEYLENGTH+1];
00173 
00174         if (base==16) {
00175             int k=0;
00176             for (int i=(keyLength-1)/4; i>=0; i--, k++)
00177                 temp[k] = HEX[this->getBitRange
00178                               (4*i,4)];
00179 
00180             temp[k] = 0;
00181             return std::string((const char*)temp);
00182         } else if (base==2) {
00183             int k=0;
00184             for (int i=keyLength-1; i>=0; i-=1, k++)
00185                 temp[k] = HEX[this->getBit(i)];
00186             temp[k] = 0;
00187             return std::string((const char*)temp);
00188         } else {
00189             throw cRuntimeError("OverlayKey::OverlayKey(): Invalid base!");
00190         }
00191 
00192 // the following native libgmp code doesn't work with leading zeros
00193 #if 0
00194         mp_size_t last = mpn_get_str((unsigned char*)temp, base,
00195                                      (mp_limb_t*)this->key, aSize);
00196         for (int i=0; i<last; i++) {
00197             temp[i] = HEX[temp[i]];
00198         }
00199         temp[last] = 0;
00200         return std::string((const char*)temp);
00201 #endif
00202 
00203     }
00204 }
00205 
00206 //--------------------------------------------------------------------
00207 // operators
00208 //--------------------------------------------------------------------
00209 
00210 // assignment operator
00211 OverlayKey& OverlayKey::operator=(const OverlayKey& rhs)
00212 {
00213     isUnspec = rhs.isUnspec;
00214     memcpy( key, rhs.key, aSize*sizeof(mp_limb_t) );
00215     return *this;
00216 }
00217 
00218 // sub one prefix operator
00219 OverlayKey& OverlayKey::operator--()
00220 {
00221     return (*this -= ONE);
00222 }
00223 
00224 // sub one postfix operator
00225 OverlayKey OverlayKey::operator--(int)
00226 {
00227     OverlayKey clone = *this;
00228     *this -= ONE;
00229     return clone;
00230 }
00231 
00232 // add one prefix operator
00233 OverlayKey& OverlayKey::operator++()
00234 {
00235     return (*this += ONE);
00236 }
00237 
00238 // sub one postfix operator
00239 OverlayKey OverlayKey::operator++(int)
00240 {
00241     OverlayKey clone = *this;
00242     *this += ONE;
00243     return clone;
00244 }
00245 
00246 // add assign operator
00247 OverlayKey& OverlayKey::operator+=( const OverlayKey& rhs )
00248 {
00249     mpn_add_n((mp_limb_t*)key, (mp_limb_t*)key, (mp_limb_t*)rhs.key, aSize);
00250     trim();
00251     isUnspec = false;
00252     return *this;
00253 }
00254 
00255 // sub assign operator
00256 OverlayKey& OverlayKey::operator-=( const OverlayKey& rhs )
00257 {
00258     mpn_sub_n((mp_limb_t*)key, (mp_limb_t*)key, (mp_limb_t*)rhs.key, aSize);
00259     trim();
00260     isUnspec = false;
00261     return *this;
00262 }
00263 
00264 // add operator
00265 OverlayKey OverlayKey::operator+(const OverlayKey& rhs) const
00266 {
00267     OverlayKey result = *this;
00268     result += rhs;
00269     return result;
00270 }
00271 
00272 // sub operator
00273 OverlayKey OverlayKey::operator-(const OverlayKey& rhs) const
00274 {
00275     OverlayKey result = *this;
00276     result -= rhs;
00277     return result;
00278 }
00279 
00280 // compare operators
00281 bool OverlayKey::operator<(const OverlayKey& compKey) const
00282 {
00283     return compareTo(compKey) < 0;
00284 }
00285 bool OverlayKey::operator>(const OverlayKey& compKey) const
00286 {
00287     return compareTo(compKey) > 0;
00288 }
00289 bool OverlayKey::operator<=(const OverlayKey& compKey) const
00290 {
00291     return compareTo(compKey) <=0;
00292 }
00293 bool OverlayKey::operator>=(const OverlayKey& compKey) const
00294 {
00295     return compareTo(compKey) >=0;
00296 }
00297 bool OverlayKey::operator==(const OverlayKey& compKey) const
00298 {
00299     return compareTo(compKey) ==0;
00300 }
00301 bool OverlayKey::operator!=(const OverlayKey& compKey) const
00302 {
00303     return compareTo(compKey) !=0;
00304 }
00305 
00306 // bitwise xor
00307 OverlayKey OverlayKey::operator^ (const OverlayKey& rhs) const
00308 {
00309     OverlayKey result = *this;
00310     for (uint32_t i=0; i<aSize; i++) {
00311         result.key[i] ^= rhs.key[i];
00312     }
00313 
00314     return result;
00315 }
00316 
00317 // bitwise or
00318 OverlayKey OverlayKey::operator| (const OverlayKey& rhs) const
00319 {
00320     OverlayKey result = *this;
00321     for (uint32_t i=0; i<aSize; i++) {
00322         result.key[i] |= rhs.key[i];
00323     }
00324 
00325     return result;
00326 }
00327 
00328 // bitwise and
00329 OverlayKey OverlayKey::operator& (const OverlayKey& rhs) const
00330 {
00331     OverlayKey result = *this;
00332     for (uint32_t i=0; i<aSize; i++) {
00333         result.key[i] &= rhs.key[i];
00334     }
00335 
00336     return result;
00337 }
00338 
00339 // complement
00340 OverlayKey OverlayKey::operator~ () const
00341 {
00342     OverlayKey result = *this;
00343     for (uint32_t i=0; i<aSize; i++) {
00344         result.key[i] = ~key[i];
00345     }
00346     result.trim();
00347 
00348     return result;
00349 }
00350 
00351 // bitwise shift right
00352 OverlayKey OverlayKey::operator>>(uint32_t num) const
00353 {
00354     OverlayKey result = ZERO;
00355     int i = num/GMP_LIMB_BITS;
00356 
00357     num %= GMP_LIMB_BITS;
00358 
00359     if (i>=(int)aSize)
00360         return result;
00361 
00362     for (int j=0; j<(int)aSize-i; j++) {
00363         result.key[j] = key[j+i];
00364     }
00365     mpn_rshift(result.key,result.key,aSize,num);
00366     result.isUnspec = false;
00367     result.trim();
00368 
00369     return result;
00370 }
00371 
00372 // bitwise shift left
00373 OverlayKey OverlayKey::operator<<(uint32_t num) const
00374 {
00375     OverlayKey result = ZERO;
00376     int i = num/GMP_LIMB_BITS;
00377 
00378     num %= GMP_LIMB_BITS;
00379 
00380     if (i>=(int)aSize)
00381         return result;
00382 
00383     for (int j=0; j<(int)aSize-i; j++) {
00384         result.key[j+i] = key[j];
00385     }
00386     mpn_lshift(result.key,result.key,aSize,num);
00387     result.isUnspec = false;
00388     result.trim();
00389 
00390     return result;
00391 }
00392 
00393 // get bit
00394 OverlayKeyBit OverlayKey::operator[](uint32_t n)
00395 {
00396     return OverlayKeyBit(getBit(n), n, this);
00397 }
00398 
00399 OverlayKey& OverlayKey::setBit(uint32_t pos, bool value)
00400 {
00401     if (pos >= keyLength) {
00402         throw cRuntimeError("OverlayKey::setBitAt(): "
00403                                 "pos >= keyLength!");
00404     }
00405 
00406     mp_limb_t digit = 1;
00407     digit = digit << (pos % GMP_LIMB_BITS);
00408 
00409     if (value) {
00410         key[pos / GMP_LIMB_BITS] |= digit;
00411     } else {
00412         //key[pos / GMP_LIMB_BITS] = key[pos / GMP_LIMB_BITS] & ~digit;
00413         key[pos / GMP_LIMB_BITS] &= ~digit;
00414     }
00415 
00416     return *this;
00417 };
00418 
00419 //--------------------------------------------------------------------
00420 // additional math
00421 //--------------------------------------------------------------------
00422 
00423 // returns a sub integer
00424 uint32_t OverlayKey::getBitRange(uint32_t p, uint32_t n) const
00425 {
00426     int i = p / GMP_LIMB_BITS,      // index of starting bit
00427         f = p % GMP_LIMB_BITS,      // position of starting bit
00428         f2 = f + n - GMP_LIMB_BITS; // how many bits to take from next index
00429 
00430     if ((p + n > OverlayKey::keyLength) || (n > 32)) {
00431         throw cRuntimeError("OverlayKey::get:  Invalid range");
00432     }
00433     if (GMP_LIMB_BITS < 32) {
00434         throw cRuntimeError("OverlayKey::get:  GMP_LIMB_BITS too small!");
00435     }
00436 
00437     return ((key[i] >> f) |                                     // get the bits of key[i]
00438             (f2 > 0 ? (key[i+1] << (GMP_LIMB_BITS - f)) : 0)) & // the extra bits from key[i+1]
00439         (((uint32_t)(~0)) >> (GMP_LIMB_BITS - n));              // delete unused bits
00440 }
00441 
00442 // fill suffix with random bits
00443 OverlayKey OverlayKey::randomSuffix( uint32_t pos ) const
00444 {
00445     OverlayKey newKey = *this;
00446     int i = pos/GMP_LIMB_BITS, j = pos%GMP_LIMB_BITS;
00447     mp_limb_t m = ((mp_limb_t)1 << j)-1;
00448     mp_limb_t rnd;
00449 
00450     //  mpn_random(&rnd,1);
00451     omnet_random(&rnd,1);
00452     newKey.key[i] &= ~m;
00453     newKey.key[i] |= (rnd&m);
00454     //  mpn_random(newKey.key,i);
00455     omnet_random(newKey.key,i);
00456     newKey.trim();
00457 
00458     return newKey;
00459 }
00460 
00461 // fill prefix with random bits
00462 OverlayKey OverlayKey::randomPrefix( uint32_t pos ) const
00463 {
00464     OverlayKey newKey = *this;
00465     int i = pos/GMP_LIMB_BITS, j = pos%GMP_LIMB_BITS;
00466     mp_limb_t m = ((mp_limb_t)1 << j)-1;
00467     mp_limb_t rnd;
00468 
00469     //  mpn_random(&rnd,1);
00470     omnet_random(&rnd,1);
00471 
00472     newKey.key[i] &= m;
00473     newKey.key[i] |= (rnd&~m);
00474     for (int k=aSize-1; k!=i; k--) {
00475         //        mpn_random( &newKey.key[k], 1 );
00476         omnet_random( &newKey.key[k], 1 );
00477     }
00478     newKey.trim();
00479 
00480     return newKey;
00481 }
00482 
00483 // calculate shared prefix length
00484 uint32_t OverlayKey::sharedPrefixLength(const OverlayKey& compKey,
00485                                         uint32_t bitsPerDigit) const
00486 {
00487     if (compareTo(compKey) == 0) return keyLength;
00488 
00489     uint32_t length = 0;
00490     int i;
00491     uint32_t j;
00492     bool msb = true;
00493 
00494     // count equal limbs first:
00495     for (i=aSize-1; i>=0; --i) {
00496         if (this->key[i] != compKey.key[i]) {
00497             // XOR first differing limb for easy counting of the bits:
00498             mp_limb_t d = this->key[i] ^ compKey.key[i];
00499             if (msb) d <<= ( GMP_LIMB_BITS - (keyLength % GMP_LIMB_BITS) );
00500             for (j = GMP_LIMB_BITS-1; d >>= 1; --j);
00501             length += j;
00502             break;
00503         }
00504         length += GMP_LIMB_BITS;
00505         msb = false;
00506     }
00507 
00508     return length / bitsPerDigit;
00509 }
00510 
00511 // calculate log of base 2
00512 int OverlayKey::log_2() const
00513 {
00514     int16_t i = aSize-1;
00515 
00516     while (i>=0 && key[i]==0) {
00517         i--;
00518     }
00519 
00520     if (i<0) {
00521         return -1;
00522     }
00523 
00524     mp_limb_t j = key[i];
00525     i *= GMP_LIMB_BITS;
00526     while (j!=0) {
00527         j >>= 1;
00528         i++;
00529     }
00530 
00531     return i-1;
00532 }
00533 
00534 // returns a simple hash of the key
00535 size_t OverlayKey::hash() const
00536 {
00537     return (size_t)key[0];
00538 }
00539 
00540 // returns true, if this key is element of the interval (keyA, keyB)
00541 bool OverlayKey::isBetween(const OverlayKey& keyA,
00542                            const OverlayKey& keyB) const
00543 {
00544     if (isUnspec || keyA.isUnspec || keyB.isUnspec)
00545         return false;
00546 
00547     if (*this == keyA)
00548         return false;
00549     else if (keyA < keyB)
00550         return ((*this > keyA) && (*this < keyB));
00551     else
00552         return ((*this > keyA) || (*this < keyB));
00553 }
00554 
00555 // returns true, if this key is element of the interval (keyA, keyB]
00556 bool OverlayKey::isBetweenR(const OverlayKey& keyA,
00557                             const OverlayKey& keyB) const
00558 {
00559     if (isUnspec || keyA.isUnspec || keyB.isUnspec)
00560         return false;
00561 
00562     if ((keyA == keyB) && (*this == keyA))
00563         return true;
00564     else if (keyA <= keyB)
00565         return ((*this > keyA) && (*this <= keyB));
00566     else
00567         return ((*this > keyA) || (*this <= keyB));
00568 }
00569 
00570 // returns true, if this key is element of the interval [keyA, keyB)
00571 bool OverlayKey::isBetweenL(const OverlayKey& keyA,
00572                             const OverlayKey& keyB) const
00573 {
00574     if (isUnspec || keyA.isUnspec || keyB.isUnspec)
00575         return false;
00576 
00577     if ((keyA == keyB) && (*this == keyA))
00578         return true;
00579     else if (keyA <= keyB)
00580         return ((*this >= keyA) && (*this < keyB));
00581     else
00582         return ((*this >= keyA) || (*this < keyB));
00583 }
00584 
00585 // returns true, if this key is element of the interval [keyA, keyB]
00586 bool OverlayKey::isBetweenLR(const OverlayKey& keyA,
00587                              const OverlayKey& keyB) const
00588 {
00589     if (isUnspec || keyA.isUnspec || keyB.isUnspec)
00590         return false;
00591 
00592     if ((keyA == keyB) && (*this == keyA))
00593         return true;
00594     else if (keyA <= keyB)
00595         return ((*this >= keyA) && (*this <= keyB));
00596     else
00597         return ((*this >= keyA) || (*this <= keyB));
00598 }
00599 
00600 
00601 //----------------------------------------------------------------------
00602 // statics and globals
00603 //----------------------------------------------------------------------
00604 
00605 // default console output
00606 std::ostream& operator<<(std::ostream& os, const OverlayKey& c)
00607 {
00608     os << c.toString(16);
00609     return os;
00610 };
00611 
00612 // returns a key filled with bit 1
00613 OverlayKey OverlayKey::getMax()
00614 {
00615     OverlayKey newKey;
00616 
00617     for (uint32_t i=0; i<aSize; i++) {
00618         newKey.key[i] = ~0;
00619     }
00620     newKey.isUnspec = false;
00621     newKey.trim();
00622 
00623     return newKey;
00624 }
00625 
00626 // generate random number
00627 OverlayKey OverlayKey::random()
00628 {
00629     OverlayKey newKey = ZERO;
00630 
00631     omnet_random(newKey.key,aSize);
00632 
00633     newKey.trim();
00634 
00635     return newKey;
00636 }
00637 
00638 // generate sha1 hash
00639 OverlayKey OverlayKey::sha1(const BinaryValue& input)
00640 {
00641     OverlayKey newKey = OverlayKey();
00642     uint8_t temp[20];
00643     CSHA1 sha1;
00644 
00645     sha1.Reset();
00646     sha1.Update((uint8_t*)(&(*input.begin())), input.size());
00647     sha1.Final();
00648     sha1.GetHash(temp);
00649     mpn_set_str(newKey.key, (const uint8_t*)temp,
00650                 (int)std::min((uint32_t)(aSize * sizeof(mp_limb_t)), 20U), 256);
00651     newKey.isUnspec = false;
00652     newKey.trim();
00653 
00654     return newKey;
00655 }
00656 
00657 // generate a key=2**exponent
00658 OverlayKey OverlayKey::pow2( uint32_t exponent )
00659 {
00660     if (exponent >= keyLength) {
00661         throw cRuntimeError("OverlayKey::pow2(): "
00662                                 "exponent >= keyLength!");
00663     }
00664 
00665     OverlayKey newKey = ZERO;
00666 
00667     newKey.key[exponent/GMP_LIMB_BITS] =
00668         (mp_limb_t)1 << (exponent % GMP_LIMB_BITS);
00669 
00670     return newKey;
00671 }
00672 
00673 // pseudo-regression test
00674 void OverlayKey::test()
00675 {
00676     // add test
00677     cout << endl << "--- Add test ..." << endl;
00678     OverlayKey key = 123456789;
00679     cout << "    key=" << key << endl;
00680     cout << "    key += 987654321 = " << (key+=987654321) << endl;
00681     cout << "    prefix++  : " << (++key) << endl;
00682     cout << "    postfix++ : " << (key++) << endl;
00683     cout << "    key=" << key << endl;
00684 
00685     OverlayKey k1 = 256, k2 = 10, k3 = 3;
00686 
00687     // compare test
00688     cout << endl << "--- Compare test ..." << endl;
00689     cout << "    256 < 10 = "<< (k1 < k2) << " k1="<<k1<<endl;
00690     cout << "    256 > 10 = "<< (k1 > k2) << " k2="<<k2<<endl;
00691 
00692     cout << "    10 isBetween(3, 256)=" << k2.isBetween(k3, k1) << endl;
00693     cout << "    3 isBetween(10, 256)=" << k3.isBetween(k2, k1) << endl;
00694     cout << "    256 isBetween(10, 256)=" << k1.isBetween(k2, k1) << endl;
00695     cout << "    256 isBetweenR(10, 256)=" << k1.isBetweenR(k2, k1) << endl;
00696     cout << "    max isBetween(max-1,0)=" << OverlayKey::getMax().isBetween(
00697                                                                          OverlayKey::getMax()-1, OverlayKey::ZERO) << endl;
00698     cout << "    max-1 isBetween(max,1)=" << (OverlayKey::getMax()-1).isBetween(
00699                                                                              OverlayKey::getMax(), OverlayKey::ONE) << endl;
00700     cout << "    max-1 isBetweenL(max-1,1)=" << (OverlayKey::getMax()-1).
00701         isBetweenL(OverlayKey::getMax()-1, OverlayKey::ONE) << endl;
00702     cout << "    1 isBetweenL(max-1,1)=" << (OverlayKey::ONE).isBetweenL(
00703                                                                          OverlayKey::getMax()-1, OverlayKey::ONE) << endl;
00704     cout << "    1 isBetweenR(max-1,1)=" << OverlayKey::ONE.isBetweenR(
00705                                                                        OverlayKey::getMax()-1, OverlayKey::ONE) << endl;
00706     cout << "    1 isBetween(max-1,1)=" << OverlayKey::ONE.isBetween(
00707                                                                      OverlayKey::getMax()-1, OverlayKey::ONE) << endl;
00708     cout << "    1 isBetween(max-1,0)=" << OverlayKey::ONE.isBetween(
00709                                                                      OverlayKey::getMax()-1, OverlayKey::ZERO) << endl;
00710     cout << "    256 sharedPrefixLength(3)=" << k1.sharedPrefixLength(k3)
00711          << endl;
00712     cout << "    256 sharedPrefixLength(256)=" << k1.sharedPrefixLength(k1)
00713          << endl;
00714 
00715     // wrap around test
00716     cout << endl << "--- Warp around test ..." << endl;
00717 
00718     k1 = OverlayKey::getMax();
00719     cout << "k1=max= " << k1.toString(16) << endl;
00720     cout << "k1+1 = " << (k1 + 1).toString(16) << endl;
00721     cout << "k1+2 = " << (k1 + 2).toString(16) << endl;
00722 
00723     k1 = OverlayKey::ZERO;
00724     cout << "k1=0= " << k1.toString(16) << endl;
00725     cout << "k1-1 = " << (k1 - 1).toString(16) << endl;
00726     cout << "k1-2 = " << (k1 - 2).toString(16) << endl;
00727 
00728     cout << "max > ONE=" << (OverlayKey::getMax() > OverlayKey::ONE) << endl;
00729     cout << "max < ONE=" << (OverlayKey::getMax() < OverlayKey::ONE) << endl;
00730 
00731     // distance test
00732     cout << endl << "--- Distance test ..." << endl;
00733 
00734     cout << "KeyRingMetric::distance(1, max)="
00735          <<  KeyRingMetric().distance(OverlayKey::ONE, OverlayKey::getMax()) << endl;
00736     cout << "KeyUniRingMetric::distance(1, max)="
00737          <<  KeyUniRingMetric().distance(OverlayKey::ONE, OverlayKey::getMax()) << endl;
00738     cout << "KeyRingMetric::distance(max, 1)="
00739          <<  KeyRingMetric().distance(OverlayKey::getMax(), OverlayKey::ONE) << endl;
00740     cout << "KeyUniRingMetric::distance(max, 1)="
00741          <<  KeyUniRingMetric().distance(OverlayKey::getMax(), OverlayKey::ONE) << endl;
00742 
00743     // suffix and log2 test
00744     cout << endl << "--- RandomSuffix and log2 test ..." << endl;
00745     k1 = OverlayKey::ZERO;
00746     for (uint32_t i=0; i<k1.getLength(); i++) {
00747         k2=k1.randomSuffix(i);
00748         cout << "    " << k2.toString(16) << " log2=" << k2.log_2() << endl;
00749     }
00750     cout << endl << "--- RandomPrefix and log2 test ..." << endl;
00751     k1 = OverlayKey::getMax();
00752     for (uint32_t i=0; i<k1.getLength(); i++) {
00753         k2=k1.randomPrefix(i);
00754         cout << "    " << k2.toString(16) << " log2=" << k2.log_2() << endl;
00755     }
00756 
00757     cout << endl << "--- pow2 test..." << endl;
00758     for (uint32_t i=0; i<k1.getLength(); i++) {
00759         k2=pow2(i);
00760         cout << " 2^" << i << " = " << k2.toString(16) << "   log2="
00761              << k2.log_2() << endl;
00762     }
00763 
00764     cout << endl << "--- Bits test ..." << endl << "    ";
00765     const char* BITS[] = { "000","001","010","011","100","101","110","111" };
00766     k1 = OverlayKey::random();
00767     for (int i=k1.getLength()-1; i>=0; i--)
00768         cout << k1[i];
00769     cout << " = " << endl << "    ";
00770     for (int i=k1.getLength()-3; i>=0; i-=3)
00771         cout << BITS[k1.getBitRange(i,3)];
00772     cout << endl;
00773 
00774     cout << endl << "--- SHA1 test ... (verified with test vectors)" << endl;
00775     cout << "    Empty string: " << OverlayKey::sha1("").toString(16)
00776          << " = da39a3ee5e6b4b0d3255bfef95601890afd80709" << endl;
00777     cout << "    'Hello World' string: "
00778          << OverlayKey::sha1("Hello World").toString(16)
00779          << " = 0a4d55a8d778e5022fab701977c5d840bbc486d0" << endl;
00780 }
00781 
00782 //--------------------------------------------------------------------
00783 // private methods (mostly inlines)
00784 //--------------------------------------------------------------------
00785 
00786 // trims a key after each operation
00787 inline void OverlayKey::trim()
00788 {
00789     key[aSize-1] &= GMP_MSB_MASK;
00790 }
00791 
00792 
00793 // compares this key to any other
00794 int OverlayKey::compareTo( const OverlayKey& compKey ) const
00795 {
00796     if (compKey.isUnspec || isUnspec)
00797         opp_error("OverlayKey::compareTo(): key is unspecified!");
00798     return mpn_cmp(key,compKey.key,aSize);
00799 }
00800 
00801 // sets key to zero and clears unspecified bit
00802 inline void OverlayKey::clear()
00803 {
00804     memset( key, 0, aSize * sizeof(mp_limb_t) );
00805     isUnspec = false;
00806 }
00807 
00808 // replacement function for mpn_random() using omnet's rng
00809 inline void omnet_random(mp_limb_t *r1p, mp_size_t r1n)
00810 {
00811     // fill in 32 bit chunks
00812     uint32_t* chunkPtr = (uint32_t*)r1p;
00813 
00814     for (uint32_t i=0; i < ((r1n*sizeof(mp_limb_t) + 3) / 4); i++) {
00815         chunkPtr[i] = intuniform(0, 0xFFFFFFFF);
00816     }
00817 }
00818 
00819 #ifdef __GMP_SHORT_LIMB
00820 #define GMP_TYPE unsigned int
00821 #else
00822 #ifdef _LONG_LONG_LIMB
00823 #define GMP_TYPE unsigned long long int
00824 #else
00825 #define GMP_TYPE unsigned long int
00826 #endif
00827 #endif
00828 
00829 void OverlayKey::netPack(cCommBuffer *b)
00830 {
00831     doPacking(b,(GMP_TYPE*)this->key, MAX_KEYLENGTH / (8*sizeof(mp_limb_t)) +
00832               (MAX_KEYLENGTH % (8*sizeof(mp_limb_t))!=0 ? 1 : 0));
00833     doPacking(b,this->isUnspec);
00834 }
00835 
00836 void OverlayKey::netUnpack(cCommBuffer *b)
00837 {
00838     doUnpacking(b,(GMP_TYPE*)this->key, MAX_KEYLENGTH / (8*sizeof(mp_limb_t)) +
00839                 (MAX_KEYLENGTH % (8*sizeof(mp_limb_t))!=0 ? 1 : 0));
00840     doUnpacking(b,this->isUnspec);
00841 
00842 }
00843 

Generated on Tue Sep 8 17:26:53 2009 for OverSim by  doxygen 1.5.8