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))
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()