1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-01 04:10:18 +02:00
guile/libguile/bitvectors.c
Daniel Llorens 04c80519bf Simplify interfaces to scm_TYPEvector_(writable_)elements
Nothing is lost in these since the functions already required true typed
vectors, the extra arguments didn't serve any purpose.

Changing my mind from (vec) to (vec, lenp), though. Will fix
vector/bitvector next.

* libguile/srfi-4.h: scm_TYPEvector_(writable_)elements take (vec, lenp).
* libguile/srfi-4.c: Fix implementation.
* libguile/bitvectors.c: Fix use.
* test-suite/standalone/test-srfi-4.c: Fix old test and write variant
  with full array handle interface.
* doc/ref/srfi-modules.texi: Fix doc for srfi-4
  scm_TYPEvector_(writable_)elements.
2020-04-09 16:59:39 +02:00

782 lines
20 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* Copyright 1995-1998,2000-2006,2009-2014,2018
Free Software Foundation, Inc.
This file is part of Guile.
Guile is free software: you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Guile is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with Guile. If not, see
<https://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include "array-handle.h"
#include "arrays.h"
#include "boolean.h"
#include "generalized-vectors.h"
#include "gsubr.h"
#include "list.h"
#include "numbers.h"
#include "pairs.h"
#include "ports.h"
#include "srfi-4.h"
#include <stdbool.h>
#include "bitvectors.h"
/* Bit vectors. Would be nice if they were implemented on top of bytevectors,
* but alack, all we have is this crufty C.
*/
#define SCM_F_BITVECTOR_IMMUTABLE (0x80)
#define IS_BITVECTOR(obj) SCM_HAS_TYP7 ((obj), scm_tc7_bitvector)
#define IS_MUTABLE_BITVECTOR(x) \
(SCM_NIMP (x) && \
((SCM_CELL_TYPE (x) & (0x7f | SCM_F_BITVECTOR_IMMUTABLE)) \
== scm_tc7_bitvector))
#define BITVECTOR_LENGTH(obj) ((size_t)SCM_CELL_WORD_1(obj))
#define BITVECTOR_BITS(obj) ((uint32_t *)SCM_CELL_WORD_2(obj))
uint32_t *
scm_i_bitvector_bits (SCM vec)
{
if (!IS_BITVECTOR (vec))
abort ();
return BITVECTOR_BITS (vec);
}
int
scm_i_is_mutable_bitvector (SCM vec)
{
return IS_MUTABLE_BITVECTOR (vec);
}
int
scm_i_print_bitvector (SCM vec, SCM port, scm_print_state *pstate)
{
size_t bit_len = BITVECTOR_LENGTH (vec);
size_t word_len = (bit_len+31)/32;
uint32_t *bits = BITVECTOR_BITS (vec);
size_t i, j;
scm_puts ("#*", port);
for (i = 0; i < word_len; i++, bit_len -= 32)
{
uint32_t mask = 1;
for (j = 0; j < 32 && j < bit_len; j++, mask <<= 1)
scm_putc ((bits[i] & mask)? '1' : '0', port);
}
return 1;
}
SCM
scm_i_bitvector_equal_p (SCM vec1, SCM vec2)
{
size_t bit_len = BITVECTOR_LENGTH (vec1);
size_t word_len = (bit_len + 31) / 32;
uint32_t last_mask = ((uint32_t)-1) >> (32*word_len - bit_len);
uint32_t *bits1 = BITVECTOR_BITS (vec1);
uint32_t *bits2 = BITVECTOR_BITS (vec2);
/* compare lengths */
if (BITVECTOR_LENGTH (vec2) != bit_len)
return SCM_BOOL_F;
/* avoid underflow in word_len-1 below. */
if (bit_len == 0)
return SCM_BOOL_T;
/* compare full words */
if (memcmp (bits1, bits2, sizeof (uint32_t) * (word_len-1)))
return SCM_BOOL_F;
/* compare partial last words */
if ((bits1[word_len-1] & last_mask) != (bits2[word_len-1] & last_mask))
return SCM_BOOL_F;
return SCM_BOOL_T;
}
int
scm_is_bitvector (SCM vec)
{
return IS_BITVECTOR (vec);
}
SCM_DEFINE (scm_bitvector_p, "bitvector?", 1, 0, 0,
(SCM obj),
"Return @code{#t} when @var{obj} is a bitvector, else\n"
"return @code{#f}.")
#define FUNC_NAME s_scm_bitvector_p
{
return scm_from_bool (scm_is_bitvector (obj));
}
#undef FUNC_NAME
SCM
scm_c_make_bitvector (size_t len, SCM fill)
{
size_t word_len = (len + 31) / 32;
uint32_t *bits;
SCM res;
bits = scm_gc_malloc_pointerless (sizeof (uint32_t) * word_len,
"bitvector");
res = scm_double_cell (scm_tc7_bitvector, len, (scm_t_bits)bits, 0);
if (!SCM_UNBNDP (fill))
scm_bitvector_fill_x (res, fill);
else
memset (bits, 0, sizeof (uint32_t) * word_len);
return res;
}
SCM_DEFINE (scm_make_bitvector, "make-bitvector", 1, 1, 0,
(SCM len, SCM fill),
"Create a new bitvector of length @var{len} and\n"
"optionally initialize all elements to @var{fill}.")
#define FUNC_NAME s_scm_make_bitvector
{
return scm_c_make_bitvector (scm_to_size_t (len), fill);
}
#undef FUNC_NAME
SCM_DEFINE (scm_bitvector, "bitvector", 0, 0, 1,
(SCM bits),
"Create a new bitvector with the arguments as elements.")
#define FUNC_NAME s_scm_bitvector
{
return scm_list_to_bitvector (bits);
}
#undef FUNC_NAME
size_t
scm_c_bitvector_length (SCM vec)
{
if (!IS_BITVECTOR (vec))
scm_wrong_type_arg_msg (NULL, 0, vec, "bitvector");
return BITVECTOR_LENGTH (vec);
}
SCM_DEFINE (scm_bitvector_length, "bitvector-length", 1, 0, 0,
(SCM vec),
"Return the length of the bitvector @var{vec}.")
#define FUNC_NAME s_scm_bitvector_length
{
return scm_from_size_t (scm_c_bitvector_length (vec));
}
#undef FUNC_NAME
const uint32_t *
scm_array_handle_bit_elements (scm_t_array_handle *h)
{
if (h->element_type != SCM_ARRAY_ELEMENT_TYPE_BIT)
scm_wrong_type_arg_msg (NULL, 0, h->array, "bit array");
return ((const uint32_t *) h->elements) + h->base/32;
}
uint32_t *
scm_array_handle_bit_writable_elements (scm_t_array_handle *h)
{
if (h->writable_elements != h->elements)
scm_wrong_type_arg_msg (NULL, 0, h->array, "mutable bit array");
return (uint32_t *) scm_array_handle_bit_elements (h);
}
size_t
scm_array_handle_bit_elements_offset (scm_t_array_handle *h)
{
return h->base % 32;
}
#define SCM_VALIDATE_BITVECTOR(pos, v) \
do { \
SCM_ASSERT_TYPE (IS_BITVECTOR (v), v, pos, __func__, \
"bitvector"); \
} while (0)
#define SCM_VALIDATE_MUTABLE_BITVECTOR(pos, v) \
do { \
SCM_ASSERT_TYPE (IS_MUTABLE_BITVECTOR (v), v, pos, __func__, \
"mutable bitvector"); \
} while (0)
const uint32_t *
scm_bitvector_elements (SCM vec)
{
SCM_VALIDATE_BITVECTOR (1, vec);
return BITVECTOR_BITS (vec);
}
uint32_t *
scm_bitvector_writable_elements (SCM vec)
{
SCM_VALIDATE_MUTABLE_BITVECTOR (1, vec);
return BITVECTOR_BITS (vec);
}
static inline bool
bitref_ (const uint32_t *bits, size_t idx)
{
return (bits[idx/32] & (1L << (idx%32)));
}
static inline void
bitset_ (uint32_t *bits, size_t idx, bool b)
{
uint32_t mask = 1L << (idx%32);
if (b)
bits[idx/32] |= mask;
else
bits[idx/32] &= ~mask;
}
SCM
scm_c_bitvector_ref (SCM vec, size_t idx)
{
const uint32_t *bits = scm_bitvector_elements (vec);
if (idx >= BITVECTOR_LENGTH (vec))
scm_out_of_range (NULL, scm_from_size_t (idx));
return scm_from_bool (bitref_(bits, idx));
}
SCM_DEFINE (scm_bitvector_ref, "bitvector-ref", 2, 0, 0,
(SCM vec, SCM idx),
"Return the element at index @var{idx} of the bitvector\n"
"@var{vec}.")
#define FUNC_NAME s_scm_bitvector_ref
{
return scm_c_bitvector_ref (vec, scm_to_size_t (idx));
}
#undef FUNC_NAME
void
scm_c_bitvector_set_x (SCM vec, size_t idx, SCM val)
{
uint32_t *bits = scm_bitvector_writable_elements (vec);
if (idx >= BITVECTOR_LENGTH (vec))
scm_out_of_range (NULL, scm_from_size_t (idx));
bitset_(bits, idx, scm_is_true (val));
}
SCM_DEFINE (scm_bitvector_set_x, "bitvector-set!", 3, 0, 0,
(SCM vec, SCM idx, SCM val),
"Set the element at index @var{idx} of the bitvector\n"
"@var{vec} when @var{val} is true, else clear it.")
#define FUNC_NAME s_scm_bitvector_set_x
{
scm_c_bitvector_set_x (vec, scm_to_size_t (idx), val);
return SCM_UNSPECIFIED;
}
#undef FUNC_NAME
SCM_DEFINE (scm_bitvector_fill_x, "bitvector-fill!", 2, 0, 0,
(SCM vec, SCM val),
"Set all elements of the bitvector\n"
"@var{vec} when @var{val} is true, else clear them.")
#define FUNC_NAME s_scm_bitvector_fill_x
{
size_t off, len;
ssize_t inc;
uint32_t *bits = scm_array1_bit_writable_elements (vec, &len, &inc, &off);
if (off == 0 && inc == 1 && len > 0)
{
/* the usual case
*/
size_t word_len = (len + 31) / 32;
uint32_t last_mask = ((uint32_t)-1) >> (32*word_len - len);
if (scm_is_true (val))
{
memset (bits, 0xFF, sizeof(uint32_t)*(word_len-1));
bits[word_len-1] |= last_mask;
}
else
{
memset (bits, 0x00, sizeof(uint32_t)*(word_len-1));
bits[word_len-1] &= ~last_mask;
}
}
else
{
size_t i;
for (i = 0; i < len; i++)
bitset_(bits, off+i*inc, scm_is_true(val));
}
return SCM_UNSPECIFIED;
}
#undef FUNC_NAME
SCM_DEFINE (scm_list_to_bitvector, "list->bitvector", 1, 0, 0,
(SCM list),
"Return a new bitvector initialized with the elements\n"
"of @var{list}.")
#define FUNC_NAME s_scm_list_to_bitvector
{
size_t bit_len = scm_to_size_t (scm_length (list));
SCM vec = scm_c_make_bitvector (bit_len, SCM_UNDEFINED);
size_t word_len = (bit_len+31)/32;
uint32_t *bits = scm_bitvector_writable_elements (vec);
size_t i, j;
for (i = 0; i < word_len && scm_is_pair (list); i++, bit_len -= 32)
{
uint32_t mask = 1;
bits[i] = 0;
for (j = 0; j < 32 && j < bit_len;
j++, mask <<= 1, list = SCM_CDR (list))
if (scm_is_true (SCM_CAR (list)))
bits[i] |= mask;
}
return vec;
}
#undef FUNC_NAME
SCM_DEFINE (scm_bitvector_to_list, "bitvector->list", 1, 0, 0,
(SCM vec),
"Return a new list initialized with the elements\n"
"of the bitvector @var{vec}.")
#define FUNC_NAME s_scm_bitvector_to_list
{
size_t off, len;
ssize_t inc;
SCM res = SCM_EOL;
const uint32_t *bits = scm_array1_bit_elements (vec, &len, &inc, &off);
if (off == 0 && inc == 1)
{
/* the usual case
*/
size_t word_len = (len + 31) / 32;
size_t i, j;
for (i = 0; i < word_len; i++, len -= 32)
{
uint32_t mask = 1;
for (j = 0; j < 32 && j < len; j++, mask <<= 1)
res = scm_cons ((bits[i] & mask)? SCM_BOOL_T : SCM_BOOL_F, res);
}
}
else
{
size_t i;
for (i = 0; i < len; i++)
res = scm_cons (scm_from_bool (bitref_ (bits, off+i*inc)), res);
}
return scm_reverse_x (res, SCM_EOL);
}
#undef FUNC_NAME
/* From mmix-arith.w by Knuth.
Here's a fun way to count the number of bits in a tetrabyte.
[This classical trick is called the ``Gillies--Miller method for
sideways addition'' in {\sl The Preparation of Programs for an
Electronic Digital Computer\/} by Wilkes, Wheeler, and Gill, second
edition (Reading, Mass.:\ Addison--Wesley, 1957), 191--193. Some of
the tricks used here were suggested by Balbir Singh, Peter
Rossmanith, and Stefan Schwoon.]
*/
static size_t
count_ones (uint32_t x)
{
x=x-((x>>1)&0x55555555);
x=(x&0x33333333)+((x>>2)&0x33333333);
x=(x+(x>>4))&0x0f0f0f0f;
x=x+(x>>8);
return (x+(x>>16)) & 0xff;
}
SCM_DEFINE (scm_bit_count, "bit-count", 2, 0, 0,
(SCM b, SCM bitvector),
"Return the number of occurrences of the boolean @var{b} in\n"
"@var{bitvector}.")
#define FUNC_NAME s_scm_bit_count
{
size_t off, len;
ssize_t inc;
int bit = scm_to_bool (b);
size_t count = 0;
const uint32_t *bits = scm_array1_bit_elements (bitvector, &len, &inc, &off);
if (off == 0 && inc == 1 && len > 0)
{
/* the usual case
*/
size_t word_len = (len + 31) / 32;
uint32_t last_mask = ((uint32_t)-1) >> (32*word_len - len);
size_t i;
for (i = 0; i < word_len-1; i++)
count += count_ones (bits[i]);
count += count_ones (bits[i] & last_mask);
}
else
{
size_t i;
for (i = 0; i < len; i++)
if (bitref_ (bits, off+i*inc))
count++;
}
return scm_from_size_t (bit? count : len-count);
}
#undef FUNC_NAME
/* returns 32 for x == 0.
*/
static size_t
find_first_one (uint32_t x)
{
size_t pos = 0;
/* do a binary search in x. */
if ((x & 0xFFFF) == 0)
x >>= 16, pos += 16;
if ((x & 0xFF) == 0)
x >>= 8, pos += 8;
if ((x & 0xF) == 0)
x >>= 4, pos += 4;
if ((x & 0x3) == 0)
x >>= 2, pos += 2;
if ((x & 0x1) == 0)
pos += 1;
return pos;
}
SCM_DEFINE (scm_bit_position, "bit-position", 3, 0, 0,
(SCM item, SCM v, SCM k),
"Return the index of the first occurrence of @var{item} in bit\n"
"vector @var{v}, starting from @var{k}. If there is no\n"
"@var{item} entry between @var{k} and the end of\n"
"@var{v}, then return @code{#f}. For example,\n"
"\n"
"@example\n"
"(bit-position #t #*000101 0) @result{} 3\n"
"(bit-position #f #*0001111 3) @result{} #f\n"
"@end example")
#define FUNC_NAME s_scm_bit_position
{
size_t off, len;
ssize_t inc;
const uint32_t *bits = scm_array1_bit_elements (v, &len, &inc, &off);
int bit = scm_to_bool (item);
SCM res = SCM_BOOL_F;
size_t first_bit = scm_to_unsigned_integer (k, 0, len);
if (off == 0 && inc == 1 && len > 0)
{
size_t word_len = (len + 31) / 32;
uint32_t last_mask = ((uint32_t)-1) >> (32*word_len - len);
size_t first_word = first_bit / 32;
uint32_t first_mask =
((uint32_t)-1) << (first_bit - 32*first_word);
uint32_t w;
for (size_t i = first_word; i < word_len; i++)
{
w = (bit? bits[i] : ~bits[i]);
if (i == first_word)
w &= first_mask;
if (i == word_len-1)
w &= last_mask;
if (w)
{
res = scm_from_size_t (32*i + find_first_one (w));
break;
}
}
}
else
{
for (size_t i = first_bit; i < len; i++)
{
if (bit == bitref_ (bits, off+i*inc))
{
res = scm_from_size_t (i);
break;
}
}
}
return res;
}
#undef FUNC_NAME
SCM_DEFINE (scm_bit_set_star_x, "bit-set*!", 3, 0, 0,
(SCM v, SCM kv, SCM obj),
"Set entries of bit vector @var{v} to @var{obj}, with @var{kv}\n"
"selecting the entries to change. The return value is\n"
"unspecified.\n"
"\n"
"If @var{kv} is a bit vector, then those entries where it has\n"
"@code{#t} are the ones in @var{v} which are set to @var{obj}.\n"
"@var{v} must be at least as long as @var{kv}. When @var{obj}\n"
"is @code{#t} it's like @var{kv} is OR'ed into @var{v}. Or when\n"
"@var{obj} is @code{#f} it can be seen as an ANDNOT.\n"
"\n"
"@example\n"
"(define bv #*01000010)\n"
"(bit-set*! bv #*10010001 #t)\n"
"bv\n"
"@result{} #*11010011\n"
"@end example\n"
"\n"
"If @var{kv} is a u32vector, then its elements are\n"
"indices into @var{v} which are set to @var{obj}.\n"
"\n"
"@example\n"
"(define bv #*01000010)\n"
"(bit-set*! bv #u32(5 2 7) #t)\n"
"bv\n"
"@result{} #*01100111\n"
"@end example")
#define FUNC_NAME s_scm_bit_set_star_x
{
size_t v_off, v_len;
ssize_t v_inc;
/* Validate that OBJ is a boolean so this is done even if we don't
need BIT.
*/
int bit = scm_to_bool (obj);
uint32_t *v_bits = scm_array1_bit_writable_elements (v, &v_len, &v_inc, &v_off);
if (scm_is_bitvector (kv))
{
size_t kv_off, kv_len;
ssize_t kv_inc;
const uint32_t *kv_bits = scm_array1_bit_elements (kv, &kv_len, &kv_inc, &kv_off);
if (v_len < kv_len)
scm_misc_error (NULL,
"bit vectors must have equal length",
SCM_EOL);
if (v_off == 0 && v_inc == 1 && kv_off == 0 && kv_inc == 1 && kv_len > 0)
{
size_t word_len = (kv_len + 31) / 32;
uint32_t last_mask = ((uint32_t)-1) >> (32*word_len - kv_len);
size_t i;
if (bit == 0)
{
for (i = 0; i < word_len-1; i++)
v_bits[i] &= ~kv_bits[i];
v_bits[i] &= ~(kv_bits[i] & last_mask);
}
else
{
for (i = 0; i < word_len-1; i++)
v_bits[i] |= kv_bits[i];
v_bits[i] |= kv_bits[i] & last_mask;
}
}
else
{
size_t i;
for (i = 0; i < kv_len; i++)
if (bitref_ (kv_bits, kv_off+i*kv_inc))
bitset_ (v_bits, v_off+i*v_inc, bit);
}
}
else if (scm_is_true (scm_u32vector_p (kv)))
{
size_t kv_len;
const uint32_t *kv_elts = scm_u32vector_elements (kv, &kv_len);
for (size_t i = 0; i < kv_len; i++)
bitset_ (v_bits, v_off+(kv_elts[i])*v_inc, bit);
}
else
scm_wrong_type_arg_msg (NULL, 0, kv, "bitvector or u32vector");
return SCM_UNSPECIFIED;
}
#undef FUNC_NAME
SCM_DEFINE (scm_bit_count_star, "bit-count*", 3, 0, 0,
(SCM v, SCM kv, SCM obj),
"Return a count of how many entries in bit vector @var{v} are\n"
"equal to @var{obj}, with @var{kv} selecting the entries to\n"
"consider.\n"
"\n"
"If @var{kv} is a bit vector, then those entries where it has\n"
"@code{#t} are the ones in @var{v} which are considered.\n"
"@var{kv} and @var{v} must be the same length.\n"
"\n"
"If @var{kv} is a u32vector, then it contains\n"
"the indexes in @var{v} to consider.\n"
"\n"
"For example,\n"
"\n"
"@example\n"
"(bit-count* #*01110111 #*11001101 #t) @result{} 3\n"
"(bit-count* #*01110111 #u32(7 0 4) #f) @result{} 2\n"
"@end example")
#define FUNC_NAME s_scm_bit_count_star
{
size_t v_off, v_len;
ssize_t v_inc;
size_t count = 0;
/* Validate that OBJ is a boolean so this is done even if we don't
need BIT.
*/
int bit = scm_to_bool (obj);
const uint32_t *v_bits = scm_array1_bit_elements (v, &v_len, &v_inc, &v_off);
if (scm_is_bitvector (kv))
{
size_t kv_off, kv_len;
ssize_t kv_inc;
const uint32_t *kv_bits = scm_array1_bit_elements (kv, &kv_len, &kv_inc, &kv_off);
if (v_len != kv_len)
scm_misc_error (NULL,
"bit vectors must have equal length",
SCM_EOL);
if (v_off == 0 && v_inc == 1 && kv_off == 0 && kv_inc == 1 && kv_len > 0)
{
size_t i, word_len = (kv_len + 31) / 32;
uint32_t last_mask = ((uint32_t)-1) >> (32*word_len - kv_len);
uint32_t xor_mask = bit? 0 : ((uint32_t)-1);
for (i = 0; i+1 < word_len; i++)
count += count_ones ((v_bits[i]^xor_mask) & kv_bits[i]);
count += count_ones ((v_bits[i]^xor_mask) & kv_bits[i] & last_mask);
}
else
{
for (size_t i = 0; i < kv_len; i++)
if (bitref_ (kv_bits, kv_off+i*kv_inc) == bitref_ (v_bits, v_off+i*v_inc))
count++;
}
}
/* FIXME This requires a true u32vector so handle, inc, etc. are superfluous */
else if (scm_is_true (scm_u32vector_p (kv)))
{
size_t kv_len;
const uint32_t *kv_elts = scm_u32vector_elements (kv, &kv_len);
for (size_t i = 0; i < kv_len; i++)
{
bool elt = bitref_ (v_bits, v_off+(kv_elts[i])*v_inc);
if ((bit && elt) || (!bit && !elt))
count++;
}
}
else
scm_wrong_type_arg_msg (NULL, 0, kv, "bitvector or u32vector");
return scm_from_size_t (count);
}
#undef FUNC_NAME
SCM_DEFINE (scm_bit_invert_x, "bit-invert!", 1, 0, 0,
(SCM v),
"Modify the bit vector @var{v} by replacing each element with\n"
"its negation.")
#define FUNC_NAME s_scm_bit_invert_x
{
size_t off, len;
ssize_t inc;
uint32_t *bits = scm_array1_bit_writable_elements (v, &len, &inc, &off);
/* FIXME could easily deal with off!=0 here */
if (off == 0 && inc == 1 && len > 0)
{
size_t i, word_len = (len + 31) / 32;
uint32_t last_mask = ((uint32_t)-1) >> (32*word_len - len);
for (i = 0; i < word_len-1; i++)
bits[i] = ~bits[i];
bits[i] = bits[i] ^ last_mask;
}
else
{
for (size_t i = 0; i < len; i++)
bitset_ (bits, off+i*inc, !(bitref_ (bits, off+i*inc)));
}
return SCM_UNSPECIFIED;
}
#undef FUNC_NAME
SCM
scm_istr2bve (SCM str)
{
size_t len = scm_i_string_length (str);
SCM vec = scm_c_make_bitvector (len, SCM_UNDEFINED);
SCM res = vec;
uint32_t mask;
size_t k, j;
const char *c_str;
uint32_t *data;
data = scm_bitvector_writable_elements (vec);
c_str = scm_i_string_chars (str);
for (k = 0; k < (len + 31) / 32; k++)
{
data[k] = 0L;
j = len - k * 32;
if (j > 32)
j = 32;
for (mask = 1L; j--; mask <<= 1)
switch (*c_str++)
{
case '0':
break;
case '1':
data[k] |= mask;
break;
default:
res = SCM_BOOL_F;
goto exit;
}
}
exit:
scm_remember_upto_here_1 (str);
return res;
}
SCM_VECTOR_IMPLEMENTATION (SCM_ARRAY_ELEMENT_TYPE_BIT, scm_make_bitvector)
void
scm_init_bitvectors ()
{
#include "bitvectors.x"
}