PageRenderTime 31ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/lphobos/std/bitarray.d

https://bitbucket.org/lindquist/ldc/
D | 955 lines | 687 code | 171 blank | 97 comment | 165 complexity | 55894e8bea19e11a61ce794133fdfad3 MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0
  1. /***********************
  2. * Macros:
  3. * WIKI = StdBitarray
  4. */
  5. module std.bitarray;
  6. //debug = bitarray; // uncomment to turn on debugging printf's
  7. private import std.intrinsic;
  8. /**
  9. * An array of bits.
  10. */
  11. struct BitArray
  12. {
  13. size_t len;
  14. uint* ptr;
  15. size_t dim()
  16. {
  17. return (len + 31) / 32;
  18. }
  19. size_t length()
  20. {
  21. return len;
  22. }
  23. void length(size_t newlen)
  24. {
  25. if (newlen != len)
  26. {
  27. size_t olddim = dim();
  28. size_t newdim = (newlen + 31) / 32;
  29. if (newdim != olddim)
  30. {
  31. // Create a fake array so we can use D's realloc machinery
  32. uint[] b = ptr[0 .. olddim];
  33. b.length = newdim; // realloc
  34. ptr = b.ptr;
  35. if (newdim & 31)
  36. { // Set any pad bits to 0
  37. ptr[newdim - 1] &= ~(~0 << (newdim & 31));
  38. }
  39. }
  40. len = newlen;
  41. }
  42. }
  43. /**********************************************
  44. * Support for [$(I index)] operation for BitArray.
  45. */
  46. bool opIndex(size_t i)
  47. in
  48. {
  49. assert(i < len);
  50. }
  51. body
  52. {
  53. return cast(bool)bt(ptr, i);
  54. }
  55. /** ditto */
  56. bool opIndexAssign(bool b, size_t i)
  57. in
  58. {
  59. assert(i < len);
  60. }
  61. body
  62. {
  63. if (b)
  64. bts(ptr, i);
  65. else
  66. btr(ptr, i);
  67. return b;
  68. }
  69. /**********************************************
  70. * Support for array.dup property for BitArray.
  71. */
  72. BitArray dup()
  73. {
  74. BitArray ba;
  75. uint[] b = ptr[0 .. dim].dup;
  76. ba.len = len;
  77. ba.ptr = b.ptr;
  78. return ba;
  79. }
  80. unittest
  81. {
  82. BitArray a;
  83. BitArray b;
  84. int i;
  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 (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 uint 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. uint *p1 = cast(uint*)this.ptr;
  249. uint *p2 = cast(uint*)a2.ptr;
  250. size_t n = this.length / (8 * uint.sizeof);
  251. for (i = 0; i < n; i++)
  252. {
  253. if (p1[i] != p2[i])
  254. return 0; // not equal
  255. }
  256. uint mask;
  257. n = this.length & ((8 * uint.sizeof) - 1);
  258. mask = (1 << n) - 1;
  259. //printf("i = %d, n = %d, mask = %x, %x, %x\n", i, n, mask, p1[i], p2[i]);
  260. return (mask == 0) || (p1[i] & mask) == (p2[i] & mask);
  261. }
  262. unittest
  263. {
  264. debug(bitarray) printf("BitArray.opEquals unittest\n");
  265. static bool[] ba = [1,0,1,0,1];
  266. static bool[] bb = [1,0,1];
  267. static bool[] bc = [1,0,1,0,1,0,1];
  268. static bool[] bd = [1,0,1,1,1];
  269. static bool[] be = [1,0,1,0,1];
  270. BitArray a; a.init(ba);
  271. BitArray b; b.init(bb);
  272. BitArray c; c.init(bc);
  273. BitArray d; d.init(bd);
  274. BitArray e; e.init(be);
  275. assert(a != b);
  276. assert(a != c);
  277. assert(a != d);
  278. assert(a == e);
  279. }
  280. /***************************************
  281. * Implement comparison operators.
  282. */
  283. int opCmp(BitArray a2)
  284. {
  285. size_t len;
  286. size_t i;
  287. len = this.length;
  288. if (a2.length < len)
  289. len = a2.length;
  290. uint* p1 = cast(uint*)this.ptr;
  291. uint* p2 = cast(uint*)a2.ptr;
  292. size_t n = len / (8 * uint.sizeof);
  293. for (i = 0; i < n; i++)
  294. {
  295. if (p1[i] != p2[i])
  296. break; // not equal
  297. }
  298. /*
  299. for (uint j = i * 8; j < len; j++)
  300. { ubyte mask = cast(ubyte)(1 << j);
  301. int c;
  302. c = cast(int)(p1[i] & mask) - cast(int)(p2[i] & mask);
  303. if (c)
  304. return c;
  305. }
  306. */
  307. uint mask = 1;
  308. for (size_t j = i * (8 * uint.sizeof); j < len; j++)
  309. { int c;
  310. c = cast(int)(p1[i] & mask) - cast(int)(p2[i] & mask);
  311. if (c)
  312. return c;
  313. mask <<= 1;
  314. }
  315. ptrdiff_t c = cast(ptrdiff_t)this.len - cast(ptrdiff_t)a2.length;
  316. if (c < 0)
  317. return -1;
  318. else if (c > 0)
  319. return 1;
  320. return 0;
  321. }
  322. unittest
  323. {
  324. debug(bitarray) printf("BitArray.opCmp unittest\n");
  325. static bool[] ba = [1,0,1,0,1];
  326. static bool[] bb = [1,0,1];
  327. static bool[] bc = [1,0,1,0,1,0,1];
  328. static bool[] bd = [1,0,1,1,1];
  329. static bool[] be = [1,0,1,0,1];
  330. BitArray a; a.init(ba);
  331. BitArray b; b.init(bb);
  332. BitArray c; c.init(bc);
  333. BitArray d; d.init(bd);
  334. BitArray e; e.init(be);
  335. assert(a > b);
  336. assert(a >= b);
  337. assert(a < c);
  338. assert(a <= c);
  339. assert(a < d);
  340. assert(a <= d);
  341. assert(a == e);
  342. assert(a <= e);
  343. assert(a >= e);
  344. }
  345. /***************************************
  346. * Set BitArray to contents of ba[]
  347. */
  348. void init(bool[] ba)
  349. {
  350. length = ba.length;
  351. foreach (i, b; ba)
  352. {
  353. (*this)[i] = b;
  354. }
  355. }
  356. /***************************************
  357. * Map BitArray onto v[], with numbits being the number of bits
  358. * in the array. Does not copy the data.
  359. *
  360. * This is the inverse of opCast.
  361. */
  362. void init(void[] v, size_t numbits)
  363. in
  364. {
  365. assert(numbits <= v.length * 8);
  366. assert((v.length & 3) == 0);
  367. }
  368. body
  369. {
  370. ptr = cast(uint*)v.ptr;
  371. len = numbits;
  372. }
  373. unittest
  374. {
  375. debug(bitarray) printf("BitArray.init unittest\n");
  376. static bool[] ba = [1,0,1,0,1];
  377. BitArray a; a.init(ba);
  378. BitArray b;
  379. void[] v;
  380. v = cast(void[])a;
  381. b.init(v, a.length);
  382. assert(b[0] == 1);
  383. assert(b[1] == 0);
  384. assert(b[2] == 1);
  385. assert(b[3] == 0);
  386. assert(b[4] == 1);
  387. a[0] = 0;
  388. assert(b[0] == 0);
  389. assert(a == b);
  390. }
  391. /***************************************
  392. * Convert to void[].
  393. */
  394. void[] opCast()
  395. {
  396. return cast(void[])ptr[0 .. dim];
  397. }
  398. unittest
  399. {
  400. debug(bitarray) printf("BitArray.opCast unittest\n");
  401. static bool[] ba = [1,0,1,0,1];
  402. BitArray a; a.init(ba);
  403. void[] v = cast(void[])a;
  404. assert(v.length == a.dim * uint.sizeof);
  405. }
  406. /***************************************
  407. * Support for unary operator ~ for bit arrays.
  408. */
  409. BitArray opCom()
  410. {
  411. auto dim = this.dim();
  412. BitArray result;
  413. result.length = len;
  414. for (size_t i = 0; i < dim; i++)
  415. result.ptr[i] = ~this.ptr[i];
  416. if (len & 31)
  417. result.ptr[dim - 1] &= ~(~0 << (len & 31));
  418. return result;
  419. }
  420. unittest
  421. {
  422. debug(bitarray) printf("BitArray.opCom unittest\n");
  423. static bool[] ba = [1,0,1,0,1];
  424. BitArray a; a.init(ba);
  425. BitArray b = ~a;
  426. assert(b[0] == 0);
  427. assert(b[1] == 1);
  428. assert(b[2] == 0);
  429. assert(b[3] == 1);
  430. assert(b[4] == 0);
  431. }
  432. /***************************************
  433. * Support for binary operator & for bit arrays.
  434. */
  435. BitArray opAnd(BitArray e2)
  436. in
  437. {
  438. assert(len == e2.length);
  439. }
  440. body
  441. {
  442. auto dim = this.dim();
  443. BitArray result;
  444. result.length = len;
  445. for (size_t i = 0; i < dim; i++)
  446. result.ptr[i] = this.ptr[i] & e2.ptr[i];
  447. return result;
  448. }
  449. unittest
  450. {
  451. debug(bitarray) printf("BitArray.opAnd unittest\n");
  452. static bool[] ba = [1,0,1,0,1];
  453. static bool[] bb = [1,0,1,1,0];
  454. BitArray a; a.init(ba);
  455. BitArray b; b.init(bb);
  456. BitArray c = a & b;
  457. assert(c[0] == 1);
  458. assert(c[1] == 0);
  459. assert(c[2] == 1);
  460. assert(c[3] == 0);
  461. assert(c[4] == 0);
  462. }
  463. /***************************************
  464. * Support for binary operator | for bit arrays.
  465. */
  466. BitArray opOr(BitArray e2)
  467. in
  468. {
  469. assert(len == e2.length);
  470. }
  471. body
  472. {
  473. auto dim = this.dim();
  474. BitArray result;
  475. result.length = len;
  476. for (size_t i = 0; i < dim; i++)
  477. result.ptr[i] = this.ptr[i] | e2.ptr[i];
  478. return result;
  479. }
  480. unittest
  481. {
  482. debug(bitarray) printf("BitArray.opOr unittest\n");
  483. static bool[] ba = [1,0,1,0,1];
  484. static bool[] bb = [1,0,1,1,0];
  485. BitArray a; a.init(ba);
  486. BitArray b; b.init(bb);
  487. BitArray c = a | b;
  488. assert(c[0] == 1);
  489. assert(c[1] == 0);
  490. assert(c[2] == 1);
  491. assert(c[3] == 1);
  492. assert(c[4] == 1);
  493. }
  494. /***************************************
  495. * Support for binary operator ^ for bit arrays.
  496. */
  497. BitArray opXor(BitArray e2)
  498. in
  499. {
  500. assert(len == e2.length);
  501. }
  502. body
  503. {
  504. auto dim = this.dim();
  505. BitArray result;
  506. result.length = len;
  507. for (size_t i = 0; i < dim; i++)
  508. result.ptr[i] = this.ptr[i] ^ e2.ptr[i];
  509. return result;
  510. }
  511. unittest
  512. {
  513. debug(bitarray) printf("BitArray.opXor unittest\n");
  514. static bool[] ba = [1,0,1,0,1];
  515. static bool[] bb = [1,0,1,1,0];
  516. BitArray a; a.init(ba);
  517. BitArray b; b.init(bb);
  518. BitArray c = a ^ b;
  519. assert(c[0] == 0);
  520. assert(c[1] == 0);
  521. assert(c[2] == 0);
  522. assert(c[3] == 1);
  523. assert(c[4] == 1);
  524. }
  525. /***************************************
  526. * Support for binary operator - for bit arrays.
  527. *
  528. * $(I a - b) for BitArrays means the same thing as $(I a &amp; ~b).
  529. */
  530. BitArray opSub(BitArray e2)
  531. in
  532. {
  533. assert(len == e2.length);
  534. }
  535. body
  536. {
  537. auto dim = this.dim();
  538. BitArray result;
  539. result.length = len;
  540. for (size_t i = 0; i < dim; i++)
  541. result.ptr[i] = this.ptr[i] & ~e2.ptr[i];
  542. return result;
  543. }
  544. unittest
  545. {
  546. debug(bitarray) printf("BitArray.opSub unittest\n");
  547. static bool[] ba = [1,0,1,0,1];
  548. static bool[] bb = [1,0,1,1,0];
  549. BitArray a; a.init(ba);
  550. BitArray b; b.init(bb);
  551. BitArray c = a - b;
  552. assert(c[0] == 0);
  553. assert(c[1] == 0);
  554. assert(c[2] == 0);
  555. assert(c[3] == 0);
  556. assert(c[4] == 1);
  557. }
  558. /***************************************
  559. * Support for operator &= bit arrays.
  560. */
  561. BitArray opAndAssign(BitArray e2)
  562. in
  563. {
  564. assert(len == e2.length);
  565. }
  566. body
  567. {
  568. auto dim = this.dim();
  569. for (size_t i = 0; i < dim; i++)
  570. ptr[i] &= e2.ptr[i];
  571. return *this;
  572. }
  573. unittest
  574. {
  575. debug(bitarray) printf("BitArray.opAndAssign unittest\n");
  576. static bool[] ba = [1,0,1,0,1];
  577. static bool[] bb = [1,0,1,1,0];
  578. BitArray a; a.init(ba);
  579. BitArray b; b.init(bb);
  580. a &= b;
  581. assert(a[0] == 1);
  582. assert(a[1] == 0);
  583. assert(a[2] == 1);
  584. assert(a[3] == 0);
  585. assert(a[4] == 0);
  586. }
  587. /***************************************
  588. * Support for operator |= for bit arrays.
  589. */
  590. BitArray opOrAssign(BitArray e2)
  591. in
  592. {
  593. assert(len == e2.length);
  594. }
  595. body
  596. {
  597. auto dim = this.dim();
  598. for (size_t i = 0; i < dim; i++)
  599. ptr[i] |= e2.ptr[i];
  600. return *this;
  601. }
  602. unittest
  603. {
  604. debug(bitarray) printf("BitArray.opOrAssign unittest\n");
  605. static bool[] ba = [1,0,1,0,1];
  606. static bool[] bb = [1,0,1,1,0];
  607. BitArray a; a.init(ba);
  608. BitArray b; b.init(bb);
  609. a |= b;
  610. assert(a[0] == 1);
  611. assert(a[1] == 0);
  612. assert(a[2] == 1);
  613. assert(a[3] == 1);
  614. assert(a[4] == 1);
  615. }
  616. /***************************************
  617. * Support for operator ^= for bit arrays.
  618. */
  619. BitArray opXorAssign(BitArray e2)
  620. in
  621. {
  622. assert(len == e2.length);
  623. }
  624. body
  625. {
  626. auto dim = this.dim();
  627. for (size_t i = 0; i < dim; i++)
  628. ptr[i] ^= e2.ptr[i];
  629. return *this;
  630. }
  631. unittest
  632. {
  633. debug(bitarray) printf("BitArray.opXorAssign unittest\n");
  634. static bool[] ba = [1,0,1,0,1];
  635. static bool[] bb = [1,0,1,1,0];
  636. BitArray a; a.init(ba);
  637. BitArray b; b.init(bb);
  638. a ^= b;
  639. assert(a[0] == 0);
  640. assert(a[1] == 0);
  641. assert(a[2] == 0);
  642. assert(a[3] == 1);
  643. assert(a[4] == 1);
  644. }
  645. /***************************************
  646. * Support for operator -= for bit arrays.
  647. *
  648. * $(I a -= b) for BitArrays means the same thing as $(I a &amp;= ~b).
  649. */
  650. BitArray opSubAssign(BitArray e2)
  651. in
  652. {
  653. assert(len == e2.length);
  654. }
  655. body
  656. {
  657. auto dim = this.dim();
  658. for (size_t i = 0; i < dim; i++)
  659. ptr[i] &= ~e2.ptr[i];
  660. return *this;
  661. }
  662. unittest
  663. {
  664. debug(bitarray) printf("BitArray.opSubAssign unittest\n");
  665. static bool[] ba = [1,0,1,0,1];
  666. static bool[] bb = [1,0,1,1,0];
  667. BitArray a; a.init(ba);
  668. BitArray b; b.init(bb);
  669. a -= b;
  670. assert(a[0] == 0);
  671. assert(a[1] == 0);
  672. assert(a[2] == 0);
  673. assert(a[3] == 0);
  674. assert(a[4] == 1);
  675. }
  676. /***************************************
  677. * Support for operator ~= for bit arrays.
  678. */
  679. BitArray opCatAssign(bool b)
  680. {
  681. length = len + 1;
  682. (*this)[len - 1] = b;
  683. return *this;
  684. }
  685. unittest
  686. {
  687. debug(bitarray) printf("BitArray.opCatAssign unittest\n");
  688. static bool[] ba = [1,0,1,0,1];
  689. BitArray a; a.init(ba);
  690. BitArray b;
  691. b = (a ~= true);
  692. assert(a[0] == 1);
  693. assert(a[1] == 0);
  694. assert(a[2] == 1);
  695. assert(a[3] == 0);
  696. assert(a[4] == 1);
  697. assert(a[5] == 1);
  698. assert(b == a);
  699. }
  700. /***************************************
  701. * ditto
  702. */
  703. BitArray opCatAssign(BitArray b)
  704. {
  705. auto istart = len;
  706. length = len + b.length;
  707. for (auto i = istart; i < len; i++)
  708. (*this)[i] = b[i - istart];
  709. return *this;
  710. }
  711. unittest
  712. {
  713. debug(bitarray) printf("BitArray.opCatAssign unittest\n");
  714. static bool[] ba = [1,0];
  715. static bool[] bb = [0,1,0];
  716. BitArray a; a.init(ba);
  717. BitArray b; b.init(bb);
  718. BitArray c;
  719. c = (a ~= b);
  720. assert(a.length == 5);
  721. assert(a[0] == 1);
  722. assert(a[1] == 0);
  723. assert(a[2] == 0);
  724. assert(a[3] == 1);
  725. assert(a[4] == 0);
  726. assert(c == a);
  727. }
  728. /***************************************
  729. * Support for binary operator ~ for bit arrays.
  730. */
  731. BitArray opCat(bool b)
  732. {
  733. BitArray r;
  734. r = this.dup;
  735. r.length = len + 1;
  736. r[len] = b;
  737. return r;
  738. }
  739. /** ditto */
  740. BitArray opCat_r(bool b)
  741. {
  742. BitArray r;
  743. r.length = len + 1;
  744. r[0] = b;
  745. for (size_t i = 0; i < len; i++)
  746. r[1 + i] = (*this)[i];
  747. return r;
  748. }
  749. /** ditto */
  750. BitArray opCat(BitArray b)
  751. {
  752. BitArray r;
  753. r = this.dup();
  754. r ~= b;
  755. return r;
  756. }
  757. unittest
  758. {
  759. debug(bitarray) printf("BitArray.opCat unittest\n");
  760. static bool[] ba = [1,0];
  761. static bool[] bb = [0,1,0];
  762. BitArray a; a.init(ba);
  763. BitArray b; b.init(bb);
  764. BitArray c;
  765. c = (a ~ b);
  766. assert(c.length == 5);
  767. assert(c[0] == 1);
  768. assert(c[1] == 0);
  769. assert(c[2] == 0);
  770. assert(c[3] == 1);
  771. assert(c[4] == 0);
  772. c = (a ~ true);
  773. assert(c.length == 3);
  774. assert(c[0] == 1);
  775. assert(c[1] == 0);
  776. assert(c[2] == 1);
  777. c = (false ~ a);
  778. assert(c.length == 3);
  779. assert(c[0] == 0);
  780. assert(c[1] == 1);
  781. assert(c[2] == 0);
  782. }
  783. }