rbitmap.cc

Go to the documentation of this file.
00001 
00002 /*
00003  * rbitmap.cc
00004  * Copyright (C) 2000 by the University of Southern California
00005  * $Id: rbitmap.cc,v 1.5 2005/08/25 18:58:11 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  * Define a bitmap object
00048  * contributed to ns
00049  * George Riley, Georgia Tech, Winter 2000
00050  */
00051 
00052 #include "config.h"
00053 #ifdef HAVE_STL
00054 
00055 // Creates a bitmap object.  The 'entries' can be more than one bit,
00056 // but default to one bit.  Bits per entry can't be more than 32.
00057 // Entries DO NOT span words, for ease of coding
00058 
00059 #include <stdio.h>
00060 #include <assert.h>
00061 
00062 #include "routealgo/rbitmap.h"
00063 
00064 #ifndef TEST_BM
00065 BitMap::BitMap() :  m_Size(0), m_BPE(0), m_Words(0), m_EPW(0), m_pM(0)
00066 { // Default constructor ...used only to input from log file
00067 }
00068 
00069 BitMap::BitMap( u_long Size, u_long BitsPerEntry)
00070   : m_Size(Size), m_BPE(BitsPerEntry)
00071 {
00072   m_EPW = BITS_ULONG / BitsPerEntry; // Entries per word
00073   m_Words = (Size + m_EPW - 1) / m_EPW;
00074   if(0)printf("Hello from bitmap constructor size %ld bpe %ld epw %d m_Words %ld\n",
00075          Size, BitsPerEntry, m_EPW, m_Words);
00076   if (m_Words > 1)
00077     {
00078       m_pM = new u_long[m_Words];
00079       for (u_long i = 0; i < m_Words; i++) m_pM[i] = 0;
00080     }
00081   else
00082     {
00083       m_pM = (u_long*)(0);
00084     }
00085   if(0)printf("Exiting bitmap constructor\n");
00086 }
00087 
00088 /*BitMap::~BitMap()
00089 {
00090   if (m_Words > 1) delete [] m_pM;
00091 }*/
00092 
00093 void BitMap::Set(u_long Which, u_long Value)
00094 {
00095 u_long* pW;
00096 u_long  Mask;
00097 short   Shift;
00098 
00099   pW    = GetWordAddress(Which);
00100   Mask  = GetBitMask(Which);
00101   Shift = GetShiftCount(Which);
00102   *pW  &= (~Mask); // Clear existing bits
00103   *pW  |= (Value << Shift);
00104 }
00105 
00106 void BitMap::Clear(u_long Which)
00107 {
00108 u_long* pW;
00109 u_long  Mask;
00110 
00111   pW    = GetWordAddress(Which);
00112   Mask  = GetBitMask(Which);
00113   *pW  &= (~Mask); // Clear existing bits
00114 }
00115 
00116 u_long BitMap::Get(u_long Which)
00117 {
00118 u_long* pW;
00119 u_long  Mask;
00120 short   Shift;
00121 u_long  r;
00122 
00123   pW    = GetWordAddress(Which);
00124   Mask  = GetBitMask(Which);
00125   Shift = GetShiftCount(Which);
00126   if(0)printf("Get which %ld Mask %08lx Shift %d\n", Which, Mask, Shift);
00127   r = *pW;
00128 
00129   r  &= (Mask); // get existing bits
00130   return (r >> Shift);
00131 }
00132 
00133 
00134 // Private subroutines
00135 
00136 u_long* BitMap::GetWordAddress(
00137     u_long Which) // Get a pointer to the word needed
00138 {
00139 u_long ind;
00140 
00141  Validate(Which);
00142  ind = Which / m_EPW; 
00143  if (m_Words == 1)
00144    { // not indirected
00145      return((u_long*)&m_pM);
00146    }
00147  return(&m_pM[ind]);
00148 }
00149 
00150 u_long BitMap::GetBitMask( // Get a bit mask to the needed bits
00151     u_long Which)
00152 {
00153 long  m;
00154 short c;
00155 u_long um;
00156 
00157   m = 0x80000000;
00158   m >>= (m_BPE - 1);
00159   c = GetShiftCount(Which);
00160   um = m;
00161   um = um >> (32 - (c + m_BPE));
00162   if(0)printf("Get Bit Mask m %08lx shifted m %08lx\n", m, um);
00163   return(um);
00164 }
00165 
00166 
00167 short BitMap::GetShiftCount( // Get a shift count for position
00168     u_long Which)  
00169 {
00170 u_long ind;
00171 short  left;
00172 
00173  Validate(Which);
00174  ind = Which / m_EPW; 
00175  left = Which - (ind * m_EPW);  // Entry number in the actual word
00176  return(left * m_BPE);
00177 }
00178 
00179 void    BitMap::Validate(u_long Which)// Validate which not too large
00180 {
00181   assert (Which < m_Size);
00182 }
00183 
00184 
00185 size_t BitMap::Size( void )
00186 {
00187   size_t r;
00188 
00189   r = sizeof(u_long*) + // m_pM
00190       sizeof(u_long) + // m_Size
00191       sizeof(u_long) + // m_BPE
00192       sizeof(u_long) + // m_Words
00193       sizeof(short); // m_EPW
00194   if (m_Size * m_BPE > BITS_ULONG)
00195     r += ((m_Size * m_BPE) + BITS_ULONG - 1 / BITS_ULONG) * 
00196          sizeof(u_long) ; // Account for the actual map
00197   return(r);
00198 }
00199 
00200 void BitMap::DBPrint()
00201 {
00202   printf("Size %ld BPE %ld Words %ld EPW %d\n", m_Size, m_BPE, m_Words, m_EPW);
00203   if (m_Words == 1)
00204     {
00205       printf("Word 0 %08lx\n", (u_long)m_pM);
00206     }
00207   else
00208     {
00209       for (u_long i = 0; i < m_Words; i++)
00210         printf("Word %ld %08lx\n", i, m_pM[i]);
00211     }
00212 }
00213 
00214 u_long BitMap::FindBPE( u_long m ) // Find how many bits/entry we need
00215 {
00216   u_long bpe = 32;
00217   u_long k = 0x80000000;
00218 
00219   while(k)
00220     {
00221       if (m & k) return(bpe);
00222       bpe--;
00223       k >>= 1;
00224     }
00225   return(0);
00226 }
00227 
00228 size_t BitMap::EstimateSize( u_long Size, u_long BitsPerEntry)
00229 {
00230   size_t r;
00231 
00232   r = sizeof(u_long*) + // m_pM
00233       sizeof(u_long) + // m_Size
00234       sizeof(u_long) + // m_BPE
00235       sizeof(u_long) + // m_Words
00236       sizeof(short); // m_EPW
00237   if (Size * BitsPerEntry > BITS_ULONG)
00238     r += ((Size * BitsPerEntry) + BITS_ULONG - 1 / BITS_ULONG) * 
00239          sizeof(u_long) ; // Account for the actual map
00240   return (r);
00241 }
00242 
00243 void BitMap::Log( ostream& os)
00244 {
00245   os << " " << m_Size;
00246   os << " " << m_BPE;
00247   os << " " << m_Words;
00248   os << " " << m_EPW;
00249   if (m_Words == 1)
00250     { // Not a pointer, but the actual map
00251       os << " " << hex << (unsigned long)m_pM << dec;
00252     }
00253   else
00254     {
00255       for (unsigned int i = 0; i < m_Words; i++)
00256         os << " " << hex << m_pM[i] << dec;
00257     }
00258 }
00259 
00260 #endif
00261 
00262 #ifdef TEST_BM
00263 int main()
00264 {
00265 BitMap B(64);
00266 BitMap B2(64, 2);
00267 BitMap B3(64, 3);
00268 
00269   B.DBPrint();
00270   B.Set(0);
00271   B.DBPrint();
00272   printf("Entry 0 is %ld\n", B.Get(0));
00273   B.Set(31);
00274   B.DBPrint();
00275   B.Set(32);
00276   B.DBPrint();
00277   B.Set(63);
00278   B.DBPrint();
00279 
00280   B2.DBPrint();
00281   B2.Set(0, 1);
00282   B2.DBPrint();
00283   B2.Set(31, 2);
00284   B2.DBPrint();
00285   B2.Set(32, 2);
00286   B2.DBPrint();
00287   B2.Set(63, 3);
00288   B2.DBPrint();
00289 
00290   B3.DBPrint();
00291   B3.Set(0, 1);
00292   B3.DBPrint();
00293   B3.Set(31, 2);
00294   B3.DBPrint();
00295   B3.Set(32, 2);
00296   B3.DBPrint();
00297   B3.Set(63, 7);
00298   B3.DBPrint();
00299 
00300 }
00301 #endif
00302 
00303 #endif /* STL */

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