PageRenderTime 50ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/d/phobos/std/bitarray.d

https://bitbucket.org/goshawk/gdc/
D | 942 lines | 685 code | 169 blank | 88 comment | 164 complexity | d55c430dd41e49dda1b6ea3d82f76aa8 MD5 | raw file
Possible License(s): GPL-2.0, AGPL-1.0
  1. /***********************
  2. * Source: $(PHOBOSSRC std/_bitarray.d)
  3. * Macros:
  4. * WIKI = StdBitarray
  5. */
  6. module std.bitarray;
  7. //debug = bitarray; // uncomment to turn on debugging printf's
  8. private import std.intrinsic;
  9. /**
  10. * An array of bits.
  11. */
  12. struct BitArray
  13. {
  14. size_t len;
  15. size_t* ptr;
  16. size_t dim()
  17. {
  18. return (len + 31) / 32;
  19. }
  20. size_t length()
  21. {
  22. return len;
  23. }
  24. void length(size_t newlen)
  25. {
  26. if (newlen != len)
  27. {
  28. size_t olddim = dim();
  29. size_t newdim = (newlen + 31) / 32;
  30. if (newdim != olddim)
  31. {
  32. // Create a fake array so we can use D's realloc machinery
  33. auto b = ptr[0 .. olddim];
  34. b.length = newdim; // realloc
  35. ptr = b.ptr;
  36. if (newdim & 31)
  37. { // Set any pad bits to 0
  38. ptr[newdim - 1] &= ~(~0 << (newdim & 31));
  39. }
  40. }
  41. len = newlen;
  42. }
  43. }
  44. /**********************************************
  45. * Support for [$(I index)] operation for BitArray.
  46. */
  47. bool opIndex(size_t i)
  48. in
  49. {
  50. assert(i < len);
  51. }
  52. body
  53. {
  54. return cast(bool)bt(ptr, i);
  55. }
  56. /** ditto */
  57. bool opIndexAssign(bool b, size_t i)
  58. in
  59. {
  60. assert(i < len);
  61. }
  62. body
  63. {
  64. if (b)
  65. bts(ptr, i);
  66. else
  67. btr(ptr, i);
  68. return b;
  69. }
  70. /**********************************************
  71. * Support for array.dup property for BitArray.
  72. */
  73. BitArray dup()
  74. {
  75. BitArray ba;
  76. auto b = ptr[0 .. dim].dup;
  77. ba.len = len;
  78. ba.ptr = b.ptr;
  79. return ba;
  80. }
  81. unittest
  82. {
  83. BitArray a;
  84. BitArray b;
  85. debug(bitarray) printf("BitArray.dup.unittest\n");
  86. a.length = 3;
  87. a[0] = 1; a[1] = 0; a[2] = 1;
  88. b = a.dup;
  89. assert(b.length == 3);
  90. for (int i = 0; i < 3; i++)
  91. { debug(bitarray) printf("b[%d] = %d\n", i, b[i]);
  92. assert(b[i] == (((i ^ 1) & 1) ? true : false));
  93. }
  94. }
  95. /**********************************************
  96. * Support for foreach loops for BitArray.
  97. */
  98. int opApply(int delegate(inout bool) dg)
  99. {
  100. int result;
  101. for (size_t i = 0; i < len; i++)
  102. { bool b = opIndex(i);
  103. result = dg(b);
  104. (*this)[i] = b;
  105. if (result)
  106. break;
  107. }
  108. return result;
  109. }
  110. /** ditto */
  111. int opApply(int delegate(inout size_t, inout bool) dg)
  112. {
  113. int result;
  114. for (size_t i = 0; i < len; i++)
  115. { bool b = opIndex(i);
  116. result = dg(i, b);
  117. (*this)[i] = b;
  118. if (result)
  119. break;
  120. }
  121. return result;
  122. }
  123. unittest
  124. {
  125. debug(bitarray) printf("BitArray.opApply unittest\n");
  126. static bool[] ba = [1,0,1];
  127. BitArray a; a.init(ba);
  128. int i;
  129. foreach (b;a)
  130. {
  131. switch (i)
  132. { case 0: assert(b == true); break;
  133. case 1: assert(b == false); break;
  134. case 2: assert(b == true); break;
  135. default: assert(0);
  136. }
  137. i++;
  138. }
  139. foreach (j,b;a)
  140. {
  141. switch (j)
  142. { case 0: assert(b == true); break;
  143. case 1: assert(b == false); break;
  144. case 2: assert(b == true); break;
  145. default: assert(0);
  146. }
  147. }
  148. }
  149. /**********************************************
  150. * Support for array.reverse property for BitArray.
  151. */
  152. BitArray reverse()
  153. out (result)
  154. {
  155. assert(result == *this);
  156. }
  157. body
  158. {
  159. if (len >= 2)
  160. {
  161. bool t;
  162. size_t lo, hi;
  163. lo = 0;
  164. hi = len - 1;
  165. for (; lo < hi; lo++, hi--)
  166. {
  167. t = (*this)[lo];
  168. (*this)[lo] = (*this)[hi];
  169. (*this)[hi] = t;
  170. }
  171. }
  172. return *this;
  173. }
  174. unittest
  175. {
  176. debug(bitarray) printf("BitArray.reverse.unittest\n");
  177. BitArray b;
  178. static bool[5] data = [1,0,1,1,0];
  179. int i;
  180. b.init(data);
  181. b.reverse;
  182. for (i = 0; i < data.length; i++)
  183. {
  184. assert(b[i] == data[4 - i]);
  185. }
  186. }
  187. /**********************************************
  188. * Support for array.sort property for BitArray.
  189. */
  190. BitArray sort()
  191. out (result)
  192. {
  193. assert(result == *this);
  194. }
  195. body
  196. {
  197. if (len >= 2)
  198. {
  199. size_t lo, hi;
  200. lo = 0;
  201. hi = len - 1;
  202. while (1)
  203. {
  204. while (1)
  205. {
  206. if (lo >= hi)
  207. goto Ldone;
  208. if ((*this)[lo] == true)
  209. break;
  210. lo++;
  211. }
  212. while (1)
  213. {
  214. if (lo >= hi)
  215. goto Ldone;
  216. if ((*this)[hi] == false)
  217. break;
  218. hi--;
  219. }
  220. (*this)[lo] = false;
  221. (*this)[hi] = true;
  222. lo++;
  223. hi--;
  224. }
  225. Ldone:
  226. ;
  227. }
  228. return *this;
  229. }
  230. unittest
  231. {
  232. debug(bitarray) printf("BitArray.sort.unittest\n");
  233. static size_t x = 0b1100011000;
  234. static BitArray ba = { 10, &x };
  235. ba.sort;
  236. for (size_t i = 0; i < 6; i++)
  237. assert(ba[i] == false);
  238. for (size_t i = 6; i < 10; i++)
  239. assert(ba[i] == true);
  240. }
  241. /***************************************
  242. * Support for operators == and != for bit arrays.
  243. */
  244. int opEquals(BitArray a2)
  245. { size_t i;
  246. if (this.length != a2.length)
  247. return 0; // not equal
  248. byte *p1 = cast(byte*)this.ptr;
  249. byte *p2 = cast(byte*)a2.ptr;
  250. auto n = this.length / 8;
  251. for (i = 0; i < n; i++)
  252. {
  253. if (p1[i] != p2[i])
  254. return 0; // not equal
  255. }
  256. n = this.length & 7;
  257. auto mask = cast(ubyte)((1 << n) - 1);
  258. //printf("i = %d, n = %d, mask = %x, %x, %x\n", i, n, mask, p1[i], p2[i]);
  259. return (mask == 0) || (p1[i] & mask) == (p2[i] & mask);
  260. }
  261. unittest
  262. {
  263. debug(bitarray) printf("BitArray.opEquals unittest\n");
  264. static bool[] ba = [1,0,1,0,1];
  265. static bool[] bb = [1,0,1];
  266. static bool[] bc = [1,0,1,0,1,0,1];
  267. static bool[] bd = [1,0,1,1,1];
  268. static bool[] be = [1,0,1,0,1];
  269. BitArray a; a.init(ba);
  270. BitArray b; b.init(bb);
  271. BitArray c; c.init(bc);
  272. BitArray d; d.init(bd);
  273. BitArray e; e.init(be);
  274. assert(a != b);
  275. assert(a != c);
  276. assert(a != d);
  277. assert(a == e);
  278. }
  279. /***************************************
  280. * Implement comparison operators.
  281. */
  282. int opCmp(BitArray a2)
  283. {
  284. size_t i;
  285. auto len = this.length;
  286. if (a2.length < len)
  287. len = a2.length;
  288. auto p1 = cast(ubyte*)this.ptr;
  289. auto p2 = cast(ubyte*)a2.ptr;
  290. auto n = len / 8;
  291. for (i = 0; i < n; i++)
  292. {
  293. if (p1[i] != p2[i])
  294. break; // not equal
  295. }
  296. for (auto j = i * 8; j < len; j++)
  297. { auto mask = cast(ubyte)(1 << j);
  298. auto c = cast(int)(p1[i] & mask) - cast(int)(p2[i] & mask);
  299. if (c)
  300. return c;
  301. }
  302. version (D_LP64)
  303. {
  304. long c = this.len - a2.length;
  305. if (c < 0)
  306. return -1;
  307. else
  308. return c != 0;
  309. }
  310. else
  311. return cast(int)this.len - cast(int)a2.length;
  312. }
  313. unittest
  314. {
  315. debug(bitarray) printf("BitArray.opCmp unittest\n");
  316. static bool[] ba = [1,0,1,0,1];
  317. static bool[] bb = [1,0,1];
  318. static bool[] bc = [1,0,1,0,1,0,1];
  319. static bool[] bd = [1,0,1,1,1];
  320. static bool[] be = [1,0,1,0,1];
  321. BitArray a; a.init(ba);
  322. BitArray b; b.init(bb);
  323. BitArray c; c.init(bc);
  324. BitArray d; d.init(bd);
  325. BitArray e; e.init(be);
  326. assert(a > b);
  327. assert(a >= b);
  328. assert(a < c);
  329. assert(a <= c);
  330. assert(a < d);
  331. assert(a <= d);
  332. assert(a == e);
  333. assert(a <= e);
  334. assert(a >= e);
  335. }
  336. /***************************************
  337. * Set BitArray to contents of ba[]
  338. */
  339. void init(bool[] ba)
  340. {
  341. length = ba.length;
  342. foreach (i, b; ba)
  343. {
  344. (*this)[i] = b;
  345. }
  346. }
  347. /***************************************
  348. * Map BitArray onto v[], with numbits being the number of bits
  349. * in the array. Does not copy the data.
  350. *
  351. * This is the inverse of opCast.
  352. */
  353. void init(void[] v, size_t numbits)
  354. in
  355. {
  356. assert(numbits <= v.length * 8);
  357. assert((v.length & 3) == 0);
  358. }
  359. body
  360. {
  361. ptr = cast(typeof(ptr))v.ptr;
  362. len = numbits;
  363. }
  364. unittest
  365. {
  366. debug(bitarray) printf("BitArray.init unittest\n");
  367. static bool[] ba = [1,0,1,0,1];
  368. BitArray a; a.init(ba);
  369. BitArray b;
  370. void[] v;
  371. v = cast(void[])a;
  372. b.init(v, a.length);
  373. assert(b[0] == 1);
  374. assert(b[1] == 0);
  375. assert(b[2] == 1);
  376. assert(b[3] == 0);
  377. assert(b[4] == 1);
  378. a[0] = 0;
  379. assert(b[0] == 0);
  380. assert(a == b);
  381. }
  382. /***************************************
  383. * Convert to void[].
  384. */
  385. void[] opCast()
  386. {
  387. return cast(void[])ptr[0 .. dim];
  388. }
  389. unittest
  390. {
  391. debug(bitarray) printf("BitArray.opCast unittest\n");
  392. static bool[] ba = [1,0,1,0,1];
  393. BitArray a; a.init(ba);
  394. void[] v = cast(void[])a;
  395. assert(v.length == a.dim * size_t.sizeof);
  396. }
  397. /***************************************
  398. * Support for unary operator ~ for bit arrays.
  399. */
  400. BitArray opCom()
  401. {
  402. auto dim = this.dim();
  403. BitArray result;
  404. result.length = len;
  405. for (size_t i = 0; i < dim; i++)
  406. result.ptr[i] = ~this.ptr[i];
  407. if (len & 31)
  408. result.ptr[dim - 1] &= ~(~0 << (len & 31));
  409. return result;
  410. }
  411. unittest
  412. {
  413. debug(bitarray) printf("BitArray.opCom unittest\n");
  414. static bool[] ba = [1,0,1,0,1];
  415. BitArray a; a.init(ba);
  416. BitArray b = ~a;
  417. assert(b[0] == 0);
  418. assert(b[1] == 1);
  419. assert(b[2] == 0);
  420. assert(b[3] == 1);
  421. assert(b[4] == 0);
  422. }
  423. /***************************************
  424. * Support for binary operator & for bit arrays.
  425. */
  426. BitArray opAnd(BitArray e2)
  427. in
  428. {
  429. assert(len == e2.length);
  430. }
  431. body
  432. {
  433. auto dim = this.dim();
  434. BitArray result;
  435. result.length = len;
  436. for (size_t i = 0; i < dim; i++)
  437. result.ptr[i] = this.ptr[i] & e2.ptr[i];
  438. return result;
  439. }
  440. unittest
  441. {
  442. debug(bitarray) printf("BitArray.opAnd unittest\n");
  443. static bool[] ba = [1,0,1,0,1];
  444. static bool[] bb = [1,0,1,1,0];
  445. BitArray a; a.init(ba);
  446. BitArray b; b.init(bb);
  447. BitArray c = a & b;
  448. assert(c[0] == 1);
  449. assert(c[1] == 0);
  450. assert(c[2] == 1);
  451. assert(c[3] == 0);
  452. assert(c[4] == 0);
  453. }
  454. /***************************************
  455. * Support for binary operator | for bit arrays.
  456. */
  457. BitArray opOr(BitArray e2)
  458. in
  459. {
  460. assert(len == e2.length);
  461. }
  462. body
  463. {
  464. auto dim = this.dim();
  465. BitArray result;
  466. result.length = len;
  467. for (size_t i = 0; i < dim; i++)
  468. result.ptr[i] = this.ptr[i] | e2.ptr[i];
  469. return result;
  470. }
  471. unittest
  472. {
  473. debug(bitarray) printf("BitArray.opOr unittest\n");
  474. static bool[] ba = [1,0,1,0,1];
  475. static bool[] bb = [1,0,1,1,0];
  476. BitArray a; a.init(ba);
  477. BitArray b; b.init(bb);
  478. BitArray c = a | b;
  479. assert(c[0] == 1);
  480. assert(c[1] == 0);
  481. assert(c[2] == 1);
  482. assert(c[3] == 1);
  483. assert(c[4] == 1);
  484. }
  485. /***************************************
  486. * Support for binary operator ^ for bit arrays.
  487. */
  488. BitArray opXor(BitArray e2)
  489. in
  490. {
  491. assert(len == e2.length);
  492. }
  493. body
  494. {
  495. auto dim = this.dim();
  496. BitArray result;
  497. result.length = len;
  498. for (size_t i = 0; i < dim; i++)
  499. result.ptr[i] = this.ptr[i] ^ e2.ptr[i];
  500. return result;
  501. }
  502. unittest
  503. {
  504. debug(bitarray) printf("BitArray.opXor unittest\n");
  505. static bool[] ba = [1,0,1,0,1];
  506. static bool[] bb = [1,0,1,1,0];
  507. BitArray a; a.init(ba);
  508. BitArray b; b.init(bb);
  509. BitArray c = a ^ b;
  510. assert(c[0] == 0);
  511. assert(c[1] == 0);
  512. assert(c[2] == 0);
  513. assert(c[3] == 1);
  514. assert(c[4] == 1);
  515. }
  516. /***************************************
  517. * Support for binary operator - for bit arrays.
  518. *
  519. * $(I a - b) for BitArrays means the same thing as $(I a &amp; ~b).
  520. */
  521. BitArray opSub(BitArray e2)
  522. in
  523. {
  524. assert(len == e2.length);
  525. }
  526. body
  527. {
  528. auto dim = this.dim();
  529. BitArray result;
  530. result.length = len;
  531. for (size_t i = 0; i < dim; i++)
  532. result.ptr[i] = this.ptr[i] & ~e2.ptr[i];
  533. return result;
  534. }
  535. unittest
  536. {
  537. debug(bitarray) printf("BitArray.opSub unittest\n");
  538. static bool[] ba = [1,0,1,0,1];
  539. static bool[] bb = [1,0,1,1,0];
  540. BitArray a; a.init(ba);
  541. BitArray b; b.init(bb);
  542. BitArray c = a - b;
  543. assert(c[0] == 0);
  544. assert(c[1] == 0);
  545. assert(c[2] == 0);
  546. assert(c[3] == 0);
  547. assert(c[4] == 1);
  548. }
  549. /***************************************
  550. * Support for operator &= bit arrays.
  551. */
  552. BitArray opAndAssign(BitArray e2)
  553. in
  554. {
  555. assert(len == e2.length);
  556. }
  557. body
  558. {
  559. auto dim = this.dim();
  560. for (size_t i = 0; i < dim; i++)
  561. ptr[i] &= e2.ptr[i];
  562. return *this;
  563. }
  564. unittest
  565. {
  566. debug(bitarray) printf("BitArray.opAndAssign unittest\n");
  567. static bool[] ba = [1,0,1,0,1];
  568. static bool[] bb = [1,0,1,1,0];
  569. BitArray a; a.init(ba);
  570. BitArray b; b.init(bb);
  571. a &= b;
  572. assert(a[0] == 1);
  573. assert(a[1] == 0);
  574. assert(a[2] == 1);
  575. assert(a[3] == 0);
  576. assert(a[4] == 0);
  577. }
  578. /***************************************
  579. * Support for operator |= for bit arrays.
  580. */
  581. BitArray opOrAssign(BitArray e2)
  582. in
  583. {
  584. assert(len == e2.length);
  585. }
  586. body
  587. {
  588. auto dim = this.dim();
  589. for (size_t i = 0; i < dim; i++)
  590. ptr[i] |= e2.ptr[i];
  591. return *this;
  592. }
  593. unittest
  594. {
  595. debug(bitarray) printf("BitArray.opOrAssign unittest\n");
  596. static bool[] ba = [1,0,1,0,1];
  597. static bool[] bb = [1,0,1,1,0];
  598. BitArray a; a.init(ba);
  599. BitArray b; b.init(bb);
  600. a |= b;
  601. assert(a[0] == 1);
  602. assert(a[1] == 0);
  603. assert(a[2] == 1);
  604. assert(a[3] == 1);
  605. assert(a[4] == 1);
  606. }
  607. /***************************************
  608. * Support for operator ^= for bit arrays.
  609. */
  610. BitArray opXorAssign(BitArray e2)
  611. in
  612. {
  613. assert(len == e2.length);
  614. }
  615. body
  616. {
  617. auto dim = this.dim();
  618. for (size_t i = 0; i < dim; i++)
  619. ptr[i] ^= e2.ptr[i];
  620. return *this;
  621. }
  622. unittest
  623. {
  624. debug(bitarray) printf("BitArray.opXorAssign unittest\n");
  625. static bool[] ba = [1,0,1,0,1];
  626. static bool[] bb = [1,0,1,1,0];
  627. BitArray a; a.init(ba);
  628. BitArray b; b.init(bb);
  629. a ^= b;
  630. assert(a[0] == 0);
  631. assert(a[1] == 0);
  632. assert(a[2] == 0);
  633. assert(a[3] == 1);
  634. assert(a[4] == 1);
  635. }
  636. /***************************************
  637. * Support for operator -= for bit arrays.
  638. *
  639. * $(I a -= b) for BitArrays means the same thing as $(I a &amp;= ~b).
  640. */
  641. BitArray opSubAssign(BitArray e2)
  642. in
  643. {
  644. assert(len == e2.length);
  645. }
  646. body
  647. {
  648. auto dim = this.dim();
  649. for (size_t i = 0; i < dim; i++)
  650. ptr[i] &= ~e2.ptr[i];
  651. return *this;
  652. }
  653. unittest
  654. {
  655. debug(bitarray) printf("BitArray.opSubAssign unittest\n");
  656. static bool[] ba = [1,0,1,0,1];
  657. static bool[] bb = [1,0,1,1,0];
  658. BitArray a; a.init(ba);
  659. BitArray b; b.init(bb);
  660. a -= b;
  661. assert(a[0] == 0);
  662. assert(a[1] == 0);
  663. assert(a[2] == 0);
  664. assert(a[3] == 0);
  665. assert(a[4] == 1);
  666. }
  667. /***************************************
  668. * Support for operator ~= for bit arrays.
  669. */
  670. BitArray opCatAssign(bool b)
  671. {
  672. length = len + 1;
  673. (*this)[len - 1] = b;
  674. return *this;
  675. }
  676. unittest
  677. {
  678. debug(bitarray) printf("BitArray.opCatAssign unittest\n");
  679. static bool[] ba = [1,0,1,0,1];
  680. BitArray a; a.init(ba);
  681. BitArray b;
  682. b = (a ~= true);
  683. assert(a[0] == 1);
  684. assert(a[1] == 0);
  685. assert(a[2] == 1);
  686. assert(a[3] == 0);
  687. assert(a[4] == 1);
  688. assert(a[5] == 1);
  689. assert(b == a);
  690. }
  691. /***************************************
  692. * ditto
  693. */
  694. BitArray opCatAssign(BitArray b)
  695. {
  696. auto istart = len;
  697. length = len + b.length;
  698. for (auto i = istart; i < len; i++)
  699. (*this)[i] = b[i - istart];
  700. return *this;
  701. }
  702. unittest
  703. {
  704. debug(bitarray) printf("BitArray.opCatAssign unittest\n");
  705. static bool[] ba = [1,0];
  706. static bool[] bb = [0,1,0];
  707. BitArray a; a.init(ba);
  708. BitArray b; b.init(bb);
  709. BitArray c;
  710. c = (a ~= b);
  711. assert(a.length == 5);
  712. assert(a[0] == 1);
  713. assert(a[1] == 0);
  714. assert(a[2] == 0);
  715. assert(a[3] == 1);
  716. assert(a[4] == 0);
  717. assert(c == a);
  718. }
  719. /***************************************
  720. * Support for binary operator ~ for bit arrays.
  721. */
  722. BitArray opCat(bool b)
  723. {
  724. auto r = this.dup;
  725. r.length = len + 1;
  726. r[len] = b;
  727. return r;
  728. }
  729. /** ditto */
  730. BitArray opCat_r(bool b)
  731. {
  732. BitArray r;
  733. r.length = len + 1;
  734. r[0] = b;
  735. for (size_t i = 0; i < len; i++)
  736. r[1 + i] = (*this)[i];
  737. return r;
  738. }
  739. /** ditto */
  740. BitArray opCat(BitArray b)
  741. {
  742. BitArray r;
  743. r = this.dup();
  744. r ~= b;
  745. return r;
  746. }
  747. unittest
  748. {
  749. debug(bitarray) printf("BitArray.opCat unittest\n");
  750. static bool[] ba = [1,0];
  751. static bool[] bb = [0,1,0];
  752. BitArray a; a.init(ba);
  753. BitArray b; b.init(bb);
  754. BitArray c;
  755. c = (a ~ b);
  756. assert(c.length == 5);
  757. assert(c[0] == 1);
  758. assert(c[1] == 0);
  759. assert(c[2] == 0);
  760. assert(c[3] == 1);
  761. assert(c[4] == 0);
  762. c = (a ~ true);
  763. assert(c.length == 3);
  764. assert(c[0] == 1);
  765. assert(c[1] == 0);
  766. assert(c[2] == 1);
  767. c = (false ~ a);
  768. assert(c.length == 3);
  769. assert(c[0] == 0);
  770. assert(c[1] == 1);
  771. assert(c[2] == 0);
  772. }
  773. }