nixvec.cc

Go to the documentation of this file.
00001 
00002 /*
00003  * nixvec.cc
00004  * Copyright (C) 2000 by the University of Southern California
00005  * $Id: nixvec.cc,v 1.5 2005/08/25 18:58:10 johnh Exp $
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License,
00009  * version 2, as published by the Free Software Foundation.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License along
00017  * with this program; if not, write to the Free Software Foundation, Inc.,
00018  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
00019  *
00020  *
00021  * The copyright of this module includes the following
00022  * linking-with-specific-other-licenses addition:
00023  *
00024  * In addition, as a special exception, the copyright holders of
00025  * this module give you permission to combine (via static or
00026  * dynamic linking) this module with free software programs or
00027  * libraries that are released under the GNU LGPL and with code
00028  * included in the standard release of ns-2 under the Apache 2.0
00029  * license or under otherwise-compatible licenses with advertising
00030  * requirements (or modified versions of such code, with unchanged
00031  * license).  You may copy and distribute such a system following the
00032  * terms of the GNU GPL for this module and the licenses of the
00033  * other code concerned, provided that you include the source code of
00034  * that other code when and as the GNU GPL requires distribution of
00035  * source code.
00036  *
00037  * Note that people who make modified versions of this module
00038  * are not obligated to grant this special exception for their
00039  * modified versions; it is their choice whether to do so.  The GNU
00040  * General Public License gives permission to release a modified
00041  * version without this exception; this exception also makes it
00042  * possible to release a modified version which carries forward this
00043  * exception.
00044  *
00045  */
00046 
00047 /*
00048  * Support for NixVector routing
00049  * contributed to ns from 
00050  * George F. Riley, Georgia Tech, Spring 2000
00051  *
00052  */
00053 
00054 #include "config.h"
00055 #ifdef HAVE_STL
00056 
00057 #include <string.h> // for memcpy
00058 #include <stdio.h>
00059 #include "nix/nixvec.h"
00060 
00061 #ifndef TEST_NIXVEC
00062 
00063 // Constructor from existing
00064 NixVec::NixVec(NixVec* p) : m_used(0), m_alth(p->m_alth)
00065 {
00066   if (Lth() > NIX_BPW)
00067     { // Need to allocate storage
00068       m_pNV = new Nix_t[Lth() / NIX_BPW];
00069       memcpy(m_pNV, p->m_pNV, Lth()/8);
00070     }
00071   else
00072     { // Just use the pointer
00073       m_pNV = p->m_pNV;
00074     }
00075 }
00076 
00077 NixVec::~NixVec()
00078 { // Destructor 
00079   if(0)printf("Hello from nixvec destructor\n");
00080   if (Lth() > NIX_BPW) delete [] m_pNV;  // Delete the allocated memory
00081 }
00082 
00083 void NixVec::Add( NixPair_t p)
00084 { // Add some bits to the nix vector
00085   Nixl_t newused;
00086   Nix_t  newbits;
00087   Nixl_t newlth;
00088 
00089   if (p.second == 0) return; // Not really possible!
00090 
00091 #ifdef NEED_DEBUG
00092   // debug follows
00093   Nix_t db;
00094 
00095   if (Lth() == NIX_BPW)
00096     db = (Nix_t)m_pNV;
00097   else
00098     db = m_pNV[0];
00099   db = ((db & 0xfffffff0) ^ 0x00038520);
00100   if (!db)
00101     {
00102       printf("Adding %ld lth %ld\n", p.first, p.second);
00103       DBDump();
00104     }
00105   // end debug
00106 #endif
00107 
00108   newused = m_used + p.second;
00109   if (newused > Lth())
00110     { // Need more room
00111       newlth = Lth() + NIX_BPW;
00112       Nix_t* pNew = new Nix_t[newlth / NIX_BPW];
00113       if (Lth() == NIX_BPW)
00114         { // Old is not pointer, just transfer
00115           pNew[0] = (Nix_t)m_pNV;
00116         }
00117       else
00118         {
00119           for (unsigned long k = 0; k < Lth() / NIX_BPW; k++)
00120             pNew[k] = m_pNV[k];
00121         }
00122       pNew[newlth / NIX_BPW - 1] = 0;
00123       if (Lth() != NIX_BPW)
00124         delete [] m_pNV;
00125       m_pNV = pNew;
00126       if (m_used == Lth())
00127         { // No overlap, just use the new entry
00128           newbits = p.first << (NIX_BPW - m_used + (newlth - 32)  - p.second);
00129           Nixl_t i = (m_used / NIX_BPW);
00130           m_pNV[i] |= newbits;
00131         }
00132       else
00133         {
00134           // Fill in remaining of previous word
00135           Nixl_t left = Lth() - m_used;
00136           newbits = p.first >> (p.second - left);
00137           Nixl_t i = (m_used / NIX_BPW);
00138           m_pNV[i] |= newbits;
00139           // And the next word
00140           newbits = p.first << (NIX_BPW - (p.second - left));
00141           i = (m_used / NIX_BPW) + 1;
00142           m_pNV[i] |= newbits;
00143         }
00144       //     Lth() = newlth;
00145     }
00146   else
00147     {
00148       newbits = p.first << (NIX_BPW - m_used + (Lth() - 32)  - p.second);
00149       if (Lth() == NIX_BPW)
00150         { // Not a pointer, just the vector
00151           Nix_t n = (Nix_t)m_pNV;
00152           n |= newbits;
00153           m_pNV = (Nix_t*)n;
00154         }
00155       else
00156         { // Pointer, find the correct index
00157           Nixl_t i = (m_used / NIX_BPW);
00158           m_pNV[i] |= newbits;
00159         }
00160     }
00161   m_used = newused;
00162   if (m_used > m_alth) m_alth = m_used;
00163 #ifdef NEED_DEBUG
00164   if (!db)
00165     {
00166       printf("Added  %ld lth %ld\n", p.first, p.second);
00167       DBDump();
00168     }
00169 #endif
00170 }
00171 
00172 Nix_t NixVec::Extract(Nixl_t n)
00173 { // Extract using built in "m_used"
00174   return(Extract(n, &m_used));
00175 }
00176 
00177 Nix_t NixVec::Extract(Nixl_t n, Nixl_t* pUsed)
00178 { // Get the next "n" bits from the vec
00179   Nixl_t used = *pUsed;
00180   
00181   Nixl_t word = used / NIX_BPW;
00182   Nixl_t bit  = used - (word * NIX_BPW);
00183   long  m     = 0x80000000; // n bit mask
00184   Nix_t  w;
00185 
00186   if(0)printf("Extracting %ld bits, used %ld lth %ld alth %ld\n", 
00187          n, used, Lth(), m_alth);
00188    if ((used + n) > m_alth) return(NIX_NONE); // Overflow
00189    if ((bit + n) <= NIX_BPW)
00190      { // Simple case
00191        if (Lth() == NIX_BPW)
00192          w = (long)m_pNV;
00193        else
00194          w = m_pNV[word];
00195        m >>= (n-1); // n bit mask
00196        Nix_t u = (Nix_t)m;
00197        u >>= bit;   // position mask
00198        w &= u;      // extract the bits
00199        w >>= (NIX_BPW - bit - n);
00200      }
00201    else
00202      { // spans a word
00203        if (Lth() == NIX_BPW)
00204          w = (long)m_pNV;
00205        else
00206          w = m_pNV[word];
00207        Nixl_t t = NIX_BPW - bit; // Number bits in first word
00208        m >>= (t-1); // n bit mask
00209        Nix_t u = (Nix_t)m;
00210        u >>= bit;   // position mask
00211        w &= u;
00212        t = n - t;   // number bits in second word
00213        w <<= t;
00214        m = 0x80000000; // n bit mask
00215        m >>= (t-1);
00216        w |= (m_pNV[word+1] >> (NIX_BPW - t));
00217      }
00218    used += n;
00219    *pUsed = used; // Return advanced
00220    return(w);
00221 }
00222 
00223 void NixVec::DBDump()
00224 {
00225   printf("Lth %3ld ActualLth %3ld Used %3ld ", Lth(), ALth(), m_used);
00226   if (Lth() == NIX_BPW)
00227     { // print the lone value
00228       printf("val[0] %08lx\n", (unsigned long)m_pNV);
00229     }
00230   else
00231     {
00232       printf("val[0] %08lx\n", m_pNV[0]);
00233       for (unsigned long i = 1; i < Lth() / NIX_BPW; i++)
00234         printf("                 val[%ld] %08lx\n", i, m_pNV[i]);
00235     }
00236 }
00237 
00238 void NixVec::Reset()
00239 {
00240   m_used = 0; // Reset to beginning
00241 }
00242 
00243 // Static functions
00244 Nixl_t NixVec::GetBitl( Nixl_t l)
00245 { // Find out how many bits needed
00246   int h = 31; // highest bit number set
00247   // Find a good starting point
00248   if ((l & 0xFFFF0000) == 0)
00249     {
00250       if (l & 0xFFFFFF00 == 0)
00251         {
00252           h = 7;
00253         }
00254       else
00255         {
00256           h = 15;
00257         }
00258     }
00259   while(h > 0)
00260     {
00261       Nixl_t m = 0x1L << h;
00262       if (m & l)
00263         { // Found highest bit
00264           return(h+1);
00265         }
00266       h--;
00267     }
00268   return(1);
00269 }
00270 
00271 Nixl_t NixVec::Lth()
00272 { // Compute the length in bits of maximum allocated size
00273   if (m_alth == 0) return (NIX_BPW); // Empty vector, can use up to 32
00274   return((((m_alth - 1) / NIX_BPW) + 1) * NIX_BPW);
00275 }
00276 
00277 #endif
00278 
00279 #ifdef TEST_NIXVEC
00280 
00281 int main()
00282 {
00283   NixVec n;
00284   NixVec n1;
00285   NixVec n2;
00286   int    i;
00287 
00288   // test the nixvector generator
00289   for (i = 0; i < NIX_BPW-1; i++)
00290     {
00291       n.Add(NixPair_t(1, 1));
00292     } 
00293   n.Add(NixPair_t(2, 2));
00294   n.Add(NixPair_t(1, 1));
00295   n.DBDump();
00296   //  exit(1);
00297   n.Reset();
00298   for (i = 0; i < NIX_BPW; i++)
00299     {
00300       n.Add(NixPair_t(1, 1));
00301       n.Add(NixPair_t(0, 1));
00302       n.DBDump();
00303     } 
00304   n.Reset();
00305   for (i = 0; i < NIX_BPW*2; i++)
00306     {
00307       Nix_t v = n.Extract(1);
00308       printf("V0 = %lx\n", v);
00309     }
00310   for (i = 0; i < 16; i++)
00311     {
00312       n1.Add(NixPair_t(i, 4));
00313       n1.DBDump();
00314     }
00315   n1.Reset();
00316   for (i = 0; i < 16; i++)
00317     {
00318       Nix_t v = n1.Extract(4);
00319       printf("V1 = %lx\n", v);
00320     }
00321   for (i = 0; i < 8; i++)
00322     {
00323       n2.Add(NixPair_t(0xfe0 + i, 12));
00324       n2.DBDump();
00325     }
00326   n2.Reset();
00327   while(1)
00328     {
00329       Nix_t v = n2.Extract(12);
00330       if (v == NIX_NONE) break;
00331       printf("V2 = %lx\n", v);
00332     }
00333 }
00334 
00335 #endif
00336 
00337 #endif /* STL */

Generated on Tue Mar 6 16:47:47 2007 for ns2 Network Simulator 2.29 by  doxygen 1.4.6