KinoSearch1
view release on metacpan or search on metacpan
lib/KinoSearch1/Util/BitVector.pm view on Meta::CPAN
package KinoSearch1::Util::BitVector;
use strict;
use warnings;
use KinoSearch1::Util::ToolSet;
use base qw( KinoSearch1::Util::CClass );
BEGIN {
__PACKAGE__->init_instance_vars(
# constructor params
capacity => 0,
);
}
1;
__END__
__XS__
MODULE = KinoSearch1 PACKAGE = KinoSearch1::Util::BitVector
void
new(either_sv, ...)
SV *either_sv;
PREINIT:
const char *class;
HV *args_hash;
U32 capacity;
BitVector *bit_vec;
PPCODE:
/* determine the class */
class = sv_isobject(either_sv)
? sv_reftype(either_sv, 0)
: SvPV_nolen(either_sv);
/* process hash-style params */
Kino1_Verify_build_args_hash(args_hash,
"KinoSearch1::Util::BitVector::instance_vars", 1);
capacity = (U32)SvUV( Kino1_Verify_extract_arg(args_hash, "capacity", 8) );
/* build object */
bit_vec = Kino1_BitVec_new(capacity);
ST(0) = sv_newmortal();
sv_setref_pv(ST(0), class, (void*)bit_vec);
XSRETURN(1);
=for comment
Return true if the bit indcated by $num has been set, false if it hasn't
(regardless of whether $num lies within the bounds of the object's capacity).
=cut
bool
get(bit_vec, num)
BitVector *bit_vec;
U32 num;
CODE:
RETVAL = Kino1_BitVec_get(bit_vec, num);
OUTPUT: RETVAL
=for comment
Set the bit at $num to 1.
=cut
void
set(bit_vec, ...)
BitVector *bit_vec;
PREINIT:
U32 i, num;
PPCODE:
for (i = 1; i < items; i++) {
num = (U32)( SvUV( ST(i) ) );
Kino1_BitVec_set(bit_vec, num);
}
=for comment
Clear the bit at $num (i.e. set it to 0).
=cut
void
clear(bit_vec, num)
BitVector *bit_vec;
U32 num;
PPCODE:
Kino1_BitVec_clear(bit_vec, num);
=for comment
Set all the bits bounded by $first and $last, inclusive, to 1.
=cut
void
bulk_set(bit_vec, first, last)
BitVector *bit_vec;
U32 first;
U32 last;
PPCODE:
Kino1_BitVec_bulk_set(bit_vec, first, last);
=for comment
Clear all the bits bounded by $first and $last, inclusive.
=cut
void
bulk_clear(bit_vec, first, last)
BitVector *bit_vec;
U32 first;
U32 last;
PPCODE:
Kino1_BitVec_bulk_clear(bit_vec, first, last);
=for comment
Given $num, return either $num (if it is set), the next set bit above it, or
if no such bit exists, undef (from Perl) or a sentinel (0xFFFFFFFF) from C.
=cut
SV*
next_set_bit(bit_vec, num)
BitVector *bit_vec;
U32 num;
CODE:
num = Kino1_BitVec_next_set_bit(bit_vec, num);
RETVAL = num == KINO_BITVEC_SENTINEL ? &PL_sv_undef : newSVuv(num);
OUTPUT: RETVAL
=for comment
Given $num, return $num (if it is clear), or the next clear bit above it.
The highest number that next_clear_bit can return is the object's capacity.
=cut
SV*
next_clear_bit(bit_vec, num)
BitVector *bit_vec;
U32 num;
CODE:
num = Kino1_BitVec_next_clear_bit(bit_vec, num);
RETVAL = num == KINO_BITVEC_SENTINEL ? &PL_sv_undef : newSVuv(num);
OUTPUT: RETVAL
=for comment
Modify the BitVector so that only bits which remain set are those which 1)
were already set in this BitVector, and 2) were also set in the other
BitVector.
=cut
void
logical_and(bit_vec, other)
BitVector *bit_vec;
BitVector *other;
PPCODE:
Kino1_BitVec_logical_and(bit_vec, other);
=for comment
Return a count of the number of set bits in the BitVector.
=cut
U32
count(bit_vec)
BitVector *bit_vec;
CODE:
RETVAL = Kino1_BitVec_count(bit_vec);
OUTPUT: RETVAL
=for comment
Return an arrayref of the with each element the number of a set bit.
=cut
void
to_arrayref(bit_vec)
BitVector *bit_vec;
PREINIT:
AV *out_av;
PPCODE:
out_av = Kino1_BitVec_to_array(bit_vec);
XPUSHs( sv_2mortal(newRV_noinc( (SV*)out_av )) );
XSRETURN(1);
=for comment
Setters and getters. A quirk: set_bits automatically adjusts capacity
upwards to the appropriate multiple of 8 if necessary.
=cut
SV*
_set_or_get(bit_vec, ...)
BitVector *bit_vec;
ALIAS:
set_capacity = 1
get_capacity = 2
set_bits = 3
get_bits = 4
PREINIT:
STRLEN len;
U32 new_capacity;
char *new_bits;
CODE:
{
KINO_START_SET_OR_GET_SWITCH
case 1: new_capacity = SvUV(ST(1));
if (new_capacity < bit_vec->capacity) {
Kino1_BitVec_shrink(bit_vec, new_capacity);
}
else if (new_capacity > bit_vec->capacity) {
Kino1_BitVec_grow(bit_vec, new_capacity);
}
/* fall through */
case 2: RETVAL = newSVuv(bit_vec->capacity);
break;
case 3: Kino1_Safefree(bit_vec->bits);
new_bits = SvPV(ST(1), len);
bit_vec->bits = (unsigned char*)Kino1_savepvn(new_bits, len);
bit_vec->capacity = len << 3;
/* fall through */
case 4: len = ceil(bit_vec->capacity / 8.0);
RETVAL = newSVpv((char*)bit_vec->bits, len);
break;
KINO_END_SET_OR_GET_SWITCH
}
OUTPUT: RETVAL
void
DESTROY(bit_vec)
BitVector *bit_vec;
PPCODE:
Kino1_BitVec_destroy(bit_vec);
__H__
#ifndef H_KINO_BIT_VECTOR
#define H_KINO_BIT_VECTOR 1
#include "limits.h"
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "KinoSearch1UtilMathUtils.h"
#include "KinoSearch1UtilCarp.h"
#include "KinoSearch1UtilMemManager.h"
#define KINO_BITVEC_SENTINEL 0xFFFFFFFF
typedef struct bitvector {
U32 capacity;
unsigned char *bits;
} BitVector;
BitVector* Kino1_BitVec_new(U32);
BitVector* Kino1_BitVec_clone(BitVector*);
void Kino1_BitVec_grow(BitVector*, U32);
void Kino1_BitVec_shrink(BitVector *, U32);
void Kino1_BitVec_set(BitVector*, U32);
void Kino1_BitVec_clear(BitVector*, U32);
void Kino1_BitVec_bulk_set(BitVector*, U32, U32);
void Kino1_BitVec_bulk_clear(BitVector*, U32, U32);
bool Kino1_BitVec_get(BitVector*, U32);
U32 Kino1_BitVec_next_set_bit(BitVector*, U32);
U32 Kino1_BitVec_next_clear_bit(BitVector*, U32);
void Kino1_BitVec_logical_and(BitVector*, BitVector*);
U32 Kino1_BitVec_count(BitVector*);
AV* Kino1_BitVec_to_array(BitVector*);
void Kino1_BitVec_destroy(BitVector*);
#endif /* include guard */
__C__
#include "KinoSearch1UtilBitVector.h"
static unsigned char bitmasks[] = {
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
};
BitVector*
Kino1_BitVec_new(U32 capacity) {
BitVector *bit_vec;
Kino1_New(0, bit_vec, 1, BitVector);
bit_vec->capacity = 0;
bit_vec->bits = NULL;
Kino1_BitVec_grow(bit_vec, capacity);
return bit_vec;
}
BitVector*
( run in 0.524 second using v1.01-cache-2.11-cpan-5511b514fd6 )