30#include "tab.macros.h"
39compar(
const void *ip0,
const void *jp0) {
41 BITS32 *ip = (BITS32 *)ip0, *jp = (BITS32 *)jp0;
42 Term i = EXO_OFFSET_TO_ADDRESS(LOCAL_exo_it, *ip)[LOCAL_exo_arg];
43 Term j = EXO_OFFSET_TO_ADDRESS(LOCAL_exo_it, *jp)[LOCAL_exo_arg];
45 return IntOfTerm(i)-IntOfTerm(j);
49cmp_extra_args(CELL *si, CELL *sj,
struct index_t *it)
51 UInt
m = it->udi_free_args;
54 for (x=0; x< it->arity; x++) {
58 return IntOfTerm(si[x])-IntOfTerm(sj[x]);
59 return AtomOfTerm(si[x])-AtomOfTerm(sj[x]);
71compar2(
const void *ip0,
const void *jp0) {
73 BITS32 *ip = (BITS32 *)ip0, *jp = (BITS32 *)jp0;
74 struct index_t *it = LOCAL_exo_it;
75 Term* si = EXO_OFFSET_TO_ADDRESS(it, *ip);
76 Term* sj = EXO_OFFSET_TO_ADDRESS(it, *jp);
77 int cmp = cmp_extra_args(si, sj, it);
80 return IntOfTerm(si[LOCAL_exo_arg])-IntOfTerm(sj[LOCAL_exo_arg]);
84compare(
const BITS32 *ip, Int j USES_REGS) {
85 Term i = EXO_OFFSET_TO_ADDRESS(LOCAL_exo_it, *ip)[LOCAL_exo_arg];
87 return IntOfTerm(i)-j;
90static UInt free_args(UInt b[], UInt arity, UInt i) {
94 for (j=0; j<arity; j++) {
95 if (i !=j && b[j] == 0)
102NEXT_DIFFERENT(BITS32 *pt0, BITS32 *pte,
struct index_t *it)
104 Term* si = EXO_OFFSET_TO_ADDRESS(it, pt0[0]);
111 sj = EXO_OFFSET_TO_ADDRESS(it, *pt0);
112 }
while (!cmp_extra_args(si, sj, it));
117PREV_DIFFERENT(BITS32 *pt0, BITS32 *pte,
struct index_t *it)
119 Term* si = EXO_OFFSET_TO_ADDRESS(it, pt0[0]);
126 sj = EXO_OFFSET_TO_ADDRESS(it, *pt0);
127 }
while (!cmp_extra_args(si, sj, it));
132NEXT_MIN(BITS32 *pt0, BITS32 *pte, Term tmin, Term tmax,
struct index_t *it)
134 Term* si = EXO_OFFSET_TO_ADDRESS(it, pt0[0]);
136 Int min = 0, max = 0;
138 if (IsVarTerm(tmin)) {
142 min = IntOfTerm(tmin);
144 if (IsVarTerm(tmax)) {
148 max = IntOfTerm(tmax);
151 while ((do_min && IntOfTerm(si[it->udi_arg]) < min) ||
152 (do_max && IntOfTerm(si[it->udi_arg]) > max)) {
156 si = EXO_OFFSET_TO_ADDRESS(it, *pt0);
162NEXT_MAX(BITS32 *pt0, BITS32 *pte, Term tmin, Term tmax,
struct index_t *it)
164 Term* si = EXO_OFFSET_TO_ADDRESS(it, pt0[0]);
166 Int min = 0, max = 0;
168 if (IsVarTerm(tmin)) {
172 min = IntOfTerm(tmin);
174 if (IsVarTerm(tmax)) {
178 max = IntOfTerm(tmax);
181 while ((do_min && IntOfTerm(si[it->udi_arg]) < min) ||
182 (do_max && IntOfTerm(si[it->udi_arg]) > max)) {
186 si = EXO_OFFSET_TO_ADDRESS(it, *pt0);
192IntervalUDIRefitIndex(
struct index_t **ip, UInt b[] USES_REGS)
201 if (it->bmap & b[i])
return;
205 LOCAL_exo_base = it->bcls;
206 LOCAL_exo_arity = it->arity;
208 it->udi_free_args = free_args(b, it->arity, i);
210 UInt ncls = it->ap->cs.p_code.NOfClauses, i;
213 sz =
sizeof(BITS32)*(ncls);
215 if (!(it->udi_data = (BITS32*)Yap_AllocCodeSpace(sz)))
217 sorted = (BITS32*)it->udi_data;
218 for (i=0; i< ncls; i++)
220 qsort(sorted, (
size_t)ncls,
sizeof(BITS32), compar);
223 BITS32 *sorted0, *sorted;
226 if (it->udi_free_args)
227 sz =
sizeof(BITS32)*(2*it->ntrys+3*it->nentries);
229 sz =
sizeof(BITS32)*(it->ntrys+2*it->nentries);
231 if (!(it->udi_data = (BITS32*)malloc(sz)))
233 sorted0 = sorted = (BITS32 *)it->udi_data;
235 for (i=0; i < it->hsize; i++) {
238 BITS32 offset = it->key[i], offset0 = offset;
243 offset = it->links[offset];
247 if (sorted-s0 == 2) {
248 it->links[offset0] = 0;
252 *s0 = sorted - (s0+1);
253 qsort(s0+1, (
size_t)*s0,
sizeof(BITS32), compar);
254 it->links[offset0] = s0-sorted0;
255 if (it->udi_free_args) {
256 memcpy(sorted, s0+1,
sizeof(BITS32)*(*s0));
257 qsort(sorted, (
size_t)*s0,
sizeof(BITS32), compar2);
263 sz =
sizeof(BITS32)*(sorted-sorted0);
264 it->udi_data = (BITS32 *)realloc((
char *)it->udi_data, sz);
268 code->opc = Yap_opcode(_try_exo_udi);
269 code = NEXTOP(code, lp);
270 code->opc = Yap_opcode(_retry_exo_udi);
274 binary_search(BITS32 *start, BITS32 *end, Int x USES_REGS)
277 while (start < end) {
279 mid = start + (end-start)/2;
280 cmp = compare(mid, x PASS_REGS);
292Interval(
struct index_t *it, Term min, Term max, Term op, BITS32 off USES_REGS)
301 LOCAL_exo_base = it->bcls;
302 LOCAL_exo_arity = it->arity;
303 LOCAL_exo_arg = it->udi_arg;
305 c = (BITS32 *)it->udi_data;
309 }
else if (it->links[off]) {
310 c = (BITS32 *)it->udi_data;
311 n = c[it->links[off]];
313 end = c+(it->links[off]+n);
316 if (!IsVarTerm(min)) {
318 if (!IsIntegerTerm(min)) {
320 if (!IsIntegerTerm(min)) {
321 Yap_Error(TYPE_ERROR_INTEGER, min,
"data-base constraint");
325 x = IntegerOfTerm(min);
326 if (x >= IntegerOfTerm(S[LOCAL_exo_arg])) {
330 if (!IsVarTerm(max)) {
332 if (!IsIntegerTerm(max)) {
334 if (!IsIntegerTerm(max)) {
335 Yap_Error(TYPE_ERROR_INTEGER, max,
"data-base constraint");
339 x = IntegerOfTerm(max);
340 if (x <= IntegerOfTerm(S[LOCAL_exo_arg])) {
344 return NEXTOP(NEXTOP(it->code,lp),lp);
347 if (!IsVarTerm(min)) {
349 if (!IsIntegerTerm(min)) {
351 if (!IsIntegerTerm(min)) {
352 Yap_Error(TYPE_ERROR_INTEGER, min,
"data-base constraint");
356 x = IntegerOfTerm(min);
359 pt = binary_search(pt, end, x PASS_REGS);
360 while ( pt < end+1 && (cmp = compare(pt, x PASS_REGS)) <= 0 ) {
365 while ( pt < end+1 && compare(pt, x PASS_REGS) <= 0 ) {
372 if (!IsVarTerm(max)) {
377 if (!IsIntegerTerm(max)) {
379 if (!IsIntegerTerm(max)) {
380 Yap_Error(TYPE_ERROR_INTEGER, max,
"data-base constraint");
384 x = IntegerOfTerm(max);
387 pt1 = binary_search(pt, end, x PASS_REGS);
388 while ( pt1 >= pt && (cmp = compare(pt1, x PASS_REGS)) >= 0 ) {
394 while ( pt1 >= pt && compare(pt1, x PASS_REGS) >= 0 ) {
403 S = EXO_OFFSET_TO_ADDRESS(it, pt[0]);
405 YENV[-1] = (CELL)( end );
406 YENV[-2] = (CELL)( pt+1 );
410 return NEXTOP(NEXTOP(it->code,lp),lp);
413 if (at == AtomAny || at == AtomMinimum) {
414 S = EXO_OFFSET_TO_ADDRESS(it, pt[0]);
415 }
else if (at == AtomMaximum) {
416 S = EXO_OFFSET_TO_ADDRESS(it, end[0]);
417 }
else if (at == AtomUnique) {
420 S = EXO_OFFSET_TO_ADDRESS(it, pt[0]);
421 }
else if (at == AtomMin) {
422 S = EXO_OFFSET_TO_ADDRESS(it, pt[0]);
423 if (it->udi_free_args) {
425 pt = c+(it->links[off]+n+1);
427 pt = NEXT_MIN(pt, end, min, max, it);
430 S = EXO_OFFSET_TO_ADDRESS(it, pt[0]);
431 ptn = NEXT_DIFFERENT(pt, end, it);
433 ptn = NEXT_MIN(ptn, end, min, max, it);
437 YENV[-3] = (CELL) end;
438 YENV[-4] = MkAtomTerm(AtomMin);
439 YENV[-5] = (CELL)( ptn );
444 return NEXTOP(NEXTOP(it->code,lp),lp);
445 }
else if (at == AtomMax) {
446 S = EXO_OFFSET_TO_ADDRESS(it, pt[0]);
447 if (it->udi_free_args) {
449 end = c+(it->links[off]+n);
451 pt = NEXT_MAX(pt, end, min, max, it);
454 S = EXO_OFFSET_TO_ADDRESS(it, pt[0]);
455 ptn = PREV_DIFFERENT(pt, end, it);
457 ptn = NEXT_MAX(ptn, end, min, max, it);
461 YENV[-3] = (CELL) end;
462 YENV[-4] = MkAtomTerm(AtomMax);
463 YENV[-5] = (CELL)( ptn );
468 return NEXTOP(NEXTOP(it->code,lp),lp);
470 return NEXTOP(NEXTOP(it->code,lp),lp);
474IntervalEnterUDIIndex(
struct index_t *it USES_REGS)
477 Term t = XREGS[i+1], a1;
478 BITS32 off = EXO_ADDRESS_TO_OFFSET(it, S);
485 if(!IsAttVar(VarOfTerm(t)))
486 return Interval(it, MkVarTerm(), MkVarTerm(), MkVarTerm(), off PASS_REGS);
487 attv = RepAttVar(VarOfTerm(t));
491 Yap_Error(INSTANTIATION_ERROR, t,
"executing exo_interval constraints");
493 }
else if (!IsApplTerm(a1)) {
494 Yap_Error(TYPE_ERROR_COMPOUND, a1,
"executing exo_interval constraints");
497 return Interval(it, ArgOfTerm(1,a1), ArgOfTerm(2,a1), ArgOfTerm(3,a1), off PASS_REGS);
502IntervalRetryUDIIndex(
struct index_t *it USES_REGS)
504 CELL *w = (CELL*)(B+1)+it->arity;
505 if (IsVarTerm(w[2])) {
506 BITS32 *end = (BITS32 *) w[2],
507 *pt = (BITS32 *) w[1];
510 S = EXO_OFFSET_TO_ADDRESS(it, f);
511 if (pt++ == end)
return FALSE;
514 BITS32 *pt0 = (BITS32 *)w[1];
515 BITS32 *pte = (BITS32 *)w[3];
516 Atom what = AtomOfTerm(w[2]);
520 S = EXO_OFFSET_TO_ADDRESS(it, pt0[0]);
521 if ( what == AtomMin ) {
522 pt0 = NEXT_DIFFERENT(pt0, pte, it);
524 pt0 = NEXT_MIN(pt0, pte, min, max, it);
526 pt0 = PREV_DIFFERENT(pt0, pte, it);
528 pt0 = NEXT_MAX(pt0, pte, min, max, it);
542 CRefitExoIndex refit;
548IntervalUdiInit (Term spec,
int arg,
int arity) {
549 ExoCB.refit = IntervalUDIRefitIndex;
550 return (
void *)&ExoCB;
554IntervalUdiInsert (
void *control,
555 Term term,
int arg,
void *data)
560 (*ip)->udi_arg = arg-1;
561 (ExoCB.refit)(ip, LOCAL_ibnds PASS_REGS);
562 (*ip)->udi_first = (
void *)IntervalEnterUDIIndex;
563 (*ip)->udi_next = (
void *)IntervalRetryUDIIndex;
567static int IntervalUdiDestroy(
void *control)
574void Yap_udi_Interval_init(
void) {
576 Atom name = Yap_LookupAtom(
"exo_interval");
577 memset((
void *) cb,0,
sizeof(*cb));
580 cb->decl= (YAP_Atom)name;
581 Yap_MkEmptyWakeUp(name);
582 cb->init= IntervalUdiInit;
583 cb->insert=IntervalUdiInsert;
585 cb->destroy=IntervalUdiDestroy;
Attributed variales are controlled by the attvar_record.