1 /*** ase-interval.c -- Interval Sorcery
3 * Copyright (C) 2006-2008 Sebastian Freundt
5 * Author: Sebastian Freundt <hroptatyr@sxemacs.org>
7 * This file is part of SXEmacs.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the author nor the names of any contributors
21 * may be used to endorse or promote products derived from this
22 * software without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
31 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
33 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
34 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 /* Synched up with: Not in FSF. */
44 #include "ase-interval.h"
46 #define EMODNAME ase_interval
47 PROVIDE(ase_interval);
48 REQUIRE(ase_interval, "ase", "ase-cartesian");
50 Lisp_Object Q_open, Q_closed, Q_less, Q_greater, Q_eql, Q_unknown;
51 Lisp_Object Q_disjoint, Q_connected;
52 Lisp_Object Qase_interval, Qase_intervalp;
53 Lisp_Object Qase_interval_union, Qase_interval_union_p;
54 Lisp_Object Qase_empty_interval, Qase_universe_interval;
56 static struct ase_category_s __interval_cat = {
64 const ase_category_t ase_interval_cat = (const ase_category_t)&__interval_cat;
65 typedef enum ase_interval_type_e ase_interval_type_t;
67 static inline int _ase_interval_less_p(ase_interval_t, ase_interval_t);
68 static inline int _ase_interval_equal_p(ase_interval_t, ase_interval_t);
69 static inline int ase_interval_less_p(Lisp_Object, Lisp_Object);
70 static inline int ase_interval_equal_p(Lisp_Object, Lisp_Object);
72 static DOESNT_RETURN ase_interval_embedding_error(Lisp_Object, Lisp_Object);
73 static ase_interval_type_t ase_interval_type(Lisp_Object o);
74 static int _ase_normalise_union_intr(ase_interval_union_item_t);
76 static inline Lisp_Object ase_intersect_intv_intv(Lisp_Object, Lisp_Object);
77 static inline Lisp_Object ase_intersect_intv_union(Lisp_Object, Lisp_Object);
78 static inline Lisp_Object ase_intersect_intr_intr(Lisp_Object, Lisp_Object);
79 static inline Lisp_Object ase_intersect_intr_union(Lisp_Object, Lisp_Object);
80 static inline Lisp_Object ase_intersect_union_intv(Lisp_Object, Lisp_Object);
81 static inline Lisp_Object ase_intersect_union_intr(Lisp_Object, Lisp_Object);
82 static inline Lisp_Object ase_intersect_union_union(Lisp_Object, Lisp_Object);
84 static inline Lisp_Object ase_subtract_intv_intv(Lisp_Object, Lisp_Object);
85 static inline Lisp_Object ase_subtract_intv_union(Lisp_Object, Lisp_Object);
86 static inline Lisp_Object ase_subtract_intr_intr(Lisp_Object, Lisp_Object);
87 static inline Lisp_Object ase_subtract_intr_union(Lisp_Object, Lisp_Object);
88 static inline Lisp_Object ase_subtract_union_intv(Lisp_Object, Lisp_Object);
89 static inline Lisp_Object ase_subtract_union_intr(Lisp_Object, Lisp_Object);
90 static inline Lisp_Object ase_subtract_union_union(Lisp_Object, Lisp_Object);
93 enum ase_interval_type_e {
101 /* the superset relation is a generalised version #'= */
102 static ase_element_relation_f
103 ase_optable_superset[NUMBER_OF_ASE_ITYPES][NUMBER_OF_ASE_ITYPES] = {
105 {(ase_element_relation_f)ase_interval_embedding_error,
106 (ase_element_relation_f)ase_interval_embedding_error,
107 (ase_element_relation_f)ase_interval_embedding_error,
108 (ase_element_relation_f)ase_interval_embedding_error},
110 {ase_interval_contains_obj_p,
111 ase_interval_contains_intv_p,
112 (ase_element_relation_f)ase_interval_embedding_error,
113 ase_interval_contains_union_p},
115 {ase_interval_interior_contains_obj_p,
116 (ase_element_relation_f)ase_interval_embedding_error,
117 ase_interval_interior_contains_intr_p,
118 ase_interval_interior_contains_union_p},
120 {ase_interval_union_contains_obj_p,
121 ase_interval_union_contains_intv_p,
122 ase_interval_union_contains_intr_p,
123 ase_interval_union_contains_union_p}};
125 /* the disjoint relation is a generalised version of #'/= */
126 static ase_st_relation_f
127 ase_optable_disjoint[NUMBER_OF_ASE_ITYPES][NUMBER_OF_ASE_ITYPES] = {
129 {(ase_st_relation_f)ase_interval_embedding_error,
130 (ase_st_relation_f)ase_interval_embedding_error,
131 (ase_st_relation_f)ase_interval_embedding_error,
132 (ase_st_relation_f)ase_interval_embedding_error},
134 {(ase_st_relation_f)ase_interval_embedding_error,
135 ase_interval_disjoint_p,
136 (ase_st_relation_f)ase_interval_embedding_error,
137 ase_interval_disjoint_union_p},
139 {(ase_st_relation_f)ase_interval_embedding_error,
140 (ase_st_relation_f)ase_interval_embedding_error,
141 ase_interval_interior_disjoint_p,
142 ase_interval_interior_disjoint_union_p},
144 {(ase_st_relation_f)ase_interval_embedding_error,
145 ase_interval_union_disjoint_intv_p,
146 ase_interval_union_disjoint_intr_p,
147 ase_interval_union_disjoint_p}};
149 /* the disjoint relation is a generalised version of #'/= */
150 static ase_st_relation_f
151 ase_optable_connected[NUMBER_OF_ASE_ITYPES][NUMBER_OF_ASE_ITYPES] = {
153 {(ase_st_relation_f)ase_interval_embedding_error,
154 (ase_st_relation_f)ase_interval_embedding_error,
155 (ase_st_relation_f)ase_interval_embedding_error,
156 (ase_st_relation_f)ase_interval_embedding_error},
158 {(ase_st_relation_f)ase_interval_embedding_error,
159 ase_interval_connected_p,
160 (ase_st_relation_f)ase_interval_embedding_error,
161 ase_interval_connected_union_p},
163 {(ase_st_relation_f)ase_interval_embedding_error,
164 (ase_st_relation_f)ase_interval_embedding_error,
165 ase_interval_interior_connected_p,
166 ase_interval_interior_connected_union_p},
168 {(ase_st_relation_f)ase_interval_embedding_error,
169 ase_interval_union_connected_intv_p,
170 ase_interval_union_connected_intr_p,
171 ase_interval_union_connected_p}};
173 /* the intersection operation */
174 static ase_binary_operation_f
175 ase_optable_intersect[NUMBER_OF_ASE_ITYPES][NUMBER_OF_ASE_ITYPES] = {
177 {(ase_binary_operation_f)ase_interval_embedding_error,
178 (ase_binary_operation_f)ase_interval_embedding_error,
179 (ase_binary_operation_f)ase_interval_embedding_error,
180 (ase_binary_operation_f)ase_interval_embedding_error},
182 {(ase_binary_operation_f)ase_interval_embedding_error,
183 ase_intersect_intv_intv,
184 (ase_binary_operation_f)ase_interval_embedding_error,
185 ase_intersect_intv_union},
187 {(ase_binary_operation_f)ase_interval_embedding_error,
188 (ase_binary_operation_f)ase_interval_embedding_error,
189 ase_intersect_intr_intr,
190 ase_intersect_intr_union},
192 {(ase_binary_operation_f)ase_interval_embedding_error,
193 ase_intersect_union_intv,
194 ase_intersect_union_intr,
195 ase_intersect_union_union}};
197 /* the difference operation */
198 static ase_binary_operation_f
199 ase_optable_subtract[NUMBER_OF_ASE_ITYPES][NUMBER_OF_ASE_ITYPES] = {
201 {(ase_binary_operation_f)ase_interval_embedding_error,
202 (ase_binary_operation_f)ase_interval_embedding_error,
203 (ase_binary_operation_f)ase_interval_embedding_error,
204 (ase_binary_operation_f)ase_interval_embedding_error},
206 {(ase_binary_operation_f)ase_interval_embedding_error,
207 ase_subtract_intv_intv,
208 (ase_binary_operation_f)ase_interval_embedding_error,
209 ase_subtract_intv_union},
211 {(ase_binary_operation_f)ase_interval_embedding_error,
212 (ase_binary_operation_f)ase_interval_embedding_error,
213 ase_subtract_intr_intr,
214 ase_subtract_intr_union},
216 {(ase_binary_operation_f)ase_interval_embedding_error,
217 ase_subtract_union_intv,
218 ase_subtract_union_intr,
219 ase_subtract_union_union}};
222 /* stuff for the dynacat, printers */
224 _ase_interval_prnt(ase_interval_t a, Lisp_Object pcf)
227 write_c_string("( )", pcf);
231 if (a->lower_eq_upper_p) {
232 write_c_string("[", pcf);
233 print_internal(a->lower, pcf, 0);
234 write_c_string("]", pcf);
239 write_c_string("(", pcf);
241 write_c_string("[", pcf);
242 print_internal(a->lower, pcf, 0);
243 write_c_string(" ", pcf);
244 print_internal(a->upper, pcf, 0);
246 write_c_string(")", pcf);
248 write_c_string("]", pcf);
252 _ase_interval_union_item_prnt(ase_interval_union_item_t u, Lisp_Object pcf)
254 dynacat_intprinter_f prfun = NULL;
255 Lisp_Object o = u->current;
257 if ((prfun = get_dynacat_intprinter(o)) == NULL)
260 prfun(get_dynacat(o), pcf);
262 write_c_string(" u ", pcf);
267 _ase_interval_union_prnt(ase_interval_union_t i, Lisp_Object pcf)
269 ase_interval_union_item_t u = ase_interval_union(i);
271 _ase_interval_union_item_prnt(u, pcf);
278 ase_interval_prnt(Lisp_Object obj, Lisp_Object pcf, int unused)
280 EMOD_ASE_DEBUG_INTV("i:0x%08x@0x%08x (rc:%d)\n",
281 (unsigned int)(XASE_INTERVAL(obj)),
283 (XASE_INTERVAL(obj) ?
284 XASE_INTERVAL_REFVAL(obj) : 1));
285 write_c_string("#<ase:interval ", pcf);
286 _ase_interval_prnt(XASE_INTERVAL(obj), pcf);
287 write_c_string(">", pcf);
291 ase_interval_union_prnt(Lisp_Object obj, Lisp_Object pcf, int unused)
293 EMOD_ASE_DEBUG_INTV("u:0x%08x@0x%08x (rc:%d)\n",
294 (unsigned int)(XASE_INTERVAL_UNION(obj)),
296 (XASE_INTERVAL_UNION(obj) ?
297 XASE_INTERVAL_UNION_REFVAL(obj) : 1));
298 write_c_string("#<ase:interval-union ", pcf);
299 _ase_interval_union_prnt(XASE_INTERVAL_UNION(obj), pcf);
300 write_c_string(">", pcf);
304 /* stuff for the dynacat, finalisers */
306 _ase_interval_union_item_fini(ase_interval_union_item_t u)
308 EMOD_ASE_DEBUG_GC("uitem:0x%08x refcnt vanished, freeing\n",
313 ASE_INTERVALP(u->current) &&
314 !ASE_INTERVAL_EMPTY_P(u->current))
315 (void)XASE_INTERVAL_DECREF(u->current);
321 _ase_interval_union_fini(ase_interval_union_item_t u)
323 ase_interval_union_item_t tmp;
326 _ase_interval_union_item_fini(tmp);
332 _ase_interval_fini(ase_interval_t a)
334 EMOD_ASE_DEBUG_GC("i:0x%08x (rc:%d) shall be freed...\n",
335 (unsigned int)(a), ase_interval_refval(a));
337 if (ase_interval_decref(a) <= 0) {
338 ase_interval_fini_refcnt(a);
341 EMOD_ASE_DEBUG_GC("VETO! References exist\n");
347 ase_interval_fini(Lisp_Object obj, int unused)
349 ase_interval_t a = XASE_INTERVAL(obj);
351 if (ase_interval_empty_p(a))
354 _ase_interval_fini(a);
359 ase_interval_union_fini(Lisp_Object obj, int unused)
361 ase_interval_union_t i = XASE_INTERVAL_UNION(obj);
366 EMOD_ASE_DEBUG_GC("u:0x%08x@0x%08x (rc:%d) shall be freed...\n",
367 (unsigned int)(i), (unsigned int)obj,
368 ase_interval_union_refval(i));
370 if (ase_interval_union_decref(i) <= 0) {
371 _ase_interval_union_fini(ase_interval_union(i));
372 ase_interval_union_fini_refcnt(i);
375 EMOD_ASE_DEBUG_GC("VETO! References exist\n");
380 /* stuff for the dynacat, markers */
382 _ase_interval_mark(ase_interval_t a)
387 mark_object(a->lower);
388 mark_object(a->upper);
389 mark_object(a->lebesgue_measure);
390 mark_object(a->rational_measure);
391 mark_object(a->colour);
396 _ase_interval_union_item_mark(ase_interval_union_item_t u)
398 mark_object(u->current);
402 _ase_interval_union_mark(ase_interval_union_t i)
404 ase_interval_union_item_t u = ase_interval_union(i);
406 mark_object(i->lebesgue_measure);
407 mark_object(i->rational_measure);
408 mark_object(i->colour);
411 _ase_interval_union_item_mark(u);
418 ase_interval_mark(Lisp_Object obj)
420 EMOD_ASE_DEBUG_INTV("i:0x%08x@0x%08x (rc:%d) shall be marked...\n",
421 (unsigned int)(XASE_INTERVAL(obj)),
423 (XASE_INTERVAL(obj) ?
424 XASE_INTERVAL_REFVAL(obj) : 1));
425 _ase_interval_mark(XASE_INTERVAL(obj));
430 ase_interval_union_mark(Lisp_Object obj)
432 EMOD_ASE_DEBUG_INTV("u:0x%08x@0x%08x (rc:%d) shall be marked...\n",
433 (unsigned int)(XASE_INTERVAL_UNION(obj)),
435 (XASE_INTERVAL_UNION(obj) ?
436 XASE_INTERVAL_UNION_REFVAL(obj) : 1));
437 _ase_interval_union_mark(XASE_INTERVAL_UNION(obj));
443 _ase_wrap_interval(ase_interval_t a)
447 result = make_dynacat(a);
448 XDYNACAT(result)->type = Qase_interval;
451 ase_interval_incref(a);
453 set_dynacat_printer(result, ase_interval_prnt);
454 set_dynacat_marker(result, ase_interval_mark);
455 set_dynacat_finaliser(result, ase_interval_fini);
456 set_dynacat_intprinter(
457 result, (dynacat_intprinter_f)_ase_interval_prnt);
459 EMOD_ASE_DEBUG_INTV("i:0x%08x (rc:%d) shall be wrapped to 0x%08x...\n",
461 (a ? ase_interval_refval(a) : 1),
462 (unsigned int)result);
468 _ase_wrap_interval_union(ase_interval_union_t iu)
472 result = make_dynacat(iu);
473 XDYNACAT(result)->type = Qase_interval_union;
476 ase_interval_union_incref(iu);
478 set_dynacat_printer(result, ase_interval_union_prnt);
479 set_dynacat_marker(result, ase_interval_union_mark);
480 set_dynacat_finaliser(result, ase_interval_union_fini);
481 set_dynacat_intprinter(
482 result, (dynacat_intprinter_f)_ase_interval_union_prnt);
484 EMOD_ASE_DEBUG_INTV("u:0x%016lx (rc:%d) "
485 "shall be wrapped to 0x%016lx...\n",
486 (long unsigned int)iu,
487 (iu ? ase_interval_union_refval(iu) : 1),
488 (long unsigned int)result);
494 _ase_make_interval(Lisp_Object lower, Lisp_Object upper,
495 int lower_open_p, int upper_open_p)
497 ase_interval_t a = NULL;
500 if ((lequ_p = _ase_equal_p(lower, upper)) &&
501 (lower_open_p || upper_open_p)) {
505 a = xnew(struct ase_interval_s);
507 a->obj.category = ase_interval_cat;
511 a->lower_eq_upper_p = lequ_p;
512 if (!INFINITYP(lower))
513 a->lower_open_p = lower_open_p;
516 if (!INFINITYP(upper))
517 a->upper_open_p = upper_open_p;
520 a->lebesgue_measure = Qnil;
521 a->rational_measure = Qnil;
524 ase_interval_init_refcnt(a);
526 EMOD_ASE_DEBUG_INTV("i:0x%08x (rc:0) shall be created...\n",
531 static ase_interval_union_item_t
532 _ase_make_interval_union_item(Lisp_Object intv)
534 ase_interval_union_item_t u = xnew(struct ase_interval_union_item_s);
538 if (ASE_INTERVALP(intv) && !ASE_INTERVAL_EMPTY_P(intv))
539 XASE_INTERVAL_INCREF(intv);
541 EMOD_ASE_DEBUG_INTV("uitem:0x%08x shall be created...\n",
546 static ase_interval_union_t
547 _ase_make_interval_union(ase_interval_union_item_t ui)
549 ase_interval_union_t i = xnew(struct ase_interval_union_s);
552 i->lebesgue_measure = Qnil;
553 i->rational_measure = Qnil;
557 ase_interval_union_init_refcnt(i);
559 EMOD_ASE_DEBUG_INTV("u:0x%08x (rc:0) shall be created...\n",
565 Lisp_Object ase_empty_interval(void)
567 Lisp_Object result = Qnil;
569 XSETASE_INTERVAL(result, NULL);
574 Lisp_Object ase_empty_interval_union(void)
576 Lisp_Object result = Qnil;
577 ase_interval_union_item_t u = NULL;
578 ase_interval_union_t i = NULL;
580 u = _ase_make_interval_union_item(Qase_empty_interval);
581 i = _ase_make_interval_union(u);
583 XSETASE_INTERVAL_UNION(result, i);
588 Lisp_Object ase_universe_interval(void)
590 ase_interval_t a = xnew(struct ase_interval_s);
592 a->lower = Vninfinity;
593 a->upper = Vpinfinity;
594 a->lower_eq_upper_p = 0;
597 a->lebesgue_measure = Qnil;
598 a->rational_measure = Qnil;
601 ase_interval_init_refcnt(a);
602 return _ase_wrap_interval(a);
605 Lisp_Object ase_make_interval(Lisp_Object lower, Lisp_Object upper,
606 int l_open_p, int u_open_p)
608 ase_interval_t a = NULL;
609 Lisp_Object result = Qnil;
611 a = _ase_make_interval(lower, upper, l_open_p, u_open_p);
612 XSETASE_INTERVAL(result, a);
619 ase_interval_embedding_error(Lisp_Object o1, Lisp_Object o2)
621 ase_cartesian_embedding_error(o1, o2);
625 /* we have 3 different arithmetics:
626 * - comparison and ordering of lower bounds
627 * - comparison and ordering of upper bounds
628 * - comparison and ordering of an upper bound with a lower bound
630 bool /* inline this? */
631 _ase_interval_contains_obj_p(ase_interval_t a, Lisp_Object obj)
633 if (UNLIKELY(a == NULL)) {
638 ? _ase_less_p(a->lower, obj)
639 : _ase_lessequal_p(a->lower, obj)) &&
641 ? _ase_greater_p(a->upper, obj)
642 : _ase_greaterequal_p(a->upper, obj))) {
649 int /* inline this? */
650 _ase_interval_contains_intv_p(ase_interval_t a1, ase_interval_t a2)
654 if (UNLIKELY(a1 == NULL))
656 if (UNLIKELY(a2 == NULL))
659 if (LIKELY(a2->lower_open_p)) {
660 result &= (_ase_interval_contains_obj_p(a1, a2->lower) ||
661 _ase_equal_p(a1->lower, a2->lower));
663 result &= _ase_interval_contains_obj_p(a1, a2->lower);
666 if (LIKELY(a2->upper_open_p)) {
667 result &= (_ase_interval_contains_obj_p(a1, a2->upper) ||
668 _ase_equal_p(a1->upper, a2->upper));
670 result &= _ase_interval_contains_obj_p(a1, a2->upper);
677 _ase_interval_contains_union_p(ase_interval_t a, ase_interval_union_t i)
679 /* true iff a \supset j \forall j in i */
680 ase_interval_union_item_t u = ase_interval_union(i);
682 if (!_ase_interval_contains_intv_p(
683 a, XASE_INTERVAL(u->current)))
691 _ase_interval_less_p(ase_interval_t a1, ase_interval_t a2)
698 /* should suffice to compare the lower bounds */
699 return (_ase_less_p(a1->lower, a2->lower) ||
700 (!a1->lower_open_p && a2->lower_open_p &&
701 _ase_equal_p(a1->lower, a2->lower)));
704 _ase_interval_equal_p(ase_interval_t a1, ase_interval_t a2)
713 else if (a1->lower_eq_upper_p && a2->lower_eq_upper_p)
714 return _ase_equal_p(a1->lower, a2->lower);
715 else if (a1->lower_eq_upper_p)
717 else if (a2->lower_eq_upper_p)
720 return (_ase_interval_contains_intv_p(a1, a2) &&
721 _ase_interval_contains_intv_p(a2, a1));
725 ase_interval_less_p(Lisp_Object a1, Lisp_Object a2)
727 if (ASE_INTERVALP(a1) && ASE_INTERVALP(a2)) {
728 return _ase_interval_less_p(
729 XASE_INTERVAL(a1), XASE_INTERVAL(a2));
735 ase_interval_equal_p(Lisp_Object a1, Lisp_Object a2)
737 if (ASE_INTERVALP(a1) && ASE_INTERVALP(a2)) {
738 return _ase_interval_equal_p(
739 XASE_INTERVAL(a1), XASE_INTERVAL(a2));
745 ase_interval_or_union_less_p(Lisp_Object a1, Lisp_Object a2)
747 Lisp_Object na1, na2;
748 if (ASE_INTERVAL_UNION_P(a1))
749 na1 = XASE_INTERVAL_UNION_FIRST(a1);
752 if (ASE_INTERVAL_UNION_P(a2))
753 na2 = XASE_INTERVAL_UNION_FIRST(a2);
756 return ase_interval_less_p(na1, na2);
760 _ase_interval_bounds_connected_p(ase_interval_t a1, ase_interval_t a2)
762 /* only compares upper with lower bound, assumes numerical equality */
763 if (a1->upper_open_p && a2->lower_open_p) {
771 _ase_interval_bounds_disjoint_p(ase_interval_t a1, ase_interval_t a2)
773 /* only compares upper with lower bound, assumes numerical equality */
774 if (!a1->upper_open_p && !a2->lower_open_p) {
782 _ase_interval_interior_contains_obj_p(
783 ase_cartesian_t iip1, ase_cartesian_t iip2)
785 return ase_cartesian_pointwise_erel_p(
786 iip1, iip2, ase_interval_contains_obj_p);
790 _ase_interval_interior_contains_intr_p(
791 ase_cartesian_t iip1, ase_cartesian_t iip2)
793 return ase_cartesian_pointwise_erel_p(
794 iip1, iip2, ase_interval_contains_intv_p);
798 _ase_interval_interior_contains_union_p(
799 ase_cartesian_t iip1, ase_interval_union_t iu)
801 /* true iff a \supset j \forall j in i */
802 ase_interval_union_item_t u = ase_interval_union(iu);
804 if (!_ase_interval_interior_contains_intr_p(
805 iip1, XASE_CARTESIAN(u->current)))
813 _ase_interval_union_contains_obj_p(ase_interval_union_t iu, Lisp_Object obj)
815 ase_interval_union_item_t u = ase_interval_union(iu);
816 Lisp_Object atmp = 0;
820 if (ASE_INTERVALP(atmp)) {
821 if (_ase_interval_contains_obj_p(
822 XASE_INTERVAL(atmp), obj))
824 } else if (ASE_INTERVAL_INTERIOR_P(atmp)) {
825 if (!NILP(_ase_interval_interior_contains_obj_p(
826 XASE_CARTESIAN(atmp),
827 XASE_CARTESIAN(obj))))
836 _ase_interval_union_contains_intv_p(ase_interval_union_t iu, ase_interval_t a)
838 ase_interval_union_item_t u = ase_interval_union(iu);
839 Lisp_Object atmp = 0;
843 if (_ase_interval_contains_intv_p(XASE_INTERVAL(atmp), a))
851 _ase_interval_union_contains_intr_p(
852 ase_interval_union_t iu, ase_cartesian_t iip)
854 ase_interval_union_item_t u = ase_interval_union(iu);
855 Lisp_Object atmp = 0;
859 if (_ase_interval_interior_contains_intr_p(
860 XASE_CARTESIAN(atmp), iip))
868 _ase_interval_union_contains_union_p(
869 ase_interval_union_t iu1, ase_interval_union_t iu2)
871 /* true iff \forall a \in iu2 \exists b \in iu1 : b \supset a */
872 ase_interval_union_item_t u1, u2;
874 u1 = ase_interval_union(iu1);
875 u2 = ase_interval_union(iu2);
878 Lisp_Object o1 = u1->current, o2 = u2->current;
879 if (ASE_INTERVALP(o1)) {
880 ase_interval_t a1 = XASE_INTERVAL(o1);
881 ase_interval_t a2 = XASE_INTERVAL(o2);
882 if (_ase_interval_contains_intv_p(a1, a2))
886 } else if (ASE_INTERVAL_INTERIOR_P(o1)) {
887 ase_cartesian_t c1 = XASE_CARTESIAN(o1);
888 ase_cartesian_t c2 = XASE_CARTESIAN(o2);
889 if (_ase_interval_interior_contains_intr_p(c1, c2))
901 _ase_interval_connected_p(ase_interval_t a1, ase_interval_t a2)
903 if (a1 == NULL || a2 == NULL)
906 if (_ase_equal_p(a1->upper, a2->lower)) {
907 return (_ase_interval_bounds_connected_p(a1, a2));
908 } else if (_ase_equal_p(a1->lower, a2->upper)) {
909 return (_ase_interval_bounds_connected_p(a2, a1) << 1);
910 } else if (_ase_interval_contains_obj_p(a1, a2->lower) ||
911 _ase_interval_contains_obj_p(a2, a1->upper)) {
913 } else if (_ase_interval_contains_obj_p(a1, a2->upper) ||
914 _ase_interval_contains_obj_p(a2, a1->lower)) {
921 _ase_interval_interior_connected_p(
922 ase_cartesian_t iip1, ase_cartesian_t iip2)
924 /* true iff componentwise connected */
925 return ase_cartesian_pointwise_rel_p(
926 iip1, iip2, ase_interval_connected_p);
930 _ase_interval_union_intv_connected_p(
931 ase_interval_union_t iu, ase_interval_t i)
933 /* true iff \forall j \in iu : j u i is connected */
934 ase_interval_union_item_t u = ase_interval_union(iu);
937 ase_interval_t a = XASE_INTERVAL(u->current);
938 if (!_ase_interval_connected_p(a, i))
946 _ase_interval_union_intr_connected_p(
947 ase_interval_union_t iu, ase_cartesian_t c)
949 /* true iff \forall j \in iu : j u i is connected */
950 ase_interval_union_item_t u = ase_interval_union(iu);
953 ase_cartesian_t t = XASE_CARTESIAN(u->current);
954 if (!_ase_interval_interior_connected_p(t, c))
962 _ase_interval_union_connected_p(
963 ase_interval_union_t iu1, ase_interval_union_t iu2)
965 /* true iff iu1 u iu2 is connected, i.e.
966 * iff \forall i \in iu1 : i u iu2 is connected */
967 ase_interval_union_item_t u1 = ase_interval_union(iu1);
970 if (ASE_INTERVALP(u1->current)) {
971 if (!_ase_interval_union_intv_connected_p(
972 iu2, XASE_INTERVAL(u1->current)))
974 } else if (ASE_INTERVAL_INTERIOR_P(u1->current)) {
975 if (!_ase_interval_union_intr_connected_p(
976 iu2, XASE_CARTESIAN(u1->current)))
985 _ase_interval_disjoint_p(ase_interval_t a1, ase_interval_t a2)
987 if (a1 == NULL || a2 == NULL)
990 if (_ase_equal_p(a1->upper, a2->lower)) {
991 return _ase_interval_bounds_disjoint_p(a1, a2);
992 } else if (_ase_equal_p(a1->lower, a2->upper)) {
993 return _ase_interval_bounds_disjoint_p(a2, a1);
995 return !((_ase_interval_contains_obj_p(a1, a2->lower)) ||
996 (_ase_interval_contains_obj_p(a1, a2->upper)) ||
997 (_ase_interval_contains_obj_p(a2, a1->lower)) ||
998 (_ase_interval_contains_obj_p(a2, a1->upper)));
1003 _ase_interval_interior_disjoint_p(
1004 ase_cartesian_t iip1, ase_cartesian_t iip2)
1006 /* true iff iip1 n iip2 = ( ), i.e.
1007 * component-intervals are disjoint in at least one dimension */
1008 return ase_cartesian_antipointwise_rel_p(
1009 iip1, iip2, ase_interval_disjoint_p);
1013 _ase_interval_union_disjoint_intv_p(
1014 ase_interval_union_t iu1, ase_interval_t i2)
1016 /* true iff \forall i \in iu1 : i n i2 = ( ) */
1017 ase_interval_union_item_t u = ase_interval_union(iu1);
1020 ase_interval_t a1 = XASE_INTERVAL(u->current);
1021 if (!_ase_interval_disjoint_p(a1, i2))
1029 _ase_interval_union_disjoint_intr_p(
1030 ase_interval_union_t iu, ase_cartesian_t c)
1032 /* true iff \forall i \in iu1 : i n i2 = ( ) */
1033 ase_interval_union_item_t u = ase_interval_union(iu);
1036 ase_cartesian_t t = XASE_CARTESIAN(u->current);
1037 if (!_ase_interval_interior_disjoint_p(t, c))
1045 _ase_interval_union_disjoint_p(
1046 ase_interval_union_t iu1, ase_interval_union_t iu2)
1048 /* true iff i1 n i2 = ( ), i.e.
1049 * iff \forall i \in i1 \forall j \in i2 : i n j = ( ) */
1050 ase_interval_union_item_t u1 = ase_interval_union(iu1);
1053 if (ASE_INTERVALP(u1->current)) {
1054 if (!_ase_interval_union_disjoint_intv_p(
1055 iu2, XASE_INTERVAL(u1->current)))
1057 } else if (ASE_INTERVAL_INTERIOR_P(u1->current)) {
1058 if (!_ase_interval_union_disjoint_intr_p(
1059 iu2, XASE_CARTESIAN(u1->current)))
1068 _ase_interval_open_p(ase_interval_t a)
1070 return ((a == NULL) || (a->lower_open_p && a->upper_open_p));
1074 _ase_interval_closed_p(ase_interval_t a)
1076 return ((a == NULL) ||
1077 ((!a->lower_open_p || INFINITYP(a->lower)) &&
1078 (!a->upper_open_p || INFINITYP(a->upper))));
1082 _ase_interval_union_open_p(ase_interval_union_item_t u)
1085 if (ASE_INTERVALP(u->current)) {
1086 if (!_ase_interval_open_p(XASE_INTERVAL(u->current)))
1088 } else if (ASE_INTERVAL_INTERIOR_P(u->current)) {
1089 if (!ase_interval_interior_open_p(u->current))
1098 _ase_interval_union_closed_p(ase_interval_union_item_t u)
1101 if (ASE_INTERVALP(u->current)) {
1102 if (!_ase_interval_closed_p(XASE_INTERVAL(u->current)))
1104 } else if (ASE_INTERVAL_INTERIOR_P(u->current)) {
1105 if (!ase_interval_interior_closed_p(u->current))
1114 ase_interval_contains_obj_p(Lisp_Object interval, Lisp_Object obj)
1116 if (_ase_interval_contains_obj_p(
1117 XASE_INTERVAL(interval), obj))
1123 ase_interval_contains_intv_p(Lisp_Object i1, Lisp_Object i2)
1125 if (_ase_interval_contains_intv_p(
1126 XASE_INTERVAL(i1), XASE_INTERVAL(i2)))
1132 ase_interval_contains_union_p(Lisp_Object i, Lisp_Object u)
1134 /* true iff i \supset j \forall j in u */
1135 if (_ase_interval_contains_union_p(
1136 XASE_INTERVAL(i), XASE_INTERVAL_UNION(u)))
1142 ase_interval_union_contains_obj_p(Lisp_Object iu, Lisp_Object obj)
1144 return _ase_interval_union_contains_obj_p(
1145 XASE_INTERVAL_UNION(iu), obj);
1149 ase_interval_union_contains_intv_p(Lisp_Object iu, Lisp_Object i)
1151 return _ase_interval_union_contains_intv_p(
1152 XASE_INTERVAL_UNION(iu), XASE_INTERVAL(i));
1156 ase_interval_union_contains_intr_p(Lisp_Object iu, Lisp_Object iip)
1158 return _ase_interval_union_contains_intr_p(
1159 XASE_INTERVAL_UNION(iu), XASE_CARTESIAN(iip));
1163 ase_interval_union_contains_union_p(Lisp_Object iu1, Lisp_Object iu2)
1165 /* true iff \forall a \in iu2 \exists b \in iu1 : b \supset a */
1166 return _ase_interval_union_contains_union_p(
1167 XASE_INTERVAL_UNION(iu1), XASE_INTERVAL_UNION(iu2));
1171 ase_interval_interior_contains_obj_p(Lisp_Object iip1, Lisp_Object iip2)
1173 if (!ASE_CARTESIAN_INTERIOR_P(iip2) ||
1174 XASE_CARTESIAN_DIMENSION(iip1) !=
1175 XASE_CARTESIAN_DIMENSION(iip2) ||
1176 !EQ(XASE_CARTESIAN_INTERIOR_TYPE(iip1), Qase_interval)) {
1177 signal_error(Qembed_error, list2(iip1, iip2));
1181 return _ase_interval_interior_contains_obj_p(
1182 XASE_CARTESIAN(iip1), XASE_CARTESIAN(iip2));
1186 ase_interval_interior_contains_intr_p(Lisp_Object iip1, Lisp_Object iip2)
1188 if (XASE_CARTESIAN_DIMENSION(iip1) !=
1189 XASE_CARTESIAN_DIMENSION(iip2) ||
1190 !EQ(XASE_CARTESIAN_INTERIOR_TYPE(iip1), Qase_interval) ||
1191 !EQ(XASE_CARTESIAN_INTERIOR_TYPE(iip2), Qase_interval)) {
1192 signal_error(Qembed_error, list2(iip1, iip2));
1195 return _ase_interval_interior_contains_intr_p(
1196 XASE_CARTESIAN(iip1), XASE_CARTESIAN(iip2));
1200 ase_interval_interior_contains_union_p(Lisp_Object iip, Lisp_Object iu)
1202 return _ase_interval_interior_contains_union_p(
1203 XASE_CARTESIAN(iip), XASE_INTERVAL_UNION(iu));
1206 int ase_interval_connected_p(Lisp_Object i1, Lisp_Object i2)
1208 return _ase_interval_connected_p(XASE_INTERVAL(i1), XASE_INTERVAL(i2));
1211 int ase_interval_connected_union_p(Lisp_Object i, Lisp_Object iu)
1213 return _ase_interval_union_intv_connected_p(
1214 XASE_INTERVAL_UNION(iu), XASE_INTERVAL(i));
1217 int ase_interval_union_connected_intv_p(Lisp_Object iu, Lisp_Object i)
1219 return _ase_interval_union_intv_connected_p(
1220 XASE_INTERVAL_UNION(iu), XASE_INTERVAL(i));
1223 int ase_interval_union_connected_intr_p(Lisp_Object iu, Lisp_Object c)
1225 return _ase_interval_union_intr_connected_p(
1226 XASE_INTERVAL_UNION(iu), XASE_CARTESIAN(c));
1229 int ase_interval_union_connected_p(Lisp_Object i1, Lisp_Object i2)
1231 return _ase_interval_union_connected_p(
1232 XASE_INTERVAL_UNION(i1), XASE_INTERVAL_UNION(i2));
1235 int ase_interval_interior_connected_p(Lisp_Object iip1, Lisp_Object iip2)
1237 return _ase_interval_interior_connected_p(
1238 XASE_CARTESIAN(iip1), XASE_CARTESIAN(iip2));
1241 int ase_interval_interior_connected_union_p(Lisp_Object c, Lisp_Object iu)
1243 return _ase_interval_union_intr_connected_p(
1244 XASE_INTERVAL_UNION(iu), XASE_CARTESIAN(c));
1247 int ase_interval_disjoint_p(Lisp_Object i1, Lisp_Object i2)
1249 return _ase_interval_disjoint_p(XASE_INTERVAL(i1), XASE_INTERVAL(i2));
1252 int ase_interval_disjoint_union_p(Lisp_Object i, Lisp_Object iu)
1254 return _ase_interval_union_disjoint_intv_p(
1255 XASE_INTERVAL_UNION(iu), XASE_INTERVAL(i));
1258 int ase_interval_interior_disjoint_p(Lisp_Object iip1, Lisp_Object iip2)
1260 return _ase_interval_interior_disjoint_p(
1261 XASE_CARTESIAN(iip1), XASE_CARTESIAN(iip2));
1264 int ase_interval_interior_disjoint_union_p(Lisp_Object c, Lisp_Object iu)
1266 return _ase_interval_union_disjoint_intr_p(
1267 XASE_INTERVAL_UNION(iu), XASE_CARTESIAN(c));
1270 int ase_interval_union_disjoint_intv_p(Lisp_Object iu, Lisp_Object i)
1272 return _ase_interval_union_disjoint_intv_p(
1273 XASE_INTERVAL_UNION(iu), XASE_INTERVAL(i));
1276 int ase_interval_union_disjoint_intr_p(Lisp_Object iu, Lisp_Object c)
1278 return _ase_interval_union_disjoint_intr_p(
1279 XASE_INTERVAL_UNION(iu), XASE_CARTESIAN(c));
1282 int ase_interval_union_disjoint_p(Lisp_Object i1, Lisp_Object i2)
1284 return _ase_interval_union_disjoint_p(
1285 XASE_INTERVAL_UNION(i1), XASE_INTERVAL_UNION(i2));
1288 int ase_interval_open_p(Lisp_Object intv)
1290 return _ase_interval_open_p(XASE_INTERVAL(intv));
1293 int ase_interval_closed_p(Lisp_Object intv)
1295 return _ase_interval_closed_p(XASE_INTERVAL(intv));
1298 int ase_interval_union_open_p(Lisp_Object iu)
1300 return _ase_interval_union_open_p(XASE_INTERVAL_UNION_SER(iu));
1303 int ase_interval_union_closed_p(Lisp_Object iu)
1305 return _ase_interval_union_closed_p(XASE_INTERVAL_UNION_SER(iu));
1308 int ase_interval_interior_open_p(Lisp_Object iip)
1310 return ase_cartesian_pointwise_pred_p(
1311 XASE_CARTESIAN(iip), ase_interval_open_p);
1314 int ase_interval_interior_closed_p(Lisp_Object iip)
1316 return ase_cartesian_pointwise_pred_p(
1317 XASE_CARTESIAN(iip), ase_interval_closed_p);
1322 static ase_interval_t
1323 _ase_unite_intervals(ase_interval_t a1, ase_interval_t a2)
1325 /* Returns a new interval item if a1 and a2 turn out not to be recyclable */
1328 if (a1 == NULL && a2 == NULL) {
1330 } else if (a2 == NULL) {
1332 } else if (a1 == NULL) {
1334 } else if (_ase_interval_contains_intv_p(a1, a2)) {
1336 } else if (_ase_interval_contains_intv_p(a2, a1)) {
1338 } else if ((where = _ase_interval_connected_p(a1, a2))) {
1339 Lisp_Object new_lower, new_upper;
1340 int new_lower_open_p, new_upper_open_p;
1343 new_lower = a1->lower;
1344 new_lower_open_p = a1->lower_open_p;
1345 new_upper = a2->upper;
1346 new_upper_open_p = a2->upper_open_p;
1348 new_lower = a2->lower;
1349 new_lower_open_p = a2->lower_open_p;
1350 new_upper = a1->upper;
1351 new_upper_open_p = a1->upper_open_p;
1354 return _ase_make_interval(
1355 new_lower, new_upper,
1356 new_lower_open_p, new_upper_open_p);
1363 _ase_interval_interior_pointintv_p(ase_cartesian_t c)
1365 int pointintvp, i, dim = ase_cartesian_dimension(c);
1367 for (i = 0, pointintvp = 1; i < dim && pointintvp; i++) {
1368 Lisp_Object a = ase_cartesian_objects(c)[i];
1369 if (!XASE_INTERVAL(a)->lower_eq_upper_p)
1375 static ase_cartesian_t
1376 _ase_unite_intervals_intr(ase_cartesian_t c1, ase_cartesian_t c2)
1378 int hypidx, hypplaneeqp = 0;
1385 if (!NILP(_ase_interval_interior_contains_intr_p(c1, c2))) {
1386 /* cartesians lack ref counters atm, hence we cant do: */
1388 } else if (!NILP(_ase_interval_interior_contains_intr_p(c2, c1))) {
1389 /* cartesians lack ref counters atm, hence we cant do: */
1393 dim = ase_cartesian_dimension(c1);
1394 for (hypidx = 0; hypidx < dim; hypidx++) {
1395 /* we build the hyperplane of the interval by
1396 * omitting the hypidx-th dimension in the next loop */
1397 for (i = 0, hypplaneeqp = 1; i < dim && hypplaneeqp; i++) {
1398 Lisp_Object i1 = ase_cartesian_objects(c1)[i];
1399 Lisp_Object i2 = ase_cartesian_objects(c2)[i];
1401 !ase_interval_equal_p(i1, i2))
1405 /* finally found a hyperplane where all
1406 * intervals coincide, this means, we can merge */
1411 /* merge along the hypidx-th dimension */
1412 Lisp_Object i1 = ase_cartesian_objects(c1)[hypidx];
1413 Lisp_Object i2 = ase_cartesian_objects(c2)[hypidx];
1414 ase_interval_t a1 = XASE_INTERVAL(i1);
1415 ase_interval_t a2 = XASE_INTERVAL(i2);
1416 ase_interval_t a = _ase_unite_intervals(a1, a2);
1417 Lisp_Object *tmp = alloca_array(Lisp_Object, dim);
1422 for (i = 0; i < dim; i++)
1423 tmp[i] = ase_cartesian_objects(c1)[i];
1424 tmp[hypidx] = _ase_wrap_interval(a);
1425 return _ase_make_cartesian(dim, tmp, 1);
1432 ase_unite_intervals_intv(Lisp_Object a1, Lisp_Object a2)
1435 _ase_unite_intervals(XASE_INTERVAL(a1), XASE_INTERVAL(a2));
1438 return _ase_wrap_interval(a);
1444 ase_unite_intervals_intr(Lisp_Object iip1, Lisp_Object iip2)
1446 ase_cartesian_t a = NULL;
1448 if (ASE_INTERVAL_EMPTY_P(iip1))
1450 if (ASE_INTERVAL_EMPTY_P(iip2))
1453 a = _ase_unite_intervals_intr(
1454 XASE_CARTESIAN(iip1), XASE_CARTESIAN(iip2));
1457 return _ase_wrap_cartesian_interior(a);
1463 ase_unite_intervals(Lisp_Object a1, Lisp_Object a2)
1465 if (ASE_INTERVAL_INTERIOR_P(a1) || ASE_INTERVAL_INTERIOR_P(a2))
1466 return ase_unite_intervals_intr(a1, a2);
1467 else if (ASE_INTERVALP(a1) || ASE_INTERVALP(a2))
1468 return ase_unite_intervals_intv(a1, a2);
1473 static ase_interval_t
1474 _ase_intersect_intv_intv(ase_interval_t a1, ase_interval_t a2)
1476 /* Returns a new interval item if a1 and a2 turn out not to be recyclable */
1479 if (a1 == NULL || a2 == NULL) {
1481 } else if (_ase_interval_disjoint_p(a1, a2)) {
1483 } else if (_ase_interval_contains_intv_p(a1, a2)) {
1485 } else if (_ase_interval_contains_intv_p(a2, a1)) {
1487 } else if ((where = _ase_interval_connected_p(a1, a2))) {
1488 Lisp_Object new_lower, new_upper;
1489 int new_lower_open_p, new_upper_open_p;
1492 new_lower = a2->lower;
1493 new_lower_open_p = a2->lower_open_p;
1494 new_upper = a1->upper;
1495 new_upper_open_p = a1->upper_open_p;
1497 new_lower = a1->lower;
1498 new_lower_open_p = a1->lower_open_p;
1499 new_upper = a2->upper;
1500 new_upper_open_p = a2->upper_open_p;
1503 return _ase_make_interval(
1504 new_lower, new_upper,
1505 new_lower_open_p, new_upper_open_p);
1512 ase_intersect_intv_intv(Lisp_Object a1, Lisp_Object a2)
1515 _ase_intersect_intv_intv(XASE_INTERVAL(a1), XASE_INTERVAL(a2));
1518 return _ase_wrap_interval(a);
1520 return Qase_empty_interval;
1523 static ase_cartesian_t
1524 _ase_intersect_intr_intr(ase_cartesian_t c1, ase_cartesian_t c2)
1526 /* Returns a new interval item if a1 and a2 turn out not to be recyclable */
1527 if (c1 == NULL || c2 == NULL) {
1529 } else if (_ase_interval_interior_disjoint_p(c1, c2)) {
1532 int i, dim = ase_cartesian_dimension(c1);
1533 Lisp_Object *newos = alloca_array(Lisp_Object, dim);
1535 for (i = 0; i < dim; i++) {
1536 Lisp_Object o1 = ase_cartesian_objects(c1)[i];
1537 Lisp_Object o2 = ase_cartesian_objects(c2)[i];
1538 newos[i] = ase_intersect_intv_intv(o1, o2);
1541 return _ase_make_cartesian(dim, newos, 1);
1548 ase_intersect_intr_intr(Lisp_Object c1, Lisp_Object c2)
1551 _ase_intersect_intr_intr(
1552 XASE_CARTESIAN(c1), XASE_CARTESIAN(c2));
1555 return _ase_wrap_cartesian_interior(c);
1557 return Qase_empty_interval;
1560 static ase_interval_union_item_t
1561 _ase_intersect_union_intv(ase_interval_union_t iu, ase_interval_t a)
1563 ase_interval_union_item_t u = ase_interval_union(iu);
1564 struct ase_interval_union_item_s ures, *ur = &ures;
1566 ur->current = Qase_empty_interval;
1569 ase_interval_t a1 = XASE_INTERVAL(u->current);
1570 ase_interval_t na = _ase_intersect_intv_intv(a1, a);
1573 ur = ur->next = _ase_make_interval_union_item(
1574 _ase_wrap_interval(na));
1582 ase_intersect_union_intv(Lisp_Object iu, Lisp_Object a)
1584 ase_interval_union_item_t nu =
1585 _ase_intersect_union_intv(
1586 XASE_INTERVAL_UNION(iu), XASE_INTERVAL(a));
1589 return _ase_wrap_interval_union(
1590 _ase_make_interval_union(nu));
1592 Lisp_Object na = nu->current;
1593 _ase_interval_union_item_fini(nu);
1596 return Qase_empty_interval;
1600 ase_intersect_intv_union(Lisp_Object a, Lisp_Object iu)
1602 return ase_intersect_union_intv(iu, a);
1605 static ase_interval_union_item_t
1606 _ase_intersect_union_intr(ase_interval_union_t iu, ase_cartesian_t c)
1608 ase_interval_union_item_t u = ase_interval_union(iu);
1609 struct ase_interval_union_item_s ures, *ur = &ures;
1611 ur->current = Qase_empty_interval;
1614 ase_cartesian_t c1 = XASE_CARTESIAN(u->current);
1615 ase_cartesian_t nc = _ase_intersect_intr_intr(c1, c);
1618 ur = ur->next = _ase_make_interval_union_item(
1619 _ase_wrap_cartesian_interior(nc));
1623 _ase_normalise_union_intr(&ures);
1629 ase_intersect_union_intr(Lisp_Object iu, Lisp_Object c)
1631 ase_interval_union_item_t nu =
1632 _ase_intersect_union_intr(
1633 XASE_INTERVAL_UNION(iu), XASE_CARTESIAN(c));
1636 return _ase_wrap_interval_union(
1637 _ase_make_interval_union(nu));
1639 Lisp_Object na = nu->current;
1640 _ase_interval_union_item_fini(nu);
1643 return Qase_empty_interval;
1647 ase_intersect_intr_union(Lisp_Object c, Lisp_Object iu)
1649 return ase_intersect_union_intr(iu, c);
1652 static ase_interval_union_item_t
1653 _ase_intersect_union_union(ase_interval_union_t iu1, ase_interval_union_t iu2)
1655 ase_interval_union_item_t u = ase_interval_union(iu1);
1656 struct ase_interval_union_item_s ures, *ur = &ures;
1658 ur->current = Qase_empty_interval;
1661 ase_interval_union_item_t na = NULL;
1663 if (ASE_INTERVALP(u->current)) {
1664 ase_interval_t a1 = XASE_INTERVAL(u->current);
1665 na = _ase_intersect_union_intv(iu2, a1);
1666 } else if (ASE_INTERVAL_INTERIOR_P(u->current)) {
1667 ase_cartesian_t c1 = XASE_CARTESIAN(u->current);
1668 na = _ase_intersect_union_intr(iu2, c1);
1673 /* forewind to the end of ur */
1680 if (ures.next && ASE_INTERVAL_INTERIOR_P(ures.next->current)) {
1681 _ase_normalise_union_intr(&ures);
1688 ase_intersect_union_union(Lisp_Object iu1, Lisp_Object iu2)
1690 ase_interval_union_item_t nu =
1691 _ase_intersect_union_union(
1692 XASE_INTERVAL_UNION(iu1), XASE_INTERVAL_UNION(iu2));
1695 return _ase_wrap_interval_union(
1696 _ase_make_interval_union(nu));
1698 Lisp_Object na = nu->current;
1699 _ase_interval_union_item_fini(nu);
1702 return Qase_empty_interval;
1705 static ase_interval_union_item_t
1706 _ase_subtract_intv_intv(ase_interval_t a1, ase_interval_t a2)
1708 /* Returns a new interval item if a1 and a2 turn out not to be recyclable */
1714 return _ase_make_interval_union_item(
1715 _ase_wrap_interval(a1));
1716 } else if (_ase_interval_disjoint_p(a1, a2)) {
1717 return _ase_make_interval_union_item(
1718 _ase_wrap_interval(a1));
1719 } else if (_ase_interval_contains_intv_p(a2, a1)) {
1721 } else if (_ase_interval_contains_intv_p(a1, a2)) {
1722 /* the hard case, now a1 decomposes to two interval items */
1723 Lisp_Object na1l, na1u, na2l, na2u;
1724 int na1lop, na1uop, na2lop, na2uop;
1725 ase_interval_union_item_t ures = NULL, u1 = NULL, u2 = NULL;
1728 na1lop = a1->lower_open_p;
1730 na1uop = !a2->lower_open_p;
1733 na2lop = !a2->upper_open_p;
1735 na2uop = a1->upper_open_p;
1737 a1 = _ase_make_interval(na1l, na1u, na1lop, na1uop);
1738 a2 = _ase_make_interval(na2l, na2u, na2lop, na2uop);
1741 u1 = _ase_make_interval_union_item(
1742 _ase_wrap_interval(a1));
1745 u2 = _ase_make_interval_union_item(
1746 _ase_wrap_interval(a2));
1759 } else if ((where = _ase_interval_connected_p(a1, a2))) {
1760 Lisp_Object new_lower, new_upper;
1761 int new_lower_open_p, new_upper_open_p;
1764 new_lower = a1->lower;
1765 new_lower_open_p = a1->lower_open_p;
1766 new_upper = a2->lower;
1767 new_upper_open_p = !a2->lower_open_p;
1769 new_lower = a2->upper;
1770 new_lower_open_p = !a2->upper_open_p;
1771 new_upper = a1->upper;
1772 new_upper_open_p = a1->upper_open_p;
1775 return _ase_make_interval_union_item(
1778 new_lower, new_upper,
1779 new_lower_open_p, new_upper_open_p)));
1781 EMOD_ASE_CRITICAL("Desaster!\n");
1788 ase_subtract_intv_intv(Lisp_Object a1, Lisp_Object a2)
1790 ase_interval_union_item_t u =
1791 _ase_subtract_intv_intv(XASE_INTERVAL(a1), XASE_INTERVAL(a2));
1794 return _ase_wrap_interval_union(
1795 _ase_make_interval_union(u));
1797 Lisp_Object na = u->current;
1798 _ase_interval_union_item_fini(u);
1801 return Qase_empty_interval;
1804 static ase_interval_union_item_t
1805 _ase_subtract_intr_intr(ase_cartesian_t c1, ase_cartesian_t c2)
1810 return _ase_make_interval_union_item(
1811 _ase_wrap_cartesian_interior(c1));
1812 } else if (_ase_interval_interior_disjoint_p(c1, c2)) {
1813 return _ase_make_interval_union_item(
1814 _ase_wrap_cartesian_interior(c1));
1815 } else if (!NILP(_ase_interval_interior_contains_intr_p(c2, c1))) {
1817 } else if (_ase_interval_interior_connected_p(c1, c2)) {
1818 //!NILP(_ase_interval_interior_contains_intr_p(c1, c2)) ||
1819 /* the hard case, we decompose c1 into at most 2n
1820 * n-dimensional interval products */
1821 int i, dim = ase_cartesian_dimension(c1);
1822 struct ase_interval_union_item_s ures, *ur = &ures;
1824 for (i = 0; i < dim; i++) {
1825 Lisp_Object o1 = ase_cartesian_objects(c1)[i];
1826 Lisp_Object o2 = ase_cartesian_objects(c2)[i];
1827 ase_interval_union_item_t dec =
1828 _ase_subtract_intv_intv(
1829 XASE_INTERVAL(o1), XASE_INTERVAL(o2));
1830 /* dec should now have two elements,
1831 * one left of o2 in o1, one right of o2 in o1 */
1832 Lisp_Object *newos = alloca_array(Lisp_Object, dim);
1835 /* copy the (i-1) whole intervals */
1836 for (j = 0; j < i; j++) {
1837 Lisp_Object t1 = ase_cartesian_objects(c1)[j];
1840 /* now push all the interval components of o2
1841 * which lie in subspaces of index >i */
1842 for (j = i+1; j < dim; j++) {
1843 Lisp_Object t1 = ase_cartesian_objects(c1)[j];
1844 Lisp_Object t2 = ase_cartesian_objects(c2)[j];
1845 newos[j] = ase_intersect_intv_intv(t1, t2);
1847 /* copy the interval left of o2 */
1848 newos[i] = dec->current;
1850 _ase_make_interval_union_item(
1851 ase_make_cartesian(dim, newos, 1));
1852 /* copy the interval right of o2, if there is one */
1854 newos[i] = dec->next->current;
1856 _ase_make_interval_union_item(
1860 _ase_interval_union_item_fini(dec);
1864 } else if (_ase_interval_interior_connected_p(c1, c2)) {
1865 /* kinda hard case, we decompose c1 into 2n-1
1866 * n-dimensional interval products */
1867 EMOD_ASE_CRITICAL("Desaster!\n");
1869 EMOD_ASE_CRITICAL("Desaster!\n");
1876 ase_subtract_intr_intr(Lisp_Object c1, Lisp_Object c2)
1878 ase_interval_union_item_t u =
1879 _ase_subtract_intr_intr(XASE_CARTESIAN(c1), XASE_CARTESIAN(c2));
1882 return _ase_wrap_interval_union(
1883 _ase_make_interval_union(u));
1885 Lisp_Object na = u->current;
1886 _ase_interval_union_item_fini(u);
1889 return Qase_empty_interval;
1892 static ase_interval_union_item_t
1893 _ase_subtract_union_intv(ase_interval_union_item_t u, ase_interval_t a)
1895 /* (A u B) \ C = (A \ C u B \ C) */
1896 struct ase_interval_union_item_s ures, *ur = &ures;
1898 ur->current = Qase_empty_interval;
1901 ase_interval_t a1 = XASE_INTERVAL(u->current);
1902 ase_interval_union_item_t na;
1904 na = _ase_subtract_intv_intv(a1, a);
1908 /* forewind to the end of ur */
1919 ase_subtract_union_intv(Lisp_Object iu, Lisp_Object a)
1921 /* (A u B) \ C = (A \ C u B \ C) */
1922 ase_interval_union_item_t nu =
1923 _ase_subtract_union_intv(
1924 XASE_INTERVAL_UNION_SER(iu),
1928 return _ase_wrap_interval_union(
1929 _ase_make_interval_union(nu));
1931 Lisp_Object na = nu->current;
1932 _ase_interval_union_item_fini(nu);
1935 return Qase_empty_interval;
1938 static ase_interval_union_item_t
1939 _ase_subtract_union_intr(ase_interval_union_item_t u, ase_cartesian_t c)
1941 /* (A u B) \ C = (A \ C u B \ C) */
1942 struct ase_interval_union_item_s ures, *ur = &ures;
1944 ur->current = Qase_empty_interval;
1947 ase_cartesian_t c1 = XASE_CARTESIAN(u->current);
1948 ase_interval_union_item_t na;
1950 na = _ase_subtract_intr_intr(c1, c);
1954 /* forewind to the end of ur */
1965 ase_subtract_union_intr(Lisp_Object iu, Lisp_Object c)
1967 /* (A u B) \ C = (A \ C u B \ C) */
1968 ase_interval_union_item_t nu =
1969 _ase_subtract_union_intr(
1970 XASE_INTERVAL_UNION_SER(iu),
1974 return _ase_wrap_interval_union(
1975 _ase_make_interval_union(nu));
1977 Lisp_Object na = nu->current;
1978 _ase_interval_union_item_fini(nu);
1981 return Qase_empty_interval;
1984 static ase_interval_union_item_t
1985 _ase_subtract_intv_union(ase_interval_t a, ase_interval_union_item_t u)
1987 /* A \ (B u C) = (A \ B) \ C */
1988 struct ase_interval_union_item_s ures, *na = &ures;
1990 na->current = _ase_wrap_interval(a);
1993 ase_interval_t a2 = XASE_INTERVAL(u->current);
1995 na = _ase_subtract_union_intv(na, a2);
2002 /* Copy the local temporary to the heap */
2003 na = xnew(struct ase_interval_union_item_s);
2005 memcpy(na,&ures,sizeof(ures));
2011 ase_subtract_intv_union(Lisp_Object a, Lisp_Object iu)
2013 /* A \ (B u C) = (A \ B) \ C */
2014 ase_interval_union_item_t nu =
2015 _ase_subtract_intv_union(
2017 XASE_INTERVAL_UNION_SER(iu));
2020 return _ase_wrap_interval_union(
2021 _ase_make_interval_union(nu));
2023 Lisp_Object na = nu->current;
2024 _ase_interval_union_item_fini(nu);
2027 return Qase_empty_interval;
2030 static ase_interval_union_item_t
2031 _ase_subtract_intr_union(ase_cartesian_t c, ase_interval_union_item_t u)
2033 /* A \ (B u C) = (A \ B) \ C */
2034 struct ase_interval_union_item_s ures, *na = &ures;
2036 na->current = _ase_wrap_cartesian_interior(c);
2039 ase_cartesian_t c2 = XASE_CARTESIAN(u->current);
2041 na = _ase_subtract_union_intr(na, c2);
2049 /* Copy the local temporary to the heap */
2050 na = xnew(struct ase_interval_union_item_s);
2052 memcpy(na,&ures,sizeof(ures));
2058 ase_subtract_intr_union(Lisp_Object c, Lisp_Object iu)
2060 /* A \ (B u C) = (A \ B) \ C */
2061 ase_interval_union_item_t nu =
2062 _ase_subtract_intr_union(
2064 XASE_INTERVAL_UNION_SER(iu));
2067 return _ase_wrap_interval_union(
2068 _ase_make_interval_union(nu));
2070 Lisp_Object na = nu->current;
2071 _ase_interval_union_item_fini(nu);
2074 return Qase_empty_interval;
2077 static ase_interval_union_item_t
2078 _ase_subtract_union_union(ase_interval_union_t iu1, ase_interval_union_t iu2)
2080 /* (A u B) \ (C u D) = ((A u B) \ C) \ D */
2081 ase_interval_union_item_t na = ase_interval_union(iu1);
2082 ase_interval_union_item_t u = ase_interval_union(iu2);
2085 if (ASE_INTERVALP(u->current)) {
2086 ase_interval_t a = XASE_INTERVAL(u->current);
2087 na = _ase_subtract_union_intv(na, a);
2088 } else if (ASE_INTERVAL_INTERIOR_P(u->current)) {
2089 ase_cartesian_t c = XASE_CARTESIAN(u->current);
2090 na = _ase_subtract_union_intr(na, c);
2102 ase_subtract_union_union(Lisp_Object iu1, Lisp_Object iu2)
2104 /* (A u B) \ (C u D) = ((A u B) \ C) \ D */
2105 ase_interval_union_item_t nu =
2106 _ase_subtract_union_union(
2107 XASE_INTERVAL_UNION(iu1), XASE_INTERVAL_UNION(iu2));
2110 return _ase_wrap_interval_union(
2111 _ase_make_interval_union(nu));
2113 Lisp_Object na = nu->current;
2114 _ase_interval_union_item_fini(nu);
2117 return Qase_empty_interval;
2122 _ase_copy_interval(ase_interval_t a)
2124 Lisp_Object result = Qnil;
2126 XSETASE_INTERVAL(result, a);
2130 Lisp_Object ase_copy_interval(Lisp_Object intv)
2132 return _ase_copy_interval(XASE_INTERVAL(intv));
2136 _ase_interval_union_explode_array(int nargs, Lisp_Object *args, int add)
2138 ase_interval_union_item_t u;
2139 Lisp_Object *newargs = args;
2142 for (j = 0; j < nargs+add; ) {
2143 if (ASE_INTERVAL_UNION_P(args[j])) {
2144 u = ase_interval_union(XASE_INTERVAL_UNION(args[j]));
2145 newargs[j] = u->current;
2148 newargs[nargs+mov] = u->current;
2159 _ase_normalise_union(ase_interval_union_item_t u)
2161 /* assumes first item of u is sorta head, we cant change that */
2162 ase_interval_union_item_t u1 = u->next, u2 = NULL, pu = u;
2163 Lisp_Object a1, a2, atmp;
2166 while ((u2 = u1->next)) {
2170 /* connectivity can solely occur at upper-lower */
2171 atmp = ase_unite_intervals(a1, a2);
2173 ase_interval_union_item_t tmp;
2175 tmp = _ase_make_interval_union_item(atmp);
2176 tmp->next = u2->next;
2178 _ase_interval_union_item_fini(u1);
2179 _ase_interval_union_item_fini(u2);
2181 pu->next = u1 = tmp;
2192 _ase_normalise_union_intr(ase_interval_union_item_t u)
2194 /* assumes first item of u is sorta head, we cant change that */
2195 ase_interval_union_item_t u1 = u->next, u2 = NULL, pu1 = u, pu2;
2196 Lisp_Object a1, a2, atmp;
2206 /* connectivity can occur everywhere! */
2207 atmp = ase_unite_intervals(a1, a2);
2209 ase_interval_union_item_t tmp, u2n;
2211 tmp = _ase_make_interval_union_item(atmp);
2212 if (u1->next == u2) {
2213 tmp->next = u2->next;
2215 tmp->next = u1->next;
2221 _ase_interval_union_item_fini(u1);
2222 _ase_interval_union_item_fini(u2);
2224 /* we start over from the very beginning
2225 * there might be new merge opportunities now
2226 * if speed is important, we should allow
2227 * a merge depth of 1, settint u1 to tmp
2228 * would be the equivalent action for this */
2243 static ase_interval_union_item_t
2244 _ase_interval_boundary(ase_interval_t a)
2246 Lisp_Object blo = Qnil, bup = Qnil;
2247 ase_interval_union_item_t ures = NULL;
2249 if (a == NULL || a->lower_eq_upper_p)
2252 blo = _ase_wrap_interval(
2253 _ase_make_interval(a->lower, a->lower, 0, 0));
2254 if (!_ase_equal_p(a->lower, a->upper)) {
2255 bup = _ase_wrap_interval(
2256 _ase_make_interval(a->upper, a->upper, 0, 0));
2259 ures = _ase_make_interval_union_item(blo);
2261 ures->next = _ase_make_interval_union_item(bup);
2266 Lisp_Object ase_interval_boundary(Lisp_Object intv)
2268 ase_interval_union_item_t u =
2269 _ase_interval_boundary(XASE_INTERVAL(intv));
2272 return Qase_empty_interval;
2274 return _ase_wrap_interval_union(
2275 _ase_make_interval_union(u));
2278 static ase_interval_union_item_t
2279 _ase_interval_interior_boundary(ase_cartesian_t c)
2281 struct ase_interval_union_item_s ures, *ur = &ures;
2282 int i, dim = ase_cartesian_dimension(c);
2284 ur->current = Qase_empty_interval;
2286 for (i = 0; i < dim; i++) {
2287 ase_interval_union_item_t tmp =
2288 _ase_interval_boundary(
2289 XASE_INTERVAL(ase_cartesian_objects(c)[i]));
2290 Lisp_Object *newos = alloca_array(Lisp_Object, dim);
2296 for (j = 0; j < dim; j++) {
2297 newos[j] = ase_cartesian_objects(c)[j];
2299 /* replace i-th component with one boundary point */
2300 newos[i] = tmp->current;
2301 /* replace with the new interior product */
2303 _ase_wrap_cartesian_interior(
2304 _ase_make_cartesian(dim, newos, 1));
2305 /* replace i-th component with the other boundary point */
2306 newos[i] = tmp->next->current;
2307 /* and replace again with new interior product */
2308 tmp->next->current =
2309 _ase_wrap_cartesian_interior(
2310 _ase_make_cartesian(dim, newos, 1));
2312 /* pump the stuff into ur */
2320 static ase_interval_union_item_t
2321 _ase_interval_union_boundary(ase_interval_union_item_t u)
2323 struct ase_interval_union_item_s ures, *ur = &ures;
2326 lastiv = ur->current = Qase_empty_interval;
2329 ase_interval_union_item_t tmp = NULL;
2332 if (ASE_INTERVALP(u->current)) {
2333 tmp = _ase_interval_boundary(
2334 XASE_INTERVAL(u->current));
2335 } else if (ASE_INTERVAL_INTERIOR_P(u->current)) {
2336 tmp = _ase_interval_interior_boundary(
2337 XASE_CARTESIAN(u->current));
2344 /* disjoint intervals may have equal boundary points */
2345 curiv = tmp->current;
2346 if (!ase_interval_equal_p(lastiv, curiv)) {
2349 ur->next = tmp->next;
2350 _ase_interval_union_item_fini(tmp);
2354 lastiv = ur->current;
2357 if (ASE_INTERVAL_INTERIOR_P(lastiv)) {
2358 _ase_normalise_union_intr(&ures);
2364 Lisp_Object ase_interval_interior_boundary(Lisp_Object intv_intr_prod)
2366 ase_interval_union_item_t u =
2367 _ase_interval_interior_boundary(
2368 XASE_CARTESIAN(intv_intr_prod));
2371 return Qase_empty_interval;
2373 return _ase_wrap_interval_union(
2374 _ase_make_interval_union(u));
2377 Lisp_Object ase_interval_union_boundary(Lisp_Object intv_union)
2379 ase_interval_union_item_t u =
2380 _ase_interval_union_boundary(
2381 XASE_INTERVAL_UNION_SER(intv_union));
2384 return Qase_empty_interval;
2386 return _ase_wrap_interval_union(
2387 _ase_make_interval_union(u));
2390 static ase_interval_t
2391 _ase_interval_closure(ase_interval_t a)
2395 if (_ase_interval_closed_p(a))
2398 return _ase_make_interval(a->lower, a->upper, 0, 0);
2401 Lisp_Object ase_interval_closure(Lisp_Object intv)
2404 _ase_interval_closure(XASE_INTERVAL(intv));
2407 return Qase_empty_interval;
2409 return _ase_wrap_interval(u);
2412 static ase_cartesian_t
2413 _ase_interval_interior_closure(ase_cartesian_t c)
2415 int i, dim = ase_cartesian_dimension(c);
2416 Lisp_Object *os = ase_cartesian_objects(c);
2417 Lisp_Object *newos = alloca_array(Lisp_Object, dim);
2419 for (i = 0; i < dim; i++) {
2420 newos[i] = ase_interval_closure(os[i]);
2423 return _ase_make_cartesian(dim, newos, 1);
2426 Lisp_Object ase_interval_interior_closure(Lisp_Object intv_intr_prod)
2429 _ase_interval_interior_closure(
2430 XASE_CARTESIAN(intv_intr_prod));
2433 return Qase_empty_interval;
2435 return _ase_wrap_cartesian_interior(c);
2438 static ase_interval_union_item_t
2439 _ase_interval_union_closure(ase_interval_union_item_t u)
2441 struct ase_interval_union_item_s ures, *ur = &ures;
2443 if (_ase_interval_union_closed_p(u))
2446 ur->current = Qase_empty_interval;
2449 Lisp_Object ltmp = Qnil;
2450 if (ASE_INTERVALP(u->current)) {
2451 ase_interval_t tmp =
2452 _ase_interval_closure(
2453 XASE_INTERVAL(u->current));
2457 ltmp = _ase_wrap_interval(tmp);
2458 } else if (ASE_INTERVAL_INTERIOR_P(u->current)) {
2459 ase_cartesian_t tmp =
2460 _ase_interval_interior_closure(
2461 XASE_CARTESIAN(u->current));
2465 ltmp = _ase_wrap_cartesian_interior(tmp);
2467 ur = ur->next = _ase_make_interval_union_item(ltmp);
2470 _ase_normalise_union(&ures);
2475 Lisp_Object ase_interval_union_closure(Lisp_Object intv_union)
2477 ase_interval_union_item_t u =
2478 _ase_interval_union_closure(
2479 XASE_INTERVAL_UNION_SER(intv_union));
2482 return Qase_empty_interval;
2485 return _ase_wrap_interval_union(
2486 _ase_make_interval_union(u));
2491 static ase_interval_t
2492 _ase_interval_interior(ase_interval_t a)
2494 if (a == NULL || _ase_equal_p(a->lower, a->upper))
2497 if (_ase_interval_open_p(a))
2500 return _ase_make_interval(a->lower, a->upper, 1, 1);
2503 Lisp_Object ase_interval_interior(Lisp_Object intv)
2506 _ase_interval_interior(XASE_INTERVAL(intv));
2509 return Qase_empty_interval;
2511 return _ase_wrap_interval(u);
2514 static ase_cartesian_t
2515 _ase_interval_interior_interior(ase_cartesian_t c)
2517 int i, dim = ase_cartesian_dimension(c);
2518 Lisp_Object *os = ase_cartesian_objects(c);
2519 Lisp_Object *newos = alloca_array(Lisp_Object, dim);
2521 for (i = 0; i < dim; i++) {
2522 newos[i] = ase_interval_interior(os[i]);
2525 return _ase_make_cartesian(dim, newos, 1);
2528 Lisp_Object ase_interval_interior_interior(Lisp_Object intv_intr_prod)
2531 _ase_interval_interior_interior(
2532 XASE_CARTESIAN(intv_intr_prod));
2535 return Qase_empty_interval;
2537 return _ase_wrap_cartesian_interior(c);
2540 static ase_interval_union_item_t
2541 _ase_interval_union_interior(ase_interval_union_item_t u)
2543 struct ase_interval_union_item_s ures, *ur = &ures;
2545 if (_ase_interval_union_open_p(u))
2548 ur->current = Qase_empty_interval;
2551 Lisp_Object ltmp = Qnil;
2552 if (ASE_INTERVALP(u->current)) {
2553 ase_interval_t tmp =
2554 _ase_interval_interior(
2555 XASE_INTERVAL(u->current));
2559 ltmp = _ase_wrap_interval(tmp);
2560 } else if (ASE_INTERVAL_INTERIOR_P(u->current)) {
2561 ase_cartesian_t tmp =
2562 _ase_interval_interior_interior(
2563 XASE_CARTESIAN(u->current));
2567 ltmp = _ase_wrap_cartesian_interior(tmp);
2569 ur = ur->next = _ase_make_interval_union_item(ltmp);
2575 Lisp_Object ase_interval_union_interior(Lisp_Object intv_union)
2577 ase_interval_union_item_t u =
2578 _ase_interval_union_interior(
2579 XASE_INTERVAL_UNION_SER(intv_union));
2582 return Qase_empty_interval;
2585 return _ase_wrap_interval_union(
2586 _ase_make_interval_union(u));
2591 static ase_interval_type_t
2592 ase_interval_type(Lisp_Object o)
2594 if (ASE_INTERVALP(o)) {
2595 return ASE_ITYPE_INTERVAL;
2596 } else if (ASE_INTERVAL_UNION_P(o)) {
2597 return ASE_ITYPE_UNION;
2598 } else if (ASE_INTERVAL_INTERIOR_P(o)) {
2599 return ASE_ITYPE_INTERIOR;
2601 return ASE_ITYPE_OBJECT;
2606 _ase_heapsort_sift(Lisp_Object *args, int start, int count,
2607 ase_order_relation_f lessp)
2609 int root = start, child;
2611 while (2*root + 1 < count) {
2614 if (child < count-1 && lessp(args[child], args[child+1]))
2616 if (lessp(args[root], args[child])) {
2617 _ase_swap(args, root, child);
2627 _ase_heapsort(int nargs, Lisp_Object *args, ase_order_relation_f lessp)
2629 int start = nargs/2 - 1, end = nargs-1;
2631 while (start >= 0) {
2632 _ase_heapsort_sift(args, start, nargs, lessp);
2636 _ase_swap(args, end, 0);
2637 _ase_heapsort_sift(args, 0, end, lessp);
2644 ase_interval_connected_p_heapify(int nargs, Lisp_Object *args)
2646 /* special case for flat intervals,
2647 * uses a heapsort to ease the connectivity question */
2648 Lisp_Object *newargs;
2651 /* check for ASE_INTERVALs and sort empty intervals to the tail */
2652 for (j = 0; j < nargs; ) {
2653 if (ASE_INTERVAL_UNION_P(args[j])) {
2654 /* remember the number of additional elements we need */
2655 add += XASE_INTERVAL_UNION(args[j])->no_intv-1;
2657 } else if (!ASE_INTERVAL_EMPTY_P(args[j])) {
2660 _ase_swap(args, nargs-1, j);
2667 else if (nargs == 1) /* reflexivity! */
2668 return (ASE_INTERVAL_UNION_P(args[0]) ? Qnil : Qt);
2671 EMOD_ASE_DEBUG_INTV("exploding %d union items\n", add);
2672 newargs = alloca_array(Lisp_Object, nargs+add);
2673 /* move the first nargs args here */
2674 memmove(newargs, args, nargs*sizeof(Lisp_Object));
2675 /* now explode the whole story */
2676 args = _ase_interval_union_explode_array(nargs, newargs, add);
2680 /* sort intervals in less-p metric */
2681 _ase_heapsort(nargs, args, ase_interval_less_p);
2683 for (j = 1; j < nargs; j++) {
2684 Lisp_Object o1 = args[j-1], o2 = args[j];
2685 if (!ase_interval_connected_p(o1, o2))
2693 ase_interval_connected_p_nsquare(int nargs, Lisp_Object *args)
2696 ase_interval_type_t t1, t2;
2697 ase_st_relation_f relf = NULL;
2701 else if (nargs == 1 && !ASE_INTERVAL_UNION_P(args[0]))
2703 else if (nargs == 1 &&
2704 ASE_INTERVAL_INTERIOR_P(XASE_INTERVAL_UNION_FIRST(args[0]))) {
2705 ase_interval_union_item_t u1, u2;
2706 u1 = XASE_INTERVAL_UNION_SER(args[0]);
2707 t1 = t2 = ASE_ITYPE_INTERIOR;
2708 relf = ase_optable_connected[t1][t2];
2709 while ((u2 = u1->next)) {
2710 Lisp_Object o1 = u1->current;
2711 Lisp_Object o2 = u2->current;
2717 } else if (nargs == 1)
2720 /* the slow approach */
2721 /* connectivity itself is an intransitive relation,
2722 * but if any two are (locally) connected then all items are
2723 * globally connected */
2724 for (i = 0; i < nargs-1; i++) {
2725 Lisp_Object o1 = args[i];
2727 t1 = ase_interval_type(o1);
2728 for (j = i+1; j < nargs && !foundp; j++) {
2729 Lisp_Object o2 = args[j];
2730 t2 = ase_interval_type(o2);
2731 relf = ase_optable_connected[t1][t2];
2732 if (relf && relf(o1, o2))
2743 ase_interval_disjoint_p_nsquare(int nargs, Lisp_Object *args)
2746 ase_interval_type_t t1, t2;
2747 ase_st_relation_f relf = NULL;
2751 else if (nargs == 1) /* irreflexivity! */
2754 /* don't think that sorting helps here, but i'll profile this one day */
2755 /* pairwise (local) disjunction implies global disjunction */
2756 for (i = 0; i < nargs-1; i++) {
2757 Lisp_Object o1 = args[i];
2758 t1 = ase_interval_type(o1);
2759 for (j = i+1; j < nargs; j++) {
2760 Lisp_Object o2 = args[j];
2761 t2 = ase_interval_type(o2);
2762 relf = ase_optable_disjoint[t1][t2];
2763 if (relf && !relf(o1, o2))
2772 ase_interval_dimension(Lisp_Object o)
2774 switch (ase_interval_type(o)) {
2775 case ASE_ITYPE_INTERVAL:
2777 case ASE_ITYPE_INTERIOR:
2778 return XASE_CARTESIAN_DIMENSION(o);
2779 case ASE_ITYPE_UNION:
2780 return ase_interval_dimension(XASE_INTERVAL_UNION_FIRST(o));
2782 case ASE_ITYPE_OBJECT:
2783 case NUMBER_OF_ASE_ITYPES:
2790 ase_interval_check_dimensions(int nargs, Lisp_Object *args)
2792 int i, predicdim = 0;
2797 /* partial loop unrolling */
2798 for (i = 0; i < nargs; i++) {
2799 CHECK_ASE_UBERINTERVAL(args[i]);
2800 if (!ASE_INTERVAL_EMPTY_P(args[i])) {
2801 predicdim = ase_interval_dimension(args[i]);
2805 for (i++; i < nargs; i++) {
2806 CHECK_ASE_UBERINTERVAL(args[i]);
2807 if (!ASE_INTERVAL_EMPTY_P(args[i]) &&
2808 predicdim != ase_interval_dimension(args[i]))
2818 _ase_interval_compute_lebesgue(ase_interval_t a)
2823 return ent_binop(ASE_BINARY_OP_DIFF, a->upper, a->lower);
2827 _ase_interval_update_lebesgue(ase_interval_t a)
2829 if (a && NILP(a->lebesgue_measure))
2830 a->lebesgue_measure = _ase_interval_compute_lebesgue(a);
2834 static inline Lisp_Object
2835 _ase_interval_lebesgue(ase_interval_t a)
2838 return a->lebesgue_measure;
2844 _ase_interval_compute_rational(ase_interval_t a)
2846 Lisp_Object args[2];
2852 if (a->lower == a->upper) {
2853 /* special case of 1 point intervals */
2854 if (INTEGERP(a->lower))
2860 if (_ase_equal_p((args[0] = Ftruncate(a->upper)), a->upper))
2861 args[0] = Fsub1(a->upper);
2862 args[1] = Ftruncate(a->lower);
2864 /* care for alternation of the signum */
2865 if (!NILP(Fnonnegativep(a->upper)) &&
2866 NILP(Fnonnegativep(a->lower)) &&
2867 !_ase_equal_p(args[1], a->lower))
2868 args[1] = Fsub1(args[1]);
2870 result = ent_binop_many(ASE_BINARY_OP_DIFF, countof(args), args);
2872 if (INTEGERP(a->upper) && !a->upper_open_p)
2873 result = Fadd1(result);
2874 if (INTEGERP(a->lower) && !a->lower_open_p)
2875 result = Fadd1(result);
2881 _ase_interval_update_rational(ase_interval_t a)
2883 if (a && NILP(a->rational_measure))
2884 a->rational_measure = _ase_interval_compute_rational(a);
2888 static inline Lisp_Object
2889 _ase_interval_rational(ase_interval_t a)
2892 return a->rational_measure;
2898 __ase_interval_interior_update_lebesgue(ase_cartesian_t c)
2900 int i = 0, dim = ase_cartesian_dimension(c);
2901 for (i = 0; i < dim; i++) {
2902 _ase_interval_update_lebesgue(
2903 XASE_INTERVAL(ase_cartesian_objects(c)[i]));
2909 __ase_interval_interior_lebesgue(ase_cartesian_t c)
2912 int i = 0, dim = __ase_interval_interior_update_lebesgue(c);
2917 args = alloca_array(Lisp_Object, dim);
2918 for (i = 0; i < dim; i++) {
2919 args[i] = _ase_interval_lebesgue(
2920 XASE_INTERVAL(ase_cartesian_objects(c)[i]));
2922 return ent_binop_many(ASE_BINARY_OP_PROD, dim, args);
2926 __ase_interval_interior_update_rational(ase_cartesian_t c)
2928 int i = 0, dim = ase_cartesian_dimension(c);
2929 for (i = 0; i < dim; i++) {
2930 _ase_interval_update_rational(
2931 XASE_INTERVAL(ase_cartesian_objects(c)[i]));
2937 __ase_interval_interior_rational(ase_cartesian_t c)
2940 int i = 0, dim = __ase_interval_interior_update_rational(c);
2945 args = alloca_array(Lisp_Object, dim);
2946 for (i = 0; i < dim; i++) {
2947 args[i] = _ase_interval_rational(
2948 XASE_INTERVAL(ase_cartesian_objects(c)[i]));
2950 return ent_binop_many(ASE_BINARY_OP_PROD, dim, args);
2954 _ase_interval_interior_update_lebesgue(ase_cartesian_t c)
2955 __attribute__((always_inline));
2957 _ase_interval_interior_update_lebesgue(ase_cartesian_t c)
2959 if (NILP(c->lebesgue_measure))
2960 c->lebesgue_measure =
2961 __ase_interval_interior_lebesgue(c);
2966 _ase_interval_interior_lebesgue(ase_cartesian_t c)
2968 return c->lebesgue_measure;
2972 _ase_interval_interior_update_rational(ase_cartesian_t c)
2974 if (NILP(c->rational_measure))
2975 c->rational_measure =
2976 __ase_interval_interior_rational(c);
2980 static inline Lisp_Object
2981 _ase_interval_interior_rational(ase_cartesian_t c)
2983 return c->rational_measure;
2987 __ase_interval_union_update_lebesgue(ase_interval_union_item_t u)
2988 __attribute__((always_inline));
2990 __ase_interval_union_update_lebesgue(ase_interval_union_item_t u)
2994 if (ASE_INTERVALP(u->current)) {
2995 _ase_interval_update_lebesgue(
2996 XASE_INTERVAL(u->current));
2997 } else if (ASE_INTERVAL_INTERIOR_P(u->current)) {
2998 _ase_interval_interior_update_lebesgue(
2999 XASE_CARTESIAN(u->current));
3008 __ase_interval_union_lebesgue(ase_interval_union_item_t u)
3011 int i = 0, nargs = __ase_interval_union_update_lebesgue(u);
3016 args = alloca_array(Lisp_Object, nargs);
3018 if (ASE_INTERVALP(u->current)) {
3019 args[i] = _ase_interval_lebesgue(
3020 XASE_INTERVAL(u->current));
3021 } else if (ASE_INTERVAL_INTERIOR_P(u->current)) {
3022 args[i] = _ase_interval_interior_lebesgue(
3023 XASE_CARTESIAN(u->current));
3028 return ent_binop_many(ASE_BINARY_OP_SUM, nargs, args);
3032 __ase_interval_union_update_rational(ase_interval_union_item_t u)
3036 if (ASE_INTERVALP(u->current)) {
3037 _ase_interval_update_rational(
3038 XASE_INTERVAL(u->current));
3039 } else if (ASE_INTERVAL_INTERIOR_P(u->current)) {
3040 _ase_interval_interior_update_rational(
3041 XASE_CARTESIAN(u->current));
3050 __ase_interval_union_rational(ase_interval_union_item_t u)
3052 int i = 0, nargs = __ase_interval_union_update_rational(u);
3056 Lisp_Object args[nargs];
3057 for ( i = nargs; i > 0; )
3061 if (ASE_INTERVALP(u->current)) {
3062 args[i] = _ase_interval_rational(
3063 XASE_INTERVAL(u->current));
3064 } else if (ASE_INTERVAL_INTERIOR_P(u->current)) {
3065 args[i] = _ase_interval_interior_rational(
3066 XASE_CARTESIAN(u->current));
3071 return ent_binop_many(ASE_BINARY_OP_SUM, nargs, args);
3076 _ase_interval_union_update_lebesgue(ase_interval_union_t iu)
3078 if (NILP(iu->lebesgue_measure))
3079 iu->lebesgue_measure =
3080 __ase_interval_union_lebesgue(ase_interval_union(iu));
3084 static inline Lisp_Object
3085 _ase_interval_union_lebesgue(ase_interval_union_t iu)
3087 return iu->lebesgue_measure;
3091 _ase_interval_union_update_rational(ase_interval_union_t iu)
3093 if (NILP(iu->rational_measure))
3094 iu->rational_measure =
3095 __ase_interval_union_rational(ase_interval_union(iu));
3099 static inline Lisp_Object
3100 _ase_interval_union_rational(ase_interval_union_t iu)
3102 return iu->rational_measure;
3106 ase_interval_lebesgue_measure(ase_interval_t a)
3108 _ase_interval_update_lebesgue(a);
3109 return _ase_interval_lebesgue(a);
3113 ase_interval_rational_measure(ase_interval_t a)
3115 _ase_interval_update_rational(a);
3116 return _ase_interval_rational(a);
3120 ase_interval_interior_lebesgue_measure(ase_cartesian_t c)
3122 _ase_interval_interior_update_lebesgue(c);
3123 return _ase_interval_interior_lebesgue(c);
3127 ase_interval_interior_rational_measure(ase_cartesian_t c)
3129 _ase_interval_interior_update_rational(c);
3130 return _ase_interval_interior_rational(c);
3134 ase_interval_union_lebesgue_measure(ase_interval_union_t iu)
3136 _ase_interval_union_update_lebesgue(iu);
3137 return _ase_interval_union_lebesgue(iu);
3141 ase_interval_union_rational_measure(ase_interval_union_t iu)
3143 _ase_interval_union_update_rational(iu);
3144 return _ase_interval_union_rational(iu);
3147 /* arithmetical operations */
3148 /* I x Q -> I : (a, b) + x -> (a+x, b+x) */
3149 /* I x I -> I : (a, b) + (c, d) -> (a+c, b+d) */
3150 /* U x Q -> U : (a, b) u (c, d) + x -> (a, b) + x u (c, d) + x */
3151 /* U x I -> U : (a, b) u (c, d) + (e, f) -> (a, b) + (e, f) u (c, d) + (e, f) */
3152 /* U x U -> U : A u B + C u D u E -> A+C u B+C u A+D u B+D u A+E u B+E */
3156 DEFUN("ase-intervalp", Fase_intervalp, 1, 1, 0, /*
3157 Return non-`nil' iff OBJECT is an ase interval.
3161 if (ASE_INTERVALP(object))
3167 DEFUN("ase-interval-union-p", Fase_interval_union_p, 1, 1, 0, /*
3168 Return non-`nil' iff OBJECT is an ase interval or union thereof.
3172 if (ASE_INTERVAL_OR_UNION_P(object))
3178 DEFUN("ase-interval-empty-p", Fase_interval_empty_p, 1, 1, 0, /*
3179 Return non-`nil' iff INTERVAL is the empty interval.
3183 CHECK_ASE_INTERVAL(interval);
3185 if (ASE_INTERVAL_EMPTY_P(interval))
3191 DEFUN("ase-interval-imprimitive-p", Fase_interval_imprimitive_p, 1, 1, 0, /*
3192 Return non-`nil' iff INTERVAL is not a primitive interval.
3196 CHECK_ASE_UBERINTERVAL(interval);
3198 if (ASE_INTERVALP(interval))
3204 DEFUN("ase-interval-open-p", Fase_interval_open_p, 1, 1, 0, /*
3205 Return non-`nil' iff INTERVAL (or a union thereof) is an open set
3206 with respect to the standard topology.
3210 CHECK_ASE_UBERINTERVAL(interval);
3212 if (ASE_INTERVALP(interval)) {
3213 if (ASE_INTERVAL_EMPTY_P(interval))
3215 if (ase_interval_open_p(interval))
3217 } else if (ASE_INTERVAL_UNION_P(interval)) {
3218 if (ase_interval_union_open_p(interval))
3220 } else if (ASE_INTERVAL_INTERIOR_P(interval)) {
3221 if (ase_interval_interior_open_p(interval))
3227 DEFUN("ase-interval-closed-p", Fase_interval_closed_p, 1, 1, 0, /*
3228 Return non-`nil' iff INTERVAL (or a union thereof) is a closed set
3229 with respect to the standard metric.
3231 An interval is said to be closed iff the complement is open.
3235 CHECK_ASE_UBERINTERVAL(interval);
3237 if (ASE_INTERVALP(interval)) {
3238 if (ASE_INTERVAL_EMPTY_P(interval))
3240 if (ase_interval_closed_p(interval))
3242 } else if (ASE_INTERVAL_UNION_P(interval)) {
3243 if (ase_interval_union_closed_p(interval))
3245 } else if (ASE_INTERVAL_INTERIOR_P(interval)) {
3246 if (ase_interval_interior_closed_p(interval))
3255 DEFUN("ase-empty-interval", Fase_empty_interval, 0, 0, 0, /*
3256 Return the empty interval.
3260 return Qase_empty_interval;
3264 DEFUN("ase-universe-interval", Fase_universe_interval, 0, 0, 0, /*
3265 Return the universe interval.
3269 return Qase_universe_interval;
3273 DEFUN("ase-interval", Fase_interval, 1, 4, 0, /*
3274 Return a (primitive) interval with lower bound LOWER and upper bound UPPER.
3275 To construct a (degenerated) one point interval, leave out the UPPER part.
3277 ASE's definition of an interval:
3278 With respect to a (strict) partial order, an interval is a connected
3281 If no special partial order is given, it defaults to less-equal-p (<=).
3282 If no special topology is given, it defaults to the po topology.
3284 (lower, upper, lower_open_p, upper_open_p))
3286 Lisp_Object result = Qnil;
3287 Lisp_Object args[2] = {lower, upper};
3289 CHECK_COMPARABLE(lower);
3291 args[1] = upper = lower;
3293 CHECK_COMPARABLE(upper);
3295 if (_ase_less_p(lower, upper))
3296 result = ase_make_interval(
3297 lower, upper, !NILP(lower_open_p), !NILP(upper_open_p));
3299 result = ase_make_interval(
3300 upper, lower, !NILP(upper_open_p), !NILP(lower_open_p));
3305 DEFUN("ase-interval-contains-p", Fase_interval_contains_p, 2, 2, 0, /*
3306 Return non-`nil' iff INTERVAL (or a union thereof) contains OBJECT
3307 as one of its elements. OBJECT can also be another interval or
3308 interval union to obtain the subset relation.
3312 ase_interval_type_t sup, sub;
3313 ase_element_relation_f relf = NULL;
3315 CHECK_ASE_UBERINTERVAL(interval);
3317 sup = ase_interval_type(interval);
3318 sub = ase_interval_type(object);
3320 if ((relf = ase_optable_superset[sup][sub]) &&
3321 (!NILP(relf(interval, object))))
3327 DEFUN("ase-interval-contains-where", Fase_interval_contains_where, 2, 2, 0, /*
3328 Return non-`nil' iff INTERVAL contains OBJECT as one of its elements.
3329 ELEMENT can also be another interval to obtain the subset relation.
3331 The non-`nil' value returned is the primitive interval which
3336 ase_interval_type_t sup, sub;
3337 ase_element_relation_f relf = NULL;
3339 CHECK_ASE_UBERINTERVAL(interval);
3341 sup = ase_interval_type(interval);
3342 sub = ase_interval_type(object);
3344 if ((relf = ase_optable_superset[sup][sub]))
3345 return relf(interval, object);
3350 DEFUN("ase-interval-connected-p", Fase_interval_connected_p, 0, MANY, 0, /*
3351 Return non-`nil' iff INTERVALS are connected.
3352 Arguments: &rest intervals
3354 Zero intervals are trivially connected, as is one interval.
3356 (int nargs, Lisp_Object *args))
3362 switch (ase_interval_check_dimensions(nargs, args)) {
3366 return ase_interval_connected_p_heapify(nargs, args);
3368 signal_error(Qembed_error, Qnil);
3371 return ase_interval_connected_p_nsquare(nargs, args);
3375 DEFUN("ase-interval-disjoint-p", Fase_interval_disjoint_p, 0, MANY, 0, /*
3376 Arguments: &rest intervals
3377 Return non-`nil' iff INTERVALS are (pairwise) disjoint.
3379 Zero intervals are trivially disjoint, while one interval is
3380 trivially not disjoint.
3382 (int nargs, Lisp_Object *args))
3388 switch (ase_interval_check_dimensions(nargs, args)) {
3392 signal_error(Qembed_error, Qnil);
3395 return ase_interval_disjoint_p_nsquare(nargs, args);
3399 DEFUN("ase-interval-equal-p", Fase_interval_equal_p, 2, 2, 0, /*
3400 Return non-`nil' if I1 and I2 are equal in some sense, equality
3401 hereby means that I1 and I2 contain each other.
3403 In fact, this is just a convenience function and totally equivalent
3405 (and (ase-interval-contains-p i1 i2) (ase-interval-contains-p i2 i1))
3409 Lisp_Object i1in2, i2in1;
3411 CHECK_ASE_UBERINTERVAL(i1);
3412 CHECK_ASE_UBERINTERVAL(i2);
3414 i1in2 = Fase_interval_contains_p(i1, i2);
3415 i2in1 = Fase_interval_contains_p(i2, i1);
3417 if (!NILP(i1in2) && !NILP(i2in1))
3423 /* more constructors */
3425 ase_interval_union_heapify(int nargs, Lisp_Object *args)
3427 Lisp_Object result = Qnil, *newargs;
3429 struct ase_interval_union_item_s _ures, *ures = &_ures, *u;
3430 ase_interval_union_t ires;
3432 /* check for ASE_INTERVALs and sort empty intervals to the tail */
3433 for (j = 0; j < nargs; ) {
3434 if (ASE_INTERVAL_UNION_P(args[j])) {
3435 /* remember the number of additional elements we need */
3436 add += XASE_INTERVAL_UNION(args[j])->no_intv-1;
3438 } else if (!ASE_INTERVAL_EMPTY_P(args[j])) {
3441 _ase_swap(args, nargs-1, j);
3447 return Qase_empty_interval;
3452 EMOD_ASE_DEBUG_INTV("exploding %d union items\n", add);
3453 newargs = alloca_array(Lisp_Object, nargs+add);
3454 /* move the first nargs args here */
3455 memmove(newargs, args, nargs*sizeof(Lisp_Object));
3456 /* now explode the whole story */
3457 args = _ase_interval_union_explode_array(nargs, newargs, add);
3461 /* sort intervals in less-p metric */
3462 _ase_heapsort(nargs, args, ase_interval_less_p);
3464 /* we start with the empty union and unite left-associatively from
3466 ures->current = Qase_empty_interval;
3467 u = ures->next = _ase_make_interval_union_item(args[0]);
3468 for (j = 1; j < nargs; j++) {
3469 u = u->next = _ase_make_interval_union_item(args[j]);
3472 j = _ase_normalise_union(ures);
3474 /* only return a union when there _is_ a union */
3475 ires = _ase_make_interval_union(ures->next);
3478 XSETASE_INTERVAL_UNION(result, ires);
3481 /* otherwise downgrade to a primitive interval */
3482 result = ures->next->current;
3483 _ase_interval_union_item_fini(ures->next);
3488 static inline Lisp_Object
3489 ase_interval_union_nsquare(int nargs, Lisp_Object *args)
3492 struct ase_interval_union_item_s _ures, *ures = &_ures, *u;
3493 ase_interval_union_t ires;
3494 Lisp_Object result = Qnil;
3497 return Qase_empty_interval;
3498 else if (nargs == 1)
3501 /* the slow approach */
3502 /* we start with the empty union and unite left-associatively from
3504 ures->current = Qase_empty_interval;
3506 for (i = 0; i < nargs; i++) {
3507 Lisp_Object tmp = args[i];
3508 if (ASE_INTERVAL_INTERIOR_P(tmp))
3509 u = u->next = _ase_make_interval_union_item(tmp);
3510 else if (ASE_INTERVAL_UNION_P(tmp)) {
3511 ase_interval_union_item_t tra =
3512 XASE_INTERVAL_UNION_SER(tmp);
3514 Lisp_Object c = tra->current;
3515 u = u->next = _ase_make_interval_union_item(c);
3521 j = _ase_normalise_union_intr(ures);
3523 /* only return a union when there _is_ a union */
3524 ires = _ase_make_interval_union(ures->next);
3527 XSETASE_INTERVAL_UNION(result, ires);
3530 /* otherwise downgrade to a primitive interval */
3531 result = ures->next->current;
3532 _ase_interval_union_item_fini(ures->next);
3537 DEFUN("ase-interval-union", Fase_interval_union, 0, MANY, 0, /*
3538 Arguments: &rest intervals
3539 Return the union of all INTERVALS.
3541 (int nargs, Lisp_Object *args))
3547 return Qase_empty_interval;
3549 dim = ase_interval_check_dimensions(nargs, args);
3552 return Qase_empty_interval;
3554 return ase_interval_union_heapify(nargs, args);
3556 signal_error(Qembed_error, Qnil);
3559 return ase_interval_union_nsquare(nargs, args);
3564 ase_interval_intersection_maybe_empty(int nargs, Lisp_Object *args)
3566 /* check for empty intervals, return 1 if there are some */
3569 for (j = 0; j < nargs; j++) {
3570 if (ASE_INTERVAL_EMPTY_P(args[j])) {
3578 ase_interval_intersection_heapify(int nargs, Lisp_Object *args)
3583 return Qase_empty_interval;
3584 else if (nargs == 1)
3586 else if (ase_interval_intersection_maybe_empty(nargs, args))
3587 return Qase_empty_interval;
3589 _ase_heapsort(nargs, args, ase_interval_or_union_less_p);
3591 /* we start with the universe and intersect left-associatively from
3593 for (j = 1; j < nargs; j++) {
3594 ase_interval_type_t t1 = ase_interval_type(args[0]);
3595 ase_interval_type_t t2 = ase_interval_type(args[j]);
3596 ase_binary_operation_f opf = ase_optable_intersect[t1][t2];
3599 args[0] = opf(args[0], args[j]);
3607 ase_interval_intersection_nsquare(int nargs, Lisp_Object *args)
3612 return Qase_empty_interval;
3613 else if (nargs == 1)
3615 else if (ase_interval_intersection_maybe_empty(nargs, args))
3616 return Qase_empty_interval;
3618 /* we start with the universe and intersect left-associatively from
3620 for (j = 1; j < nargs; j++) {
3621 ase_interval_type_t t1 = ase_interval_type(args[0]);
3622 ase_interval_type_t t2 = ase_interval_type(args[j]);
3623 ase_binary_operation_f opf = ase_optable_intersect[t1][t2];
3626 args[0] = opf(args[0], args[j]);
3633 DEFUN("ase-interval-intersection", Fase_interval_intersection, 0, MANY, 0, /*
3634 Arguments: &rest intervals
3635 Return the intersection of all INTERVALS.
3637 (int nargs, Lisp_Object *args))
3641 return Qase_empty_interval;
3642 else if (nargs == 1)
3645 switch (ase_interval_check_dimensions(nargs, args)) {
3647 return Qase_empty_interval;
3649 return ase_interval_intersection_heapify(nargs, args);
3651 signal_error(Qembed_error, Qnil);
3654 return ase_interval_intersection_nsquare(nargs, args);
3658 static inline Lisp_Object
3659 ase_interval_difference_nsquare(int nargs, Lisp_Object *args)
3663 /* check for ASE_INTERVALs and sort empty intervals to the tail */
3664 for (j = 1; j < nargs; j++) {
3665 /* we can only resort empty intervals for j >= 1 */
3666 if (ASE_INTERVAL_EMPTY_P(args[j])) {
3667 _ase_swap(args, nargs-1, j);
3673 return Qase_empty_interval;
3677 /* we must not use heapsort here, since subtracting sets is
3678 * not commutative */
3680 /* we start with args[0] and subtract left-associatively from
3682 for (j = 1; j < nargs; j++) {
3683 ase_interval_type_t t1 = ase_interval_type(args[0]);
3684 ase_interval_type_t t2 = ase_interval_type(args[j]);
3685 ase_binary_operation_f opf = ase_optable_subtract[t1][t2];
3688 args[0] = opf(args[0], args[j]);
3695 DEFUN("ase-interval-difference", Fase_interval_difference, 0, MANY, 0, /*
3696 Arguments: &rest intervals
3697 Return the difference of all INTERVALS from left to right.
3699 (int nargs, Lisp_Object *args))
3701 /* Treat the case args[0] = ( ) specially */
3703 return Qase_empty_interval;
3704 else if (nargs == 1)
3707 switch (ase_interval_check_dimensions(nargs, args)) {
3709 return Qase_empty_interval;
3711 signal_error(Qembed_error, Qnil);
3714 return ase_interval_difference_nsquare(nargs, args);
3718 DEFUN("ase-copy-interval", Fase_copy_interval, 1, 1, 0, /*
3719 Return a copy of INTERVAL.
3723 CHECK_ASE_INTERVAL(interval);
3725 return ase_copy_interval(interval);
3728 DEFUN("ase-interval-boundary", Fase_interval_boundary, 1, 1, 0, /*
3729 Return the boundary of INTERVAL, that is the interior of INTERVAL
3730 subtracted from the closure of INTERVAL.
3734 CHECK_ASE_UBERINTERVAL(interval);
3736 if (ASE_INTERVAL_EMPTY_P(interval))
3737 return Qase_empty_interval;
3738 else if (ASE_INTERVALP(interval))
3739 return ase_interval_boundary(interval);
3740 else if (ASE_INTERVAL_INTERIOR_P(interval))
3741 return ase_interval_interior_boundary(interval);
3742 else if (ASE_INTERVAL_UNION_P(interval))
3743 return ase_interval_union_boundary(interval);
3748 DEFUN("ase-interval-closure", Fase_interval_closure, 1, 1, 0, /*
3749 Return the closure of INTERVAL, that is the smallest closed set
3750 that contains INTERVAL.
3754 CHECK_ASE_UBERINTERVAL(interval);
3756 if (ASE_INTERVAL_EMPTY_P(interval))
3757 return Qase_empty_interval;
3758 else if (ASE_INTERVALP(interval))
3759 return ase_interval_closure(interval);
3760 else if (ASE_INTERVAL_INTERIOR_P(interval))
3761 return ase_interval_interior_closure(interval);
3762 else if (ASE_INTERVAL_UNION_P(interval))
3763 return ase_interval_union_closure(interval);
3768 DEFUN("ase-interval-interior", Fase_interval_interior, 1, 1, 0, /*
3769 Return the interior of INTERVAL, that is the largest open set that
3770 is contained in INTERVAL.
3774 CHECK_ASE_UBERINTERVAL(interval);
3776 if (ASE_INTERVAL_EMPTY_P(interval))
3777 return Qase_empty_interval;
3778 else if (ASE_INTERVALP(interval))
3779 return ase_interval_interior(interval);
3780 else if (ASE_INTERVAL_INTERIOR_P(interval))
3781 return ase_interval_interior_interior(interval);
3782 else if (ASE_INTERVAL_UNION_P(interval))
3783 return ase_interval_union_interior(interval);
3789 DEFUN("ase-interval-lower", Fase_interval_lower, 1, 1, 0, /*
3790 Return the lower bound of INTERVAL or `nil' if empty.
3791 Only the numerical value is returned.
3795 CHECK_ASE_INTERVAL(interval);
3797 if (ASE_INTERVAL_EMPTY_P(interval))
3800 return XASE_INTERVAL(interval)->lower;
3803 DEFUN("ase-interval-upper", Fase_interval_upper, 1, 1, 0, /*
3804 Return the upper bound of INTERVAL or `nil' if empty.
3805 Only the numerical value is returned.
3809 CHECK_ASE_INTERVAL(interval);
3811 if (ASE_INTERVAL_EMPTY_P(interval))
3814 return XASE_INTERVAL(interval)->upper;
3817 DEFUN("ase-interval-lower*", Fase_interval_lower_, 1, 1, 0, /*
3818 Return the lower bound of INTERVAL or `nil' if empty
3819 along with the boundary shape.
3825 CHECK_ASE_INTERVAL(interval);
3826 if (ASE_INTERVAL_EMPTY_P(interval))
3829 res = XASE_INTERVAL(interval)->lower;
3830 if (XASE_INTERVAL(interval)->lower_open_p)
3831 return Fcons(Q_open, res);
3833 return Fcons(Q_closed, res);
3836 DEFUN("ase-interval-upper*", Fase_interval_upper_, 1, 1, 0, /*
3837 Return the upper bound of INTERVAL or `nil' if empty
3838 along with the boundary shape.
3844 CHECK_ASE_INTERVAL(interval);
3845 if (ASE_INTERVAL_EMPTY_P(interval))
3848 res = XASE_INTERVAL(interval)->upper;
3849 if (XASE_INTERVAL(interval)->upper_open_p)
3850 return Fcons(Q_open, res);
3852 return Fcons(Q_closed, res);
3855 DEFUN("ase-interval-explode-union", Fase_interval_explode_union, 1, 1, 0, /*
3856 Return IUNION exploded into primitive intervals and listed in a dllist.
3860 Lisp_Object result = Qnil;
3861 dllist_t resdll = make_dllist();
3862 ase_interval_union_item_t u;
3864 CHECK_ASE_INTERVAL_UNION(iunion);
3865 u = XASE_INTERVAL_UNION_SER(iunion);
3867 dllist_append(resdll, (void*)u->current);
3871 XSETDLLIST(result, resdll);
3877 DEFUN("ase-interval-lebesgue-measure",
3878 Fase_interval_lebesgue_measure, 1, 1, 0, /*
3879 Return the Lebesgue measure of INTERVAL.
3883 CHECK_ASE_UBERINTERVAL(interval);
3885 if (ASE_INTERVALP(interval))
3886 return ase_interval_lebesgue_measure(XASE_INTERVAL(interval));
3887 else if (ASE_INTERVAL_INTERIOR_P(interval))
3888 return ase_interval_interior_lebesgue_measure(
3889 XASE_CARTESIAN(interval));
3890 else if (ASE_INTERVAL_UNION_P(interval))
3891 return ase_interval_union_lebesgue_measure(
3892 XASE_INTERVAL_UNION(interval));
3896 DEFUN("ase-interval-rational-measure",
3897 Fase_interval_rational_measure, 1, 1, 0, /*
3898 Return the number of rational integers in INTERVAL.
3902 CHECK_ASE_UBERINTERVAL(interval);
3904 if (ASE_INTERVALP(interval))
3905 return ase_interval_rational_measure(XASE_INTERVAL(interval));
3906 else if (ASE_INTERVAL_INTERIOR_P(interval))
3907 return ase_interval_interior_rational_measure(
3908 XASE_CARTESIAN(interval));
3909 else if (ASE_INTERVAL_UNION_P(interval))
3910 return ase_interval_union_rational_measure(
3911 XASE_INTERVAL_UNION(interval));
3915 DEFUN("ase-interval-dump", Fase_interval_dump, 1, 1, 0, /*
3919 CHECK_ASE_INTERVAL_OR_UNION(interval);
3921 if (ASE_INTERVALP(interval)) {
3922 ase_interval_prnt(interval, Qexternal_debugging_output, 0);
3923 write_c_string("\n", Qexternal_debugging_output);
3926 ase_interval_union_prnt(
3927 interval, Qexternal_debugging_output, 0);
3928 write_c_string("\n", Qexternal_debugging_output);
3934 static inline Lisp_Object
3935 ase_interval_add_i_obj(Lisp_Object intv, Lisp_Object number)
3937 int lopenp = XASE_INTERVAL(intv)->lower_open_p;
3938 int uopenp = XASE_INTERVAL(intv)->upper_open_p;
3939 int lequp = XASE_INTERVAL(intv)->lower_eq_upper_p;
3940 Lisp_Object args[2] = {Qnil, number};
3941 Lisp_Object newl, newu;
3943 args[0] = XASE_INTERVAL(intv)->lower;
3944 newl = ent_binop(ASE_BINARY_OP_SUM, args[0], args[1]);
3946 args[0] = XASE_INTERVAL(intv)->upper;
3947 newu = ent_binop(ASE_BINARY_OP_SUM, args[0], args[1]);
3948 return ase_make_interval(newl, newu, lopenp, uopenp);
3950 return ase_make_interval(newl, newl, lopenp, uopenp);
3954 static inline Lisp_Object
3955 ase_interval_add_obj_i(Lisp_Object number, Lisp_Object intv)
3957 return ase_interval_add_i_obj(intv, number);
3961 /* initialiser stuff */
3963 ase_interval_binary_optable_init(void)
3965 int idx = ase_optable_index_typesym(Qase_interval);
3966 ent_binop_register(ASE_BINARY_OP_SUM,
3967 idx, INT_T, ase_interval_add_i_obj);
3968 ent_binop_register(ASE_BINARY_OP_SUM,
3969 INT_T, idx, ase_interval_add_obj_i);
3970 ent_binop_register(ASE_BINARY_OP_SUM,
3971 idx, FLOAT_T, ase_interval_add_obj_i);
3972 ent_binop_register(ASE_BINARY_OP_SUM,
3973 FLOAT_T, idx, ase_interval_add_obj_i);
3980 DEFSUBR(Fase_empty_interval);
3981 DEFSUBR(Fase_universe_interval);
3982 DEFSUBR(Fase_interval);
3983 DEFSUBR(Fase_interval_union);
3984 DEFSUBR(Fase_interval_intersection);
3985 DEFSUBR(Fase_interval_difference);
3986 DEFSUBR(Fase_copy_interval);
3987 DEFSUBR(Fase_interval_boundary);
3988 DEFSUBR(Fase_interval_interior);
3989 DEFSUBR(Fase_interval_closure);
3991 DEFSUBR(Fase_intervalp);
3992 DEFSUBR(Fase_interval_union_p);
3993 DEFSUBR(Fase_interval_empty_p);
3994 DEFSUBR(Fase_interval_imprimitive_p);
3995 DEFSUBR(Fase_interval_open_p);
3996 DEFSUBR(Fase_interval_closed_p);
3997 DEFSUBR(Fase_interval_contains_p);
3998 DEFSUBR(Fase_interval_contains_where);
3999 DEFSUBR(Fase_interval_connected_p);
4000 DEFSUBR(Fase_interval_disjoint_p);
4001 DEFSUBR(Fase_interval_equal_p);
4003 DEFSUBR(Fase_interval_lower);
4004 DEFSUBR(Fase_interval_lower_);
4005 DEFSUBR(Fase_interval_upper);
4006 DEFSUBR(Fase_interval_upper_);
4007 DEFSUBR(Fase_interval_explode_union);
4009 DEFSUBR(Fase_interval_lebesgue_measure);
4010 DEFSUBR(Fase_interval_rational_measure);
4012 DEFASETYPE_WITH_OPS(Qase_interval, "ase:interval");
4013 defsymbol(&Qase_intervalp, "ase:intervalp");
4014 DEFASETYPE_WITH_OPS(Qase_interval_union, "ase:interval-union");
4015 defsymbol(&Qase_interval_union_p, "ase:interval-union-p");
4017 defsymbol(&Q_less, ":<");
4018 defsymbol(&Q_greater, ":>");
4019 defsymbol(&Q_eql, ":=");
4020 DEFKEYWORD(Q_unknown);
4022 DEFKEYWORD(Q_closed);
4023 DEFKEYWORD(Q_disjoint);
4024 DEFKEYWORD(Q_connected);
4027 DEFSUBR(Fase_interval_dump);
4029 ase_interval_binary_optable_init();
4033 DEFVAR_CONST_LISP("ase-empty-interval", &Qase_empty_interval /*
4034 The interval which contains no elements.
4036 DEFVAR_CONST_LISP("ase-universe-interval", &Qase_universe_interval /*
4037 The interval which contains all elements.
4040 Fprovide(intern("ase-interval"));
4045 EMOD_PUBREINIT(void)
4047 Qase_empty_interval = ase_empty_interval();
4048 Qase_universe_interval = ase_universe_interval();
4049 staticpro(&Qase_empty_interval);
4050 staticpro(&Qase_universe_interval);
4052 if (LIKELY(ase_empty_sets != NULL)) {
4053 dllist_append(ase_empty_sets, (void*)Qase_empty_interval);
4055 EMOD_ASE_CRITICAL("Cannot proclaim empty elements\n");
4061 EMOD_PUBDEINIT(void)
4063 Frevoke(intern("ase-interval"));
4067 /* ase-interval ends here */