| OLD | NEW |
|---|---|
| (Empty) | |
| 1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ | |
| 2 /* | |
| 3 * Copyright (c) 2009 The Georgia Institute of Technology | |
| 4 * | |
| 5 * This program is free software; you can redistribute it and/or modify | |
| 6 * it under the terms of the GNU General Public License version 2 as | |
| 7 * published by the Free Software Foundation; | |
| 8 * | |
| 9 * This program is distributed in the hope that it will be useful, | |
| 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 12 * GNU General Public License for more details. | |
| 13 * | |
| 14 * You should have received a copy of the GNU General Public License | |
| 15 * along with this program; if not, write to the Free Software | |
| 16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 17 * | |
| 18 * Authors: Josh Pelkey <jpelkey@gatech.edu> | |
| 19 */ | |
| 20 | |
| 21 #include "ns3/log.h" | |
| 22 | |
| 23 #include "nix-vector.h" | |
| 24 | |
| 25 NS_LOG_COMPONENT_DEFINE ("NixVector"); | |
| 26 | |
| 27 namespace ns3 { | |
| 28 | |
| 29 NS_OBJECT_ENSURE_REGISTERED (NixVector); | |
| 30 | |
| 31 typedef std::vector<uint32_t> NixBits_t; | |
| 32 | |
| 33 NixVector::NixVector () | |
| 34 : m_nixVector (0),m_used (0),m_currentVectorBitSize (0),m_totalBitSize (0) | |
| 35 { | |
| 36 NS_LOG_FUNCTION_NOARGS (); | |
| 37 | |
| 38 m_nixVector.push_back (0); | |
| 39 } | |
| 40 | |
| 41 NixVector::~NixVector () | |
| 42 { | |
| 43 NS_LOG_FUNCTION_NOARGS (); | |
| 44 } | |
| 45 | |
| 46 Ptr<NixVector> | |
| 47 NixVector::Copy (void) const | |
| 48 { | |
| 49 // we need to invoke the copy constructor directly | |
| 50 // rather than calling Create because the copy constructor | |
| 51 // is private. | |
| 52 return Ptr<NixVector> (new NixVector (*this), false); | |
| 53 } | |
| 54 | |
| 55 NixVector::NixVector (const NixVector &o) | |
| 56 : m_nixVector (o.m_nixVector), | |
| 57 m_used (o.m_used), | |
| 58 m_currentVectorBitSize (o.m_currentVectorBitSize), | |
| 59 m_totalBitSize (o.m_totalBitSize) | |
| 60 {} | |
| 61 | |
| 62 NixVector & | |
| 63 NixVector::operator = (const NixVector &o) | |
| 64 { | |
| 65 if (this == &o) | |
| 66 { | |
| 67 return *this; | |
| 68 } | |
| 69 m_nixVector = o.m_nixVector; | |
| 70 m_used = o.m_used; | |
| 71 m_currentVectorBitSize = o.m_currentVectorBitSize; | |
| 72 m_totalBitSize = o.m_totalBitSize; | |
| 73 return *this; | |
| 74 } | |
| 75 | |
| 76 TypeId | |
| 77 NixVector::GetTypeId(void) | |
| 78 { | |
| 79 static TypeId tid = TypeId ("ns3::NixVector") | |
| 80 .SetParent<Object> () | |
| 81 .AddConstructor<NixVector> () | |
| 82 ; | |
| 83 | |
| 84 return tid; | |
| 85 } | |
| 86 | |
| 87 std::ostream & operator << (std::ostream &os, const NixVector &nix) | |
| 88 { | |
| 89 nix.DumpNixVector (os); | |
| 90 return os; | |
| 91 } | |
| 92 | |
| 93 void | |
| 94 NixVector::AddNeighborIndex (uint32_t newBits, uint32_t numberOfBits) | |
| 95 { | |
| 96 NS_LOG_FUNCTION_NOARGS (); | |
| 97 | |
| 98 if (numberOfBits > 32) | |
| 99 NS_FATAL_ERROR ("Can't add more than 32 bits to a nix-vector at one time"); | |
| 100 | |
| 101 // Check to see if the number | |
| 102 // of new bits forces the creation of | |
| 103 // a new entry into the NixVector vector | |
| 104 // i.e., we will overflow int o.w. | |
| 105 if (m_currentVectorBitSize + numberOfBits > 32) | |
| 106 { | |
| 107 if (m_currentVectorBitSize == 32) | |
| 108 { | |
| 109 // can't add any more to this vector, so | |
| 110 // start a new one | |
| 111 m_nixVector.push_back(newBits); | |
| 112 | |
| 113 // also reset number of bits in | |
| 114 // m_currentVectorBitSize | |
| 115 // because we are working with a new | |
| 116 // entry in the vector | |
| 117 m_currentVectorBitSize = numberOfBits; | |
| 118 m_totalBitSize += numberOfBits; | |
| 119 } | |
| 120 else | |
| 121 { | |
| 122 // Put what we can in the remaining portion of the | |
| 123 // vector entry | |
| 124 uint32_t tempBits = newBits; | |
| 125 tempBits = newBits << m_currentVectorBitSize; | |
| 126 tempBits |= m_nixVector.back (); | |
| 127 m_nixVector.back () = tempBits; | |
| 128 | |
| 129 // Now start a new vector entry | |
| 130 // and push the remaining bits | |
| 131 // there | |
| 132 newBits = newBits >> (32 - m_currentVectorBitSize); | |
| 133 m_nixVector.push_back (newBits); | |
| 134 | |
| 135 // also reset number of bits in | |
| 136 // m_currentVectorBitSize | |
| 137 // because we are working with a new | |
| 138 // entry in the vector | |
| 139 m_currentVectorBitSize = (numberOfBits - (32 - m_currentVectorBitSize)); | |
| 140 m_totalBitSize += numberOfBits; | |
| 141 } | |
| 142 } | |
| 143 else | |
| 144 { | |
| 145 // Shift over the newbits by the | |
| 146 // number of current bits. This allows | |
| 147 // us to logically OR with the present | |
| 148 // NixVector, resulting in the new | |
| 149 // NixVector | |
| 150 newBits = newBits << m_currentVectorBitSize; | |
| 151 newBits |= m_nixVector.back (); | |
| 152 | |
| 153 // Now insert the new NixVector and | |
| 154 // increment number of bits for | |
| 155 // m_currentVectorBitSize and m_totalBitSize | |
| 156 // accordingly | |
| 157 m_nixVector.back () = newBits; | |
| 158 m_currentVectorBitSize += numberOfBits; | |
| 159 m_totalBitSize += numberOfBits; | |
| 160 } | |
| 161 } | |
| 162 | |
| 163 uint32_t | |
| 164 NixVector::ExtractNeighborIndex (uint32_t numberOfBits) | |
| 165 { | |
| 166 NS_LOG_FUNCTION_NOARGS (); | |
| 167 | |
| 168 if (numberOfBits > 32) | |
|
craigdo
2009/09/11 22:38:17
Coding standard says to add braces even if single
jpelkey
2009/09/12 18:34:14
On 2009/09/11 22:38:17, craigdo wrote:
> Coding st
| |
| 169 NS_FATAL_ERROR ("Can't extract more than 32 bits to a nix-vector at one time "); | |
| 170 | |
| 171 uint32_t vectorIndex = 0; | |
| 172 uint32_t extractedBits = 0; | |
| 173 uint32_t totalRemainingBits = GetRemainingBits (); | |
| 174 | |
| 175 if (numberOfBits > totalRemainingBits) | |
| 176 { | |
| 177 NS_FATAL_ERROR ("You've tried to extract too many bits of the Nix-vector, " << this << ". NumberBits: " | |
| 178 << numberOfBits << " Remaining: " << totalRemainingBits); | |
| 179 } | |
| 180 | |
| 181 if (numberOfBits <= 0) | |
| 182 { | |
| 183 NS_FATAL_ERROR ("You've specified a number of bits for Nix-vector <= 0!"); | |
| 184 } | |
| 185 | |
| 186 // First determine where in the NixVector | |
| 187 // vector we need to extract which depends | |
| 188 // on the number of used bits and the total | |
| 189 // number of bits | |
| 190 vectorIndex = ((totalRemainingBits-1) / 32); | |
| 191 | |
| 192 // Next, determine if this extraction will | |
| 193 // span multiple vector entries | |
| 194 if (vectorIndex > 0) // we could span more than one | |
| 195 { | |
| 196 if ((numberOfBits-1) > ((totalRemainingBits-1) % 32)) // we do span more tha n one | |
| 197 { | |
| 198 | |
| 199 extractedBits = m_nixVector.at (vectorIndex) << (32 - (totalRemainingBits % 32)); | |
| 200 extractedBits = extractedBits >> ((32 - (totalRemainingBits % 32)) - (numb erOfBits - (totalRemainingBits % 32))); | |
| 201 | |
| 202 extractedBits |= (m_nixVector.at (vectorIndex-1) >> (32 - (numberOfBits - (totalRemainingBits % 32)))); | |
| 203 m_used += numberOfBits; | |
| 204 | |
| 205 return extractedBits; | |
| 206 } | |
| 207 } | |
| 208 | |
| 209 // we don't span more than one | |
| 210 extractedBits = m_nixVector.at (vectorIndex) << (32 - (totalRemainingBits % 32 )); | |
| 211 extractedBits = extractedBits >> (32 - (numberOfBits)); | |
| 212 | |
| 213 m_used += numberOfBits; | |
| 214 | |
| 215 return extractedBits; | |
| 216 | |
| 217 } | |
| 218 | |
| 219 NixBits_t | |
| 220 NixVector::GetNixVector (void) | |
| 221 { | |
| 222 NS_LOG_FUNCTION_NOARGS (); | |
| 223 | |
| 224 return m_nixVector; | |
| 225 } | |
| 226 | |
| 227 uint32_t | |
| 228 NixVector::GetSerializedSize (void) const | |
| 229 { | |
| 230 uint32_t totalSizeInBytes; | |
| 231 totalSizeInBytes = sizeof (m_used) + sizeof (m_currentVectorBitSize) + | |
| 232 sizeof (m_totalBitSize) + (4 * m_nixVector.size ()); | |
| 233 | |
| 234 // add four to this to account | |
| 235 // for the nix-vector length | |
| 236 // entry | |
| 237 return totalSizeInBytes+4; | |
| 238 } | |
| 239 | |
| 240 void | |
| 241 NixVector::Serialize (Buffer::Iterator i, uint32_t size) const | |
| 242 { | |
| 243 uint32_t bytesWritten = 0; | |
| 244 | |
| 245 i.WriteU32 (size); | |
| 246 bytesWritten += 4; | |
| 247 | |
| 248 i.WriteU32 (m_used); | |
| 249 bytesWritten += 4; | |
| 250 | |
| 251 i.WriteU32 (m_currentVectorBitSize); | |
| 252 bytesWritten += 4; | |
| 253 | |
| 254 i.WriteU32 (m_totalBitSize); | |
| 255 bytesWritten += 4; | |
| 256 | |
| 257 for (uint32_t j = 0; j < m_nixVector.size (); j++) | |
| 258 { | |
| 259 i.WriteU32 (m_nixVector.at(j)); | |
| 260 bytesWritten += 4; | |
| 261 } | |
| 262 | |
| 263 NS_ASSERT (bytesWritten == size); | |
| 264 } | |
| 265 | |
| 266 uint32_t | |
| 267 NixVector::Deserialize (Buffer::Iterator i) | |
| 268 { | |
| 269 NS_LOG_FUNCTION (this); | |
| 270 uint32_t totalSize = i.ReadU32 (); | |
| 271 uint32_t size = totalSize; | |
| 272 size -= 4; | |
| 273 | |
| 274 NS_ASSERT (size >= 4); | |
| 275 m_used = i.ReadU32 (); | |
| 276 size -=4; | |
| 277 | |
| 278 NS_ASSERT (size >= 4); | |
| 279 m_currentVectorBitSize = i.ReadU32 (); | |
| 280 size -=4; | |
| 281 | |
| 282 NS_ASSERT (size >= 4); | |
| 283 m_totalBitSize = i.ReadU32 (); | |
| 284 size -=4; | |
| 285 | |
| 286 // make sure the nix-vector | |
| 287 // is empty | |
| 288 m_nixVector.clear (); | |
| 289 while (size > 0) | |
| 290 { | |
| 291 NS_ASSERT (size >= 4); | |
| 292 m_nixVector.push_back (i.ReadU32 ()); | |
| 293 size -=4; | |
| 294 } | |
| 295 | |
| 296 NS_ASSERT (size == 0); | |
| 297 return totalSize; | |
| 298 } | |
| 299 | |
| 300 void | |
| 301 NixVector::DumpNixVector (std::ostream &os) const | |
| 302 { | |
| 303 NS_LOG_FUNCTION_NOARGS (); | |
| 304 uint32_t i = m_nixVector.size (); | |
| 305 std::vector<uint32_t>::const_iterator iter = m_nixVector.end (); | |
| 306 do | |
|
craigdo
2009/09/11 22:38:17
I'm curious why this isn't a for loop. That would
jpelkey
2009/09/12 18:34:14
On 2009/09/11 22:38:17, craigdo wrote:
> I'm curio
| |
| 307 { | |
| 308 iter--; | |
| 309 | |
| 310 // all this work just to get the nix | |
| 311 // vector to print out neat | |
| 312 if (m_totalBitSize == 32) | |
|
craigdo
2009/09/11 22:38:17
Coding standard says use {}. Many more instances
jpelkey
2009/09/12 18:34:14
On 2009/09/11 22:38:17, craigdo wrote:
> Coding st
| |
| 313 PrintDec2BinNixFill (*iter,32,os); | |
| 314 else if (m_totalBitSize > ((sizeof (uint32_t)*8) * i)) | |
| 315 PrintDec2BinNix (*iter,BitCount (*iter),os); | |
| 316 else | |
| 317 PrintDec2BinNixFill (*iter,m_totalBitSize%32,os); | |
| 318 | |
| 319 i--; | |
| 320 | |
| 321 if (iter != m_nixVector.begin ()) | |
| 322 os << "--"; | |
| 323 | |
| 324 } while (iter != m_nixVector.begin ()); | |
| 325 | |
| 326 } | |
| 327 | |
| 328 uint32_t | |
| 329 NixVector::GetRemainingBits (void) | |
| 330 { | |
| 331 NS_LOG_FUNCTION_NOARGS (); | |
| 332 | |
| 333 return (m_totalBitSize - m_used); | |
| 334 } | |
| 335 | |
| 336 uint32_t | |
| 337 NixVector::BitCount (uint32_t numberOfNeighbors) const | |
| 338 { | |
| 339 NS_LOG_FUNCTION_NOARGS (); | |
| 340 | |
| 341 // Given the numberOfNeighbors, return the number | |
| 342 // of bits needed (essentailly, log2(numberOfNeighbors-1) | |
|
craigdo
2009/09/11 22:38:17
essentially
jpelkey
2009/09/12 18:34:14
On 2009/09/11 22:38:17, craigdo wrote:
> essential
| |
| 343 uint32_t bitCount = 0; | |
| 344 | |
| 345 if (numberOfNeighbors < 2) | |
| 346 return 1; | |
| 347 else | |
| 348 { | |
| 349 for (numberOfNeighbors -= 1; numberOfNeighbors != 0; numberOfNeighbors >>= 1 ) | |
| 350 bitCount++; | |
| 351 | |
| 352 return bitCount; | |
| 353 } | |
| 354 } | |
| 355 | |
| 356 void | |
| 357 NixVector::PrintDec2BinNixFill (uint32_t decimalNum, uint32_t bitCount, std::ost ream &os) const | |
| 358 { | |
| 359 if(decimalNum == 0) | |
| 360 { | |
| 361 os << 0; | |
| 362 return; | |
| 363 } | |
| 364 if(decimalNum == 1) | |
| 365 { | |
| 366 for (; bitCount > 1; bitCount--) | |
| 367 os << 0; | |
| 368 | |
| 369 os << 1; | |
| 370 } | |
| 371 else | |
| 372 { | |
| 373 PrintDec2BinNixFill (decimalNum / 2,bitCount-1, os); | |
| 374 os << decimalNum % 2; | |
| 375 } | |
| 376 } | |
| 377 | |
| 378 void | |
| 379 NixVector::PrintDec2BinNix (uint32_t decimalNum, uint32_t bitCount, std::ostream &os) const | |
| 380 { | |
| 381 if(decimalNum == 0) | |
| 382 { | |
| 383 os << 0; | |
| 384 return; | |
| 385 } | |
| 386 if(decimalNum == 1) | |
| 387 { | |
| 388 // check to see if we need to | |
| 389 // print out some zeros at the | |
| 390 // beginning of the nix vector | |
| 391 if ((uint32_t)(sizeof (uint32_t)*8) > bitCount) | |
| 392 { | |
| 393 for (uint32_t i = ((sizeof (uint32_t)*8)-bitCount); i > 0; i--) | |
| 394 os << 0; | |
| 395 } | |
| 396 | |
| 397 os << 1; | |
| 398 } | |
| 399 else | |
| 400 { | |
| 401 PrintDec2BinNix (decimalNum / 2, bitCount, os); | |
| 402 os << decimalNum % 2; | |
| 403 } | |
| 404 } | |
|
craigdo
2009/09/11 22:38:17
It would be nice to see some unit tests for this.
jpelkey
2009/09/12 18:34:14
On 2009/09/11 22:38:17, craigdo wrote:
> It would
| |
| 405 } // namespace ns3 | |
| OLD | NEW |