8#ifndef Sawyer_BitVectorSupport_H
9#define Sawyer_BitVectorSupport_H
12#include <boost/cstdint.hpp>
13#include <boost/foreach.hpp>
14#include <boost/lexical_cast.hpp>
16#include <Sawyer/Assert.h>
17#include <Sawyer/Interval.h>
18#include <Sawyer/Optional.h>
19#include <Sawyer/Sawyer.h>
27namespace BitVectorSupport {
31template<
class T>
struct RemoveConst<const T> {
typedef T Base; };
42 enum { value = 8 *
sizeof(Word) };
72Word
bitMask(
size_t offset,
size_t nbits) {
75 return mask << offset;
83template<
class Processor,
class Word>
84bool processWord(Processor &processor,
const Word &word,
size_t shift,
size_t nbits) {
87 const Word tmp = word >> shift;
88 return processor(tmp, nbits);
91template<
class Processor,
class Word>
92bool processWord(Processor &processor, Word &word,
size_t shift,
size_t nbits) {
94 Word tmp = word >> shift;
95 bool retval = processor(tmp, nbits);
96 word &= ~bitMask<Word>(shift, nbits);
97 word |= (tmp & bitMask<Word>(0, nbits)) << shift;
101template<
class Processor,
class Word>
102bool processWord(Processor &processor,
const Word &src, Word &dst,
size_t shift,
size_t nbits) {
105 const Word tmpSrc = src >> shift;
106 Word tmpDst = dst >> shift;
107 bool retval = processor(tmpSrc, tmpDst, nbits);
108 dst &= ~bitMask<Word>(shift, nbits);
109 dst |= (tmpDst & bitMask<Word>(0, nbits)) << shift;
112template<
class Processor,
class Word>
113bool processWord(Processor &processor, Word &w1, Word &w2,
size_t shift,
size_t nbits) {
116 Word tmp1 = w1 >> shift;
117 Word tmp2 = w2 >> shift;
118 bool retval = processor(tmp1, tmp2, nbits);
119 Word mask = bitMask<Word>(shift, nbits);
121 w1 |= (tmp1 << shift) & mask;
123 w2 |= (tmp2 << shift) & mask;
126template<
class Processor,
class Word>
127bool processWord(Processor &processor,
const Word &w1,
const Word &w2,
size_t shift,
size_t nbits) {
130 Word tmp1 = w1 >> shift;
131 Word tmp2 = w2 >> shift;
132 return processor(tmp1, tmp2, nbits);
138void nonoverlappingCopy(
const Word *src,
const BitRange &srcRange, Word *dst,
const BitRange &dstRange) {
139 ASSERT_require(srcRange.size()==dstRange.size());
140 ASSERT_require(src != dst);
142 size_t dstFirstIdx = wordIndex<Word>(dstRange.least());
143 size_t dstLastIdx = wordIndex<Word>(dstRange.greatest());
144 size_t srcFirstIdx = wordIndex<Word>(srcRange.least());
145 size_t srcLastIdx = wordIndex<Word>(srcRange.greatest());
147 size_t srcOffset = srcFirstIdx - dstFirstIdx;
149 size_t srcBitIdx = bitIndex<Word>(srcRange.least());
150 size_t dstBitIdx = bitIndex<Word>(dstRange.least());
152 if (srcBitIdx < dstBitIdx) {
154 const size_t leftShiftAmount = dstBitIdx - srcBitIdx;
155 const size_t rightShiftAmount = bitsPerWord<Word>::value - leftShiftAmount;
157 for (
size_t i=dstFirstIdx; i<=dstLastIdx; ++i) {
158 const Word tmp = (i+srcOffset > srcFirstIdx ? (src[i+srcOffset-1] >> rightShiftAmount) : Word(0)) |
159 (i+srcOffset > srcLastIdx ? Word(0) : (src[i+srcOffset] << leftShiftAmount));
160 Word mask = bitMask<Word>(0, bitsPerWord<Word>::value);
162 mask &= ~bitMask<Word>(0, bitIndex<Word>(dstRange.least()));
164 mask &= bitMask<Word>(0, bitIndex<Word>(dstRange.greatest())+1);
166 dst[i] |= tmp & mask;
168 }
else if (srcBitIdx > dstBitIdx) {
170 const size_t rightShiftAmount = srcBitIdx - dstBitIdx;
171 const size_t leftShiftAmount = bitsPerWord<Word>::value - rightShiftAmount;
173 for (
size_t i=dstFirstIdx; i<=dstLastIdx; ++i) {
174 const Word tmp = (src[i+srcOffset] >> rightShiftAmount) |
175 (i+srcOffset+1 <= srcLastIdx ? (src[i+srcOffset+1] << leftShiftAmount) : Word(0));
176 Word mask = bitMask<Word>(0, bitsPerWord<Word>::value);
178 mask &= ~bitMask<Word>(0, bitIndex<Word>(dstRange.least()));
180 mask &= bitMask<Word>(0, bitIndex<Word>(dstRange.greatest())+1);
182 dst[i] |= tmp & mask;
186 for (
size_t i=dstFirstIdx; i<=dstLastIdx; ++i) {
187 const Word tmp = src[i+srcOffset];
188 Word
mask = bitMask<Word>(0, bitsPerWord<Word>::value);
190 mask &= ~bitMask<Word>(0, bitIndex<Word>(dstRange.least()));
192 mask &= bitMask<Word>(0, bitIndex<Word>(dstRange.greatest())+1);
194 dst[i] |= tmp &
mask;
199template<
class Src,
class Dst>
200void conditionalCopy(
const Src *src,
const BitRange &srcRange, Dst *dst,
const BitRange &dstRange) {
201 nonoverlappingCopy(src, srcRange, dst, dstRange);
203template<
class Src,
class Dst>
204void conditionalCopy(
const Src *,
const BitRange &,
const Dst *,
const BitRange &) {
213template<
class Processor,
class Word>
217 size_t nRemaining = range.size();
218 size_t offsetInWord = bitIndex<Word>(range.least());
220 for (
size_t wordIdx = wordIndex<Word>(range.least()); !done && nRemaining > 0; ++wordIdx) {
222 ASSERT_require(nbits > 0);
223 done =
processWord(processor, words[wordIdx], offsetInWord, nbits);
230template<
class Processor,
class Word>
234 size_t nRemaining = range.size();
235 size_t offsetInWord = bitIndex<Word>(range.least());
237 size_t firstWordIdx = wordIndex<Word>(range.least());
238 size_t lastWordIdx = wordIndex<Word>(range.greatest());
239 for (
size_t wordIdx=lastWordIdx; !done && nRemaining > 0; --wordIdx) {
241 if (wordIdx == firstWordIdx) {
244 }
else if (wordIdx < lastWordIdx) {
248 ASSERT_require(wordIdx==lastWordIdx);
249 ASSERT_require(wordIdx>firstWordIdx);
252 ASSERT_require(nRemaining > nBitsToLeft);
253 nbits = nRemaining - nBitsToLeft;
256 done =
processWord(processor, words[wordIdx], wordIdx==firstWordIdx ? offsetInWord : 0, nbits);
262template<
class Processor,
class Word1,
class Word2>
264 ASSERT_require(
sizeof(Word1)==
sizeof(Word2));
268 ASSERT_require(range1.
size() == range2.
size());
273 size_t offsetInWord = bitIndex<Word2>(range2.
least());
274 const size_t nWordsTmp = numberOfWords<Word2>(offsetInWord + range2.
size());
275 SAWYER_VARIABLE_LENGTH_ARRAY(
typename RemoveConst<Word1>::Base, tmp, nWordsTmp);
277 nonoverlappingCopy(vec1, range1, tmp, tmpRange);
281 const size_t vec2WordOffset = wordIndex<Word2>(range2.
least());
282 size_t nRemaining = range2.
size();
284 for (
size_t wordIdx=0; !done && nRemaining > 0; ++wordIdx) {
285 ASSERT_require(wordIdx < nWordsTmp);
287 ASSERT_require(nbits > 0);
288 done =
processWord(processor, *
const_cast<Word1*
>(tmp+wordIdx), vec2[wordIdx+vec2WordOffset], offsetInWord, nbits);
294 conditionalCopy(tmp, tmpRange, vec1, range1);
298template<
class Processor,
class Word1,
class Word2>
300 ASSERT_require(
sizeof(Word1)==
sizeof(Word2));
304 ASSERT_require(range1.
size() == range2.
size());
309 const size_t offsetInWord = bitIndex<Word2>(range2.
least());
310 const size_t nWordsTmp = numberOfWords<Word2>(offsetInWord + range2.
size());
311 SAWYER_VARIABLE_LENGTH_ARRAY(
typename RemoveConst<Word1>::Base, tmp, nWordsTmp);
313 nonoverlappingCopy(vec1, range1, tmp, tmpRange);
316 size_t nRemaining = range2.
size();
318 const size_t vec2WordOffset = wordIndex<Word2>(range2.
least());
319 for (
size_t wordIdx=nWordsTmp-1; !done && nRemaining>0; --wordIdx) {
324 }
else if (wordIdx < nWordsTmp-1) {
328 ASSERT_require(wordIdx==nWordsTmp-1);
329 ASSERT_require(wordIdx>0);
331 ASSERT_require(nRemaining > nBitsToLeft);
332 nbits = nRemaining - nBitsToLeft;
335 done =
processWord(processor, *
const_cast<Word1*
>(tmp+wordIdx), vec2[wordIdx+vec2WordOffset],
336 wordIdx==0 ? offsetInWord : 0, nbits);
341 conditionalCopy(tmp, tmpRange, vec1, range1);
344template<
class Processor,
class Word>
346 const Word *vec1,
const BitRange &range1,
347 const Word *vec2,
const BitRange &range2,
349 traverse2(processor, vec1, range1, vec2, range2, dir);
352template<
class Processor,
class Word>
354 const Word *vec1,
const BitRange &range1,
355 const Word *vec2,
const BitRange &range2,
357 traverse2(processor, vec1, range1, vec2, range2, dir);
359template<
class Processor,
class Word>
361 const Word *vec1,
const BitRange &range1,
362 Word *vec2,
const BitRange &range2,
364 traverse2(processor, vec1, range1, vec2, range2, dir);
366template<
class Processor,
class Word>
368 Word *vec1,
const BitRange &range1,
369 Word *vec2,
const BitRange &range2,
371 traverse2(processor, vec1, range1, vec2, range2, dir);
384bool get(
const Word *words,
size_t idx) {
385 return 0 != (words[wordIndex<Word>(idx)] & bitMask<Word>(bitIndex<Word>(idx), 1));
390 bool operator()(Word &word,
size_t nbits) {
391 word &= ~bitMask<Word>(0, nbits);
407 bool operator()(Word &word,
size_t nbits) {
408 word |= bitMask<Word>(0, nbits);
436 bool operator()(
const Word &src, Word &dst,
size_t nbits) {
437 dst &= ~bitMask<Word>(0, nbits);
438 dst |= src & bitMask<Word>(0, nbits);
455 bool operator()(Word &w1, Word &w2,
size_t nbits) {
456 Word tmp = w1, mask = bitMask<Word>(0, nbits);
472 ASSERT_require(vec1!=vec2 || !range1.
overlaps(range2));
483 bool operator()(
const Word &w1, Word &w2,
size_t nbits) {
485 Word a = w1 & bitMask<Word>(0, nbits);
486 Word b = w2 & bitMask<Word>(0, nbits);
502 return visitor.wasEqv;
515 bool operator()(
const Word &word,
size_t nbits) {
516 if (0 != (word & bitMask<Word>(0, nbits))) {
517 for (
size_t i=0; i<nbits; ++i) {
518 if (0 != (word & bitMask<Word>(i, 1))) {
538 return range.least() + *visitor.result;
547 bool operator()(
const Word &word,
size_t nbits) {
548 if (bitMask<Word>(0, nbits) != (word & bitMask<Word>(0, nbits))) {
549 for (
size_t i=0; i<nbits; ++i) {
550 if (0 == (word & bitMask<Word>(i, 1))) {
570 return range.least() + *visitor.result;
579 bool operator()(
const Word &word,
size_t nbits) {
580 ASSERT_require(nbits <= offset);
582 if (0 != (word & bitMask<Word>(0, nbits))) {
583 for (
size_t i=nbits; i>0; --i) {
584 if (0 != (word & bitMask<Word>(i-1, 1))) {
585 result = offset + i-1;
603 return range.least() + *visitor.result;
612 bool operator()(
const Word &word,
size_t nbits) {
613 ASSERT_require(nbits <= offset);
615 if (bitMask<Word>(0, nbits) != (word & bitMask<Word>(0, nbits))) {
616 for (
size_t i=nbits; i>0; --i) {
617 if (0 == (word & bitMask<Word>(i-1, 1))) {
618 result = offset + i-1;
636 return range.least() + *visitor.result;
660 bool operator()(
const Word &word,
size_t nbits) {
661 if (0 != (word & bitMask<Word>(0, nbits))) {
662 for (
size_t i=0; i<nbits; ++i) {
663 if (0 != (word & bitMask<Word>(i, 1)))
678 return visitor.result;
685 bool operator()(
const Word &word,
size_t nbits) {
686 if (bitMask<Word>(0, nbits) != (word & bitMask<Word>(0, nbits))) {
687 for (
size_t i=0; i<nbits; ++i) {
688 if (0 == (word & bitMask<Word>(i, 1)))
703 return visitor.result;
711 bool operator()(
const Word &w1,
const Word &w2,
size_t nbits) {
712 Word mask = bitMask<Word>(0, nbits);
713 if ((w1 & mask) != (w2 & mask)) {
714 for (
size_t i=0; i<nbits; ++i) {
715 if ((w1 ^ w2) & bitMask<Word>(i, 1)) {
733 const Word *vec2,
const BitRange &range2) {
736 return visitor.result;
744 bool operator()(
const Word &w1,
const Word &w2,
size_t nbits) {
745 ASSERT_require(nbits <= offset);
747 Word mask = bitMask<Word>(0, nbits);
748 if ((w1 & mask) != (w2 & mask)) {
749 for (
size_t i=nbits; i>0; --i) {
750 if ((w1 ^ w2) & bitMask<Word>(i-1, 1)) {
751 result = offset + i-1;
767 const Word *vec2,
const BitRange &range2) {
770 return visitor.result;
794 if (nShift < range.size()) {
795 size_t nbits = range.size() - nShift;
799 copy(words, shiftedFrom, words, shiftedTo);
800 setValue(words, introduced, newBits);
812 if (nShift < range.size()) {
813 size_t nbits = range.size() - nShift;
817 copy(words, shiftedFrom, words, shiftedTo);
818 setValue(words, introduced, newBits);
830 if (!range.isEmpty()) {
831 bool newBits =
get(words, range.greatest());
844 nShift %= range.size();
849 size_t nSavedWords = numberOfWords<Word>(nShift);
850 SAWYER_VARIABLE_LENGTH_ARRAY(Word, saved, nSavedWords);
857 copy(saved, savedRange, words, introduced);
868 nShift %= range.size();
879 bool operator()(Word &word,
size_t nbits) {
880 word ^= bitMask<Word>(0, nbits);
896 bool operator()(
const Word &w1, Word &w2,
size_t nbits) {
897 w2 &= w1 | ~bitMask<Word>(0, nbits);
914 bool operator()(
const Word &w1, Word &w2,
size_t nbits) {
915 w2 |= w1 & bitMask<Word>(0, nbits);
932 bool operator()(
const Word &w1, Word &w2,
size_t nbits) {
933 w2 ^= w1 & bitMask<Word>(0, nbits);
958 ASSERT_require(8==
sizeof value);
963 size_t nbits = std::min(range.size(), (
size_t)64);
965 size_t nTmpWords = numberOfWords<Word>(nbits);
966 SAWYER_VARIABLE_LENGTH_ARRAY(Word, tmp, nTmpWords);
967 for (
size_t i=0; i<nTmpWords; ++i)
972 if (range.size() >= 64) {
984 boost::uint64_t result = 0;
985 ASSERT_require(8==
sizeof result);
988 size_t nbits = std::min(range.size(), (
size_t)64);
989 size_t nTmpWords = numberOfWords<Word>(nbits);
990 SAWYER_VARIABLE_LENGTH_ARRAY(
typename RemoveConst<Word>::Base, tmp, nTmpWords);
995 for (
size_t i=0; i<nTmpWords; ++i)
1005 boost::uint64_t result = 0;
1006 ASSERT_require(nbits <= 64);
1007 size_t nTmpWords = numberOfWords<Word>(nbits);
1008 for (
size_t i=0; i<nTmpWords; ++i)
1011 result &= ~((~(boost::uint64_t)0) << nbits);
1022 boost::uint64_t u = toInteger<Word>(words, range);
1023 const size_t nBits = range.size();
1024 if (nBits > 1 && nBits < 64) {
1025 bool isNegative = (u & (boost::uint64_t(1) << (nBits-1))) != 0;
1027 u |= boost::uint64_t(-1) << nBits;
1029 return boost::int64_t(u);
1038 boost::uint64_t u = toInteger<Word>(words, nBits);
1039 if (nBits > 1 && nBits < 64) {
1040 bool isNegative = (u & (boost::uint64_t(1) << (nBits-1))) != 0;
1042 u |= boost::uint64_t(-1) << nBits;
1044 return boost::int64_t(u);
1051 bool operator()(Word &word,
size_t nbits) {
1052 ASSERT_require(carry);
1053 Word mask = bitMask<Word>(0, nbits);
1054 Word arg1 = word & mask;
1055 Word sum = arg1 + 1;
1058 carry = (sum & mask) < arg1;
1070 return visitor.carry;
1077 bool operator()(Word &word,
size_t nbits) {
1078 ASSERT_require(borrowed);
1079 Word mask = bitMask<Word>(0, nbits);
1080 Word arg1 = word & mask;
1082 Word difference = (arg1 - 1) & mask;
1097 return visitor.borrowed;
1112 AddBits(
bool carry): carry(carry) {}
1113 bool operator()(
const Word &w1, Word &w2,
size_t nbits) {
1114 Word mask = bitMask<Word>(0, nbits);
1115 Word addend1(carry ? 1 : 0);
1116 Word addend2(w1 & mask);
1117 Word addend3(w2 & mask);
1118 Word sum = addend1 + addend2 + addend3;
1122 carry = sum < addend2 || (sum==addend2 && carry);
1124 carry = 0 != (sum & bitMask<Word>(nbits, 1));
1138 return visitor.carry;
1149 size_t nTempWords = numberOfWords<Word>(range1.
size());
1150 SAWYER_VARIABLE_LENGTH_ARRAY(Word, temp, nTempWords);
1152 copy(vec1, range1, temp, tempRange);
1154 return add(temp, tempRange, vec2, range2,
true);
1167 }
else if (range1.
isEmpty()) {
1168 clear(vec2, range2);
1170 }
else if (range1.
size() < range2.
size()) {
1176 ASSERT_require(range1.
size() >= range2.
size());
1178 copy(vec1, copyFrom, vec2, range2);
1189 const size_t nWords = numberOfWords<Word>(range.size());
1191 SAWYER_VARIABLE_LENGTH_ARRAY(Word, part, nWords);
1192 copy(vec, range, part, partRange);
1195 add(part, partRange, vec, range);
1214 bool operator()(
const Word &w1,
const Word &w2,
size_t nbits) {
1215 Word mask = bitMask<Word>(0, nbits);
1216 Word tmp1 = w1 & mask;
1217 Word tmp2 = w2 & mask;
1221 }
else if (tmp1 > tmp2) {
1240 }
else if (range1.
isEmpty()) {
1242 }
else if (range2.
isEmpty()) {
1244 }
else if (range1.
size() < range2.
size()) {
1249 return compare(vec1, range1, vec2, lo);
1250 }
else if (range1.
size() > range2.
size()) {
1255 return compare(vec1, lo, vec2, range2);
1258 ASSERT_require(range1.
size() == range2.
size());
1261 return visitor.result;
1275 }
else if (range1.
isEmpty()) {
1277 return *mssb == range2.
greatest() ? 1 : -1;
1281 }
else if (range2.
isEmpty()) {
1283 return *mssb == range1.
greatest() ? -1 : 1;
1287 }
else if (range1.
size() < range2.
size()) {
1291 if (!neg1 && !neg2) {
1292 return compare(vec1, range1, vec2, range2);
1293 }
else if (neg1 && neg2) {
1304 }
else if (range1.
size() > range2.
size()) {
1307 ASSERT_require(range1.
size()==range2.
size());
1310 if (!neg1 && !neg2) {
1311 return compare(vec1, range1, vec2, range2);
1312 }
else if (neg1 && neg2) {
1314 return get(vec1, range1.
least() + *diff) ? 1 : -1;
1332 size_t nremaining = 0;
1333 std::vector<uint8_t> bytes;
1336 const size_t nBytes = (nBitsTotal + 7) / 8;
1337 bytes.reserve(nBytes);
1340 bool operator()(
const Word &word,
size_t nbits) {
1342 ASSERT_require(nremaining <
size_t(8));
1343 while (nremaining + nbits >=
size_t(8)) {
1344 const size_t nrem = nremaining;
1345 const size_t nnew = size_t(8) - nrem;
1346 const Word
byte = (remaining & bitMask<Word>(0, nrem)) | ((tmp & bitMask<Word>(0, nnew)) << nrem);
1347 bytes.push_back(
byte);
1357 std::vector<uint8_t> result() {
1358 if (nremaining > 0) {
1359 ASSERT_require(nremaining <= 7);
1360 const uint8_t
byte = remaining & bitMask<Word>(0, nremaining);
1361 bytes.push_back(
byte);
1363 return std::move(bytes);
1369toBytes(
const Word *vec,
const BitRange &range) {
1372 return visitor.result();
1376void fromBytes(Word *vec,
const BitRange &range,
const std::vector<uint8_t> &input) {
1379 for (
size_t idx = 0; idx < input.size() && offset < range.size(); ++idx) {
1380 const Word
byte = input[idx];
1381 const size_t nbits = std::min(
size_t(8), range.size() - offset);
1387 if (offset < range.size())
1396template<
class Word,
size_t bitsPerDigit>
1400 std::string reversed;
1402 ToString(): remaining(0), nremaining(0) {
1403 ASSERT_require(bitsPerDigit >= 1 && bitsPerDigit <= 4);
1407 bool operator()(
const Word &word,
size_t nbits) {
1408 static const char digits[] = {
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'a',
'b',
'c',
'd',
'e',
'f'};
1409 Word tmp = word & bitMask<Word>(0, nbits);
1410 ASSERT_require(nremaining < bitsPerDigit);
1411 while (nremaining+nbits >= bitsPerDigit) {
1412 size_t nrem = std::min(nremaining, bitsPerDigit);
1413 size_t nnew = bitsPerDigit - nrem;
1414 Word digit = (remaining & bitMask<Word>(0, nrem)) | ((tmp & bitMask<Word>(0, nnew)) << nrem);
1415 reversed += digits[digit];
1425 std::string result() {
1426 if (nremaining > 0) {
1427 ASSERT_require(nremaining <= 3);
1428 reversed +=
'0' + (remaining & bitMask<Word>(0, nremaining));
1432 std::swap(s, reversed);
1433 std::reverse(s.begin(), s.end());
1448 return visitor.result();
1460 return visitor.result();
1472 return visitor.result();
1480Word charToDigit(
char ch) {
1482 if (ch >=
'0' && ch <=
'9') {
1484 }
else if (ch >=
'a' && ch <=
'f') {
1485 digit = ch -
'a' + 10;
1486 }
else if (ch >=
'A' && ch <=
'F') {
1487 digit = ch -
'A' + 10;
1494template<
class Word,
size_t bitsPerDigit>
1495void fromString(Word *vec,
const BitRange &range,
const std::string &input) {
1496 ASSERT_require(bitsPerDigit >= 1 && bitsPerDigit <= 4);
1497 ASSERT_require(bitsPerDigit <= bitsPerWord<Word>::value);
1500 for (
size_t idx=0; idx<input.size(); ++idx) {
1501 if (
'_'!=input[idx] && charToDigit<Word>(input[idx]) >= Word(1) << bitsPerDigit) {
1502 throw std::runtime_error(std::string(
"invalid character '") + input[idx] +
"' at index " +
1503 boost::lexical_cast<std::string>(idx) +
" in base-" +
1504 boost::lexical_cast<std::string>(1 << bitsPerDigit) +
" input string");
1510 for (
size_t idx=input.size(); idx>0 && offset<
range.size(); --idx) {
1511 if (
'_'!=input[idx-1]) {
1512 Word digit = charToDigit<Word>(input[idx-1]);
1513 size_t nbits = std::min(bitsPerDigit,
range.size()-offset);
1516 offset += bitsPerDigit;
1521 if (offset <
range.size())
1535 boost::uint64_t v = 0;
1536 bool hadOverflow =
false;
1537 BOOST_FOREACH (
char ch, input) {
1539 boost::uint64_t tmp = v * 10 + (ch -
'0');
1545 }
else if (ch !=
'_') {
1546 throw std::runtime_error(
"invalid decimal digit \"" + std::string(1, ch) +
"\"");
1555 const size_t nWords = numberOfWords<Word>(range.size());
1556 SAWYER_VARIABLE_LENGTH_ARRAY(Word, accumulator, nWords);
1557 SAWYER_VARIABLE_LENGTH_ARRAY(Word, digit, nWords);
1559 BOOST_FOREACH (
char ch, input) {
1562 add(digit, accumulatorRange, accumulator, accumulatorRange);
1564 copy(accumulator, accumulatorRange, vec, range);
1576 fromString<Word, 4>(vec, range, input);
1587 fromString<Word, 3>(vec, range, input);
1598 fromString<Word, 1>(vec, range, input);
Range of values delimited by endpoints.
T greatest() const
Returns upper limit.
static Interval baseSize(size_t lo, size_t size)
Construct an interval from one endpoint and a size.
static Interval hull(size_t v1, size_t v2)
Construct an interval from two endpoints.
Value size() const
Size of interval.
bool isEmpty() const
True if interval is empty.
T least() const
Returns lower limit.
bool overlaps(const Interval &other) const
True if two intervals overlap.
Holds a value or nothing.
void fromString(source_position &, const std::string &input)
Parse a string (such as 12.10, 13, 0 etc )into source position data structure.
Unsigned mask(size_t least, size_t greatest)
Generate a mask.
SgRangeExp * range(const SgAdaAttributeExp *rangeAttribute)
returns a range for the range attribute rangeAttribute.
bool isEqualToZero(const Word *vec1, const BitRange &range1)
Compares with zero.
bool isAllSet(const Word *words, const BitRange &range)
True if all bits are set.
void rotateLeft(Word *words, const BitRange &range, size_t nShift)
Rotate bits to the left.
Optional< size_t > mostSignificantDifference(const Word *vec1, const BitRange &range1, const Word *vec2, const BitRange &range2)
Find most significant different bits.
void negate(Word *vec1, const BitRange &range)
Negate bits as an integer.
size_t numberOfWords(size_t nbits)
Number of words to hold indicated number of bits.
std::string toBinary(const Word *vec, const BitRange &range)
Binary representation.
size_t nClear(const Word *words, const BitRange &range)
Number of clear bits.
bool signExtend(const Word *vec1, const BitRange &range1, Word *vec2, const BitRange &range2)
Sign extend.
bool decrement(Word *vec1, const BitRange &range1)
Decrement.
void bitwiseOr(const Word *vec1, const BitRange &range1, Word *vec2, const BitRange &range2)
Bit-wise OR.
void shiftLeft(Word *words, const BitRange &range, size_t nShift, bool newBits=0)
Shift bits left.
int compare(const Word *vec1, const BitRange &range1, const Word *vec2, const BitRange &range2)
Unsigned comparison.
boost::uint64_t toInteger(const Word *words, const BitRange &range)
Convert a bit vector to an integer.
void multiply10(Word *vec, const BitRange &range)
Multiply by 10.
bool subtract(const Word *vec1, const BitRange &range1, Word *vec2, const BitRange &range2)
Subtract bits.
void fromBinary(Word *vec, const BitRange &range, const std::string &input)
Obtain bits from a binary representation.
void fromOctal(Word *vec, const BitRange &range, const std::string &input)
Obtain bits from an octal representation.
void fromDecimal(Word *vec, const BitRange &range, const std::string &input)
Obtain bits from a decimal representation.
void shiftRightArithmetic(Word *words, const BitRange &range, size_t nShift)
Shift bits right arithmetically.
Optional< size_t > leastSignificantClearBit(const Word *words, const BitRange &range)
Index of least significant zero bit.
void swap(Word *vec1, const BitRange &range1, Word *vec2, const BitRange &range2)
Swap some bits.
size_t nSet(const Word *words, const BitRange &range)
Number of set bits.
void clear(Word *words, const BitRange &where)
Clear some bits.
void traverse2(Processor &processor, Word1 *vec1, const BitRange &range1, Word2 *vec2, const BitRange &range2, LowToHigh)
Traverse two ranges of bits from low to high.
Optional< size_t > mostSignificantClearBit(const Word *words, const BitRange &range)
Index of most significant clear bit.
void bitwiseAnd(const Word *vec1, const BitRange &range1, Word *vec2, const BitRange &range2)
Bit-wise AND.
void set(Word *words, const BitRange &where)
Set some bits.
Word bitMask(size_t offset, size_t nbits)
Creates a mask.
void fromHex(Word *vec, const BitRange &range, const std::string &input)
Obtain bits from a hexadecimal representation.
bool get(const Word *words, size_t idx)
Return a single bit.
void rotateRight(Word *words, const BitRange &range, size_t nShift)
Rotate bits to the right.
void bitwiseXor(const Word *vec1, const BitRange &range1, Word *vec2, const BitRange &range2)
Bit-wise XOR.
bool equalTo(const Word *vec1, const BitRange &range1, const Word *vec2, const BitRange &range2)
Compare bits for equality.
boost::int64_t toSignedInteger(const Word *words, const BitRange &range)
Convert a bit vector to a signed integer.
bool increment(Word *vec1, const BitRange &range1)
Increment.
int compareSigned(const Word *vec1, const BitRange &range1, const Word *vec2, const BitRange &range2)
Signed comparison.
bool add(const Word *vec1, const BitRange &range1, Word *vec2, const BitRange &range2, bool carryIn=false)
Add bits.
Optional< size_t > leastSignificantSetBit(const Word *words, const BitRange &range)
Index of least significant set bit.
Optional< size_t > mostSignificantSetBit(const Word *words, const BitRange &range)
Index of most significant set bit.
std::string toOctal(const Word *vec, const BitRange &range)
Octal representation.
void fromInteger(Word *words, const BitRange &range, boost::uint64_t value)
Assign an unsigned value to a bit range.
void shiftRight(Word *words, const BitRange &range, size_t nShift, bool newBits=0)
Shift bits right.
void invert(Word *words, const BitRange &range)
Invert bits.
void traverse(Processor &processor, Word *words, const BitRange &range, LowToHigh)
Traverses a range of bits.
bool areEqual(const Word *vec1, const BitRange &range1, const Word *vec2, const BitRange &range2)
Equality predicate.
bool processWord(Processor &processor, const Word &word, size_t shift, size_t nbits)
Invoke the a processor for a vector traversal.
bool isAllClear(const Word *words, const BitRange &range)
True if all bits are clear.
Optional< size_t > leastSignificantDifference(const Word *vec1, const BitRange &range1, const Word *vec2, const BitRange &range2)
Find least significant different bits.
size_t bitIndex(size_t idx)
Index to bit within word.
size_t wordIndex(size_t idx)
Index to bit vector word.
std::string toHex(const Word *vec, const BitRange &range)
Hexadecimal representation.
void setValue(Word *words, const BitRange &where, bool value)
Set or clear some bits.
void copy(const Word *src, const BitRange &srcRange, Word *dst, const BitRange &dstRange)
Copy some bits.
Tags for traversal directions.
For removing const qualifiers.