bitvectors.c 22 KB

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