static int PyJudyIntSet_contains(PyJudyIntSet* self, PyObject* key) { Word_t v; if (!pyobject_as_word_t(key, &v)) return 0; JError_t JError; int i = Judy1Test(self->s, v, &JError); if (i == JERR) { judy_set_error(&JError); return -1; } return (i ? 1 : 0); }
FUNCTION Word_t JUDY_EXTERN Judy1Count #else FUNCTION Word_t JUDY_EXTERN JudyLCount #endif ( Pcvoid_t PArray, // JRP to first branch/leaf in SM. Word_t Index1, // starting Index. Word_t Index2, // ending Index. PJError_t PJError // optional, for returning error info. ) { jpm_t fakejpm; // local temporary for small arrays. Pjpm_t Pjpm; // top JPM or local temporary for error info. jp_t fakejp; // constructed for calling j__udy1LCountSM(). Pjp_t Pjp; // JP to pass to j__udy1LCountSM(). Word_t pop1; // total for the array. Word_t pop1above1; // indexes at or above Index1, inclusive. Word_t pop1above2; // indexes at or above Index2, exclusive. int retcode; // from Judy*First() calls. JUDYLCODE(PPvoid_t PPvalue); // from JudyLFirst() calls. // CHECK FOR SHORTCUTS: // // As documented, return C_JERR if the Judy array is empty or Index1 > Index2. if ((PArray == (Pvoid_t) NULL) || (Index1 > Index2)) { JU_SET_ERRNO(PJError, JU_ERRNO_NONE); return(C_JERR); } // If Index1 == Index2, simply check if the specified Index is set; pass // through the return value from Judy1Test() or JudyLGet() with appropriate // translations. if (Index1 == Index2) { #ifdef JUDY1 retcode = Judy1Test(PArray, Index1, PJError); if (retcode == JERRI) return(C_JERR); // pass through error. if (retcode == 0) { JU_SET_ERRNO(PJError, JU_ERRNO_NONE); return(C_JERR); } #else PPvalue = JudyLGet(PArray, Index1, PJError); if (PPvalue == PPJERR) return(C_JERR); // pass through error. if (PPvalue == (PPvoid_t) NULL) // Index is not set. { JU_SET_ERRNO(PJError, JU_ERRNO_NONE); return(C_JERR); } #endif return(1); // single index is set. } // CHECK JRP TYPE: // // Use an if/then for speed rather than a switch, and put the most common cases // first. // // Note: Since even cJU_LEAFW types require counting between two Indexes, // prepare them here for common code below that calls j__udy1LCountSM(), rather // than handling them even more specially here. if (JU_LEAFW_POP0(PArray) < cJU_LEAFW_MAXPOP1) // must be a LEAFW { Pjlw_t Pjlw = P_JLW(PArray); // first word of leaf. Pjpm = & fakejpm; Pjp = & fakejp; Pjp->jp_Addr = (Word_t) Pjlw; Pjp->jp_Type = cJU_LEAFW; Pjpm->jpm_Pop0 = Pjlw[0]; // from first word of leaf. pop1 = Pjpm->jpm_Pop0 + 1; } else { Pjpm = P_JPM(PArray); Pjp = &(Pjpm->jpm_JP); pop1 = (Pjpm->jpm_Pop0) + 1; // note: can roll over to 0. #if (defined(JUDY1) && (! defined(JU_64BIT))) if (pop1 == 0) // rare special case of full array: { Word_t count = Index2 - Index1 + 1; // can roll over again. if (count == 0) { JU_SET_ERRNO(PJError, JU_ERRNO_FULL); return(C_JERR); } return(count); } #else assert(pop1); // JudyL or 64-bit cannot create a full array! #endif } // COUNT POP1 ABOVE INDEX1, INCLUSIVE: assert(pop1); // just to be safe. if (Index1 == 0) // shortcut, pop1above1 is entire population: { pop1above1 = pop1; } else // find first valid Index above Index1, if any: { #ifdef JUDY1 if ((retcode = Judy1First(PArray, & Index1, PJError)) == JERRI) return(C_JERR); // pass through error. #else if ((PPvalue = JudyLFirst(PArray, & Index1, PJError)) == PPJERR) return(C_JERR); // pass through error. retcode = (PPvalue != (PPvoid_t) NULL); // found a next Index. #endif // If theres no Index at or above Index1, just return C_JERR (early exit): if (retcode == 0) { JU_SET_ERRNO(PJError, JU_ERRNO_NONE); return(C_JERR); } // If a first/next Index was found, call the counting motor starting with that // known valid Index, meaning the return should be positive, not C_JERR except // in case of a real error: if ((pop1above1 = j__udy1LCountSM(Pjp, Index1, Pjpm)) == C_JERR) { JU_COPY_ERRNO(PJError, Pjpm); // pass through error. return(C_JERR); } } // COUNT POP1 ABOVE INDEX2, EXCLUSIVE, AND RETURN THE DIFFERENCE: // // In principle, calculate the ordinal of each Index and take the difference, // with caution about off-by-one errors due to the specified Indexes being set // or unset. In practice: // // - The ordinals computed here are inverse ordinals, that is, the populations // ABOVE the specified Indexes (Index1 inclusive, Index2 exclusive), so // subtract pop1above2 from pop1above1, rather than vice-versa. // // - Index1s result already includes a count for Index1 and/or Index2 if // either is set, so calculate pop1above2 exclusive of Index2. // // TBD: If Index1 and Index2 fall in the same expanse in the top-state // branch(es), would it be faster to walk the SM only once, to their divergence // point, before calling j__udy1LCountSM() or equivalent? Possibly a non-issue // if a top-state pop1 becomes stored with each Judy1 array. Also, consider // whether the first call of j__udy1LCountSM() fills the cache, for common tree // branches, for the second call. // // As for pop1above1, look for shortcuts for special cases when pop1above2 is // zero. Otherwise call the counting "motor". assert(pop1above1); // just to be safe. if (Index2++ == cJU_ALLONES) return(pop1above1); // Index2 at limit. #ifdef JUDY1 if ((retcode = Judy1First(PArray, & Index2, PJError)) == JERRI) return(C_JERR); #else if ((PPvalue = JudyLFirst(PArray, & Index2, PJError)) == PPJERR) return(C_JERR); retcode = (PPvalue != (PPvoid_t) NULL); // found a next Index. #endif if (retcode == 0) return(pop1above1); // no Index above Index2. // Just as for Index1, j__udy1LCountSM() cannot return 0 (locally == C_JERR) // except in case of a real error: if ((pop1above2 = j__udy1LCountSM(Pjp, Index2, Pjpm)) == C_JERR) { JU_COPY_ERRNO(PJError, Pjpm); // pass through error. return(C_JERR); } if (pop1above1 == pop1above2) { JU_SET_ERRNO(PJError, JU_ERRNO_NONE); return(C_JERR); } return(pop1above1 - pop1above2); } // Judy1Count() / JudyLCount()
char get_s_selected(struct symbol *s) { int rc = Judy1Test(GLOBALS->s_selected, (Word_t)s, PJE0); return(rc); }