ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-4/src/openbabel/bitvec.cpp
Revision: 2440
Committed: Wed Nov 16 19:42:11 2005 UTC (18 years, 8 months ago) by tim
File size: 12099 byte(s)
Log Message:
adding openbabel

File Contents

# User Rev Content
1 tim 2440 /**********************************************************************
2     bitvec.cpp - Fast and efficient bitstring class.
3    
4     Copyright (C) 1998-2001 by OpenEye Scientific Software, Inc.
5     Some portions Copyright (C) 2001-2005 by Geoffrey R. Hutchison
6    
7     This file is part of the Open Babel project.
8     For more information, see <http://openbabel.sourceforge.net/>
9    
10     This program is free software; you can redistribute it and/or modify
11     it under the terms of the GNU General Public License as published by
12     the Free Software Foundation version 2 of the License.
13    
14     This program is distributed in the hope that it will be useful,
15     but WITHOUT ANY WARRANTY; without even the implied warranty of
16     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17     GNU General Public License for more details.
18     ***********************************************************************/
19    
20     #include "bitvec.hpp"
21     #include "oberror.hpp"
22    
23     using namespace std;
24    
25     namespace OpenBabel
26     {
27    
28     extern OBMessageHandler obErrorLog;
29    
30     /*! \class OBBitVec
31     \brief Fast and efficient bitstring class
32    
33     The OBBitVec class is a fast and efficient bitstring class that is
34     handy to use as a truth table. Truth tables are an easy way to store
35     whether a list of items has a particular propery. Instances of
36     OBBitVec can by dynamically resized, and have a number of overloaded
37     operators that make code simple and readable. The following examples
38     demonstrate uses of the OBBitVec class:
39     \code
40     OBBitVec bv1,bv2,bv3;
41     bv1.SetBitOn(5);
42     bv2.SetBitOff(200);
43     bv1 |= bv2;
44     bv1 = bv1 & bv2;
45     if (bv1.Empty()) //Empty() returns true if no bits are set on
46     {
47     cout << "bv1 = " << bv1 << endl;
48     }
49    
50     int bit;
51     for (bit = bv1.NextBit(0);bit != bv1.EndBit();bit = bv1.NextBit(bit))
52     {
53     cout << "the next bit turned on is " << bit << endl;
54     }
55     \endcode
56     */
57    
58     static int bitsoff[SETWORD] =
59     {
60     0xFFFFFFFF,0xFFFFFFFE,0xFFFFFFFC,0xFFFFFFF8,0xFFFFFFF0,0xFFFFFFE0,0xFFFFFFC0,
61     0xFFFFFF80,0xFFFFFF00,0xFFFFFE00,0xFFFFFC00,0xFFFFF800,0xFFFFF000,0xFFFFE000,
62     0xFFFFC000,0xFFFF8000,0xFFFF0000,0xFFFE0000,0xFFFC0000,0xFFF80000,0xFFF00000,
63     0xFFE00000,0xFFC00000,0xFF800000,0xFF000000,0xFE000000,0xFC000000,0xF8000000,
64     0xF0000000,0xE0000000,0xC0000000,0x80000000
65     };
66    
67     #ifndef LowBit
68     #define LowBit(set, bit)\
69     {register int m;\
70     if (set != 0)\
71     {\
72     bit = 31;\
73     if (set != 0x80000000) {\
74     if ((m = (set & 0x0000ffff))) {set = m; bit -= 16;}\
75     if ((m = (set & 0x00ff00ff))) {set = m; bit -= 8;}\
76     if ((m = (set & 0x0f0f0f0f))) {set = m; bit -= 4;}\
77     if ((m = (set & 0x33333333))) {set = m; bit -= 2;}\
78     if ((m = (set & 0x55555555))) {set = m; bit -= 1;}}}\
79     else bit = -1;}
80     #endif
81    
82     OBBitVec::OBBitVec(const OBBitVec &bv)
83     {
84     _size = 0;
85     (*this) = bv;
86     }
87    
88     void OBBitVec::SetBitOn(int bit)
89     {
90     int word = bit/SETWORD;
91     bit = bit%SETWORD;
92    
93     //if (word+1 >= GetSize()) Resize((word+1)*SETWORD);
94     if (word >= _size)
95     Resize((word+1)*SETWORD);
96     _set[word] |= (1<<bit);
97     }
98    
99     void OBBitVec::SetRangeOn(int lobit, int hibit)
100     {
101     int i;
102    
103     if (lobit > hibit)
104     return;
105     else if (lobit == hibit)
106     SetBitOn(hibit);
107     else
108     {
109     int loword = lobit / SETWORD;
110     int hiword = hibit / SETWORD;
111     int lobitp = lobit % SETWORD;
112     int hibitp = hibit % SETWORD;
113    
114     if (hiword >= _size)
115     Resize((hiword+1) * SETWORD);
116    
117     if (loword == hiword)
118     {
119     for ( i = lobitp ; i <= hibitp ; i++ )
120     _set[loword] |= (1<<i);
121     }
122     else
123     {
124     for ( i = lobitp ; i < SETWORD ; i++ )
125     _set[loword] |= (1<<i);
126     for ( i = loword + 1 ; i < hiword ; i++ )
127     _set[i] = 0xFFFFFFFF;
128     for ( i = 0 ; i <= hibitp ; i++ )
129     _set[hiword] |= (1<<i);
130     }
131     }
132     }
133    
134     void OBBitVec::SetBitOff(int bit)
135     {
136     int word = bit/SETWORD;
137     bit = bit%SETWORD;
138     _set[word] &= (~(1 << bit));
139     }
140    
141     void OBBitVec::SetRangeOff(int lobit, int hibit)
142     {
143     int i;
144    
145     if (lobit > hibit)
146     return;
147     else if (lobit == hibit)
148     SetBitOff(hibit);
149     else
150     {
151     int loword = lobit / SETWORD;
152     int hiword = hibit / SETWORD;
153     int lobitp = lobit % SETWORD;
154     int hibitp = hibit % SETWORD;
155    
156     if (hiword >= _size)
157     {
158     hiword = _size - 1;
159     hibitp = SETWORD - 1;
160     }
161    
162     if (loword == hiword)
163     {
164     for ( i = lobitp ; i <= hibitp ; i++ )
165     _set[loword] &= (~(1<<i));
166     }
167     else
168     {
169     for ( i = lobitp ; i < SETWORD ; i++ )
170     _set[loword] &= (~(1<<i));
171     for ( i = loword + 1 ; i < hiword ; i++ )
172     _set[i] = 0x00000000;
173     for ( i = 0 ; i <= hibitp ; i++ )
174     _set[hiword] &= (~(1<<i));
175     }
176     }
177     }
178    
179     int OBBitVec::NextBit(int last)
180     {
181     unsigned s;
182     register int bit,wrdcnt;
183     last++;
184    
185     wrdcnt = last/SETWORD;
186    
187     if (wrdcnt >= _size)
188     return(-1);
189    
190     if (_set[wrdcnt] != 0)
191     {
192     s = (_set[wrdcnt]) & bitsoff[last - (wrdcnt*SETWORD)];
193     if (s)
194     {
195     LowBit(s,bit);
196     if (bit != -1)
197     return(bit + (wrdcnt*SETWORD));
198     }
199     }
200     wrdcnt++;
201    
202     while(wrdcnt < _size)
203     {
204     if (this->_set[wrdcnt] != 0)
205     {
206     s = this->_set[wrdcnt];
207     LowBit(s, bit);
208    
209     if (bit != -1)
210     return(bit+(wrdcnt*SETWORD));
211     }
212     wrdcnt++;
213     }
214    
215     return(-1);
216     }
217    
218     bool OBBitVec::Resize(int maxbits)
219     {
220     if(!maxbits)
221     return(false);
222     unsigned int maxword = maxbits/SETWORD;
223     if (maxbits%SETWORD)
224     maxword++;
225     if (maxword >= _set.size())
226     {
227     _set.resize(maxword);
228     _size = _set.size();
229     }
230    
231     return(true);
232     }
233    
234     OBBitVec &OBBitVec::operator= (const OBBitVec &bv)
235     {
236     if (_size != bv._size)
237     Resize(bv._size*SETWORD);
238    
239     int i;
240     for ( i = 0 ; i < bv._size ; i++ )
241     _set[i] = bv._set[i];
242     for ( ; i < _size ; i++ )
243     _set[i] = 0;
244    
245     return(*this);
246     }
247    
248     OBBitVec &OBBitVec::operator&= ( OBBitVec &bv)
249     {
250     int i;
251     int min = (bv._size < _size) ? bv._size : _size;
252    
253     for (i = 0;i < min;i++)
254     _set[i] &= bv._set[i];
255     for (;i < _size;i++)
256     _set[i] = 0;
257    
258     return(*this);
259     }
260    
261     OBBitVec &OBBitVec::operator|= (OBBitVec &bv)
262     {
263     if (_size != bv._size)
264     {
265     if (_size < bv._size)
266     Resize(bv._size*SETWORD);
267     else
268     bv.Resize(_size*SETWORD);
269     }
270     for (int i = 0;i < _size;i++)
271     _set[i] |= bv._set[i];
272    
273     return(*this);
274     }
275    
276     OBBitVec &OBBitVec::operator^= (OBBitVec &bv)
277     {
278     int i;
279     if (_size != bv._size)
280     {
281     if (_size < bv._size)
282     Resize(bv._size*SETWORD);
283     else
284     bv.Resize(_size*SETWORD);
285     }
286     for (i = 0;i < _size;i++)
287     _set[i] ^= bv._set[i];
288    
289     return(*this);
290     }
291    
292     OBBitVec &OBBitVec::operator-= (OBBitVec &bv)
293     {
294     if (GetSize() != bv._size)
295     obErrorLog.ThrowError(__FUNCTION__, "Subtracting sets of != size", obDebug);
296     else
297     {
298     OBBitVec tmp;
299     tmp = *this ^ bv;
300     *this &= tmp;
301     }
302     return(*this);
303     }
304    
305     OBBitVec &OBBitVec::operator+= (OBBitVec &bv)
306     {
307     int old_size = _size;
308     Resize(_size*SETWORD+bv._size*SETWORD);
309     for (int i = 0;i < bv._size;i++)
310     _set[i+old_size] = bv._set[i];
311     return(*this);
312     }
313    
314     OBBitVec operator| (OBBitVec &bv1,OBBitVec &bv2)
315     {
316     OBBitVec bv;
317     bv = bv1;
318     bv |= bv2;
319    
320     return(bv);
321     }
322    
323     OBBitVec operator& (OBBitVec &bv1, OBBitVec &bv2)
324     {
325     OBBitVec bv;
326     bv = bv1;
327     bv &= bv2;
328    
329     return(bv);
330     }
331    
332     OBBitVec operator^ (OBBitVec &bv1, OBBitVec &bv2)
333     {
334     OBBitVec bv;
335     bv = bv1;
336     bv ^= bv2;
337     return(bv);
338     }
339    
340     bool operator== (const OBBitVec &bv1,const OBBitVec &bv2)
341     {
342     if (bv1._size != bv2._size)
343     return(false);
344    
345     int i;
346     for (i = 0;i < bv1._size;i++)
347     if (bv1._set[i] != bv2._set[i])
348     return(false);
349    
350     return(true);
351     }
352    
353     OBBitVec operator- (OBBitVec &bv1,OBBitVec &bv2)
354     {
355     OBBitVec bv;
356     bv = bv1 ^ bv2;
357     bv &= bv1;
358     return(bv);
359     }
360    
361     istream& operator>> ( istream &is, OBBitVec &bv )
362     {
363     size_t startpos = 0, endpos = 0;
364     vector<string> tokens;
365     string line;
366    
367     getline(is,line);
368    
369     for (;;)
370     {
371     startpos = line.find_first_not_of(" \t\n",startpos);
372     endpos = line.find_first_of(" \t\n",startpos);
373    
374     if (endpos < line.size() && startpos <= line.size())
375     tokens.push_back(line.substr(startpos,endpos-startpos));
376     else
377     break;
378    
379     startpos = endpos + 1;
380     }
381    
382     for (unsigned int i = 0 ; i < tokens.size() ; i++ )
383     {
384     if ( tokens[i] == "[" )
385     continue;
386     else if ( tokens[i] == "]" )
387     break;
388    
389     int bit = atoi(tokens[i].c_str());
390    
391     if (bit >= 0)
392     bv.SetBitOn(bit);
393     else
394     {
395     #ifdef HAVE_SSTREAM
396     stringstream errorMsg;
397     #else
398     strstream errorMsg;
399     #endif
400     errorMsg << "Negative Bit: " << bit << endl;
401     obErrorLog.ThrowError(__FUNCTION__, errorMsg.str(), obDebug);
402     }
403     }
404    
405     return is;
406     }
407    
408     ostream& operator<< ( ostream &os, const OBBitVec& bv)
409     {
410     os << "[ " << flush;
411    
412     int i,j;
413     for (i = 0;i < bv._size;i++)
414     for (j = 0;j < SETWORD;j++)
415     if (bv._set[i]>>(j%SETWORD)&1)
416     os << (j+(i*SETWORD)) << ' ' << flush;
417    
418     os << "]" << flush;
419     return(os);
420     }
421    
422     void OBBitVec::Fold(int nbits)
423     {
424     int nwords = nbits/SETWORD;
425    
426     if (_size < nwords)
427     {
428     _set.resize(nwords);
429     _size = nwords;
430     return;
431     }
432    
433     int i,idx = nwords;
434     for (i = 0,idx=nwords;idx < _size;idx++)
435     {
436     _set[i] |= _set[idx];
437     if (i+1 < nwords)
438     i++;
439     else
440     i = 0;
441     }
442     _set.resize(nwords);
443     _size = nwords;
444     }
445    
446     void OBBitVec::FromVecInt(vector<int> &v)
447     {
448     vector<int>::iterator i;
449     int max = 0;
450    
451     for (i = v.begin();i != v.end();i++)
452     if (*i > max)
453     max = *i;
454    
455     Resize(max/SETWORD);
456     for (i = v.begin();i != v.end();i++)
457     SetBitOn(*i);
458     }
459    
460     void OBBitVec::FromString(string &line, int bits)
461     {
462     size_t startpos = 0, endpos = 0;
463     vector<string> tokens;
464    
465     Resize(bits);
466     Clear();
467    
468     for (;;)
469     {
470     startpos = line.find_first_not_of(" \t\n",startpos);
471     endpos = line.find_first_of(" \t\n",startpos);
472    
473     if (endpos < line.size() && startpos <= line.size())
474     tokens.push_back(line.substr(startpos,endpos-startpos));
475     else
476     break;
477    
478     startpos = endpos + 1;
479     }
480    
481     for (unsigned int i = 0 ; i < tokens.size() ; i++ )
482     {
483     if ( tokens[i] == "[" )
484     continue;
485     else if ( tokens[i] == "]" )
486     break;
487    
488     int bit = atoi(tokens[i].c_str());
489    
490     if (bit >= 0)
491     SetBitOn(bit);
492     else
493     {
494     #ifdef HAVE_SSTREAM
495     stringstream errorMsg;
496     #else
497     strstream errorMsg;
498     #endif
499     errorMsg << "Negative Bit: " << bit << endl;
500     obErrorLog.ThrowError(__FUNCTION__, errorMsg.str(), obDebug);
501     }
502     }
503     }
504    
505     void OBBitVec::ToVecInt(vector<int> &v)
506     {
507     v.clear();
508     v.reserve(CountBits());
509     for (int i = NextBit(-1);i != -1;i = NextBit(i))
510     v.push_back(i);
511     }
512    
513     void OBBitVec::Clear()
514     {
515     vector<int>::iterator i;
516     for (i = _set.begin();i != _set.end();i++)
517     *i = 0;
518     }
519    
520     int OBBitVec::CountBits()
521     {
522     int i,count=0;
523     for (i = NextBit(-1);i != -1;i = NextBit(i))
524     count++;
525    
526     return(count);
527     }
528    
529     bool OBBitVec::IsEmpty()
530     {
531     vector<int>::iterator i;
532     for (i = _set.begin();i != _set.end();i++)
533     if (*i)
534     return(false);
535    
536     return(true);
537     }
538    
539     double Tanimoto(OBBitVec &bv1,OBBitVec &bv2)
540     {
541     OBBitVec bvtmp;
542     double andbits,orbits;
543    
544     bvtmp = bv1 & bv2;
545     andbits = (double)bvtmp.CountBits();
546     bvtmp = bv1 | bv2;
547     orbits = (double)bvtmp.CountBits();
548    
549     return(andbits/orbits);
550     }
551    
552     } // end namespace OpenBabel
553    
554     //! \file bitvec.cpp
555     //! \brief Fast and efficient bitstring class
556