Algorithm-BinarySearch-Vec
view release on metacpan or search on metacpan
/*-*- Mode: C -*-*/
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include <inttypes.h>
/*#include "ppport.h"*/
#ifndef uchar
typedef unsigned char uchar;
#endif
#ifdef U64TYPE
#define ABSV_HAVE_QUAD
#define ABSV_UINT U64TYPE
#define ABSV_PRI "%" PRIu64
#else
#undef ABSV_HAVE_QUAD
#define ABSV_UINT U32
#define ABSV_PRI "%" PRIu32
#endif /* U64TYPE */
//const ABSV_UINT KEY_NOT_FOUND = (ABSV_UINT)-1;
const ABSV_UINT KEY_NOT_FOUND = 0xffffffff; /*-- still always just 32-bit --*/
/*==============================================================================
* Utils
*/
//--------------------------------------------------------------
static inline int absv_cmp(ABSV_UINT a, ABSV_UINT b)
{
if (a<b) return -1;
else if (a>b) return 1;
return 0;
}
//--------------------------------------------------------------
static inline ABSV_UINT absv_vget(const uchar *v, ABSV_UINT i, ABSV_UINT nbits)
{
//fprintf(stderr, "DEBUG: absv_vget() called with INDEX=%lu, NBITS=%lu\n", i, nbits);
switch (nbits) {
case 1: return (v[i>>3] >> (i&7) ) & 1;
case 2: return (v[i>>2] >> ((i&3)<<1)) & 3;
case 4: return (v[i>>1] >> ((i&1)<<2)) & 15;
case 8: return (v[i]);
case 16: i <<= 1; return (v[i]<<8) | (v[i+1]);
case 32: i <<= 2; return (v[i]<<24) | (v[i+1]<<16) | (v[i+2]<<8) | (v[i+3]);
#ifdef ABSV_HAVE_QUAD
case 64:
i <<= 3;
return ((ABSV_UINT)(v[i] )<<56) | ((ABSV_UINT)(v[i+1])<<48) | ((ABSV_UINT)(v[i+2])<<40) | ((ABSV_UINT)(v[i+3])<<32)
|((ABSV_UINT)(v[i+4])<<24) | ((ABSV_UINT)(v[i+5])<<16) | ((ABSV_UINT)(v[i+6])<< 8) | ((ABSV_UINT)(v[i+7]) );
#endif
default: break;
}
croak("absv_vget() cannot handle NBITS=" ABSV_PRI " for INDEX=" ABSV_PRI, nbits, i);
return KEY_NOT_FOUND;
}
//--------------------------------------------------------------
static inline void absv_vset(uchar *v, ABSV_UINT i, ABSV_UINT nbits, ABSV_UINT val)
{
ABSV_UINT b;
switch (nbits) {
case 1: b=i&7; i>>=3; v[i] = (v[i]&~( 1<<b)) | ((val& 1)<<b); break;
case 2: b=(i&3)<<1; i>>=2; v[i] = (v[i]&~( 3<<b)) | ((val& 3)<<b); break;
case 4: b=(i&1)<<2; i>>=1; v[i] = (v[i]&~(15<<b)) | ((val&15)<<b); break;
case 8: v[i] = (val & 255); break;
case 16: v += (i<<1); *v++=(val>> 8)&0xff; *v=(val&0xff); break;
case 32: v += (i<<2); *v++=(val>>24)&0xff; *v++=(val>>16)&0xff; *v++=(val>>8)&0xff; *v=val&0xff; break;
#ifdef ABSV_HAVE_QUAD
case 64:
v += (i<<3);
*v++=(val>>56)&0xff; *v++=(val>>48)&0xff; *v++=(val>>40)&0xff; *v++=(val>>32)&0xff;
*v++=(val>>24)&0xff; *v++=(val>>16)&0xff; *v++=(val>> 8)&0xff; *v =val &0xff;
break;
#endif
default:
croak("absv_vset() cannot handle NBITS=" ABSV_PRI " for INDEX=" ABSV_PRI, nbits, i);
break;
}
}
//--------------------------------------------------------------
static ABSV_UINT absv_bsearch(const uchar *v, ABSV_UINT key, ABSV_UINT ilo, ABSV_UINT ihi, ABSV_UINT nbits)
{
while (ilo < ihi) {
ABSV_UINT imid = (ilo+ihi) >> 1;
if (absv_vget(v, imid, nbits) < key)
ilo = imid + 1;
else
ihi = imid;
}
if ((ilo == ihi) && (absv_vget(v,ilo,nbits) == key))
return ilo;
else
return KEY_NOT_FOUND;
}
//--------------------------------------------------------------
( run in 2.153 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )