diff --git a/C/exo_udi.c b/C/exo_udi.c index 544ac7bc4..7c9fb3dea 100644 --- a/C/exo_udi.c +++ b/C/exo_udi.c @@ -54,81 +54,161 @@ compare(const BITS32 *ip, Int j USES_REGS) { return IntOfTerm(i)-j; } - - static void - IntervalUDIRefitIndex(struct index_t **ip, UInt b[] USES_REGS) - { - size_t sz; - struct index_t *it = *ip; - yamop *code; - - /* hard-wired implementation for the Interval case */ - Int i = it->udi_arg; - /* it is bound, use hash */ - if (it->bmap & b[i]) return; - /* no constraints, nothing to gain */ - if (!IsAttVar(VarOfTerm(XREGS[i+1]))) return; - LOCAL_exo_it = it; - LOCAL_exo_base = it->bcls; - LOCAL_exo_arity = it->arity; - LOCAL_exo_arg = i; - if (!it->key) { - UInt ncls = it->ap->cs.p_code.NOfClauses, i; - BITS32 *sorted; - /* handle ll variables */ - sz = sizeof(BITS32)*(ncls); - /* allocate space */ - if (!(it->udi_data = (BITS32*)Yap_AllocCodeSpace(sz))) - return; - sorted = (BITS32*)it->udi_data; - for (i=0; i< ncls; i++) - sorted[i] = i; - qsort(sorted, (size_t)ncls, sizeof(BITS32), compar); - it->links = NULL; - } else { - BITS32 *sorted0, *sorted; - - /* be conservative */ - sz = sizeof(BITS32)*(2*it->ntrys+it->nentries); - /* allocate space */ - if (!(it->udi_data = (BITS32*)Yap_AllocCodeSpace(sz))) - return; - sorted0 = sorted = (BITS32 *)it->udi_data; - sorted++; /* leave an initial hole */ - for (i=0; i < it->hsize; i++) { - if (it->key[i]) { - BITS32 *s0 = sorted; - BITS32 offset = it->key[i], offset0 = offset; - - *sorted++ = 0; - do { - *sorted++ = offset; - offset = it->links[offset]; - } while (offset); - // S = EXO_OFFSET_TO_ADDRESS(it, offset0); Yap_DebugPlWrite(S[0]); - // fprintf(stderr, " key[i]=%d offset=%d %d\n", it->key[i], offset0, (sorted-s0)-1); - if (sorted-s0 == 2) { - it->links[offset0] = 0; - sorted = s0; - } else { - /* number of elements comes first */ - *s0 = sorted - (s0+1); - qsort(s0+1, (size_t)*s0, sizeof(BITS32), compar); - it->links[offset0] = s0-sorted0; - // fprintf(stderr," %d links %d=%d \n", offset0, s0-sorted0, s0[0]); - } - } - } - sz = sizeof(BITS32)*(sorted-sorted0); - it->udi_data = (BITS32 *)Yap_ReallocCodeSpace((char *)it->udi_data, sz); - } - it->is_udi = i+1; - code = it->code; - code->opc = Yap_opcode(_try_exo_udi); - code = NEXTOP(code, lp); - code->opc = Yap_opcode(_retry_exo_udi); +static int +same_free(BITS32 i, BITS32 j, struct index_t *it) { + CELL *ip = EXO_OFFSET_TO_ADDRESS(it, i); + CELL *jp = EXO_OFFSET_TO_ADDRESS(it, j); + UInt m = it->udi_free_args, m0 = 1, x; + for (x=0; x< it->arity; x++) { + if (m0 & m) { + if (ip[x] != jp[x]) + return FALSE; + m -= m0; + if (!m) + return TRUE; + } + m0 <<= 1; + } + return TRUE; } +static UInt free_args(UInt b[], UInt arity, UInt i) { + UInt j; + UInt rc = 0; + + for (j=0; j= x) + return x; + } + return x; +} + +static Int +BIGGEST_EL(Int x0, BITS32 *p, Int xe) +{ + Int x = x0; + + while (x <= xe) { + if (p[x] == x0) + x0 = x; + x++; + } + return x0; +} + +static void +IntervalUDIRefitIndex(struct index_t **ip, UInt b[] USES_REGS) +{ + size_t sz; + struct index_t *it = *ip; + yamop *code; + + /* hard-wired implementation for the Interval case */ + Int i = it->udi_arg; + /* it is bound, use hash */ + if (it->bmap & b[i]) return; + /* no constraints, nothing to gain */ + if (!IsAttVar(VarOfTerm(XREGS[i+1]))) return; + LOCAL_exo_it = it; + LOCAL_exo_base = it->bcls; + LOCAL_exo_arity = it->arity; + LOCAL_exo_arg = i; + it->udi_free_args = free_args(b, it->arity, i); + if (!it->key) { + UInt ncls = it->ap->cs.p_code.NOfClauses, i; + BITS32 *sorted; + /* handle ll variables */ + sz = sizeof(BITS32)*(ncls); + /* allocate space */ + if (!(it->udi_data = (BITS32*)Yap_AllocCodeSpace(sz))) + return; + sorted = (BITS32*)it->udi_data; + for (i=0; i< ncls; i++) + sorted[i] = i; + qsort(sorted, (size_t)ncls, sizeof(BITS32), compar); + it->links = NULL; + } else { + BITS32 *sorted0, *sorted; + + /* be conservative */ + if (it->udi_free_args) + sz = sizeof(BITS32)*(3*it->ntrys+2*it->nentries); + else + sz = sizeof(BITS32)*(2*it->ntrys+it->nentries); + /* allocate space */ + if (!(it->udi_data = (BITS32*)Yap_AllocCodeSpace(sz))) + return; + sorted0 = sorted = (BITS32 *)it->udi_data; + sorted++; /* leave an initial hole */ + for (i=0; i < it->hsize; i++) { + if (it->key[i]) { + BITS32 *s0 = sorted; + BITS32 offset = it->key[i], offset0 = offset; + + *sorted++ = 0; + do { + *sorted++ = offset; + offset = it->links[offset]; + } while (offset); + // S = EXO_OFFSET_TO_ADDRESS(it, offset0); Yap_DebugPlWrite(S[0]); + // fprintf(stderr, " key[i]=%d offset=%d %d\n", it->key[i], offset0, (sorted-s0)-1); + if (sorted-s0 == 2) { + it->links[offset0] = 0; + sorted = s0; + } else { + /* number of elements comes first */ + *s0 = sorted - (s0+1); + qsort(s0+1, (size_t)*s0, sizeof(BITS32), compar); + it->links[offset0] = s0-sorted0; + // fprintf(stderr," %d links %d=%d \n", offset0, s0-sorted0, s0[0]); + if (it->udi_free_args) { + bzero(sorted, sizeof(BITS32)*(*s0)); + /* chain elements with same unbound vars together */ + chain(sorted, s0+1, *s0, it); + sorted += *s0; + } + } + } + } + sz = sizeof(BITS32)*(sorted-sorted0); + it->udi_data = (BITS32 *)Yap_ReallocCodeSpace((char *)it->udi_data, sz); + } + it->is_udi = i+1; + code = it->code; + code->opc = Yap_opcode(_try_exo_udi); + code = NEXTOP(code, lp); + code->opc = Yap_opcode(_retry_exo_udi); +} + static BITS32 * binary_search(BITS32 *start, BITS32 *end, Int x USES_REGS) { @@ -154,6 +234,7 @@ Interval(struct index_t *it, Term min, Term max, Term op, BITS32 off USES_REGS) BITS32 n; BITS32 *pt; BITS32 *end; + BITS32 *pt0, *end0; Atom at; LOCAL_exo_it = it; @@ -165,11 +246,14 @@ Interval(struct index_t *it, Term min, Term max, Term op, BITS32 off USES_REGS) n = it->nels; pt = c; end = c+(n-1); + pt0 = pt; + end0 = end+1; } else if (it->links[off]) { c = (BITS32 *)it->udi_data; n = c[it->links[off]]; - pt = c+(it->links[off]+1); + pt0 = pt = c+(it->links[off]+1); end = c+(it->links[off]+n); + end0 = end+1; // fprintf(stderr," %d links %d=%d \n", off, it->links[off], n); } else { if (!IsVarTerm(min)) { @@ -261,22 +345,57 @@ Interval(struct index_t *it, Term min, Term max, Term op, BITS32 off USES_REGS) if (IsVarTerm(op)) { S = EXO_OFFSET_TO_ADDRESS(it, pt[0]); if (pt < end ) { - YENV[-2] = (CELL)( pt+1 ); YENV[-1] = (CELL)( end ); + YENV[-2] = (CELL)( pt+1 ); YENV -= 2; return it->code; } return NEXTOP(NEXTOP(it->code,lp),lp); } at = AtomOfTerm(op); - if (at == AtomAny || at == AtomMin) { + if (at == AtomAny || at == AtomMinimum) { S = EXO_OFFSET_TO_ADDRESS(it, pt[0]); - } else if (at == AtomMax) { + } else if (at == AtomMaximum) { S = EXO_OFFSET_TO_ADDRESS(it, end[0]); } else if (at == AtomUnique) { if (end-2 > pt) return FAILCODE; S = EXO_OFFSET_TO_ADDRESS(it, pt[0]); + } else if (at == AtomMin) { + Int x0, xe, x; + + x0 = pt-pt0; + xe = end-pt0; + S = EXO_OFFSET_TO_ADDRESS(it, pt[0]); + x = NEXT_DIFFERENT(x0, x0, end0, xe); + if (x < xe ) { + YENV[-5] = (CELL)( pt0 ); // base for array of pointed pointers + YENV[-4] = MkIntegerTerm( x ); // where we are in pt0 array + YENV[-3] = MkIntegerTerm( xe ); // our visit will end here + YENV[-2] = MkIntegerTerm( x0 ); // our visit started here + YENV[-1] = (CELL)( end0 ); // base for array into pt + YENV -= 5; + return it->code; + } + return NEXTOP(NEXTOP(it->code,lp),lp); + } else if (at == AtomMax) { + Int x0, xe, x, y; + + x0 = pt-pt0; + xe = end-pt0; + y = BIGGEST_EL( x0, end0, xe ); + S = EXO_OFFSET_TO_ADDRESS(it, pt[0]); + x = NEXT_DIFFERENT(x0, x0, end0, xe); + if (x < xe ) { + YENV[-5] = (CELL)( pt0 ); // base for array of pointed pointers + YENV[-4] = MkIntegerTerm( -x ); // where we are in pt0 array + YENV[-3] = MkIntegerTerm( xe ); // our visit will end here + YENV[-2] = MkIntegerTerm( x0 ); // our visit started here + YENV[-1] = (CELL)( end0 ); // base for array into pt + YENV -= 5; + return it->code; + } + return NEXTOP(NEXTOP(it->code,lp),lp); } return NEXTOP(NEXTOP(it->code,lp),lp); } @@ -312,14 +431,40 @@ IntervalEnterUDIIndex(struct index_t *it USES_REGS) static int IntervalRetryUDIIndex(struct index_t *it USES_REGS) { - CELL *w = (CELL*)(B+1); - BITS32 *end = (BITS32 *) w[it->arity+2], - *pt = (BITS32 *) w[it->arity+1]; - BITS32 f = *pt; + CELL *w = (CELL*)(B+1)+it->arity; + if (IsVarTerm(w[2])) { + BITS32 *end = (BITS32 *) w[2], + *pt = (BITS32 *) w[1]; + BITS32 f = *pt; - S = EXO_OFFSET_TO_ADDRESS(it, f); - if (pt++ == end) return FALSE; - w[it->arity+1] = (CELL)pt; + S = EXO_OFFSET_TO_ADDRESS(it, f); + if (pt++ == end) return FALSE; + w[1] = (CELL)pt; + } else { + BITS32 *pt0 = (BITS32 *)w[1]; + Int x = IntegerOfTerm( w[2] ); + Int xe = IntegerOfTerm( w[3] ); + Int x0 = IntegerOfTerm( w[4] ); + BITS32 *base = (BITS32 *)w[5]; + if ( x > 0) { + //Yap_DebugPlWrite( EXO_OFFSET_TO_ADDRESS(it, el[i])[1] ); fprintf(stderr,"\n"); + S = EXO_OFFSET_TO_ADDRESS(it, pt0[x]); + //fprintf(stderr,"S=%p x=%d/%d %d %d %p %p \n", S, x, base[x], x0, xe, pt0, base); + x = NEXT_DIFFERENT(x0, x, base, xe); + if (x > xe) return FALSE; + w[2] = MkIntegerTerm(x); + } else { + x = -x; + //Yap_DebugPlWrite( EXO_OFFSET_TO_ADDRESS(it, el[i])[1] ); fprintf(stderr,"\n"); + S = EXO_OFFSET_TO_ADDRESS(it, pt0[BIGGEST_EL(x, base, xe) ]); + x = NEXT_DIFFERENT(x0, x, base, xe); + // fprintf(stderr,"S=%p x=%d/%d %d %d %p %p \n", S, x, base[x], x0, xe, pt0, base); + if (x > xe) { + return FALSE; + } + w[2] = MkIntegerTerm(-x); + } + } return TRUE; } diff --git a/H/clause.h b/H/clause.h index 760ffa6fc..f8c6a0ad0 100644 --- a/H/clause.h +++ b/H/clause.h @@ -178,6 +178,7 @@ typedef struct index_t { yamop *code; BITS32 *udi_data; void *udi_first, *udi_next; + UInt udi_free_args; UInt udi_arg; } Index_t; diff --git a/H/iatoms.h b/H/iatoms.h index 21a801e98..1e41143a5 100644 --- a/H/iatoms.h +++ b/H/iatoms.h @@ -156,6 +156,7 @@ AtomLT = Yap_LookupAtom("<"); AtomLastExecuteWithin = Yap_FullLookupAtom("$last_execute_within"); AtomLeash = Yap_FullLookupAtom("$leash"); + AtomLeast = Yap_LookupAtom("least"); AtomLength = Yap_FullLookupAtom("length"); AtomList = Yap_LookupAtom("list"); AtomLive = Yap_FullLookupAtom("$live"); @@ -164,14 +165,17 @@ AtomLocalSp = Yap_LookupAtom("local_sp"); AtomLocalTrie = Yap_LookupAtom("local_trie"); AtomMax = Yap_LookupAtom("max"); + AtomMaximum = Yap_LookupAtom("maximum"); AtomMaxArity = Yap_LookupAtom("max_arity"); AtomMaxFiles = Yap_LookupAtom("max_files"); AtomMegaClause = Yap_FullLookupAtom("$mega_clause"); AtomMetaCall = Yap_FullLookupAtom("$call"); AtomMfClause = Yap_FullLookupAtom("$mf_clause"); AtomMin = Yap_LookupAtom("min"); + AtomMinimum = Yap_LookupAtom("minimum"); AtomMinus = Yap_LookupAtom("-"); AtomModify = Yap_LookupAtom("modify"); + AtomMost = Yap_LookupAtom("most"); AtomMultiFile = Yap_FullLookupAtom("$mf"); AtomMutable = Yap_LookupAtom("mutable"); AtomMutableVariable = Yap_FullLookupAtom("$mutable_variable"); diff --git a/H/ratoms.h b/H/ratoms.h index c0cdbe9f5..807d4d0b6 100644 --- a/H/ratoms.h +++ b/H/ratoms.h @@ -156,6 +156,7 @@ AtomLT = AtomAdjust(AtomLT); AtomLastExecuteWithin = AtomAdjust(AtomLastExecuteWithin); AtomLeash = AtomAdjust(AtomLeash); + AtomLeast = AtomAdjust(AtomLeast); AtomLength = AtomAdjust(AtomLength); AtomList = AtomAdjust(AtomList); AtomLive = AtomAdjust(AtomLive); @@ -164,14 +165,17 @@ AtomLocalSp = AtomAdjust(AtomLocalSp); AtomLocalTrie = AtomAdjust(AtomLocalTrie); AtomMax = AtomAdjust(AtomMax); + AtomMaximum = AtomAdjust(AtomMaximum); AtomMaxArity = AtomAdjust(AtomMaxArity); AtomMaxFiles = AtomAdjust(AtomMaxFiles); AtomMegaClause = AtomAdjust(AtomMegaClause); AtomMetaCall = AtomAdjust(AtomMetaCall); AtomMfClause = AtomAdjust(AtomMfClause); AtomMin = AtomAdjust(AtomMin); + AtomMinimum = AtomAdjust(AtomMinimum); AtomMinus = AtomAdjust(AtomMinus); AtomModify = AtomAdjust(AtomModify); + AtomMost = AtomAdjust(AtomMost); AtomMultiFile = AtomAdjust(AtomMultiFile); AtomMutable = AtomAdjust(AtomMutable); AtomMutableVariable = AtomAdjust(AtomMutableVariable); diff --git a/H/tatoms.h b/H/tatoms.h index d98452b6f..1e859e4ad 100644 --- a/H/tatoms.h +++ b/H/tatoms.h @@ -310,6 +310,8 @@ #define AtomLastExecuteWithin Yap_heap_regs->AtomLastExecuteWithin_ Atom AtomLeash_; #define AtomLeash Yap_heap_regs->AtomLeash_ + Atom AtomLeast_; +#define AtomLeast Yap_heap_regs->AtomLeast_ Atom AtomLength_; #define AtomLength Yap_heap_regs->AtomLength_ Atom AtomList_; @@ -326,6 +328,8 @@ #define AtomLocalTrie Yap_heap_regs->AtomLocalTrie_ Atom AtomMax_; #define AtomMax Yap_heap_regs->AtomMax_ + Atom AtomMaximum_; +#define AtomMaximum Yap_heap_regs->AtomMaximum_ Atom AtomMaxArity_; #define AtomMaxArity Yap_heap_regs->AtomMaxArity_ Atom AtomMaxFiles_; @@ -338,10 +342,14 @@ #define AtomMfClause Yap_heap_regs->AtomMfClause_ Atom AtomMin_; #define AtomMin Yap_heap_regs->AtomMin_ + Atom AtomMinimum_; +#define AtomMinimum Yap_heap_regs->AtomMinimum_ Atom AtomMinus_; #define AtomMinus Yap_heap_regs->AtomMinus_ Atom AtomModify_; #define AtomModify Yap_heap_regs->AtomModify_ + Atom AtomMost_; +#define AtomMost Yap_heap_regs->AtomMost_ Atom AtomMultiFile_; #define AtomMultiFile Yap_heap_regs->AtomMultiFile_ Atom AtomMutable_; diff --git a/misc/ATOMS b/misc/ATOMS index 1b539c7c4..17c1bdc10 100644 --- a/misc/ATOMS +++ b/misc/ATOMS @@ -161,6 +161,7 @@ A LOOP N "_LOOP_" A LT N "<" A LastExecuteWithin F "$last_execute_within" A Leash F "$leash" +A Least N "least" A Length F "length" A List N "list" A Live F "$live" @@ -169,14 +170,17 @@ A Local N "local" A LocalSp N "local_sp" A LocalTrie N "local_trie" A Max N "max" +A Maximum N "maximum" A MaxArity N "max_arity" A MaxFiles N "max_files" A MegaClause F "$mega_clause" A MetaCall F "$call" A MfClause F "$mf_clause" A Min N "min" +A Minimum N "minimum" A Minus N "-" A Modify N "modify" +A Most N "most" A MultiFile F "$mf" A Mutable N "mutable" A MutableVariable F "$mutable_variable"