bitvectors.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895
  1. /* Copyright 1995-1998,2000-2006,2009-2014,2018
  2. Free Software Foundation, Inc.
  3. This file is part of Guile.
  4. Guile is free software: you can redistribute it and/or modify it
  5. under the terms of the GNU Lesser General Public License as published
  6. by the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. Guile is distributed in the hope that it will be useful, but WITHOUT
  9. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10. FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
  11. License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with Guile. If not, see
  14. <https://www.gnu.org/licenses/>. */
  15. #ifdef HAVE_CONFIG_H
  16. # include <config.h>
  17. #endif
  18. #include <string.h>
  19. #include "array-handle.h"
  20. #include "arrays.h"
  21. #include "boolean.h"
  22. #include "generalized-vectors.h"
  23. #include "gsubr.h"
  24. #include "list.h"
  25. #include "numbers.h"
  26. #include "pairs.h"
  27. #include "ports.h"
  28. #include "srfi-4.h"
  29. #include "bitvectors.h"
  30. /* Bit vectors. Would be nice if they were implemented on top of bytevectors,
  31. * but alack, all we have is this crufty C.
  32. */
  33. #define SCM_F_BITVECTOR_IMMUTABLE (0x800)
  34. #define IS_BITVECTOR(obj) SCM_HAS_TYP11 ((obj), scm_tc11_bitvector)
  35. #define IS_MUTABLE_BITVECTOR(x) \
  36. (SCM_NIMP (x) && \
  37. ((SCM_CELL_TYPE (x) & (0x7ff | SCM_F_BITVECTOR_IMMUTABLE)) \
  38. == scm_tc11_bitvector))
  39. #define BITVECTOR_LENGTH(obj) ((size_t)SCM_CELL_WORD_1(obj))
  40. #define BITVECTOR_BITS(obj) ((uint32_t *)SCM_CELL_WORD_2(obj))
  41. uint32_t *
  42. scm_i_bitvector_bits (SCM vec)
  43. {
  44. if (!IS_BITVECTOR (vec))
  45. abort ();
  46. return BITVECTOR_BITS (vec);
  47. }
  48. int
  49. scm_i_is_mutable_bitvector (SCM vec)
  50. {
  51. return IS_MUTABLE_BITVECTOR (vec);
  52. }
  53. int
  54. scm_i_print_bitvector (SCM vec, SCM port, scm_print_state *pstate)
  55. {
  56. size_t bit_len = BITVECTOR_LENGTH (vec);
  57. size_t word_len = (bit_len+31)/32;
  58. uint32_t *bits = BITVECTOR_BITS (vec);
  59. size_t i, j;
  60. scm_puts ("#*", port);
  61. for (i = 0; i < word_len; i++, bit_len -= 32)
  62. {
  63. uint32_t mask = 1;
  64. for (j = 0; j < 32 && j < bit_len; j++, mask <<= 1)
  65. scm_putc ((bits[i] & mask)? '1' : '0', port);
  66. }
  67. return 1;
  68. }
  69. SCM
  70. scm_i_bitvector_equal_p (SCM vec1, SCM vec2)
  71. {
  72. size_t bit_len = BITVECTOR_LENGTH (vec1);
  73. size_t word_len = (bit_len + 31) / 32;
  74. uint32_t last_mask = ((uint32_t)-1) >> (32*word_len - bit_len);
  75. uint32_t *bits1 = BITVECTOR_BITS (vec1);
  76. uint32_t *bits2 = BITVECTOR_BITS (vec2);
  77. /* compare lengths */
  78. if (BITVECTOR_LENGTH (vec2) != bit_len)
  79. return SCM_BOOL_F;
  80. /* avoid underflow in word_len-1 below. */
  81. if (bit_len == 0)
  82. return SCM_BOOL_T;
  83. /* compare full words */
  84. if (memcmp (bits1, bits2, sizeof (uint32_t) * (word_len-1)))
  85. return SCM_BOOL_F;
  86. /* compare partial last words */
  87. if ((bits1[word_len-1] & last_mask) != (bits2[word_len-1] & last_mask))
  88. return SCM_BOOL_F;
  89. return SCM_BOOL_T;
  90. }
  91. int
  92. scm_is_bitvector (SCM vec)
  93. {
  94. return IS_BITVECTOR (vec);
  95. }
  96. SCM_DEFINE (scm_bitvector_p, "bitvector?", 1, 0, 0,
  97. (SCM obj),
  98. "Return @code{#t} when @var{obj} is a bitvector, else\n"
  99. "return @code{#f}.")
  100. #define FUNC_NAME s_scm_bitvector_p
  101. {
  102. return scm_from_bool (scm_is_bitvector (obj));
  103. }
  104. #undef FUNC_NAME
  105. SCM
  106. scm_c_make_bitvector (size_t len, SCM fill)
  107. {
  108. size_t word_len = (len + 31) / 32;
  109. uint32_t *bits;
  110. SCM res;
  111. bits = scm_gc_malloc_pointerless (sizeof (uint32_t) * word_len,
  112. "bitvector");
  113. res = scm_double_cell (scm_tc11_bitvector, len, (scm_t_bits)bits, 0);
  114. if (!SCM_UNBNDP (fill))
  115. scm_bitvector_fill_x (res, fill);
  116. else
  117. memset (bits, 0, sizeof (uint32_t) * word_len);
  118. return res;
  119. }
  120. SCM_DEFINE (scm_make_bitvector, "make-bitvector", 1, 1, 0,
  121. (SCM len, SCM fill),
  122. "Create a new bitvector of length @var{len} and\n"
  123. "optionally initialize all elements to @var{fill}.")
  124. #define FUNC_NAME s_scm_make_bitvector
  125. {
  126. return scm_c_make_bitvector (scm_to_size_t (len), fill);
  127. }
  128. #undef FUNC_NAME
  129. SCM_DEFINE (scm_bitvector, "bitvector", 0, 0, 1,
  130. (SCM bits),
  131. "Create a new bitvector with the arguments as elements.")
  132. #define FUNC_NAME s_scm_bitvector
  133. {
  134. return scm_list_to_bitvector (bits);
  135. }
  136. #undef FUNC_NAME
  137. size_t
  138. scm_c_bitvector_length (SCM vec)
  139. {
  140. if (!IS_BITVECTOR (vec))
  141. scm_wrong_type_arg_msg (NULL, 0, vec, "bitvector");
  142. return BITVECTOR_LENGTH (vec);
  143. }
  144. SCM_DEFINE (scm_bitvector_length, "bitvector-length", 1, 0, 0,
  145. (SCM vec),
  146. "Return the length of the bitvector @var{vec}.")
  147. #define FUNC_NAME s_scm_bitvector_length
  148. {
  149. return scm_from_size_t (scm_c_bitvector_length (vec));
  150. }
  151. #undef FUNC_NAME
  152. const uint32_t *
  153. scm_array_handle_bit_elements (scm_t_array_handle *h)
  154. {
  155. if (h->element_type != SCM_ARRAY_ELEMENT_TYPE_BIT)
  156. scm_wrong_type_arg_msg (NULL, 0, h->array, "bit array");
  157. return ((const uint32_t *) h->elements) + h->base/32;
  158. }
  159. uint32_t *
  160. scm_array_handle_bit_writable_elements (scm_t_array_handle *h)
  161. {
  162. if (h->writable_elements != h->elements)
  163. scm_wrong_type_arg_msg (NULL, 0, h->array, "mutable bit array");
  164. return (uint32_t *) scm_array_handle_bit_elements (h);
  165. }
  166. size_t
  167. scm_array_handle_bit_elements_offset (scm_t_array_handle *h)
  168. {
  169. return h->base % 32;
  170. }
  171. const uint32_t *
  172. scm_bitvector_elements (SCM vec,
  173. scm_t_array_handle *h,
  174. size_t *offp,
  175. size_t *lenp,
  176. ssize_t *incp)
  177. {
  178. scm_array_get_handle (vec, h);
  179. if (1 != scm_array_handle_rank (h))
  180. {
  181. scm_array_handle_release (h);
  182. scm_wrong_type_arg_msg (NULL, 0, vec, "rank 1 bit array");
  183. }
  184. if (offp)
  185. {
  186. scm_t_array_dim *dim = scm_array_handle_dims (h);
  187. *offp = scm_array_handle_bit_elements_offset (h);
  188. *lenp = dim->ubnd - dim->lbnd + 1;
  189. *incp = dim->inc;
  190. }
  191. return scm_array_handle_bit_elements (h);
  192. }
  193. uint32_t *
  194. scm_bitvector_writable_elements (SCM vec,
  195. scm_t_array_handle *h,
  196. size_t *offp,
  197. size_t *lenp,
  198. ssize_t *incp)
  199. {
  200. const uint32_t *ret = scm_bitvector_elements (vec, h, offp, lenp, incp);
  201. if (h->writable_elements != h->elements)
  202. scm_wrong_type_arg_msg (NULL, 0, h->array, "mutable bit array");
  203. return (uint32_t *) ret;
  204. }
  205. SCM
  206. scm_c_bitvector_ref (SCM vec, size_t idx)
  207. {
  208. scm_t_array_handle handle;
  209. const uint32_t *bits;
  210. if (IS_BITVECTOR (vec))
  211. {
  212. if (idx >= BITVECTOR_LENGTH (vec))
  213. scm_out_of_range (NULL, scm_from_size_t (idx));
  214. bits = BITVECTOR_BITS(vec);
  215. return scm_from_bool (bits[idx/32] & (1L << (idx%32)));
  216. }
  217. else
  218. {
  219. SCM res;
  220. size_t len, off;
  221. ssize_t inc;
  222. bits = scm_bitvector_elements (vec, &handle, &off, &len, &inc);
  223. if (idx >= len)
  224. scm_out_of_range (NULL, scm_from_size_t (idx));
  225. idx = idx*inc + off;
  226. res = scm_from_bool (bits[idx/32] & (1L << (idx%32)));
  227. scm_array_handle_release (&handle);
  228. return res;
  229. }
  230. }
  231. SCM_DEFINE (scm_bitvector_ref, "bitvector-ref", 2, 0, 0,
  232. (SCM vec, SCM idx),
  233. "Return the element at index @var{idx} of the bitvector\n"
  234. "@var{vec}.")
  235. #define FUNC_NAME s_scm_bitvector_ref
  236. {
  237. return scm_c_bitvector_ref (vec, scm_to_size_t (idx));
  238. }
  239. #undef FUNC_NAME
  240. void
  241. scm_c_bitvector_set_x (SCM vec, size_t idx, SCM val)
  242. {
  243. scm_t_array_handle handle;
  244. uint32_t *bits, mask;
  245. if (IS_MUTABLE_BITVECTOR (vec))
  246. {
  247. if (idx >= BITVECTOR_LENGTH (vec))
  248. scm_out_of_range (NULL, scm_from_size_t (idx));
  249. bits = BITVECTOR_BITS(vec);
  250. }
  251. else
  252. {
  253. size_t len, off;
  254. ssize_t inc;
  255. bits = scm_bitvector_writable_elements (vec, &handle, &off, &len, &inc);
  256. if (idx >= len)
  257. scm_out_of_range (NULL, scm_from_size_t (idx));
  258. idx = idx*inc + off;
  259. }
  260. mask = 1L << (idx%32);
  261. if (scm_is_true (val))
  262. bits[idx/32] |= mask;
  263. else
  264. bits[idx/32] &= ~mask;
  265. if (!IS_MUTABLE_BITVECTOR (vec))
  266. scm_array_handle_release (&handle);
  267. }
  268. SCM_DEFINE (scm_bitvector_set_x, "bitvector-set!", 3, 0, 0,
  269. (SCM vec, SCM idx, SCM val),
  270. "Set the element at index @var{idx} of the bitvector\n"
  271. "@var{vec} when @var{val} is true, else clear it.")
  272. #define FUNC_NAME s_scm_bitvector_set_x
  273. {
  274. scm_c_bitvector_set_x (vec, scm_to_size_t (idx), val);
  275. return SCM_UNSPECIFIED;
  276. }
  277. #undef FUNC_NAME
  278. SCM_DEFINE (scm_bitvector_fill_x, "bitvector-fill!", 2, 0, 0,
  279. (SCM vec, SCM val),
  280. "Set all elements of the bitvector\n"
  281. "@var{vec} when @var{val} is true, else clear them.")
  282. #define FUNC_NAME s_scm_bitvector_fill_x
  283. {
  284. scm_t_array_handle handle;
  285. size_t off, len;
  286. ssize_t inc;
  287. uint32_t *bits;
  288. bits = scm_bitvector_writable_elements (vec, &handle,
  289. &off, &len, &inc);
  290. if (off == 0 && inc == 1 && len > 0)
  291. {
  292. /* the usual case
  293. */
  294. size_t word_len = (len + 31) / 32;
  295. uint32_t last_mask = ((uint32_t)-1) >> (32*word_len - len);
  296. if (scm_is_true (val))
  297. {
  298. memset (bits, 0xFF, sizeof(uint32_t)*(word_len-1));
  299. bits[word_len-1] |= last_mask;
  300. }
  301. else
  302. {
  303. memset (bits, 0x00, sizeof(uint32_t)*(word_len-1));
  304. bits[word_len-1] &= ~last_mask;
  305. }
  306. }
  307. else
  308. {
  309. size_t i;
  310. for (i = 0; i < len; i++)
  311. scm_array_handle_set (&handle, i*inc, val);
  312. }
  313. scm_array_handle_release (&handle);
  314. return SCM_UNSPECIFIED;
  315. }
  316. #undef FUNC_NAME
  317. SCM_DEFINE (scm_list_to_bitvector, "list->bitvector", 1, 0, 0,
  318. (SCM list),
  319. "Return a new bitvector initialized with the elements\n"
  320. "of @var{list}.")
  321. #define FUNC_NAME s_scm_list_to_bitvector
  322. {
  323. size_t bit_len = scm_to_size_t (scm_length (list));
  324. SCM vec = scm_c_make_bitvector (bit_len, SCM_UNDEFINED);
  325. size_t word_len = (bit_len+31)/32;
  326. scm_t_array_handle handle;
  327. uint32_t *bits = scm_bitvector_writable_elements (vec, &handle,
  328. NULL, NULL, NULL);
  329. size_t i, j;
  330. for (i = 0; i < word_len && scm_is_pair (list); i++, bit_len -= 32)
  331. {
  332. uint32_t mask = 1;
  333. bits[i] = 0;
  334. for (j = 0; j < 32 && j < bit_len;
  335. j++, mask <<= 1, list = SCM_CDR (list))
  336. if (scm_is_true (SCM_CAR (list)))
  337. bits[i] |= mask;
  338. }
  339. scm_array_handle_release (&handle);
  340. return vec;
  341. }
  342. #undef FUNC_NAME
  343. SCM_DEFINE (scm_bitvector_to_list, "bitvector->list", 1, 0, 0,
  344. (SCM vec),
  345. "Return a new list initialized with the elements\n"
  346. "of the bitvector @var{vec}.")
  347. #define FUNC_NAME s_scm_bitvector_to_list
  348. {
  349. scm_t_array_handle handle;
  350. size_t off, len;
  351. ssize_t inc;
  352. const uint32_t *bits;
  353. SCM res = SCM_EOL;
  354. bits = scm_bitvector_elements (vec, &handle, &off, &len, &inc);
  355. if (off == 0 && inc == 1)
  356. {
  357. /* the usual case
  358. */
  359. size_t word_len = (len + 31) / 32;
  360. size_t i, j;
  361. for (i = 0; i < word_len; i++, len -= 32)
  362. {
  363. uint32_t mask = 1;
  364. for (j = 0; j < 32 && j < len; j++, mask <<= 1)
  365. res = scm_cons ((bits[i] & mask)? SCM_BOOL_T : SCM_BOOL_F, res);
  366. }
  367. }
  368. else
  369. {
  370. size_t i;
  371. for (i = 0; i < len; i++)
  372. res = scm_cons (scm_array_handle_ref (&handle, i*inc), res);
  373. }
  374. scm_array_handle_release (&handle);
  375. return scm_reverse_x (res, SCM_EOL);
  376. }
  377. #undef FUNC_NAME
  378. /* From mmix-arith.w by Knuth.
  379. Here's a fun way to count the number of bits in a tetrabyte.
  380. [This classical trick is called the ``Gillies--Miller method for
  381. sideways addition'' in {\sl The Preparation of Programs for an
  382. Electronic Digital Computer\/} by Wilkes, Wheeler, and Gill, second
  383. edition (Reading, Mass.:\ Addison--Wesley, 1957), 191--193. Some of
  384. the tricks used here were suggested by Balbir Singh, Peter
  385. Rossmanith, and Stefan Schwoon.]
  386. */
  387. static size_t
  388. count_ones (uint32_t x)
  389. {
  390. x=x-((x>>1)&0x55555555);
  391. x=(x&0x33333333)+((x>>2)&0x33333333);
  392. x=(x+(x>>4))&0x0f0f0f0f;
  393. x=x+(x>>8);
  394. return (x+(x>>16)) & 0xff;
  395. }
  396. SCM_DEFINE (scm_bit_count, "bit-count", 2, 0, 0,
  397. (SCM b, SCM bitvector),
  398. "Return the number of occurrences of the boolean @var{b} in\n"
  399. "@var{bitvector}.")
  400. #define FUNC_NAME s_scm_bit_count
  401. {
  402. scm_t_array_handle handle;
  403. size_t off, len;
  404. ssize_t inc;
  405. const uint32_t *bits;
  406. int bit = scm_to_bool (b);
  407. size_t count = 0;
  408. bits = scm_bitvector_elements (bitvector, &handle, &off, &len, &inc);
  409. if (off == 0 && inc == 1 && len > 0)
  410. {
  411. /* the usual case
  412. */
  413. size_t word_len = (len + 31) / 32;
  414. uint32_t last_mask = ((uint32_t)-1) >> (32*word_len - len);
  415. size_t i;
  416. for (i = 0; i < word_len-1; i++)
  417. count += count_ones (bits[i]);
  418. count += count_ones (bits[i] & last_mask);
  419. }
  420. else
  421. {
  422. size_t i;
  423. for (i = 0; i < len; i++)
  424. if (scm_is_true (scm_array_handle_ref (&handle, i*inc)))
  425. count++;
  426. }
  427. scm_array_handle_release (&handle);
  428. return scm_from_size_t (bit? count : len-count);
  429. }
  430. #undef FUNC_NAME
  431. /* returns 32 for x == 0.
  432. */
  433. static size_t
  434. find_first_one (uint32_t x)
  435. {
  436. size_t pos = 0;
  437. /* do a binary search in x. */
  438. if ((x & 0xFFFF) == 0)
  439. x >>= 16, pos += 16;
  440. if ((x & 0xFF) == 0)
  441. x >>= 8, pos += 8;
  442. if ((x & 0xF) == 0)
  443. x >>= 4, pos += 4;
  444. if ((x & 0x3) == 0)
  445. x >>= 2, pos += 2;
  446. if ((x & 0x1) == 0)
  447. pos += 1;
  448. return pos;
  449. }
  450. SCM_DEFINE (scm_bit_position, "bit-position", 3, 0, 0,
  451. (SCM item, SCM v, SCM k),
  452. "Return the index of the first occurrence of @var{item} in bit\n"
  453. "vector @var{v}, starting from @var{k}. If there is no\n"
  454. "@var{item} entry between @var{k} and the end of\n"
  455. "@var{v}, then return @code{#f}. For example,\n"
  456. "\n"
  457. "@example\n"
  458. "(bit-position #t #*000101 0) @result{} 3\n"
  459. "(bit-position #f #*0001111 3) @result{} #f\n"
  460. "@end example")
  461. #define FUNC_NAME s_scm_bit_position
  462. {
  463. scm_t_array_handle handle;
  464. size_t off, len, first_bit;
  465. ssize_t inc;
  466. const uint32_t *bits;
  467. int bit = scm_to_bool (item);
  468. SCM res = SCM_BOOL_F;
  469. bits = scm_bitvector_elements (v, &handle, &off, &len, &inc);
  470. first_bit = scm_to_unsigned_integer (k, 0, len);
  471. if (off == 0 && inc == 1 && len > 0)
  472. {
  473. size_t i, word_len = (len + 31) / 32;
  474. uint32_t last_mask = ((uint32_t)-1) >> (32*word_len - len);
  475. size_t first_word = first_bit / 32;
  476. uint32_t first_mask =
  477. ((uint32_t)-1) << (first_bit - 32*first_word);
  478. uint32_t w;
  479. for (i = first_word; i < word_len; i++)
  480. {
  481. w = (bit? bits[i] : ~bits[i]);
  482. if (i == first_word)
  483. w &= first_mask;
  484. if (i == word_len-1)
  485. w &= last_mask;
  486. if (w)
  487. {
  488. res = scm_from_size_t (32*i + find_first_one (w));
  489. break;
  490. }
  491. }
  492. }
  493. else
  494. {
  495. size_t i;
  496. for (i = first_bit; i < len; i++)
  497. {
  498. SCM elt = scm_array_handle_ref (&handle, i*inc);
  499. if ((bit && scm_is_true (elt)) || (!bit && scm_is_false (elt)))
  500. {
  501. res = scm_from_size_t (i);
  502. break;
  503. }
  504. }
  505. }
  506. scm_array_handle_release (&handle);
  507. return res;
  508. }
  509. #undef FUNC_NAME
  510. SCM_DEFINE (scm_bit_set_star_x, "bit-set*!", 3, 0, 0,
  511. (SCM v, SCM kv, SCM obj),
  512. "Set entries of bit vector @var{v} to @var{obj}, with @var{kv}\n"
  513. "selecting the entries to change. The return value is\n"
  514. "unspecified.\n"
  515. "\n"
  516. "If @var{kv} is a bit vector, then those entries where it has\n"
  517. "@code{#t} are the ones in @var{v} which are set to @var{obj}.\n"
  518. "@var{v} must be at least as long as @var{kv}. When @var{obj}\n"
  519. "is @code{#t} it's like @var{kv} is OR'ed into @var{v}. Or when\n"
  520. "@var{obj} is @code{#f} it can be seen as an ANDNOT.\n"
  521. "\n"
  522. "@example\n"
  523. "(define bv #*01000010)\n"
  524. "(bit-set*! bv #*10010001 #t)\n"
  525. "bv\n"
  526. "@result{} #*11010011\n"
  527. "@end example\n"
  528. "\n"
  529. "If @var{kv} is a u32vector, then its elements are\n"
  530. "indices into @var{v} which are set to @var{obj}.\n"
  531. "\n"
  532. "@example\n"
  533. "(define bv #*01000010)\n"
  534. "(bit-set*! bv #u32(5 2 7) #t)\n"
  535. "bv\n"
  536. "@result{} #*01100111\n"
  537. "@end example")
  538. #define FUNC_NAME s_scm_bit_set_star_x
  539. {
  540. scm_t_array_handle v_handle;
  541. size_t v_off, v_len;
  542. ssize_t v_inc;
  543. uint32_t *v_bits;
  544. int bit;
  545. /* Validate that OBJ is a boolean so this is done even if we don't
  546. need BIT.
  547. */
  548. bit = scm_to_bool (obj);
  549. v_bits = scm_bitvector_writable_elements (v, &v_handle,
  550. &v_off, &v_len, &v_inc);
  551. if (scm_is_bitvector (kv))
  552. {
  553. scm_t_array_handle kv_handle;
  554. size_t kv_off, kv_len;
  555. ssize_t kv_inc;
  556. const uint32_t *kv_bits;
  557. kv_bits = scm_bitvector_elements (kv, &kv_handle,
  558. &kv_off, &kv_len, &kv_inc);
  559. if (v_len < kv_len)
  560. scm_misc_error (NULL,
  561. "bit vectors must have equal length",
  562. SCM_EOL);
  563. if (v_off == 0 && v_inc == 1 && kv_off == 0 && kv_inc == 1 && kv_len > 0)
  564. {
  565. size_t word_len = (kv_len + 31) / 32;
  566. uint32_t last_mask = ((uint32_t)-1) >> (32*word_len - kv_len);
  567. size_t i;
  568. if (bit == 0)
  569. {
  570. for (i = 0; i < word_len-1; i++)
  571. v_bits[i] &= ~kv_bits[i];
  572. v_bits[i] &= ~(kv_bits[i] & last_mask);
  573. }
  574. else
  575. {
  576. for (i = 0; i < word_len-1; i++)
  577. v_bits[i] |= kv_bits[i];
  578. v_bits[i] |= kv_bits[i] & last_mask;
  579. }
  580. }
  581. else
  582. {
  583. size_t i;
  584. for (i = 0; i < kv_len; i++)
  585. if (scm_is_true (scm_array_handle_ref (&kv_handle, i*kv_inc)))
  586. scm_array_handle_set (&v_handle, i*v_inc, obj);
  587. }
  588. scm_array_handle_release (&kv_handle);
  589. }
  590. else if (scm_is_true (scm_u32vector_p (kv)))
  591. {
  592. scm_t_array_handle kv_handle;
  593. size_t i, kv_len;
  594. ssize_t kv_inc;
  595. const uint32_t *kv_elts;
  596. kv_elts = scm_u32vector_elements (kv, &kv_handle, &kv_len, &kv_inc);
  597. for (i = 0; i < kv_len; i++, kv_elts += kv_inc)
  598. scm_array_handle_set (&v_handle, (*kv_elts)*v_inc, obj);
  599. scm_array_handle_release (&kv_handle);
  600. }
  601. else
  602. scm_wrong_type_arg_msg (NULL, 0, kv, "bitvector or u32vector");
  603. scm_array_handle_release (&v_handle);
  604. return SCM_UNSPECIFIED;
  605. }
  606. #undef FUNC_NAME
  607. SCM_DEFINE (scm_bit_count_star, "bit-count*", 3, 0, 0,
  608. (SCM v, SCM kv, SCM obj),
  609. "Return a count of how many entries in bit vector @var{v} are\n"
  610. "equal to @var{obj}, with @var{kv} selecting the entries to\n"
  611. "consider.\n"
  612. "\n"
  613. "If @var{kv} is a bit vector, then those entries where it has\n"
  614. "@code{#t} are the ones in @var{v} which are considered.\n"
  615. "@var{kv} and @var{v} must be the same length.\n"
  616. "\n"
  617. "If @var{kv} is a u32vector, then it contains\n"
  618. "the indexes in @var{v} to consider.\n"
  619. "\n"
  620. "For example,\n"
  621. "\n"
  622. "@example\n"
  623. "(bit-count* #*01110111 #*11001101 #t) @result{} 3\n"
  624. "(bit-count* #*01110111 #u32(7 0 4) #f) @result{} 2\n"
  625. "@end example")
  626. #define FUNC_NAME s_scm_bit_count_star
  627. {
  628. scm_t_array_handle v_handle;
  629. size_t v_off, v_len;
  630. ssize_t v_inc;
  631. const uint32_t *v_bits;
  632. size_t count = 0;
  633. int bit;
  634. /* Validate that OBJ is a boolean so this is done even if we don't
  635. need BIT.
  636. */
  637. bit = scm_to_bool (obj);
  638. v_bits = scm_bitvector_elements (v, &v_handle,
  639. &v_off, &v_len, &v_inc);
  640. if (scm_is_bitvector (kv))
  641. {
  642. scm_t_array_handle kv_handle;
  643. size_t kv_off, kv_len;
  644. ssize_t kv_inc;
  645. const uint32_t *kv_bits;
  646. kv_bits = scm_bitvector_elements (kv, &kv_handle,
  647. &kv_off, &kv_len, &kv_inc);
  648. if (v_len != kv_len)
  649. scm_misc_error (NULL,
  650. "bit vectors must have equal length",
  651. SCM_EOL);
  652. if (v_off == 0 && v_inc == 1 && kv_off == 0 && kv_inc == 1 && kv_len > 0)
  653. {
  654. size_t i, word_len = (kv_len + 31) / 32;
  655. uint32_t last_mask = ((uint32_t)-1) >> (32*word_len - kv_len);
  656. uint32_t xor_mask = bit? 0 : ((uint32_t)-1);
  657. for (i = 0; i < word_len-1; i++)
  658. count += count_ones ((v_bits[i]^xor_mask) & kv_bits[i]);
  659. count += count_ones ((v_bits[i]^xor_mask) & kv_bits[i] & last_mask);
  660. }
  661. else
  662. {
  663. size_t i;
  664. for (i = 0; i < kv_len; i++)
  665. if (scm_is_true (scm_array_handle_ref (&kv_handle, i)))
  666. {
  667. SCM elt = scm_array_handle_ref (&v_handle, i*v_inc);
  668. if ((bit && scm_is_true (elt)) || (!bit && scm_is_false (elt)))
  669. count++;
  670. }
  671. }
  672. scm_array_handle_release (&kv_handle);
  673. }
  674. else if (scm_is_true (scm_u32vector_p (kv)))
  675. {
  676. scm_t_array_handle kv_handle;
  677. size_t i, kv_len;
  678. ssize_t kv_inc;
  679. const uint32_t *kv_elts;
  680. kv_elts = scm_u32vector_elements (kv, &kv_handle, &kv_len, &kv_inc);
  681. for (i = 0; i < kv_len; i++, kv_elts += kv_inc)
  682. {
  683. SCM elt = scm_array_handle_ref (&v_handle, (*kv_elts)*v_inc);
  684. if ((bit && scm_is_true (elt)) || (!bit && scm_is_false (elt)))
  685. count++;
  686. }
  687. scm_array_handle_release (&kv_handle);
  688. }
  689. else
  690. scm_wrong_type_arg_msg (NULL, 0, kv, "bitvector or u32vector");
  691. scm_array_handle_release (&v_handle);
  692. return scm_from_size_t (count);
  693. }
  694. #undef FUNC_NAME
  695. SCM_DEFINE (scm_bit_invert_x, "bit-invert!", 1, 0, 0,
  696. (SCM v),
  697. "Modify the bit vector @var{v} by replacing each element with\n"
  698. "its negation.")
  699. #define FUNC_NAME s_scm_bit_invert_x
  700. {
  701. scm_t_array_handle handle;
  702. size_t off, len;
  703. ssize_t inc;
  704. uint32_t *bits;
  705. bits = scm_bitvector_writable_elements (v, &handle, &off, &len, &inc);
  706. if (off == 0 && inc == 1 && len > 0)
  707. {
  708. size_t word_len = (len + 31) / 32;
  709. uint32_t last_mask = ((uint32_t)-1) >> (32*word_len - len);
  710. size_t i;
  711. for (i = 0; i < word_len-1; i++)
  712. bits[i] = ~bits[i];
  713. bits[i] = bits[i] ^ last_mask;
  714. }
  715. else
  716. {
  717. size_t i;
  718. for (i = 0; i < len; i++)
  719. scm_array_handle_set (&handle, i*inc,
  720. scm_not (scm_array_handle_ref (&handle, i*inc)));
  721. }
  722. scm_array_handle_release (&handle);
  723. return SCM_UNSPECIFIED;
  724. }
  725. #undef FUNC_NAME
  726. SCM
  727. scm_istr2bve (SCM str)
  728. {
  729. scm_t_array_handle handle;
  730. size_t len = scm_i_string_length (str);
  731. SCM vec = scm_c_make_bitvector (len, SCM_UNDEFINED);
  732. SCM res = vec;
  733. uint32_t mask;
  734. size_t k, j;
  735. const char *c_str;
  736. uint32_t *data;
  737. data = scm_bitvector_writable_elements (vec, &handle, NULL, NULL, NULL);
  738. c_str = scm_i_string_chars (str);
  739. for (k = 0; k < (len + 31) / 32; k++)
  740. {
  741. data[k] = 0L;
  742. j = len - k * 32;
  743. if (j > 32)
  744. j = 32;
  745. for (mask = 1L; j--; mask <<= 1)
  746. switch (*c_str++)
  747. {
  748. case '0':
  749. break;
  750. case '1':
  751. data[k] |= mask;
  752. break;
  753. default:
  754. res = SCM_BOOL_F;
  755. goto exit;
  756. }
  757. }
  758. exit:
  759. scm_array_handle_release (&handle);
  760. scm_remember_upto_here_1 (str);
  761. return res;
  762. }
  763. SCM_VECTOR_IMPLEMENTATION (SCM_ARRAY_ELEMENT_TYPE_BIT, scm_make_bitvector)
  764. void
  765. scm_init_bitvectors ()
  766. {
  767. #include "bitvectors.x"
  768. }