Alien-Judy
view release on metacpan or search on metacpan
src/judy-1.0.5/src/JudyCommon/JudyPrevNextEmpty.c view on Meta::CPAN
// no reason to search it. "Slide right" to the high end of the leaf
// (modify Index to maxindex) and continue with step 2 above.
//
// 3c. If LESS, continue with step 4.
//
// 4. If the offset based on maxindex minus Index falls BEFORE the start of
// the leaf, or if, per 3c above, baseindex is LESS than Index, the leaf is
// guaranteed "not dense to the end" and a usable empty Index must exist.
// This supports a more efficient search loop. Start at the FIRST index in
// the leaf, or one BEYOND baseindex, respectively, and search the leaf as
// follows, comparing each current index (currindex) with Index:
//
// 4a. If LESS, keep going to next index. Note: This is certain to terminate
// because maxindex is known to be greater than Index, hence the loop can
// be small and fast.
//
// 4b. If EQUAL, loop and increment Index until finding currindex greater than
// Index, and return success with the modified Index.
//
// 4c. If GREATER, return success, Index (unmodified) is empty.
//
// Note: These are macros rather than functions for speed.
#ifdef JUDYPREV
#define JSLE_EVEN(Addr,Pop0,cDigits,LeafType) \
{ \
LeafType * PjllLSB = (LeafType *) (Addr); \
LeafType IndexLSB = Index; /* auto-masking */ \
\
/* Index before or at start of leaf: */ \
\
if (*PjllLSB >= IndexLSB) /* no need to search */ \
{ \
if (*PjllLSB > IndexLSB) RET_SUCCESS; /* Index empty */ \
LEAF_EDGE(*PjllLSB, cDigits); \
} \
\
/* Index in or after leaf: */ \
\
offset = IndexLSB - *PjllLSB; /* tentative offset */ \
if (offset <= (Pop0)) /* can check density */ \
{ \
PjllLSB += offset; /* move to slot */ \
\
if (*PjllLSB <= IndexLSB) /* dense or corrupt */ \
{ \
if (*PjllLSB == IndexLSB) /* dense, check edge */ \
LEAF_EDGE_SET(PjllLSB[-offset], cDigits); \
RET_CORRUPT; \
} \
--PjllLSB; /* not dense, start at previous */ \
} \
else PjllLSB = ((LeafType *) (Addr)) + (Pop0); /* start at max */ \
\
LEAF_HOLE_EVEN(cDigits, PjllLSB, IndexLSB); \
}
// JSLE_ODD is completely different from JSLE_EVEN because its important to
// minimize copying odd indexes to compare them (see 4.14). Furthermore, a
// very complex version (4.17, but abandoned before fully debugged) that
// avoided calling j__udySearchLeaf*() ran twice as fast as 4.14, but still
// half as fast as SearchValid. Doug suggested that to minimize complexity and
// share common code we should use j__udySearchLeaf*() for the initial search
// to establish if Index is empty, which should be common. If Index is valid
// in a leaf or immediate indexes, odds are good that an empty Index is nearby,
// so for simplicity just use a *COPY* function to linearly search the
// remainder.
//
// TBD: Pathological case? Average performance should be good, but worst-case
// might suffer. When Search says the initial Index is valid, so a linear
// copy-and-compare is begun, if the caller builds fairly large leaves with
// dense clusters AND frequently does a SearchEmpty at one end of such a
// cluster, performance wont be very good. Might a dense-check help? This
// means checking offset against the index at offset, and then against the
// first/last index in the leaf. We doubt the pathological case will appear
// much in real applications because they will probably alternate SearchValid
// and SearchEmpty calls.
#define JSLE_ODD(cDigits,Pjll,Pop0,Search,Copy) \
{ \
Word_t IndexLSB; /* least bytes only */ \
Word_t IndexFound; /* in leaf */ \
\
if ((offset = Search(Pjll, (Pop0) + 1, Index)) < 0) \
RET_SUCCESS; /* Index is empty */ \
\
IndexLSB = JU_LEASTBYTES(Index, cDigits); \
offset *= (cDigits); \
\
while ((offset -= (cDigits)) >= 0) \
{ /* skip until empty or start */ \
Copy(IndexFound, ((uint8_t *) (Pjll)) + offset); \
if (IndexFound != (--IndexLSB)) /* found an empty */ \
{ JU_SETDIGITS(Index, IndexLSB, cDigits); RET_SUCCESS; }\
} \
LEAF_EDGE_SET(IndexLSB, cDigits); \
}
#else // JUDYNEXT
#define JSLE_EVEN(Addr,Pop0,cDigits,LeafType) \
{ \
LeafType * PjllLSB = ((LeafType *) (Addr)) + (Pop0); \
LeafType IndexLSB = Index; /* auto-masking */ \
\
/* Index at or after end of leaf: */ \
\
if (*PjllLSB <= IndexLSB) /* no need to search */ \
{ \
if (*PjllLSB < IndexLSB) RET_SUCCESS; /* Index empty */\
LEAF_EDGE(*PjllLSB, cDigits); \
} \
\
/* Index before or in leaf: */ \
\
offset = *PjllLSB - IndexLSB; /* tentative offset */ \
if (offset <= (Pop0)) /* can check density */ \
{ \
PjllLSB -= offset; /* move to slot */ \
\
( run in 1.028 second using v1.01-cache-2.11-cpan-5511b514fd6 )