OpenMD 3.0
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
OpenMDBitSet.cpp
1/*
2 * Copyright (c) 2004-present, The University of Notre Dame. All rights
3 * reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 * SUPPORT OPEN SCIENCE! If you use OpenMD or its source code in your
32 * research, please cite the appropriate papers when you publish your
33 * work. Good starting points are:
34 *
35 * [1] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005).
36 * [2] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006).
37 * [3] Sun, Lin & Gezelter, J. Chem. Phys. 128, 234107 (2008).
38 * [4] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
39 * [5] Kuang & Gezelter, Mol. Phys., 110, 691-701 (2012).
40 * [6] Lamichhane, Gezelter & Newman, J. Chem. Phys. 141, 134109 (2014).
41 * [7] Lamichhane, Newman & Gezelter, J. Chem. Phys. 141, 134110 (2014).
42 * [8] Bhattarai, Newman & Gezelter, Phys. Rev. B 99, 094106 (2019).
43 */
44
45#include "utils/OpenMDBitSet.hpp"
46
47#include <algorithm>
48#include <cassert>
49#include <functional>
50#include <iterator>
51#include <string>
52
53#ifdef IS_MPI
54#include <mpi.h>
55#endif
56
57namespace OpenMD {
58
60 return std::count(bitset_.begin(), bitset_.end(), true);
61 }
62
63 void OpenMDBitSet::flip(size_t fromIndex, size_t toIndex) {
64 assert(fromIndex <= toIndex);
65 assert(fromIndex >= 0);
66 assert(toIndex <= size());
67 std::vector<bool>::iterator first = bitset_.begin() + fromIndex;
68 std::vector<bool>::iterator last = bitset_.begin() + toIndex;
69
70 std::transform(first, last, first, std::logical_not<bool>());
71 }
72
73 OpenMDBitSet OpenMDBitSet::get(size_t fromIndex, size_t toIndex) {
74 assert(fromIndex <= toIndex);
75 assert(fromIndex >= 0);
76 assert(toIndex <= size());
77 std::vector<bool>::iterator first = bitset_.begin() + fromIndex;
78 std::vector<bool>::iterator last = bitset_.begin() + toIndex;
79
80 OpenMDBitSet result;
81 std::copy(first, last, std::back_inserter(result.bitset_));
82 return result;
83 }
84
86 std::vector<bool>::iterator i =
87 std::find(bitset_.begin(), bitset_.end(), true);
88 return i == bitset_.end() ? true : false;
89 }
90
91 int OpenMDBitSet::nextOffBit(int fromIndex) const {
92 if (fromIndex <= -1) {
93 // in case -1 or other negative number is passed to this function
94 return -1;
95 }
96
97 ++fromIndex;
98 while (fromIndex < static_cast<int>(size())) {
99 if (!bitset_[fromIndex]) { return fromIndex; }
100 ++fromIndex;
101 }
102
103 return -1;
104 }
105
106 int OpenMDBitSet::nthOffBit(unsigned long int n) const {
107 std::vector<int> indices;
108 for (int i = firstOffBit(); i != -1; i = nextOffBit(i)) {
109 indices.push_back(i);
110 }
111
112 if (n < indices.size()) return indices[n];
113 return -1;
114 }
115
116 int OpenMDBitSet::nextOnBit(int fromIndex) const {
117 if (fromIndex <= -1) {
118 // in case -1 or other negative number is passed to this function
119 return -1;
120 }
121
122 ++fromIndex;
123 while (fromIndex < static_cast<int>(size())) {
124 if (bitset_[fromIndex]) { return fromIndex; }
125 ++fromIndex;
126 }
127
128 return -1;
129 }
130
131 int OpenMDBitSet::nthOnBit(unsigned long int n) const {
132 std::vector<int> indices;
133 for (int i = firstOnBit(); i != -1; i = nextOnBit(i)) {
134 indices.push_back(i);
135 }
136
137 if (n < indices.size()) return indices[n];
138 return -1;
139 }
140
142 assert(size() == bs.size());
143
144 std::transform(bs.bitset_.begin(), bs.bitset_.end(), bitset_.begin(),
145 bitset_.begin(), std::logical_and<bool>());
146 }
147
149 assert(size() == bs.size());
150 std::transform(bs.bitset_.begin(), bs.bitset_.end(), bitset_.begin(),
151 bitset_.begin(), std::logical_or<bool>());
152 }
153
155 assert(size() == bs.size());
156 std::transform(bs.bitset_.begin(), bs.bitset_.end(), bitset_.begin(),
157 bitset_.begin(), std::bit_xor<bool>());
158 }
159
160 void OpenMDBitSet::setBits(size_t fromIndex, size_t toIndex, bool value) {
161 assert(fromIndex <= toIndex);
162 assert(fromIndex >= 0);
163 assert(toIndex <= size());
164 std::vector<bool>::iterator first = bitset_.begin() + fromIndex;
165 std::vector<bool>::iterator last = bitset_.begin() + toIndex;
166 std::fill(first, last, value);
167 }
168
169 void OpenMDBitSet::resize(size_t nbits) {
170 size_t oldSize = size();
171 bitset_.resize(nbits);
172 if (nbits > oldSize) {
173 std::fill(bitset_.begin() + oldSize, bitset_.end(), false);
174 }
175 }
176
177 OpenMDBitSet operator|(const OpenMDBitSet& bs1, const OpenMDBitSet& bs2) {
178 assert(bs1.size() == bs2.size());
179
180 OpenMDBitSet result(bs1);
181 result |= bs2;
182 return result;
183 }
184
185 OpenMDBitSet operator&(const OpenMDBitSet& bs1, const OpenMDBitSet& bs2) {
186 assert(bs1.size() == bs2.size());
187
188 OpenMDBitSet result(bs1);
189 result &= bs2;
190 return result;
191 }
192
193 OpenMDBitSet operator^(const OpenMDBitSet& bs1, const OpenMDBitSet& bs2) {
194 assert(bs1.size() == bs2.size());
195
196 OpenMDBitSet result(bs1);
197 result ^= bs2;
198 return result;
199 }
200
201 OpenMDBitSet operator-(const OpenMDBitSet& bs1, const OpenMDBitSet& bs2) {
202 assert(bs1.size() == bs2.size());
203
204 OpenMDBitSet result(bs1);
205 result -= bs2;
206 return result;
207 }
208
209 bool operator==(const OpenMDBitSet& bs1, const OpenMDBitSet& bs2) {
210 assert(bs1.size() == bs2.size());
211 return std::equal(bs1.bitset_.begin(), bs1.bitset_.end(),
212 bs2.bitset_.begin());
213 }
214
215 OpenMDBitSet OpenMDBitSet::parallelReduce() {
216 OpenMDBitSet result;
217
218#ifdef IS_MPI
219
220 // This is necessary because std::vector<bool> isn't really a
221 // std::vector, so we can't pass the address of the first element
222 // to the MPI call that follows. We first have to convert to a
223 // std::vector<int> to do the logical_or Allreduce call, then back
224 // convert it into the vector<bool>.
225
226 std::vector<int> bsInt(bitset_.begin(), bitset_.end());
227
228 MPI_Allreduce(MPI_IN_PLACE, &bsInt[0], bsInt.size(), MPI_INT, MPI_LOR,
229 MPI_COMM_WORLD);
230
231 std::transform(bsInt.begin(), bsInt.end(),
232 std::back_inserter(result.bitset_),
233 [](int val) { return val != 0; });
234#else
235 // Not in MPI? Just return a copy of the current bitset:
236 std::copy(bitset_.begin(), bitset_.end(),
237 std::back_inserter(result.bitset_));
238#endif
239
240 return result;
241 }
242
243 // std::istream& operator>> ( std::istream& is, const OpenMDBitSet& bs) {
244 //
245 // return is;
246 //}
247
248 std::ostream& operator<<(std::ostream& os, const OpenMDBitSet& bs) {
249 for (size_t i = 0; i < bs.bitset_.size(); ++i) {
250 std::string val = bs[i] ? "true" : "false";
251 os << "OpenMDBitSet[" << i << "] = " << val << std::endl;
252 }
253
254 return os;
255 }
256
257} // namespace OpenMD
OpenMDBitSet is a wrapper class of std::vector<bool> to act as a growable std::bitset.
void andOperator(const OpenMDBitSet &bs)
Performs a logical AND of this target bit set with the argument bit set.
void flip()
Sets each bit to the complement of its current value.
bool none()
Returns true if no bits are set to true.
void resize(size_t nbits)
Changes the size of OpenMDBitSet.
int countBits()
Returns the number of bits set to true in this OpenMDBitSet.
size_t size() const
Returns the number of bits of space actually in use by this OpenMDBitSet to represent bit values.
int nextOnBit(int fromIndex) const
Returns the index of the first bit that is set to true that occurs on or after the specified starting...
bool get(size_t bitIndex)
Returns the value of the bit with the specified index.
void xorOperator(const OpenMDBitSet &bs)
Performs a logical XOR of this bit set with the bit set argument.
int nthOffBit(unsigned long int n) const
Returns the index of the n^th bit that is set to false.
int nextOffBit(int fromIndex) const
Returns the index of the first bit that is set to false that occurs on or after the specified startin...
void orOperator(const OpenMDBitSet &bs)
Performs a logical OR of this bit set with the bit set argument.
int nthOnBit(unsigned long int n) const
Returns the index of the n^th bit that is set to true.
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
DynamicRectMatrix< Real > operator-(const DynamicRectMatrix< Real > &m)
Negate the value of every element of this matrix.