bitvectors.c 23 KB

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