A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
nix-vector.cc
Go to the documentation of this file.
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 #include "ns3/fatal-error.h"
23 
24 #include "nix-vector.h"
25 
26 NS_LOG_COMPONENT_DEFINE ("NixVector");
27 
28 namespace ns3 {
29 
30 typedef std::vector<uint32_t> NixBits_t;
31 
33  : m_nixVector (0),
34  m_used (0),
35  m_currentVectorBitSize (0),
36  m_totalBitSize (0)
37 {
39 
40  m_nixVector.push_back (0);
41 }
42 
44 {
46 }
47 
49  : m_nixVector (o.m_nixVector),
50  m_used (o.m_used),
51  m_currentVectorBitSize (o.m_currentVectorBitSize),
52  m_totalBitSize (o.m_totalBitSize)
53 {
54 }
55 
56 NixVector &
58 {
59  if (this == &o)
60  {
61  return *this;
62  }
64  m_used = o.m_used;
67  return *this;
68 }
69 
71 NixVector::Copy (void) const
72 {
73  // we need to invoke the copy constructor directly
74  // rather than calling Create because the copy constructor
75  // is private.
76  return Ptr<NixVector> (new NixVector (*this), false);
77 }
78 
79 std::ostream & operator << (std::ostream &os, const NixVector &nix)
80 {
81  nix.DumpNixVector (os);
82  return os;
83 }
84 
85 void
86 NixVector::AddNeighborIndex (uint32_t newBits, uint32_t numberOfBits)
87 {
89 
90  if (numberOfBits > 32)
91  {
92  NS_FATAL_ERROR ("Can't add more than 32 bits to a nix-vector at one time");
93  }
94 
95  // Check to see if the number
96  // of new bits forces the creation of
97  // a new entry into the NixVector vector
98  // i.e., we will overflow int o.w.
99  if (m_currentVectorBitSize + numberOfBits > 32)
100  {
101  if (m_currentVectorBitSize == 32)
102  {
103  // can't add any more to this vector, so
104  // start a new one
105  m_nixVector.push_back (newBits);
106 
107  // also reset number of bits in
108  // m_currentVectorBitSize
109  // because we are working with a new
110  // entry in the vector
111  m_currentVectorBitSize = numberOfBits;
112  m_totalBitSize += numberOfBits;
113  }
114  else
115  {
116  // Put what we can in the remaining portion of the
117  // vector entry
118  uint32_t tempBits = newBits;
119  tempBits = newBits << m_currentVectorBitSize;
120  tempBits |= m_nixVector.back ();
121  m_nixVector.back () = tempBits;
122 
123  // Now start a new vector entry
124  // and push the remaining bits
125  // there
126  newBits = newBits >> (32 - m_currentVectorBitSize);
127  m_nixVector.push_back (newBits);
128 
129  // also reset number of bits in
130  // m_currentVectorBitSize
131  // because we are working with a new
132  // entry in the vector
133  m_currentVectorBitSize = (numberOfBits - (32 - m_currentVectorBitSize));
134  m_totalBitSize += numberOfBits;
135  }
136  }
137  else
138  {
139  // Shift over the newbits by the
140  // number of current bits. This allows
141  // us to logically OR with the present
142  // NixVector, resulting in the new
143  // NixVector
144  newBits = newBits << m_currentVectorBitSize;
145  newBits |= m_nixVector.back ();
146 
147  // Now insert the new NixVector and
148  // increment number of bits for
149  // m_currentVectorBitSize and m_totalBitSize
150  // accordingly
151  m_nixVector.back () = newBits;
152  m_currentVectorBitSize += numberOfBits;
153  m_totalBitSize += numberOfBits;
154  }
155 }
156 
157 uint32_t
158 NixVector::ExtractNeighborIndex (uint32_t numberOfBits)
159 {
161 
162  if (numberOfBits > 32)
163  {
164  NS_FATAL_ERROR ("Can't extract more than 32 bits to a nix-vector at one time");
165  }
166 
167  uint32_t vectorIndex = 0;
168  uint32_t extractedBits = 0;
169  uint32_t totalRemainingBits = GetRemainingBits ();
170 
171  if (numberOfBits > totalRemainingBits)
172  {
173  NS_FATAL_ERROR ("You've tried to extract too many bits of the Nix-vector, " << this << ". NumberBits: "
174  << numberOfBits << " Remaining: " << totalRemainingBits);
175  }
176 
177  if (numberOfBits <= 0)
178  {
179  NS_FATAL_ERROR ("You've specified a number of bits for Nix-vector <= 0!");
180  }
181 
182  // First determine where in the NixVector
183  // vector we need to extract which depends
184  // on the number of used bits and the total
185  // number of bits
186  vectorIndex = ((totalRemainingBits-1) / 32);
187 
188  // Next, determine if this extraction will
189  // span multiple vector entries
190  if (vectorIndex > 0) // we could span more than one
191  {
192  if ((numberOfBits-1) > ((totalRemainingBits-1) % 32)) // we do span more than one
193  {
194  extractedBits = m_nixVector.at (vectorIndex) << (32 - (totalRemainingBits % 32));
195  extractedBits = extractedBits >> ((32 - (totalRemainingBits % 32))
196  - (numberOfBits - (totalRemainingBits % 32)));
197  extractedBits |= (m_nixVector.at (vectorIndex-1)
198  >> (32 - (numberOfBits - (totalRemainingBits % 32))));
199  m_used += numberOfBits;
200  return extractedBits;
201  }
202  }
203 
204  // we don't span more than one
205  extractedBits = m_nixVector.at (vectorIndex) << (32 - (totalRemainingBits % 32));
206  extractedBits = extractedBits >> (32 - (numberOfBits));
207  m_used += numberOfBits;
208  return extractedBits;
209 }
210 
211 uint32_t
213 {
214  uint32_t totalSizeInBytes = 0;
215  totalSizeInBytes = sizeof (m_used) + sizeof (m_currentVectorBitSize) +
216  sizeof (m_totalBitSize) + (4 * m_nixVector.size ());
217 
218  return totalSizeInBytes;
219 }
220 
221 uint32_t
222 NixVector::Serialize (uint32_t* buffer, uint32_t maxSize) const
223 {
224  NS_LOG_FUNCTION (this);
225  uint32_t* p = buffer;
226  uint32_t size = 0;
227 
228  if (size + 4 <= maxSize)
229  {
230  size += 4;
231  // grab number of used bits
232  *p++ = m_used;
233  }
234  else
235  {
236  return 0;
237  }
238 
239  if (size + 4 <= maxSize)
240  {
241  size += 4;
242  // grab number of current used bits
243  // for the front vector
244  *p++ = m_currentVectorBitSize;
245  }
246  else
247  {
248  return 0;
249  }
250 
251  if (size + 4 <= maxSize)
252  {
253  size += 4;
254  // grab total bit size
255  *p++ = m_totalBitSize;
256  }
257  else
258  {
259  return 0;
260  }
261  for (uint32_t j = 0; j < m_nixVector.size (); j++)
262  {
263  if (size + 4 <= maxSize)
264  {
265  size += 4;
266  *p++ = m_nixVector.at (j);
267  }
268  else
269  {
270  return 0;
271  }
272  }
273 
274  // Serialized successfully
275  return 1;
276 }
277 
278 uint32_t
279 NixVector::Deserialize (const uint32_t* buffer, uint32_t size)
280 {
281  NS_LOG_FUNCTION (this);
282  const uint32_t* p = buffer;
283  uint32_t sizeCheck = size - 4;
284 
285  NS_ASSERT (sizeCheck >= 4);
286  m_used = *p++;
287  sizeCheck -= 4;
288 
289  NS_ASSERT (sizeCheck >= 4);
290  m_currentVectorBitSize = *p++;
291  sizeCheck -= 4;
292 
293  NS_ASSERT (sizeCheck >= 4);
294  m_totalBitSize = *p++;
295  sizeCheck -= 4;
296 
297  // make sure the nix-vector
298  // is empty
299  m_nixVector.clear ();
300  while (sizeCheck > 0)
301  {
302  NS_ASSERT (sizeCheck >= 4);
303  uint32_t nix = *p++;
304  m_nixVector.push_back (nix);
305  sizeCheck -= 4;
306  }
307 
308  NS_ASSERT (sizeCheck == 0);
309 
310  // return zero if an entire nix-vector was
311  // not deserialized
312  return (sizeCheck != 0) ? 0 : 1;
313 }
314 
315 void
316 NixVector::DumpNixVector (std::ostream &os) const
317 {
319  uint32_t i = m_nixVector.size ();
320  std::vector<uint32_t>::const_reverse_iterator rIter;
321  for (rIter = m_nixVector.rbegin (); rIter != m_nixVector.rend (); rIter++)
322  {
323  uint32_t numBits = BitCount (*rIter);
324 
325  // all this work just to get the nix
326  // vector to print out neat
327 
328  // if it's not the first entry in the vector,
329  // we may have to add some zeros and fill
330  // out the vector
331  if (m_totalBitSize > ((sizeof (uint32_t)*8) * i))
332  {
333  PrintDec2BinNixFill (*rIter,numBits,os);
334  }
335  else if (m_totalBitSize%32 == 0)
336  {
337  PrintDec2BinNix (*rIter,32,os);
338  }
339  else
340  {
341  PrintDec2BinNix (*rIter,m_totalBitSize%32,os);
342  }
343 
344  i--;
345 
346  if (i > 0)
347  {
348  os << "--";
349  }
350  }
351 }
352 
353 uint32_t
355 {
357 
358  return (m_totalBitSize - m_used);
359 }
360 
361 uint32_t
362 NixVector::BitCount (uint32_t numberOfNeighbors) const
363 {
365 
366  // Given the numberOfNeighbors, return the number
367  // of bits needed (essentially, log2(numberOfNeighbors-1)
368  uint32_t bitCount = 0;
369 
370  if (numberOfNeighbors < 2)
371  {
372  return 1;
373  }
374  else
375  {
376  for (numberOfNeighbors -= 1; numberOfNeighbors != 0; numberOfNeighbors >>= 1)
377  {
378  bitCount++;
379  }
380  return bitCount;
381  }
382 }
383 
384 void
385 NixVector::PrintDec2BinNix (uint32_t decimalNum, uint32_t bitCount, std::ostream &os) const
386 {
387  if(decimalNum == 0)
388  {
389  for (; bitCount > 0; bitCount--)
390  {
391  os << 0;
392  }
393  return;
394  }
395  if(decimalNum == 1)
396  {
397  for (; bitCount > 1; bitCount--)
398  {
399  os << 0;
400  }
401  os << 1;
402  }
403  else
404  {
405  PrintDec2BinNix (decimalNum / 2,bitCount-1, os);
406  os << decimalNum % 2;
407  }
408 }
409 
410 void
411 NixVector::PrintDec2BinNixFill (uint32_t decimalNum, uint32_t bitCount, std::ostream &os) const
412 {
413  if(decimalNum == 0)
414  {
415  os << 0;
416  return;
417  }
418  if(decimalNum == 1)
419  {
420  // check to see if we need to
421  // print out some zeros at the
422  // beginning of the nix vector
423  if ((uint32_t)(sizeof (uint32_t)*8) > bitCount)
424  {
425  for (uint32_t i = ((sizeof (uint32_t)*8)-bitCount); i > 0; i--)
426  {
427  os << 0;
428  }
429  }
430  os << 1;
431  }
432  else
433  {
434  PrintDec2BinNixFill (decimalNum / 2, bitCount, os);
435  os << decimalNum % 2;
436  }
437 }
438 
439 } // namespace ns3