FixedBitVector.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #include "CommonDataStructuresPch.h"
  6. BVFixed::BVFixed(BVFixed * initBv) :
  7. len(initBv->Length())
  8. {
  9. this->Copy(initBv);
  10. }
  11. BVFixed::BVFixed(BVIndex length, bool initialSet) :
  12. len(length)
  13. {
  14. Assert(length != 0);
  15. if (initialSet)
  16. {
  17. this->SetAll();
  18. }
  19. else
  20. {
  21. this->ClearAll();
  22. }
  23. }
  24. size_t
  25. BVFixed::GetAllocSize(BVIndex length)
  26. {
  27. Assert(length != 0);
  28. return sizeof(BVFixed) + sizeof(BVUnit) * BVFixed::WordCount(length);
  29. }
  30. void
  31. BVFixed::Init(BVIndex length)
  32. {
  33. Assert(length != 0);
  34. len = length;
  35. }
  36. BVIndex
  37. BVFixed::WordCount(BVIndex length)
  38. {
  39. Assert(length != 0);
  40. return ((length - 1) >> BVUnit::ShiftValue) + 1;
  41. }
  42. BVIndex
  43. BVFixed::WordCount() const
  44. {
  45. return WordCount(Length());
  46. }
  47. const BVUnit *
  48. BVFixed::BitsFromIndex(BVIndex i) const
  49. {
  50. AssertRange(i);
  51. return &this->data[BVUnit::Position(i)];
  52. }
  53. BVUnit *
  54. BVFixed::BitsFromIndex(BVIndex i)
  55. {
  56. AssertRange(i);
  57. return &this->data[BVUnit::Position(i)];
  58. }
  59. const BVUnit *
  60. BVFixed::BeginUnit() const
  61. {
  62. return &this->data[0];
  63. }
  64. const BVUnit *
  65. BVFixed::EndUnit() const
  66. {
  67. return &this->data[WordCount()];
  68. }
  69. BVUnit *
  70. BVFixed::BeginUnit()
  71. {
  72. return &this->data[0];
  73. }
  74. BVUnit *
  75. BVFixed::EndUnit()
  76. {
  77. return &this->data[WordCount()];
  78. }
  79. BVIndex
  80. BVFixed::GetNextBit(BVIndex i) const
  81. {
  82. AssertRange(i);
  83. const BVUnit * chunk = BitsFromIndex(i);
  84. BVIndex base = BVUnit::Floor(i);
  85. BVIndex offset = chunk->GetNextBit(BVUnit::Offset(i));
  86. if(-1 != offset)
  87. {
  88. return base + offset;
  89. }
  90. while(++chunk != this->EndUnit())
  91. {
  92. base += BVUnit::BitsPerWord;
  93. offset = chunk->GetNextBit();
  94. if(-1 != offset)
  95. {
  96. return base + offset;
  97. }
  98. }
  99. return BVInvalidIndex;
  100. }
  101. void
  102. BVFixed::AssertRange(BVIndex i) const
  103. {
  104. AssertMsg(i < this->Length(), "index out of bound");
  105. }
  106. void
  107. BVFixed::AssertBV(const BVFixed *bv) const
  108. {
  109. AssertMsg(NULL != bv, "Cannot operate on NULL bitvector");
  110. }
  111. BVIndex
  112. BVFixed::Length() const
  113. {
  114. return this->len;
  115. }
  116. void
  117. BVFixed::SetAll()
  118. {
  119. memset(&this->data[0], -1, WordCount() * sizeof(BVUnit));
  120. ClearEnd();
  121. }
  122. void
  123. BVFixed::ClearAll()
  124. {
  125. ZeroMemory(&this->data[0], WordCount() * sizeof(BVUnit));
  126. }
  127. BOOLEAN
  128. BVFixed::TestAndSet(BVIndex i)
  129. {
  130. AssertRange(i);
  131. BVUnit * bvUnit = this->BitsFromIndex(i);
  132. BVIndex offset = BVUnit::Offset(i);
  133. BOOLEAN bit = bvUnit->Test(offset);
  134. bvUnit->Set(offset);
  135. return bit;
  136. }
  137. BOOLEAN
  138. BVFixed::TestAndClear(BVIndex i)
  139. {
  140. AssertRange(i);
  141. BVUnit * bvUnit = this->BitsFromIndex(i);
  142. BVIndex offset = BVUnit::Offset(i);
  143. BOOLEAN bit = bvUnit->Test(offset);
  144. bvUnit->Clear(offset);
  145. return bit;
  146. }
  147. BOOLEAN
  148. BVFixed::operator[](BVIndex i) const
  149. {
  150. AssertRange(i);
  151. return this->Test(i);
  152. }
  153. void
  154. BVFixed::Or(const BVFixed*bv)
  155. {
  156. AssertBV(bv);
  157. this->for_each(bv, &BVUnit::Or);
  158. }
  159. //
  160. // Xors the two bit vectors and returns the count of bits which are different.
  161. //
  162. uint
  163. BVFixed::DiffCount(const BVFixed*bv) const
  164. {
  165. const BVUnit *i, *j;
  166. uint count = 0;
  167. for(i = this->BeginUnit(), j = bv->BeginUnit();
  168. i != this->EndUnit() && j != bv->EndUnit();
  169. i++, j++)
  170. {
  171. count += i->DiffCount(*j);
  172. }
  173. // Assumes that the default value of is 0
  174. while(i != this->EndUnit())
  175. {
  176. count += i->Count();
  177. i++;
  178. }
  179. while(j != bv->EndUnit())
  180. {
  181. count += j->Count();
  182. j++;
  183. }
  184. return count;
  185. }
  186. void
  187. BVFixed::OrComplimented(const BVFixed*bv)
  188. {
  189. AssertBV(bv);
  190. this->for_each(bv, &BVUnit::OrComplimented);
  191. ClearEnd();
  192. }
  193. void
  194. BVFixed::And(const BVFixed*bv)
  195. {
  196. AssertBV(bv);
  197. this->for_each(bv, &BVUnit::And);
  198. }
  199. void
  200. BVFixed::Minus(const BVFixed*bv)
  201. {
  202. AssertBV(bv);
  203. this->for_each(bv, &BVUnit::Minus);
  204. }
  205. void
  206. BVFixed::Copy(const BVFixed*bv)
  207. {
  208. AssertBV(bv);
  209. Assert(len >= bv->len);
  210. #if 1
  211. js_memcpy_s(&this->data[0], WordCount() * sizeof(BVUnit), &bv->data[0], bv->WordCount() * sizeof(BVUnit));
  212. #else
  213. this->for_each(bv, &BVUnit::Copy);
  214. #endif
  215. }
  216. void
  217. BVFixed::CopyBits(const BVFixed * bv, BVIndex i)
  218. {
  219. AssertBV(bv);
  220. BVIndex offset = BVUnit::Offset(i);
  221. BVIndex position = BVUnit::Position(i);
  222. BVIndex len = bv->WordCount() - position;
  223. BVIndex copylen = min(WordCount(), len);
  224. if (offset == 0)
  225. {
  226. js_memcpy_s(&this->data[0], copylen * sizeof(BVUnit), &bv->data[BVUnit::Position(i)], copylen * sizeof(BVUnit));
  227. }
  228. else
  229. {
  230. BVIndex pos = position;
  231. for (BVIndex j = 0; j < copylen; j++)
  232. {
  233. Assert(pos < bv->WordCount());
  234. this->data[j] = bv->data[pos];
  235. this->data[j].ShiftRight(offset);
  236. pos++;
  237. if (pos >= bv->WordCount())
  238. {
  239. break;
  240. }
  241. BVUnit temp = bv->data[pos];
  242. temp.ShiftLeft(BVUnit::BitsPerWord - offset);
  243. this->data[j].Or(temp);
  244. }
  245. }
  246. #if DBG
  247. for (BVIndex curr = i; curr < i + this->Length(); curr++)
  248. {
  249. Assert(this->Test(curr - i) == bv->Test(curr));
  250. }
  251. #endif
  252. }
  253. void
  254. BVFixed::ComplimentAll()
  255. {
  256. for(BVIndex i=0; i < this->WordCount(); i++)
  257. {
  258. this->data[i].ComplimentAll();
  259. }
  260. ClearEnd();
  261. }
  262. void
  263. BVFixed::ClearEnd()
  264. {
  265. uint offset = BVUnit::Offset(this->Length());
  266. if (offset != 0)
  267. {
  268. Assert((((uint64)1 << BVUnit::Offset(this->Length())) - 1) == BVUnit::GetTopBitsClear(this->Length()));
  269. this->data[this->WordCount() - 1].And(BVUnit::GetTopBitsClear(this->Length()));
  270. }
  271. }
  272. BVIndex
  273. BVFixed::Count() const
  274. {
  275. BVIndex sum = 0;
  276. for (BVIndex i=0; i < this->WordCount(); i++)
  277. {
  278. sum += this->data[i].Count();
  279. }
  280. Assert(sum <= this->Length());
  281. return sum;
  282. }
  283. JsUtil::FBVEnumerator
  284. BVFixed::BeginSetBits()
  285. {
  286. return JsUtil::FBVEnumerator(this->BeginUnit(), this->EndUnit());
  287. }
  288. bool BVFixed::IsAllClear() const
  289. {
  290. bool isClear = true;
  291. for (BVIndex i=0; i < this->WordCount(); i++)
  292. {
  293. isClear = this->data[i].IsEmpty() && isClear;
  294. if(!isClear)
  295. {
  296. break;
  297. }
  298. }
  299. return isClear;
  300. }
  301. #if DBG_DUMP
  302. void
  303. BVFixed::Dump() const
  304. {
  305. bool hasBits = false;
  306. Output::Print(_u("[ "));
  307. for(BVIndex i=0; i < this->WordCount(); i++)
  308. {
  309. hasBits = this->data[i].Dump(i * BVUnit::BitsPerWord, hasBits);
  310. }
  311. Output::Print(_u("]\n"));
  312. }
  313. #endif