Example #1
0
FUNCTION static Word_t j__udyGetMemActive(
	Pjp_t  Pjp)		// top of subtree.
{
	Word_t offset;		// in a branch.
	Word_t Bytes = 0;	// actual bytes used at this level.
	Word_t IdxSz;		// bytes per index in leaves

	switch (JU_JPTYPE(Pjp))
	{

	case cJU_JPBRANCH_L2:
	case cJU_JPBRANCH_L3:
#ifdef JU_64BIT
	case cJU_JPBRANCH_L4:
	case cJU_JPBRANCH_L5:
	case cJU_JPBRANCH_L6:
	case cJU_JPBRANCH_L7:
#endif
	case cJU_JPBRANCH_L:
	{
	    Pjbl_t Pjbl = P_JBL(Pjp->jp_Addr);

	    for (offset = 0; offset < (Pjbl->jbl_NumJPs); ++offset)
	        Bytes += j__udyGetMemActive((Pjbl->jbl_jp) + offset);

	    return(Bytes + sizeof(jbl_t));
	}

	case cJU_JPBRANCH_B2:
	case cJU_JPBRANCH_B3:
#ifdef JU_64BIT
	case cJU_JPBRANCH_B4:
	case cJU_JPBRANCH_B5:
	case cJU_JPBRANCH_B6:
	case cJU_JPBRANCH_B7:
#endif
	case cJU_JPBRANCH_B:
	{
	    Word_t subexp;
	    Word_t jpcount;
	    Pjbb_t Pjbb = P_JBB(Pjp->jp_Addr);

	    for (subexp = 0; subexp < cJU_NUMSUBEXPB; ++subexp)
	    {
	        jpcount = j__udyCountBitsB(JU_JBB_BITMAP(Pjbb, subexp));
                Bytes  += jpcount * sizeof(jp_t);

		for (offset = 0; offset < jpcount; ++offset)
		{
		    Bytes += j__udyGetMemActive(P_JP(JU_JBB_PJP(Pjbb, subexp))
			   + offset);
		}
	    }

	    return(Bytes + sizeof(jbb_t));
	}

	case cJU_JPBRANCH_U2:
	case cJU_JPBRANCH_U3:
#ifdef JU_64BIT
	case cJU_JPBRANCH_U4:
	case cJU_JPBRANCH_U5:
	case cJU_JPBRANCH_U6:
	case cJU_JPBRANCH_U7:
#endif
	case cJU_JPBRANCH_U:
        {
	    Pjbu_t Pjbu = P_JBU(Pjp->jp_Addr);

            for (offset = 0; offset < cJU_BRANCHUNUMJPS; ++offset)
	    {
		if (((Pjbu->jbu_jp[offset].jp_Type) >= cJU_JPNULL1)
		 && ((Pjbu->jbu_jp[offset].jp_Type) <= cJU_JPNULLMAX))
		{
		    continue;		// skip null JP to save time.
		}

	        Bytes += j__udyGetMemActive(Pjbu->jbu_jp + offset);
	    }

	    return(Bytes + sizeof(jbu_t));
        }


// -- Cases below here terminate and do not recurse. --

#if (defined(JUDYL) || (! defined(JU_64BIT)))
        case cJU_JPLEAF1: IdxSz = 1; goto LeafWords;
#endif
	case cJU_JPLEAF2: IdxSz = 2; goto LeafWords;
	case cJU_JPLEAF3: IdxSz = 3; goto LeafWords;
#ifdef JU_64BIT
	case cJU_JPLEAF4: IdxSz = 4; goto LeafWords;
	case cJU_JPLEAF5: IdxSz = 5; goto LeafWords;
	case cJU_JPLEAF6: IdxSz = 6; goto LeafWords;
	case cJU_JPLEAF7: IdxSz = 7; goto LeafWords;
#endif
LeafWords:

#ifdef JUDY1
            return(IdxSz * (JU_JPLEAF_POP0(Pjp) + 1));
#else
            return((IdxSz + sizeof(Word_t))
		 * (JU_JPLEAF_POP0(Pjp) + 1));
#endif
	case cJU_JPLEAF_B1:
	{
#ifdef JUDY1
            return(sizeof(jlb_t));
#else
            Bytes = (JU_JPLEAF_POP0(Pjp) + 1) * sizeof(Word_t);

	    return(Bytes + sizeof(jlb_t));
#endif
	}

	JUDY1CODE(case cJ1_JPFULLPOPU1: return(0);)

#ifdef JUDY1
#define J__Mpy 0
#else
#define J__Mpy sizeof(Word_t)
#endif

	case cJU_JPIMMED_1_01:	return(0);
	case cJU_JPIMMED_2_01:	return(0);
	case cJU_JPIMMED_3_01:	return(0);
#ifdef JU_64BIT
	case cJU_JPIMMED_4_01:	return(0);
	case cJU_JPIMMED_5_01:	return(0);
	case cJU_JPIMMED_6_01:	return(0);
	case cJU_JPIMMED_7_01:	return(0);
#endif

	case cJU_JPIMMED_1_02:	return(J__Mpy * 2);
	case cJU_JPIMMED_1_03:	return(J__Mpy * 3);
#if (defined(JUDY1) || defined(JU_64BIT))
	case cJU_JPIMMED_1_04:	return(J__Mpy * 4);
	case cJU_JPIMMED_1_05:	return(J__Mpy * 5);
	case cJU_JPIMMED_1_06:	return(J__Mpy * 6);
	case cJU_JPIMMED_1_07:	return(J__Mpy * 7);
#endif
#if (defined(JUDY1) && defined(JU_64BIT))
	case cJ1_JPIMMED_1_08:	return(0);
	case cJ1_JPIMMED_1_09:	return(0);
	case cJ1_JPIMMED_1_10:	return(0);
	case cJ1_JPIMMED_1_11:	return(0);
	case cJ1_JPIMMED_1_12:	return(0);
	case cJ1_JPIMMED_1_13:	return(0);
	case cJ1_JPIMMED_1_14:	return(0);
	case cJ1_JPIMMED_1_15:	return(0);
#endif

#if (defined(JUDY1) || defined(JU_64BIT))
	case cJU_JPIMMED_2_02:	return(J__Mpy * 2);
	case cJU_JPIMMED_2_03:	return(J__Mpy * 3);
#endif
#if (defined(JUDY1) && defined(JU_64BIT))
	case cJ1_JPIMMED_2_04:	return(0);
	case cJ1_JPIMMED_2_05:	return(0);
	case cJ1_JPIMMED_2_06:	return(0);
	case cJ1_JPIMMED_2_07:	return(0);
#endif

#if (defined(JUDY1) || defined(JU_64BIT))
	case cJU_JPIMMED_3_02:	return(J__Mpy * 2);
#endif
#if (defined(JUDY1) && defined(JU_64BIT))
	case cJ1_JPIMMED_3_03:	return(0);
	case cJ1_JPIMMED_3_04:	return(0);
	case cJ1_JPIMMED_3_05:	return(0);

	case cJ1_JPIMMED_4_02:	return(0);
	case cJ1_JPIMMED_4_03:	return(0);
	case cJ1_JPIMMED_5_02:	return(0);
	case cJ1_JPIMMED_5_03:	return(0);
	case cJ1_JPIMMED_6_02:	return(0);
	case cJ1_JPIMMED_7_02:	return(0);
#endif

	} // switch (JU_JPTYPE(Pjp))
Example #2
0
FUNCTION static Word_t j__udy1LCountSM(
const	Pjp_t	Pjp,		// top of Judy (sub)SM.
const	Word_t	Index,		// count at or above this Index.
const	Pjpm_t	Pjpm)		// for returning error info.
{
	Pjbl_t	Pjbl;		// Pjp->jp_Addr masked and cast to types:
	Pjbb_t	Pjbb;
	Pjbu_t	Pjbu;
	Pjll_t	Pjll;		// a Judy lower-level linear leaf.

	Word_t	digit;		// next digit to decode from Index.
	long	jpnum;		// JP number in a branch (base 0).
	int	offset;		// index ordinal within a leaf, base 0.
	Word_t	pop1;		// total population of an expanse.
	Word_t	pop1above;	// to return.

// Common code to check Decode bits in a JP against the equivalent portion of
// Index; XOR together, then mask bits of interest; must be all 0:
//
// Note:  Why does this code only assert() compliance rather than actively
// checking for outliers?  Its because Index is supposed to be valid, hence
// always match any Dcd bits traversed.
//
// Note:  This assertion turns out to be always true for cState = 3 on 32-bit
// and 7 on 64-bit, but its harmless, probably removed by the compiler.

#define	CHECKDCD(Pjp,cState) \
	assert(! JU_DCDNOTMATCHINDEX(Index, Pjp, cState))

// Common code to prepare to handle a root-level or lower-level branch:
// Extract a state-dependent digit from Index in a "constant" way, obtain the
// total population for the branch in a state-dependent way, and then branch to
// common code for multiple cases:
//
// For root-level branches, the state is always cJU_ROOTSTATE, and the
// population is received in Pjpm->jpm_Pop0.
//
// Note:  The total population is only needed in cases where the common code
// "counts up" instead of down to minimize cache line fills.  However, its
// available cheaply, and its better to do it with a constant shift (constant
// state value) instead of a variable shift later "when needed".

#define	PREPB_ROOT(Pjp,Next)				\
	digit = JU_DIGITATSTATE(Index, cJU_ROOTSTATE);	\
	pop1  = (Pjpm->jpm_Pop0) + 1;			\
	goto Next

#define	PREPB(Pjp,cState,Next)				\
	digit = JU_DIGITATSTATE(Index, cState);		\
	pop1  = JU_JPBRANCH_POP0(Pjp, (cState)) + 1;    \
	goto Next


// SWITCH ON JP TYPE:
//
// WARNING:  For run-time efficiency the following cases replicate code with
// varying constants, rather than using common code with variable values!

	switch (JU_JPTYPE(Pjp))
	{


// ----------------------------------------------------------------------------
// ROOT-STATE LEAF that starts with a Pop0 word; just count within the leaf:

	case cJU_LEAFW:
	{
	    Pjlw_t Pjlw = P_JLW(Pjp->jp_Addr);		// first word of leaf.

	    assert((Pjpm->jpm_Pop0) + 1 == Pjlw[0] + 1);  // sent correctly.
	    offset = j__udySearchLeafW(Pjlw + 1, Pjpm->jpm_Pop0 + 1, Index);
	    assert(offset >= 0);			// Index must exist.
	    assert(offset < (Pjpm->jpm_Pop0) + 1);	// Index be in range.
	    return((Pjpm->jpm_Pop0) + 1 - offset);	// INCLUSIVE of Index.
	}

// ----------------------------------------------------------------------------
// LINEAR BRANCH; count populations in JPs in the JBL ABOVE the next digit in
// Index, and recurse for the next digit in Index:
//
// Note:  There are no null JPs in a JBL; watch out for pop1 == 0.
//
// Note:  A JBL should always fit in one cache line => no need to count up
// versus down to save cache line fills.  (PREPB() sets pop1 for no reason.)

	case cJU_JPBRANCH_L2:  CHECKDCD(Pjp, 2); PREPB(Pjp, 2, BranchL);
	case cJU_JPBRANCH_L3:  CHECKDCD(Pjp, 3); PREPB(Pjp, 3, BranchL);

#ifdef JU_64BIT
	case cJU_JPBRANCH_L4:  CHECKDCD(Pjp, 4); PREPB(Pjp, 4, BranchL);
	case cJU_JPBRANCH_L5:  CHECKDCD(Pjp, 5); PREPB(Pjp, 5, BranchL);
	case cJU_JPBRANCH_L6:  CHECKDCD(Pjp, 6); PREPB(Pjp, 6, BranchL);
	case cJU_JPBRANCH_L7:  CHECKDCD(Pjp, 7); PREPB(Pjp, 7, BranchL);
#endif
	case cJU_JPBRANCH_L:   PREPB_ROOT(Pjp, BranchL);

// Common code (state-independent) for all cases of linear branches:

BranchL:

	Pjbl      = P_JBL(Pjp->jp_Addr);
	jpnum     = Pjbl->jbl_NumJPs;			// above last JP.
	pop1above = 0;

	while (digit < (Pjbl->jbl_Expanse[--jpnum]))	 // still ABOVE digit.
	{
	    if ((pop1 = j__udyJPPop1((Pjbl->jbl_jp) + jpnum)) == cJU_ALLONES)
	    {
		JU_SET_ERRNO_NONNULL(Pjpm, JU_ERRNO_CORRUPT);
		return(C_JERR);
	    }

	    pop1above += pop1;
	    assert(jpnum > 0);				// should find digit.
	}

	assert(digit == (Pjbl->jbl_Expanse[jpnum]));	// should find digit.

	pop1 = j__udy1LCountSM((Pjbl->jbl_jp) + jpnum, Index, Pjpm);
	if (pop1 == C_JERR) return(C_JERR);		// pass error up.

	assert(pop1above + pop1);
	return(pop1above + pop1);


// ----------------------------------------------------------------------------
// BITMAP BRANCH; count populations in JPs in the JBB ABOVE the next digit in
// Index, and recurse for the next digit in Index:
//
// Note:  There are no null JPs in a JBB; watch out for pop1 == 0.

	case cJU_JPBRANCH_B2:  CHECKDCD(Pjp, 2); PREPB(Pjp, 2, BranchB);
	case cJU_JPBRANCH_B3:  CHECKDCD(Pjp, 3); PREPB(Pjp, 3, BranchB);
#ifdef JU_64BIT
	case cJU_JPBRANCH_B4:  CHECKDCD(Pjp, 4); PREPB(Pjp, 4, BranchB);
	case cJU_JPBRANCH_B5:  CHECKDCD(Pjp, 5); PREPB(Pjp, 5, BranchB);
	case cJU_JPBRANCH_B6:  CHECKDCD(Pjp, 6); PREPB(Pjp, 6, BranchB);
	case cJU_JPBRANCH_B7:  CHECKDCD(Pjp, 7); PREPB(Pjp, 7, BranchB);
#endif
	case cJU_JPBRANCH_B:   PREPB_ROOT(Pjp, BranchB);

// Common code (state-independent) for all cases of bitmap branches:

BranchB:
	{
	    intptr_t subexp;	// for stepping through layer 1 (subexpanses).
	    intptr_t  findsub;	// subexpanse containing   Index (digit).
	    Word_t findbit;	// bit	      representing Index (digit).
	    Word_t lowermask;	// bits for indexes at or below Index.
	    Word_t jpcount;	// JPs in a subexpanse.
	    Word_t clbelow;	// cache lines below digits cache line.
	    Word_t clabove;	// cache lines above digits cache line.

	    Pjbb      = P_JBB(Pjp->jp_Addr);
	    findsub   = digit / cJU_BITSPERSUBEXPB;
	    findbit   = digit % cJU_BITSPERSUBEXPB;
	    lowermask = JU_MASKLOWERINC(JU_BITPOSMASKB(findbit));
	    clbelow   = clabove = 0;	// initial/default => always downward.

	    assert(JU_BITMAPTESTB(Pjbb, digit)); // digit must have a JP.
	    assert(findsub < cJU_NUMSUBEXPB);	 // falls in expected range.

// Shorthand for one subexpanse in a bitmap and for one JP in a bitmap branch:
//
// Note: BMPJP0 exists separately to support assertions.

#define	BMPJP0(Subexp)       (P_JP(JU_JBB_PJP(Pjbb, Subexp)))
#define	BMPJP(Subexp,JPnum)  (BMPJP0(Subexp) + (JPnum))

#ifndef NOSMARTJBB  // enable to turn off smart code for comparison purposes.

// FIGURE OUT WHICH DIRECTION CAUSES FEWER CACHE LINE FILLS; adding the pop1s
// in JPs above Indexs JP, or subtracting the pop1s in JPs below Indexs JP.
//
// This is tricky because, while each set bit in the bitmap represents a JP,
// the JPs are scattered over cJU_NUMSUBEXPB subexpanses, each of which can
// contain JPs packed into multiple cache lines, and this code must visit every
// JP either BELOW or ABOVE the JP for Index.
//
// Number of cache lines required to hold a linear list of the given number of
// JPs, assuming the first JP is at the start of a cache line or the JPs in
// jpcount fit wholly within a single cache line, which is ensured by
// JudyMalloc():

#define	CLPERJPS(jpcount) \
	((((jpcount) * cJU_WORDSPERJP) + cJU_WORDSPERCL - 1) / cJU_WORDSPERCL)

// Count cache lines below/above for each subexpanse:

	    for (subexp = 0; subexp < cJU_NUMSUBEXPB; ++subexp)
	    {
		jpcount = j__udyCountBitsB(JU_JBB_BITMAP(Pjbb, subexp));

// When at the subexpanse containing Index (digit), add cache lines
// below/above appropriately, excluding the cache line containing the JP for
// Index itself:

		if	(subexp <  findsub)  clbelow += CLPERJPS(jpcount);
		else if (subexp >  findsub)  clabove += CLPERJPS(jpcount);
		else // (subexp == findsub)
		{
		    Word_t clfind;	// cache line containing Index (digit).

		    clfind = CLPERJPS(j__udyCountBitsB(
				    JU_JBB_BITMAP(Pjbb, subexp) & lowermask));

		    assert(clfind > 0);	 // digit itself should have 1 CL.
		    clbelow += clfind - 1;
		    clabove += CLPERJPS(jpcount) - clfind;
		}
	    }
#endif // ! NOSMARTJBB

// Note:  Its impossible to get through the following "if" without setting
// jpnum -- see some of the assertions below -- but gcc -Wall doesnt know
// this, so preset jpnum to make it happy:

	    jpnum = 0;


// COUNT POPULATION FOR A BITMAP BRANCH, in whichever direction should result
// in fewer cache line fills:
//
// Note:  If the remainder of Index is zero, pop1above is the pop1 of the
// entire expanse and theres no point in recursing to lower levels; but this
// should be so rare that its not worth checking for;
// Judy1Count()/JudyLCount() never even calls the motor for Index == 0 (all
// bytes).


// COUNT UPWARD, subtracting each "below or at" JPs pop1 from the whole
// expanses pop1:
//
// Note:  If this causes clbelow + 1 cache line fills including JPs cache
// line, thats OK; at worst this is the same as clabove.

	    if (clbelow < clabove)
	    {
#ifdef SMARTMETRICS
		++jbb_upward;
#endif
		pop1above = pop1;		// subtract JPs at/below Index.

// Count JPs for which to accrue pop1s in this subexpanse:
//
// TBD:  If JU_JBB_BITMAP is cJU_FULLBITMAPB, dont bother counting.

		for (subexp = 0; subexp <= findsub; ++subexp)
		{
		    jpcount = j__udyCountBitsB((subexp < findsub) ?
				      JU_JBB_BITMAP(Pjbb, subexp) :
				      JU_JBB_BITMAP(Pjbb, subexp) & lowermask);

		    // should always find findbit:
		    assert((subexp < findsub) || jpcount);

// Subtract pop1s from JPs BELOW OR AT Index (digit):
//
// Note:  The pop1 for Indexs JP itself is partially added back later at a
// lower state.
//
// Note:  An empty subexpanse (jpcount == 0) is handled "for free".
//
// Note:  Must be null JP subexp pointer in empty subexpanse and non-empty in
// non-empty subexpanse:

		    assert(   jpcount  || (BMPJP0(subexp) == (Pjp_t) NULL));
		    assert((! jpcount) || (BMPJP0(subexp) != (Pjp_t) NULL));

		    for (jpnum = 0; jpnum < jpcount; ++jpnum)
		    {
			if ((pop1 = j__udyJPPop1(BMPJP(subexp, jpnum)))
			    == cJU_ALLONES)
			{
			    JU_SET_ERRNO_NONNULL(Pjpm, JU_ERRNO_CORRUPT);
			    return(C_JERR);
			}

			pop1above -= pop1;
		    }

		    jpnum = jpcount - 1;	// make correct for digit.
		}
	    }

// COUNT DOWNWARD, adding each "above" JPs pop1:

	    else
	    {
		long jpcountbf;			// below findbit, inclusive.
#ifdef SMARTMETRICS
		++jbb_downward;
#endif
		pop1above = 0;			// add JPs above Index.
		jpcountbf = 0;			// until subexp == findsub.

// Count JPs for which to accrue pop1s in this subexpanse:
//
// This is more complicated than counting upward because the scan of digits
// subexpanse must count ALL JPs, to know where to START counting down, and
// ALSO note the offset of digits JP to know where to STOP counting down.

		for (subexp = cJU_NUMSUBEXPB - 1; subexp >= findsub; --subexp)
		{
		    jpcount = j__udyCountBitsB(JU_JBB_BITMAP(Pjbb, subexp));

		    // should always find findbit:
		    assert((subexp > findsub) || jpcount);

		    if (! jpcount) continue;	// empty subexpanse, save time.

// Count JPs below digit, inclusive:

		    if (subexp == findsub)
		    {
			jpcountbf = j__udyCountBitsB(JU_JBB_BITMAP(Pjbb, subexp)
						  & lowermask);
		    }

		    // should always find findbit:
		    assert((subexp > findsub) || jpcountbf);
		    assert(jpcount >= jpcountbf);	// proper relationship.

// Add pop1s from JPs ABOVE Index (digit):

		    // no null JP subexp pointers:
		    assert(BMPJP0(subexp) != (Pjp_t) NULL);

		    for (jpnum = jpcount - 1; jpnum >= jpcountbf; --jpnum)
		    {
			if ((pop1 = j__udyJPPop1(BMPJP(subexp, jpnum)))
			    == cJU_ALLONES)
			{
			    JU_SET_ERRNO_NONNULL(Pjpm, JU_ERRNO_CORRUPT);
			    return(C_JERR);
			}

			pop1above += pop1;
		    }
		    // jpnum is now correct for digit.
		}
	    } // else.

// Return the net population ABOVE the digits JP at this state (in this JBB)
// plus the population AT OR ABOVE Index in the SM under the digits JP:

	    pop1 = j__udy1LCountSM(BMPJP(findsub, jpnum), Index, Pjpm);
	    if (pop1 == C_JERR) return(C_JERR);		// pass error up.

	    assert(pop1above + pop1);
	    return(pop1above + pop1);

	} // case.


// ----------------------------------------------------------------------------
// UNCOMPRESSED BRANCH; count populations in JPs in the JBU ABOVE the next
// digit in Index, and recurse for the next digit in Index:
//
// Note:  If the remainder of Index is zero, pop1above is the pop1 of the
// entire expanse and theres no point in recursing to lower levels; but this
// should be so rare that its not worth checking for;
// Judy1Count()/JudyLCount() never even calls the motor for Index == 0 (all
// bytes).

	case cJU_JPBRANCH_U2:  CHECKDCD(Pjp, 2); PREPB(Pjp, 2, BranchU);
	case cJU_JPBRANCH_U3:  CHECKDCD(Pjp, 3); PREPB(Pjp, 3, BranchU);
#ifdef JU_64BIT
	case cJU_JPBRANCH_U4:  CHECKDCD(Pjp, 4); PREPB(Pjp, 4, BranchU);
	case cJU_JPBRANCH_U5:  CHECKDCD(Pjp, 5); PREPB(Pjp, 5, BranchU);
	case cJU_JPBRANCH_U6:  CHECKDCD(Pjp, 6); PREPB(Pjp, 6, BranchU);
	case cJU_JPBRANCH_U7:  CHECKDCD(Pjp, 7); PREPB(Pjp, 7, BranchU);
#endif
	case cJU_JPBRANCH_U:   PREPB_ROOT(Pjp, BranchU);

// Common code (state-independent) for all cases of uncompressed branches:

BranchU:
	    Pjbu = P_JBU(Pjp->jp_Addr);

#ifndef NOSMARTJBU  // enable to turn off smart code for comparison purposes.

// FIGURE OUT WHICH WAY CAUSES FEWER CACHE LINE FILLS; adding the JPs above
// Indexs JP, or subtracting the JPs below Indexs JP.
//
// COUNT UPWARD, subtracting the pop1 of each JP BELOW OR AT Index, from the
// whole expanses pop1:

	    if (digit < (cJU_BRANCHUNUMJPS / 2))
	    {
		pop1above = pop1;		// subtract JPs below Index.
#ifdef SMARTMETRICS
		++jbu_upward;
#endif
		for (jpnum = 0; jpnum <= digit; ++jpnum)
		{
		    if ((Pjbu->jbu_jp[jpnum].jp_Type) <= cJU_JPNULLMAX)
			continue;	// shortcut, save a function call.

		    if ((pop1 = j__udyJPPop1(Pjbu->jbu_jp + jpnum))
		     == cJU_ALLONES)
		    {
			JU_SET_ERRNO_NONNULL(Pjpm, JU_ERRNO_CORRUPT);
			return(C_JERR);
		    }

		    pop1above -= pop1;
		}
	    }

// COUNT DOWNWARD, simply adding the pop1 of each JP ABOVE Index:

	    else
#endif // NOSMARTJBU
	    {
		assert(digit < cJU_BRANCHUNUMJPS);
#ifdef SMARTMETRICS
		++jbu_downward;
#endif
		pop1above = 0;			// add JPs above Index.

		for (jpnum = cJU_BRANCHUNUMJPS - 1; jpnum > digit; --jpnum)
		{
		    if ((Pjbu->jbu_jp[jpnum].jp_Type) <= cJU_JPNULLMAX)
			continue;	// shortcut, save a function call.

		    if ((pop1 = j__udyJPPop1(Pjbu->jbu_jp + jpnum))
		     == cJU_ALLONES)
		    {
			JU_SET_ERRNO_NONNULL(Pjpm, JU_ERRNO_CORRUPT);
			return(C_JERR);
		    }

		    pop1above += pop1;
		}
	    }

	    if ((pop1 = j__udy1LCountSM(Pjbu->jbu_jp + digit, Index, Pjpm))
	     == C_JERR) return(C_JERR);		// pass error up.

	    assert(pop1above + pop1);
	    return(pop1above + pop1);


// ----------------------------------------------------------------------------
// LEAF COUNT MACROS:
//
// LEAF*ABOVE() are common code for different JP types (linear leaves, bitmap
// leaves, and immediates) and different leaf Index Sizes, which result in
// calling different leaf search functions.  Linear leaves get the leaf address
// from jp_Addr and the Population from jp_DcdPopO, while immediates use Pjp
// itself as the leaf address and get Population from jp_Type.

#define	LEAFLABOVE(Func)				\
	Pjll = P_JLL(Pjp->jp_Addr);			\
	pop1 = JU_JPLEAF_POP0(Pjp) + 1;	                \
	LEAFABOVE(Func, Pjll, pop1)

#define	LEAFB1ABOVE(Func) LEAFLABOVE(Func)  // different Func, otherwise same.

#ifdef JUDY1
#define	IMMABOVE(Func,Pop1)	\
	Pjll = (Pjll_t) Pjp;	\
	LEAFABOVE(Func, Pjll, Pop1)
#else
// Note:  For JudyL immediates with >= 2 Indexes, the index bytes are in a
// different place than for Judy1:

#define	IMMABOVE(Func,Pop1) \
	LEAFABOVE(Func, (Pjll_t) (Pjp->jp_LIndex), Pop1)
#endif

// For all leaf types, the population AT OR ABOVE is the total pop1 less the
// offset of Index; and Index should always be found:

#define	LEAFABOVE(Func,Pjll,Pop1)		\
	offset = Func(Pjll, Pop1, Index);	\
	assert(offset >= 0);			\
	assert(offset < (Pop1));		\
	return((Pop1) - offset)

// IMMABOVE_01 handles the special case of an immediate JP with 1 index, which
// the search functions arent used for anyway:
//
// The target Index should be the one in this Immediate, in which case the
// count above (inclusive) is always 1.

#define	IMMABOVE_01						\
	assert((JU_JPDCDPOP0(Pjp)) == JU_TRIMTODCDSIZE(Index));	\
	return(1)


// ----------------------------------------------------------------------------
// LINEAR LEAF; search the leaf for Index; size is computed from jp_Type:

#if (defined(JUDYL) || (! defined(JU_64BIT)))
	case cJU_JPLEAF1:  LEAFLABOVE(j__udySearchLeaf1);
#endif
	case cJU_JPLEAF2:  LEAFLABOVE(j__udySearchLeaf2);
	case cJU_JPLEAF3:  LEAFLABOVE(j__udySearchLeaf3);

#ifdef JU_64BIT
	case cJU_JPLEAF4:  LEAFLABOVE(j__udySearchLeaf4);
	case cJU_JPLEAF5:  LEAFLABOVE(j__udySearchLeaf5);
	case cJU_JPLEAF6:  LEAFLABOVE(j__udySearchLeaf6);
	case cJU_JPLEAF7:  LEAFLABOVE(j__udySearchLeaf7);
#endif


// ----------------------------------------------------------------------------
// BITMAP LEAF; search the leaf for Index:
//
// Since the bitmap describes Indexes digitally rather than linearly, this is
// not really a search, but just a count.

	case cJU_JPLEAF_B1:  LEAFB1ABOVE(j__udyCountLeafB1);


#ifdef JUDY1
// ----------------------------------------------------------------------------
// FULL POPULATION:
//
// Return the count of Indexes AT OR ABOVE Index, which is the total population
// of the expanse (a constant) less the value of the undecoded digit remaining
// in Index (its base-0 offset in the expanse), which yields an inclusive count
// above.
//
// TBD:  This only supports a 1-byte full expanse.  Should this extract a
// stored value for pop0 and possibly more LSBs of Index, to handle larger full
// expanses?

	case cJ1_JPFULLPOPU1:
	    return(cJU_JPFULLPOPU1_POP0 + 1 - JU_DIGITATSTATE(Index, 1));
#endif


// ----------------------------------------------------------------------------
// IMMEDIATE:

	case cJU_JPIMMED_1_01:  IMMABOVE_01;
	case cJU_JPIMMED_2_01:  IMMABOVE_01;
	case cJU_JPIMMED_3_01:  IMMABOVE_01;
#ifdef JU_64BIT
	case cJU_JPIMMED_4_01:  IMMABOVE_01;
	case cJU_JPIMMED_5_01:  IMMABOVE_01;
	case cJU_JPIMMED_6_01:  IMMABOVE_01;
	case cJU_JPIMMED_7_01:  IMMABOVE_01;
#endif

	case cJU_JPIMMED_1_02:  IMMABOVE(j__udySearchLeaf1,  2);
	case cJU_JPIMMED_1_03:  IMMABOVE(j__udySearchLeaf1,  3);
#if (defined(JUDY1) || defined(JU_64BIT))
	case cJU_JPIMMED_1_04:  IMMABOVE(j__udySearchLeaf1,  4);
	case cJU_JPIMMED_1_05:  IMMABOVE(j__udySearchLeaf1,  5);
	case cJU_JPIMMED_1_06:  IMMABOVE(j__udySearchLeaf1,  6);
	case cJU_JPIMMED_1_07:  IMMABOVE(j__udySearchLeaf1,  7);
#endif
#if (defined(JUDY1) && defined(JU_64BIT))
	case cJ1_JPIMMED_1_08:  IMMABOVE(j__udySearchLeaf1,  8);
	case cJ1_JPIMMED_1_09:  IMMABOVE(j__udySearchLeaf1,  9);
	case cJ1_JPIMMED_1_10:  IMMABOVE(j__udySearchLeaf1, 10);
	case cJ1_JPIMMED_1_11:  IMMABOVE(j__udySearchLeaf1, 11);
	case cJ1_JPIMMED_1_12:  IMMABOVE(j__udySearchLeaf1, 12);
	case cJ1_JPIMMED_1_13:  IMMABOVE(j__udySearchLeaf1, 13);
	case cJ1_JPIMMED_1_14:  IMMABOVE(j__udySearchLeaf1, 14);
	case cJ1_JPIMMED_1_15:  IMMABOVE(j__udySearchLeaf1, 15);
#endif

#if (defined(JUDY1) || defined(JU_64BIT))
	case cJU_JPIMMED_2_02:  IMMABOVE(j__udySearchLeaf2,  2);
	case cJU_JPIMMED_2_03:  IMMABOVE(j__udySearchLeaf2,  3);
#endif
#if (defined(JUDY1) && defined(JU_64BIT))
	case cJ1_JPIMMED_2_04:  IMMABOVE(j__udySearchLeaf2,  4);
	case cJ1_JPIMMED_2_05:  IMMABOVE(j__udySearchLeaf2,  5);
	case cJ1_JPIMMED_2_06:  IMMABOVE(j__udySearchLeaf2,  6);
	case cJ1_JPIMMED_2_07:  IMMABOVE(j__udySearchLeaf2,  7);
#endif

#if (defined(JUDY1) || defined(JU_64BIT))
	case cJU_JPIMMED_3_02:  IMMABOVE(j__udySearchLeaf3,  2);
#endif
#if (defined(JUDY1) && defined(JU_64BIT))
	case cJ1_JPIMMED_3_03:  IMMABOVE(j__udySearchLeaf3,  3);
	case cJ1_JPIMMED_3_04:  IMMABOVE(j__udySearchLeaf3,  4);
	case cJ1_JPIMMED_3_05:  IMMABOVE(j__udySearchLeaf3,  5);

	case cJ1_JPIMMED_4_02:  IMMABOVE(j__udySearchLeaf4,  2);
	case cJ1_JPIMMED_4_03:  IMMABOVE(j__udySearchLeaf4,  3);

	case cJ1_JPIMMED_5_02:  IMMABOVE(j__udySearchLeaf5,  2);
	case cJ1_JPIMMED_5_03:  IMMABOVE(j__udySearchLeaf5,  3);

	case cJ1_JPIMMED_6_02:  IMMABOVE(j__udySearchLeaf6,  2);

	case cJ1_JPIMMED_7_02:  IMMABOVE(j__udySearchLeaf7,  2);
#endif


// ----------------------------------------------------------------------------
// OTHER CASES:

	default: JU_SET_ERRNO_NONNULL(Pjpm, JU_ERRNO_CORRUPT); return(C_JERR);

	} // switch on JP type

	/*NOTREACHED*/

} // j__udy1LCountSM()
FUNCTION int j__udyCreateBranchB(
    Pjp_t    Pjp,        // Build JPs from this place
    Pjp_t    PJPs,        // Array of JPs to put into Bitmap branch
    uint8_t Exp[],        // Array of expanses to put into bitmap
    Word_t  ExpCnt,        // Number of above JPs and Expanses
    Pvoid_t    Pjpm)
{
    Pjbb_t    PjbbRaw;    // pointer to bitmap branch.
    Pjbb_t    Pjbb;
    Word_t  ii, jj;        // Temps
    uint8_t CurrSubExp;    // Current sub expanse for BM

// This assertion says the number of populated subexpanses is not too large.
// This function is only called when a BranchL overflows to a BranchB or when a
// cascade occurs, meaning a leaf overflows.  Either way ExpCnt cant be very
// large, in fact a lot smaller than cJU_BRANCHBMAXJPS.  (Otherwise a BranchU
// would be used.)  Popping this assertion means something (unspecified) has
// gone very wrong, or else Judys design criteria have changed, although in
// fact there should be no HARM in creating a BranchB with higher actual
// fanout.

    assert(ExpCnt <= cJU_BRANCHBMAXJPS);

//    Get memory for a Bitmap branch
    PjbbRaw    = j__udyAllocJBB(Pjpm);
    if (PjbbRaw == (Pjbb_t) NULL) return(-1);
    Pjbb = P_JBB(PjbbRaw);

//    Get 1st "sub" expanse (0..7) of bitmap branch
    CurrSubExp = Exp[0] / cJU_BITSPERSUBEXPB;

// Index thru all 1 byte sized expanses:

    for (jj = ii = 0; ii <= ExpCnt; ii++)
    {
        Word_t SubExp;    // Cannot be a uint8_t

//        Make sure we cover the last one
        if (ii == ExpCnt)
        {
            SubExp = cJU_ALLONES;    // Force last one
        }
        else
        {
//            Calculate the "sub" expanse of the byte expanse
            SubExp = Exp[ii] / cJU_BITSPERSUBEXPB;  // Bits 5..7.

//            Set the bit that represents the expanse in Exp[]
            JU_JBB_BITMAP(Pjbb, SubExp) |= JU_BITPOSMASKB(Exp[ii]);
        }
//        Check if a new "sub" expanse range needed
        if (SubExp != CurrSubExp)
        {
//            Get number of JPs in this sub expanse
            Word_t NumJP = ii - jj;
            Pjp_t  PjpRaw;
            Pjp_t  Pjp;

            PjpRaw = j__udyAllocJBBJP(NumJP, Pjpm);
                        Pjp    = P_JP(PjpRaw);

            if (PjpRaw == (Pjp_t) NULL)    // out of memory.
            {

// Free any previous allocations:

                while(CurrSubExp--)
                {
                NumJP = j__udyCountBitsB(JU_JBB_BITMAP(Pjbb,
                                  CurrSubExp));
                if (NumJP)
                {
                    j__udyFreeJBBJP(JU_JBB_PJP(Pjbb,
                            CurrSubExp), NumJP, Pjpm);
                }
                }
                j__udyFreeJBB(PjbbRaw, Pjpm);
                return(-1);
            }

// Place the array of JPs in bitmap branch:

            JU_JBB_PJP(Pjbb, CurrSubExp) = PjpRaw;

// Copy the JPs to new leaf:

            JU_COPYMEM(Pjp, PJPs + jj, NumJP);

// On to the next bitmap branch "sub" expanse:

            jj       = ii;
            CurrSubExp = SubExp;
        }
    } // for each 1-byte expanse

// Pass back some of the JP to the new Bitmap branch:

    Pjp->jp_Addr = (Word_t) PjbbRaw;

    return(1);

} // j__udyCreateBranchB()