Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(16)

Side by Side Diff: src/common/nix-vector.cc

Issue 117046: Ns-3 Nix-vector Routing
Patch Set: Created 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
OLDNEW
(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
OLDNEW

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld r511