bitvectors.c 22 KB

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