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 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;
1379 int i, dim = ase_cartesian_dimension(c1);
1386 if (!NILP(_ase_interval_interior_contains_intr_p(c1, c2))) {
1387 /* cartesians lack ref counters atm, hence we cant do: */
1389 } else if (!NILP(_ase_interval_interior_contains_intr_p(c2, c1))) {
1390 /* cartesians lack ref counters atm, hence we cant do: */
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(
1863 } else if (_ase_interval_interior_connected_p(c1, c2)) {
1864 /* kinda hard case, we decompose c1 into 2n-1
1865 * n-dimensional interval products */
1866 EMOD_ASE_CRITICAL("Desaster!\n");
1868 EMOD_ASE_CRITICAL("Desaster!\n");
1875 ase_subtract_intr_intr(Lisp_Object c1, Lisp_Object c2)
1877 ase_interval_union_item_t u =
1878 _ase_subtract_intr_intr(XASE_CARTESIAN(c1), XASE_CARTESIAN(c2));
1881 return _ase_wrap_interval_union(
1882 _ase_make_interval_union(u));
1884 Lisp_Object na = u->current;
1885 _ase_interval_union_item_fini(u);
1888 return Qase_empty_interval;
1891 static ase_interval_union_item_t
1892 _ase_subtract_union_intv(ase_interval_union_item_t u, ase_interval_t a)
1894 /* (A u B) \ C = (A \ C u B \ C) */
1895 struct ase_interval_union_item_s ures, *ur = &ures;
1897 ur->current = Qase_empty_interval;
1900 ase_interval_t a1 = XASE_INTERVAL(u->current);
1901 ase_interval_union_item_t na;
1903 na = _ase_subtract_intv_intv(a1, a);
1907 /* forewind to the end of ur */
1918 ase_subtract_union_intv(Lisp_Object iu, Lisp_Object a)
1920 /* (A u B) \ C = (A \ C u B \ C) */
1921 ase_interval_union_item_t nu =
1922 _ase_subtract_union_intv(
1923 XASE_INTERVAL_UNION_SER(iu),
1927 return _ase_wrap_interval_union(
1928 _ase_make_interval_union(nu));
1930 Lisp_Object na = nu->current;
1931 _ase_interval_union_item_fini(nu);
1934 return Qase_empty_interval;
1937 static ase_interval_union_item_t
1938 _ase_subtract_union_intr(ase_interval_union_item_t u, ase_cartesian_t c)
1940 /* (A u B) \ C = (A \ C u B \ C) */
1941 struct ase_interval_union_item_s ures, *ur = &ures;
1943 ur->current = Qase_empty_interval;
1946 ase_cartesian_t c1 = XASE_CARTESIAN(u->current);
1947 ase_interval_union_item_t na;
1949 na = _ase_subtract_intr_intr(c1, c);
1953 /* forewind to the end of ur */
1964 ase_subtract_union_intr(Lisp_Object iu, Lisp_Object c)
1966 /* (A u B) \ C = (A \ C u B \ C) */
1967 ase_interval_union_item_t nu =
1968 _ase_subtract_union_intr(
1969 XASE_INTERVAL_UNION_SER(iu),
1973 return _ase_wrap_interval_union(
1974 _ase_make_interval_union(nu));
1976 Lisp_Object na = nu->current;
1977 _ase_interval_union_item_fini(nu);
1980 return Qase_empty_interval;
1983 static ase_interval_union_item_t
1984 _ase_subtract_intv_union(ase_interval_t a, ase_interval_union_item_t u)
1986 /* A \ (B u C) = (A \ B) \ C */
1987 struct ase_interval_union_item_s ures, *na = &ures;
1989 na->current = _ase_wrap_interval(a);
1992 ase_interval_t a2 = XASE_INTERVAL(u->current);
1994 na = _ase_subtract_union_intv(na, a2);
2001 /* Copy the local temporary to the heap */
2002 na = xnew(struct ase_interval_union_item_s);
2004 memcpy(na,&ures,sizeof(ures));
2010 ase_subtract_intv_union(Lisp_Object a, Lisp_Object iu)
2012 /* A \ (B u C) = (A \ B) \ C */
2013 ase_interval_union_item_t nu =
2014 _ase_subtract_intv_union(
2016 XASE_INTERVAL_UNION_SER(iu));
2019 return _ase_wrap_interval_union(
2020 _ase_make_interval_union(nu));
2022 Lisp_Object na = nu->current;
2023 _ase_interval_union_item_fini(nu);
2026 return Qase_empty_interval;
2029 static ase_interval_union_item_t
2030 _ase_subtract_intr_union(ase_cartesian_t c, ase_interval_union_item_t u)
2032 /* A \ (B u C) = (A \ B) \ C */
2033 struct ase_interval_union_item_s ures, *na = &ures;
2035 na->current = _ase_wrap_cartesian_interior(c);
2038 ase_cartesian_t c2 = XASE_CARTESIAN(u->current);
2040 na = _ase_subtract_union_intr(na, c2);
2048 /* Copy the local temporary to the heap */
2049 na = xnew(struct ase_interval_union_item_s);
2051 memcpy(na,&ures,sizeof(ures));
2057 ase_subtract_intr_union(Lisp_Object c, Lisp_Object iu)
2059 /* A \ (B u C) = (A \ B) \ C */
2060 ase_interval_union_item_t nu =
2061 _ase_subtract_intr_union(
2063 XASE_INTERVAL_UNION_SER(iu));
2066 return _ase_wrap_interval_union(
2067 _ase_make_interval_union(nu));
2069 Lisp_Object na = nu->current;
2070 _ase_interval_union_item_fini(nu);
2073 return Qase_empty_interval;
2076 static ase_interval_union_item_t
2077 _ase_subtract_union_union(ase_interval_union_t iu1, ase_interval_union_t iu2)
2079 /* (A u B) \ (C u D) = ((A u B) \ C) \ D */
2080 ase_interval_union_item_t na = ase_interval_union(iu1);
2081 ase_interval_union_item_t u = ase_interval_union(iu2);
2084 if (ASE_INTERVALP(u->current)) {
2085 ase_interval_t a = XASE_INTERVAL(u->current);
2086 na = _ase_subtract_union_intv(na, a);
2087 } else if (ASE_INTERVAL_INTERIOR_P(u->current)) {
2088 ase_cartesian_t c = XASE_CARTESIAN(u->current);
2089 na = _ase_subtract_union_intr(na, c);
2101 ase_subtract_union_union(Lisp_Object iu1, Lisp_Object iu2)
2103 /* (A u B) \ (C u D) = ((A u B) \ C) \ D */
2104 ase_interval_union_item_t nu =
2105 _ase_subtract_union_union(
2106 XASE_INTERVAL_UNION(iu1), XASE_INTERVAL_UNION(iu2));
2109 return _ase_wrap_interval_union(
2110 _ase_make_interval_union(nu));
2112 Lisp_Object na = nu->current;
2113 _ase_interval_union_item_fini(nu);
2116 return Qase_empty_interval;
2121 _ase_copy_interval(ase_interval_t a)
2123 Lisp_Object result = Qnil;
2125 XSETASE_INTERVAL(result, a);
2129 Lisp_Object ase_copy_interval(Lisp_Object intv)
2131 return _ase_copy_interval(XASE_INTERVAL(intv));
2135 _ase_interval_union_explode_array(int nargs, Lisp_Object *args, int add)
2137 ase_interval_union_item_t u;
2138 Lisp_Object *newargs = args;
2141 for (j = 0; j < nargs+add; ) {
2142 if (ASE_INTERVAL_UNION_P(args[j])) {
2143 u = ase_interval_union(XASE_INTERVAL_UNION(args[j]));
2144 newargs[j] = u->current;
2147 newargs[nargs+mov] = u->current;
2158 _ase_normalise_union(ase_interval_union_item_t u)
2160 /* assumes first item of u is sorta head, we cant change that */
2161 ase_interval_union_item_t u1 = u->next, u2 = NULL, pu = u;
2162 Lisp_Object a1, a2, atmp;
2165 while ((u2 = u1->next)) {
2169 /* connectivity can solely occur at upper-lower */
2170 atmp = ase_unite_intervals(a1, a2);
2172 ase_interval_union_item_t tmp;
2174 tmp = _ase_make_interval_union_item(atmp);
2175 tmp->next = u2->next;
2177 _ase_interval_union_item_fini(u1);
2178 _ase_interval_union_item_fini(u2);
2180 pu->next = u1 = tmp;
2191 _ase_normalise_union_intr(ase_interval_union_item_t u)
2193 /* assumes first item of u is sorta head, we cant change that */
2194 ase_interval_union_item_t u1 = u->next, u2 = NULL, pu1 = u, pu2;
2195 Lisp_Object a1, a2, atmp;
2205 /* connectivity can occur everywhere! */
2206 atmp = ase_unite_intervals(a1, a2);
2208 ase_interval_union_item_t tmp, u2n;
2210 tmp = _ase_make_interval_union_item(atmp);
2211 if (u1->next == u2) {
2212 tmp->next = u2->next;
2214 tmp->next = u1->next;
2220 _ase_interval_union_item_fini(u1);
2221 _ase_interval_union_item_fini(u2);
2223 /* we start over from the very beginning
2224 * there might be new merge opportunities now
2225 * if speed is important, we should allow
2226 * a merge depth of 1, settint u1 to tmp
2227 * would be the equivalent action for this */
2242 static ase_interval_union_item_t
2243 _ase_interval_boundary(ase_interval_t a)
2245 Lisp_Object blo = Qnil, bup = Qnil;
2246 ase_interval_union_item_t ures = NULL;
2248 if (a == NULL || a->lower_eq_upper_p)
2251 blo = _ase_wrap_interval(
2252 _ase_make_interval(a->lower, a->lower, 0, 0));
2253 if (!_ase_equal_p(a->lower, a->upper)) {
2254 bup = _ase_wrap_interval(
2255 _ase_make_interval(a->upper, a->upper, 0, 0));
2258 ures = _ase_make_interval_union_item(blo);
2260 ures->next = _ase_make_interval_union_item(bup);
2265 Lisp_Object ase_interval_boundary(Lisp_Object intv)
2267 ase_interval_union_item_t u =
2268 _ase_interval_boundary(XASE_INTERVAL(intv));
2271 return Qase_empty_interval;
2273 return _ase_wrap_interval_union(
2274 _ase_make_interval_union(u));
2277 static ase_interval_union_item_t
2278 _ase_interval_interior_boundary(ase_cartesian_t c)
2280 struct ase_interval_union_item_s ures, *ur = &ures;
2281 int i, dim = ase_cartesian_dimension(c);
2283 ur->current = Qase_empty_interval;
2285 for (i = 0; i < dim; i++) {
2286 ase_interval_union_item_t tmp =
2287 _ase_interval_boundary(
2288 XASE_INTERVAL(ase_cartesian_objects(c)[i]));
2289 Lisp_Object *newos = alloca_array(Lisp_Object, dim);
2295 for (j = 0; j < dim; j++) {
2296 newos[j] = ase_cartesian_objects(c)[j];
2298 /* replace i-th component with one boundary point */
2299 newos[i] = tmp->current;
2300 /* replace with the new interior product */
2302 _ase_wrap_cartesian_interior(
2303 _ase_make_cartesian(dim, newos, 1));
2304 /* replace i-th component with the other boundary point */
2305 newos[i] = tmp->next->current;
2306 /* and replace again with new interior product */
2307 tmp->next->current =
2308 _ase_wrap_cartesian_interior(
2309 _ase_make_cartesian(dim, newos, 1));
2311 /* pump the stuff into ur */
2319 static ase_interval_union_item_t
2320 _ase_interval_union_boundary(ase_interval_union_item_t u)
2322 struct ase_interval_union_item_s ures, *ur = &ures;
2325 lastiv = ur->current = Qase_empty_interval;
2328 ase_interval_union_item_t tmp = NULL;
2331 if (ASE_INTERVALP(u->current)) {
2332 tmp = _ase_interval_boundary(
2333 XASE_INTERVAL(u->current));
2334 } else if (ASE_INTERVAL_INTERIOR_P(u->current)) {
2335 tmp = _ase_interval_interior_boundary(
2336 XASE_CARTESIAN(u->current));
2343 /* disjoint intervals may have equal boundary points */
2344 curiv = tmp->current;
2345 if (!ase_interval_equal_p(lastiv, curiv)) {
2348 ur->next = tmp->next;
2352 lastiv = ur->current;
2355 if (ASE_INTERVAL_INTERIOR_P(lastiv)) {
2356 _ase_normalise_union_intr(&ures);
2362 Lisp_Object ase_interval_interior_boundary(Lisp_Object intv_intr_prod)
2364 ase_interval_union_item_t u =
2365 _ase_interval_interior_boundary(
2366 XASE_CARTESIAN(intv_intr_prod));
2369 return Qase_empty_interval;
2371 return _ase_wrap_interval_union(
2372 _ase_make_interval_union(u));
2375 Lisp_Object ase_interval_union_boundary(Lisp_Object intv_union)
2377 ase_interval_union_item_t u =
2378 _ase_interval_union_boundary(
2379 XASE_INTERVAL_UNION_SER(intv_union));
2382 return Qase_empty_interval;
2384 return _ase_wrap_interval_union(
2385 _ase_make_interval_union(u));
2388 static ase_interval_t
2389 _ase_interval_closure(ase_interval_t a)
2393 if (_ase_interval_closed_p(a))
2396 return _ase_make_interval(a->lower, a->upper, 0, 0);
2399 Lisp_Object ase_interval_closure(Lisp_Object intv)
2402 _ase_interval_closure(XASE_INTERVAL(intv));
2405 return Qase_empty_interval;
2407 return _ase_wrap_interval(u);
2410 static ase_cartesian_t
2411 _ase_interval_interior_closure(ase_cartesian_t c)
2413 int i, dim = ase_cartesian_dimension(c);
2414 Lisp_Object *os = ase_cartesian_objects(c);
2415 Lisp_Object *newos = alloca_array(Lisp_Object, dim);
2417 for (i = 0; i < dim; i++) {
2418 newos[i] = ase_interval_closure(os[i]);
2421 return _ase_make_cartesian(dim, newos, 1);
2424 Lisp_Object ase_interval_interior_closure(Lisp_Object intv_intr_prod)
2427 _ase_interval_interior_closure(
2428 XASE_CARTESIAN(intv_intr_prod));
2431 return Qase_empty_interval;
2433 return _ase_wrap_cartesian_interior(c);
2436 static ase_interval_union_item_t
2437 _ase_interval_union_closure(ase_interval_union_item_t u)
2439 struct ase_interval_union_item_s ures, *ur = &ures;
2441 if (_ase_interval_union_closed_p(u))
2444 ur->current = Qase_empty_interval;
2447 Lisp_Object ltmp = Qnil;
2448 if (ASE_INTERVALP(u->current)) {
2449 ase_interval_t tmp =
2450 _ase_interval_closure(
2451 XASE_INTERVAL(u->current));
2455 ltmp = _ase_wrap_interval(tmp);
2456 } else if (ASE_INTERVAL_INTERIOR_P(u->current)) {
2457 ase_cartesian_t tmp =
2458 _ase_interval_interior_closure(
2459 XASE_CARTESIAN(u->current));
2463 ltmp = _ase_wrap_cartesian_interior(tmp);
2465 ur = ur->next = _ase_make_interval_union_item(ltmp);
2468 _ase_normalise_union(&ures);
2473 Lisp_Object ase_interval_union_closure(Lisp_Object intv_union)
2475 ase_interval_union_item_t u =
2476 _ase_interval_union_closure(
2477 XASE_INTERVAL_UNION_SER(intv_union));
2480 return Qase_empty_interval;
2483 return _ase_wrap_interval_union(
2484 _ase_make_interval_union(u));
2489 static ase_interval_t
2490 _ase_interval_interior(ase_interval_t a)
2492 if (a == NULL || _ase_equal_p(a->lower, a->upper))
2495 if (_ase_interval_open_p(a))
2498 return _ase_make_interval(a->lower, a->upper, 1, 1);
2501 Lisp_Object ase_interval_interior(Lisp_Object intv)
2504 _ase_interval_interior(XASE_INTERVAL(intv));
2507 return Qase_empty_interval;
2509 return _ase_wrap_interval(u);
2512 static ase_cartesian_t
2513 _ase_interval_interior_interior(ase_cartesian_t c)
2515 int i, dim = ase_cartesian_dimension(c);
2516 Lisp_Object *os = ase_cartesian_objects(c);
2517 Lisp_Object *newos = alloca_array(Lisp_Object, dim);
2519 for (i = 0; i < dim; i++) {
2520 newos[i] = ase_interval_interior(os[i]);
2523 return _ase_make_cartesian(dim, newos, 1);
2526 Lisp_Object ase_interval_interior_interior(Lisp_Object intv_intr_prod)
2529 _ase_interval_interior_interior(
2530 XASE_CARTESIAN(intv_intr_prod));
2533 return Qase_empty_interval;
2535 return _ase_wrap_cartesian_interior(c);
2538 static ase_interval_union_item_t
2539 _ase_interval_union_interior(ase_interval_union_item_t u)
2541 struct ase_interval_union_item_s ures, *ur = &ures;
2543 if (_ase_interval_union_open_p(u))
2546 ur->current = Qase_empty_interval;
2549 Lisp_Object ltmp = Qnil;
2550 if (ASE_INTERVALP(u->current)) {
2551 ase_interval_t tmp =
2552 _ase_interval_interior(
2553 XASE_INTERVAL(u->current));
2557 ltmp = _ase_wrap_interval(tmp);
2558 } else if (ASE_INTERVAL_INTERIOR_P(u->current)) {
2559 ase_cartesian_t tmp =
2560 _ase_interval_interior_interior(
2561 XASE_CARTESIAN(u->current));
2565 ltmp = _ase_wrap_cartesian_interior(tmp);
2567 ur = ur->next = _ase_make_interval_union_item(ltmp);
2573 Lisp_Object ase_interval_union_interior(Lisp_Object intv_union)
2575 ase_interval_union_item_t u =
2576 _ase_interval_union_interior(
2577 XASE_INTERVAL_UNION_SER(intv_union));
2580 return Qase_empty_interval;
2583 return _ase_wrap_interval_union(
2584 _ase_make_interval_union(u));
2589 static ase_interval_type_t
2590 ase_interval_type(Lisp_Object o)
2592 if (ASE_INTERVALP(o)) {
2593 return ASE_ITYPE_INTERVAL;
2594 } else if (ASE_INTERVAL_UNION_P(o)) {
2595 return ASE_ITYPE_UNION;
2596 } else if (ASE_INTERVAL_INTERIOR_P(o)) {
2597 return ASE_ITYPE_INTERIOR;
2599 return ASE_ITYPE_OBJECT;
2604 _ase_heapsort_sift(Lisp_Object *args, int start, int count,
2605 ase_order_relation_f lessp)
2607 int root = start, child;
2609 while (2*root + 1 < count) {
2612 if (child < count-1 && lessp(args[child], args[child+1]))
2614 if (lessp(args[root], args[child])) {
2615 _ase_swap(args, root, child);
2625 _ase_heapsort(int nargs, Lisp_Object *args, ase_order_relation_f lessp)
2627 int start = nargs/2 - 1, end = nargs-1;
2629 while (start >= 0) {
2630 _ase_heapsort_sift(args, start, nargs, lessp);
2634 _ase_swap(args, end, 0);
2635 _ase_heapsort_sift(args, 0, end, lessp);
2642 ase_interval_connected_p_heapify(int nargs, Lisp_Object *args)
2644 /* special case for flat intervals,
2645 * uses a heapsort to ease the connectivity question */
2646 Lisp_Object *newargs;
2649 /* check for ASE_INTERVALs and sort empty intervals to the tail */
2650 for (j = 0; j < nargs; ) {
2651 if (ASE_INTERVAL_UNION_P(args[j])) {
2652 /* remember the number of additional elements we need */
2653 add += XASE_INTERVAL_UNION(args[j])->no_intv-1;
2655 } else if (!ASE_INTERVAL_EMPTY_P(args[j])) {
2658 _ase_swap(args, nargs-1, j);
2665 else if (nargs == 1) /* reflexivity! */
2666 return (ASE_INTERVAL_UNION_P(args[0]) ? Qnil : Qt);
2669 EMOD_ASE_DEBUG_INTV("exploding %d union items\n", add);
2670 newargs = alloca_array(Lisp_Object, nargs+add);
2671 /* move the first nargs args here */
2672 memmove(newargs, args, nargs*sizeof(Lisp_Object));
2673 /* now explode the whole story */
2674 args = _ase_interval_union_explode_array(nargs, newargs, add);
2678 /* sort intervals in less-p metric */
2679 _ase_heapsort(nargs, args, ase_interval_less_p);
2681 for (j = 1; j < nargs; j++) {
2682 Lisp_Object o1 = args[j-1], o2 = args[j];
2683 if (!ase_interval_connected_p(o1, o2))
2691 ase_interval_connected_p_nsquare(int nargs, Lisp_Object *args)
2694 ase_interval_type_t t1, t2;
2695 ase_st_relation_f relf = NULL;
2699 else if (nargs == 1 && !ASE_INTERVAL_UNION_P(args[0]))
2701 else if (nargs == 1 &&
2702 ASE_INTERVAL_INTERIOR_P(XASE_INTERVAL_UNION_FIRST(args[0]))) {
2703 ase_interval_union_item_t u1, u2;
2704 u1 = XASE_INTERVAL_UNION_SER(args[0]);
2705 t1 = t2 = ASE_ITYPE_INTERIOR;
2706 relf = ase_optable_connected[t1][t2];
2707 while ((u2 = u1->next)) {
2708 Lisp_Object o1 = u1->current;
2709 Lisp_Object o2 = u2->current;
2715 } else if (nargs == 1)
2718 /* the slow approach */
2719 /* connectivity itself is an intransitive relation,
2720 * but if any two are (locally) connected then all items are
2721 * globally connected */
2722 for (i = 0; i < nargs-1; i++) {
2723 Lisp_Object o1 = args[i];
2725 t1 = ase_interval_type(o1);
2726 for (j = i+1; j < nargs && !foundp; j++) {
2727 Lisp_Object o2 = args[j];
2728 t2 = ase_interval_type(o2);
2729 relf = ase_optable_connected[t1][t2];
2730 if (relf && relf(o1, o2))
2741 ase_interval_disjoint_p_nsquare(int nargs, Lisp_Object *args)
2744 ase_interval_type_t t1, t2;
2745 ase_st_relation_f relf = NULL;
2749 else if (nargs == 1) /* irreflexivity! */
2752 /* don't think that sorting helps here, but i'll profile this one day */
2753 /* pairwise (local) disjunction implies global disjunction */
2754 for (i = 0; i < nargs-1; i++) {
2755 Lisp_Object o1 = args[i];
2756 t1 = ase_interval_type(o1);
2757 for (j = i+1; j < nargs; j++) {
2758 Lisp_Object o2 = args[j];
2759 t2 = ase_interval_type(o2);
2760 relf = ase_optable_disjoint[t1][t2];
2761 if (relf && !relf(o1, o2))
2770 ase_interval_dimension(Lisp_Object o)
2772 switch (ase_interval_type(o)) {
2773 case ASE_ITYPE_INTERVAL:
2775 case ASE_ITYPE_INTERIOR:
2776 return XASE_CARTESIAN_DIMENSION(o);
2777 case ASE_ITYPE_UNION:
2778 return ase_interval_dimension(XASE_INTERVAL_UNION_FIRST(o));
2780 case ASE_ITYPE_OBJECT:
2781 case NUMBER_OF_ASE_ITYPES:
2788 ase_interval_check_dimensions(int nargs, Lisp_Object *args)
2790 int i, predicdim = 0;
2795 /* partial loop unrolling */
2796 for (i = 0; i < nargs; i++) {
2797 CHECK_ASE_UBERINTERVAL(args[i]);
2798 if (!ASE_INTERVAL_EMPTY_P(args[i])) {
2799 predicdim = ase_interval_dimension(args[i]);
2803 for (i++; i < nargs; i++) {
2804 CHECK_ASE_UBERINTERVAL(args[i]);
2805 if (!ASE_INTERVAL_EMPTY_P(args[i]) &&
2806 predicdim != ase_interval_dimension(args[i]))
2816 _ase_interval_compute_lebesgue(ase_interval_t a)
2821 return ent_binop(ASE_BINARY_OP_DIFF, a->upper, a->lower);
2825 _ase_interval_update_lebesgue(ase_interval_t a)
2827 if (a && NILP(a->lebesgue_measure))
2828 a->lebesgue_measure = _ase_interval_compute_lebesgue(a);
2832 static inline Lisp_Object
2833 _ase_interval_lebesgue(ase_interval_t a)
2836 return a->lebesgue_measure;
2842 _ase_interval_compute_rational(ase_interval_t a)
2844 Lisp_Object args[2];
2850 if (a->lower == a->upper) {
2851 /* special case of 1 point intervals */
2852 if (INTEGERP(a->lower))
2858 if (_ase_equal_p((args[0] = Ftruncate(a->upper)), a->upper))
2859 args[0] = Fsub1(a->upper);
2860 args[1] = Ftruncate(a->lower);
2862 /* care for alternation of the signum */
2863 if (!NILP(Fnonnegativep(a->upper)) &&
2864 NILP(Fnonnegativep(a->lower)) &&
2865 !_ase_equal_p(args[1], a->lower))
2866 args[1] = Fsub1(args[1]);
2868 result = ent_binop_many(ASE_BINARY_OP_DIFF, countof(args), args);
2870 if (INTEGERP(a->upper) && !a->upper_open_p)
2871 result = Fadd1(result);
2872 if (INTEGERP(a->lower) && !a->lower_open_p)
2873 result = Fadd1(result);
2879 _ase_interval_update_rational(ase_interval_t a)
2881 if (a && NILP(a->rational_measure))
2882 a->rational_measure = _ase_interval_compute_rational(a);
2886 static inline Lisp_Object
2887 _ase_interval_rational(ase_interval_t a)
2890 return a->rational_measure;
2896 __ase_interval_interior_update_lebesgue(ase_cartesian_t c)
2898 int i = 0, dim = ase_cartesian_dimension(c);
2899 for (i = 0; i < dim; i++) {
2900 _ase_interval_update_lebesgue(
2901 XASE_INTERVAL(ase_cartesian_objects(c)[i]));
2907 __ase_interval_interior_lebesgue(ase_cartesian_t c)
2910 int i = 0, dim = __ase_interval_interior_update_lebesgue(c);
2915 args = alloca_array(Lisp_Object, dim);
2916 for (i = 0; i < dim; i++) {
2917 args[i] = _ase_interval_lebesgue(
2918 XASE_INTERVAL(ase_cartesian_objects(c)[i]));
2920 return ent_binop_many(ASE_BINARY_OP_PROD, dim, args);
2924 __ase_interval_interior_update_rational(ase_cartesian_t c)
2926 int i = 0, dim = ase_cartesian_dimension(c);
2927 for (i = 0; i < dim; i++) {
2928 _ase_interval_update_rational(
2929 XASE_INTERVAL(ase_cartesian_objects(c)[i]));
2935 __ase_interval_interior_rational(ase_cartesian_t c)
2938 int i = 0, dim = __ase_interval_interior_update_rational(c);
2943 args = alloca_array(Lisp_Object, dim);
2944 for (i = 0; i < dim; i++) {
2945 args[i] = _ase_interval_rational(
2946 XASE_INTERVAL(ase_cartesian_objects(c)[i]));
2948 return ent_binop_many(ASE_BINARY_OP_PROD, dim, args);
2952 _ase_interval_interior_update_lebesgue(ase_cartesian_t c)
2953 __attribute__((always_inline));
2955 _ase_interval_interior_update_lebesgue(ase_cartesian_t c)
2957 if (NILP(c->lebesgue_measure))
2958 c->lebesgue_measure =
2959 __ase_interval_interior_lebesgue(c);
2964 _ase_interval_interior_lebesgue(ase_cartesian_t c)
2966 return c->lebesgue_measure;
2970 _ase_interval_interior_update_rational(ase_cartesian_t c)
2972 if (NILP(c->rational_measure))
2973 c->rational_measure =
2974 __ase_interval_interior_rational(c);
2978 static inline Lisp_Object
2979 _ase_interval_interior_rational(ase_cartesian_t c)
2981 return c->rational_measure;
2985 __ase_interval_union_update_lebesgue(ase_interval_union_item_t u)
2986 __attribute__((always_inline));
2988 __ase_interval_union_update_lebesgue(ase_interval_union_item_t u)
2992 if (ASE_INTERVALP(u->current)) {
2993 _ase_interval_update_lebesgue(
2994 XASE_INTERVAL(u->current));
2995 } else if (ASE_INTERVAL_INTERIOR_P(u->current)) {
2996 _ase_interval_interior_update_lebesgue(
2997 XASE_CARTESIAN(u->current));
3006 __ase_interval_union_lebesgue(ase_interval_union_item_t u)
3009 int i = 0, nargs = __ase_interval_union_update_lebesgue(u);
3014 args = alloca_array(Lisp_Object, nargs);
3016 if (ASE_INTERVALP(u->current)) {
3017 args[i] = _ase_interval_lebesgue(
3018 XASE_INTERVAL(u->current));
3019 } else if (ASE_INTERVAL_INTERIOR_P(u->current)) {
3020 args[i] = _ase_interval_interior_lebesgue(
3021 XASE_CARTESIAN(u->current));
3026 return ent_binop_many(ASE_BINARY_OP_SUM, nargs, args);
3030 __ase_interval_union_update_rational(ase_interval_union_item_t u)
3034 if (ASE_INTERVALP(u->current)) {
3035 _ase_interval_update_rational(
3036 XASE_INTERVAL(u->current));
3037 } else if (ASE_INTERVAL_INTERIOR_P(u->current)) {
3038 _ase_interval_interior_update_rational(
3039 XASE_CARTESIAN(u->current));
3048 __ase_interval_union_rational(ase_interval_union_item_t u)
3050 int i = 0, nargs = __ase_interval_union_update_rational(u);
3054 Lisp_Object args[nargs];
3055 for ( i = nargs; i > 0; )
3059 if (ASE_INTERVALP(u->current)) {
3060 args[i] = _ase_interval_rational(
3061 XASE_INTERVAL(u->current));
3062 } else if (ASE_INTERVAL_INTERIOR_P(u->current)) {
3063 args[i] = _ase_interval_interior_rational(
3064 XASE_CARTESIAN(u->current));
3069 return ent_binop_many(ASE_BINARY_OP_SUM, nargs, args);
3074 _ase_interval_union_update_lebesgue(ase_interval_union_t iu)
3076 if (NILP(iu->lebesgue_measure))
3077 iu->lebesgue_measure =
3078 __ase_interval_union_lebesgue(ase_interval_union(iu));
3082 static inline Lisp_Object
3083 _ase_interval_union_lebesgue(ase_interval_union_t iu)
3085 return iu->lebesgue_measure;
3089 _ase_interval_union_update_rational(ase_interval_union_t iu)
3091 if (NILP(iu->rational_measure))
3092 iu->rational_measure =
3093 __ase_interval_union_rational(ase_interval_union(iu));
3097 static inline Lisp_Object
3098 _ase_interval_union_rational(ase_interval_union_t iu)
3100 return iu->rational_measure;
3104 ase_interval_lebesgue_measure(ase_interval_t a)
3106 _ase_interval_update_lebesgue(a);
3107 return _ase_interval_lebesgue(a);
3111 ase_interval_rational_measure(ase_interval_t a)
3113 _ase_interval_update_rational(a);
3114 return _ase_interval_rational(a);
3118 ase_interval_interior_lebesgue_measure(ase_cartesian_t c)
3120 _ase_interval_interior_update_lebesgue(c);
3121 return _ase_interval_interior_lebesgue(c);
3125 ase_interval_interior_rational_measure(ase_cartesian_t c)
3127 _ase_interval_interior_update_rational(c);
3128 return _ase_interval_interior_rational(c);
3132 ase_interval_union_lebesgue_measure(ase_interval_union_t iu)
3134 _ase_interval_union_update_lebesgue(iu);
3135 return _ase_interval_union_lebesgue(iu);
3139 ase_interval_union_rational_measure(ase_interval_union_t iu)
3141 _ase_interval_union_update_rational(iu);
3142 return _ase_interval_union_rational(iu);
3145 /* arithmetical operations */
3146 /* I x Q -> I : (a, b) + x -> (a+x, b+x) */
3147 /* I x I -> I : (a, b) + (c, d) -> (a+c, b+d) */
3148 /* U x Q -> U : (a, b) u (c, d) + x -> (a, b) + x u (c, d) + x */
3149 /* U x I -> U : (a, b) u (c, d) + (e, f) -> (a, b) + (e, f) u (c, d) + (e, f) */
3150 /* 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 */
3154 DEFUN("ase-intervalp", Fase_intervalp, 1, 1, 0, /*
3155 Return non-`nil' iff OBJECT is an ase interval.
3159 if (ASE_INTERVALP(object))
3165 DEFUN("ase-interval-union-p", Fase_interval_union_p, 1, 1, 0, /*
3166 Return non-`nil' iff OBJECT is an ase interval or union thereof.
3170 if (ASE_INTERVAL_OR_UNION_P(object))
3176 DEFUN("ase-interval-empty-p", Fase_interval_empty_p, 1, 1, 0, /*
3177 Return non-`nil' iff INTERVAL is the empty interval.
3181 CHECK_ASE_INTERVAL(interval);
3183 if (ASE_INTERVAL_EMPTY_P(interval))
3189 DEFUN("ase-interval-imprimitive-p", Fase_interval_imprimitive_p, 1, 1, 0, /*
3190 Return non-`nil' iff INTERVAL is not a primitive interval.
3194 CHECK_ASE_UBERINTERVAL(interval);
3196 if (ASE_INTERVALP(interval))
3202 DEFUN("ase-interval-open-p", Fase_interval_open_p, 1, 1, 0, /*
3203 Return non-`nil' iff INTERVAL (or a union thereof) is an open set
3204 with respect to the standard topology.
3208 CHECK_ASE_UBERINTERVAL(interval);
3210 if (ASE_INTERVALP(interval)) {
3211 if (ASE_INTERVAL_EMPTY_P(interval))
3213 if (ase_interval_open_p(interval))
3215 } else if (ASE_INTERVAL_UNION_P(interval)) {
3216 if (ase_interval_union_open_p(interval))
3218 } else if (ASE_INTERVAL_INTERIOR_P(interval)) {
3219 if (ase_interval_interior_open_p(interval))
3225 DEFUN("ase-interval-closed-p", Fase_interval_closed_p, 1, 1, 0, /*
3226 Return non-`nil' iff INTERVAL (or a union thereof) is a closed set
3227 with respect to the standard metric.
3229 An interval is said to be closed iff the complement is open.
3233 CHECK_ASE_UBERINTERVAL(interval);
3235 if (ASE_INTERVALP(interval)) {
3236 if (ASE_INTERVAL_EMPTY_P(interval))
3238 if (ase_interval_closed_p(interval))
3240 } else if (ASE_INTERVAL_UNION_P(interval)) {
3241 if (ase_interval_union_closed_p(interval))
3243 } else if (ASE_INTERVAL_INTERIOR_P(interval)) {
3244 if (ase_interval_interior_closed_p(interval))
3253 DEFUN("ase-empty-interval", Fase_empty_interval, 0, 0, 0, /*
3254 Return the empty interval.
3258 return Qase_empty_interval;
3262 DEFUN("ase-universe-interval", Fase_universe_interval, 0, 0, 0, /*
3263 Return the universe interval.
3267 return Qase_universe_interval;
3271 DEFUN("ase-interval", Fase_interval, 1, 4, 0, /*
3272 Return a (primitive) interval with lower bound LOWER and upper bound UPPER.
3273 To construct a (degenerated) one point interval, leave out the UPPER part.
3275 ASE's definition of an interval:
3276 With respect to a (strict) partial order, an interval is a connected
3279 If no special partial order is given, it defaults to less-equal-p (<=).
3280 If no special topology is given, it defaults to the po topology.
3282 (lower, upper, lower_open_p, upper_open_p))
3284 Lisp_Object result = Qnil;
3285 Lisp_Object args[2] = {lower, upper};
3287 CHECK_COMPARABLE(lower);
3289 args[1] = upper = lower;
3291 CHECK_COMPARABLE(upper);
3293 if (_ase_less_p(lower, upper))
3294 result = ase_make_interval(
3295 lower, upper, !NILP(lower_open_p), !NILP(upper_open_p));
3297 result = ase_make_interval(
3298 upper, lower, !NILP(upper_open_p), !NILP(lower_open_p));
3303 DEFUN("ase-interval-contains-p", Fase_interval_contains_p, 2, 2, 0, /*
3304 Return non-`nil' iff INTERVAL (or a union thereof) contains OBJECT
3305 as one of its elements. OBJECT can also be another interval or
3306 interval union to obtain the subset relation.
3310 ase_interval_type_t sup, sub;
3311 ase_element_relation_f relf = NULL;
3313 CHECK_ASE_UBERINTERVAL(interval);
3315 sup = ase_interval_type(interval);
3316 sub = ase_interval_type(object);
3318 if ((relf = ase_optable_superset[sup][sub]) &&
3319 (!NILP(relf(interval, object))))
3325 DEFUN("ase-interval-contains-where", Fase_interval_contains_where, 2, 2, 0, /*
3326 Return non-`nil' iff INTERVAL contains OBJECT as one of its elements.
3327 ELEMENT can also be another interval to obtain the subset relation.
3329 The non-`nil' value returned is the primitive interval which
3334 ase_interval_type_t sup, sub;
3335 ase_element_relation_f relf = NULL;
3337 CHECK_ASE_UBERINTERVAL(interval);
3339 sup = ase_interval_type(interval);
3340 sub = ase_interval_type(object);
3342 if ((relf = ase_optable_superset[sup][sub]))
3343 return relf(interval, object);
3348 DEFUN("ase-interval-connected-p", Fase_interval_connected_p, 0, MANY, 0, /*
3349 Return non-`nil' iff INTERVALS are connected.
3350 Arguments: &rest intervals
3352 Zero intervals are trivially connected, as is one interval.
3354 (int nargs, Lisp_Object *args))
3360 switch (ase_interval_check_dimensions(nargs, args)) {
3364 return ase_interval_connected_p_heapify(nargs, args);
3366 signal_error(Qembed_error, Qnil);
3369 return ase_interval_connected_p_nsquare(nargs, args);
3373 DEFUN("ase-interval-disjoint-p", Fase_interval_disjoint_p, 0, MANY, 0, /*
3374 Arguments: &rest intervals
3375 Return non-`nil' iff INTERVALS are (pairwise) disjoint.
3377 Zero intervals are trivially disjoint, while one interval is
3378 trivially not disjoint.
3380 (int nargs, Lisp_Object *args))
3386 switch (ase_interval_check_dimensions(nargs, args)) {
3390 signal_error(Qembed_error, Qnil);
3393 return ase_interval_disjoint_p_nsquare(nargs, args);
3397 DEFUN("ase-interval-equal-p", Fase_interval_equal_p, 2, 2, 0, /*
3398 Return non-`nil' if I1 and I2 are equal in some sense, equality
3399 hereby means that I1 and I2 contain each other.
3401 In fact, this is just a convenience function and totally equivalent
3403 (and (ase-interval-contains-p i1 i2) (ase-interval-contains-p i2 i1))
3407 Lisp_Object i1in2, i2in1;
3409 CHECK_ASE_UBERINTERVAL(i1);
3410 CHECK_ASE_UBERINTERVAL(i2);
3412 i1in2 = Fase_interval_contains_p(i1, i2);
3413 i2in1 = Fase_interval_contains_p(i2, i1);
3415 if (!NILP(i1in2) && !NILP(i2in1))
3421 /* more constructors */
3423 ase_interval_union_heapify(int nargs, Lisp_Object *args)
3425 Lisp_Object result = Qnil, *newargs;
3427 struct ase_interval_union_item_s _ures, *ures = &_ures, *u;
3428 ase_interval_union_t ires;
3430 /* check for ASE_INTERVALs and sort empty intervals to the tail */
3431 for (j = 0; j < nargs; ) {
3432 if (ASE_INTERVAL_UNION_P(args[j])) {
3433 /* remember the number of additional elements we need */
3434 add += XASE_INTERVAL_UNION(args[j])->no_intv-1;
3436 } else if (!ASE_INTERVAL_EMPTY_P(args[j])) {
3439 _ase_swap(args, nargs-1, j);
3445 return Qase_empty_interval;
3450 EMOD_ASE_DEBUG_INTV("exploding %d union items\n", add);
3451 newargs = alloca_array(Lisp_Object, nargs+add);
3452 /* move the first nargs args here */
3453 memmove(newargs, args, nargs*sizeof(Lisp_Object));
3454 /* now explode the whole story */
3455 args = _ase_interval_union_explode_array(nargs, newargs, add);
3459 /* sort intervals in less-p metric */
3460 _ase_heapsort(nargs, args, ase_interval_less_p);
3462 /* we start with the empty union and unite left-associatively from
3464 ures->current = Qase_empty_interval;
3465 u = ures->next = _ase_make_interval_union_item(args[0]);
3466 for (j = 1; j < nargs; j++) {
3467 u = u->next = _ase_make_interval_union_item(args[j]);
3470 j = _ase_normalise_union(ures);
3472 /* only return a union when there _is_ a union */
3473 ires = _ase_make_interval_union(ures->next);
3476 XSETASE_INTERVAL_UNION(result, ires);
3479 /* otherwise downgrade to a primitive interval */
3480 result = ures->next->current;
3481 _ase_interval_union_item_fini(ures->next);
3486 static inline Lisp_Object
3487 ase_interval_union_nsquare(int nargs, Lisp_Object *args)
3490 struct ase_interval_union_item_s _ures, *ures = &_ures, *u;
3491 ase_interval_union_t ires;
3492 Lisp_Object result = Qnil;
3495 return Qase_empty_interval;
3496 else if (nargs == 1)
3499 /* the slow approach */
3500 /* we start with the empty union and unite left-associatively from
3502 ures->current = Qase_empty_interval;
3504 for (i = 0; i < nargs; i++) {
3505 Lisp_Object tmp = args[i];
3506 if (ASE_INTERVAL_INTERIOR_P(tmp))
3507 u = u->next = _ase_make_interval_union_item(tmp);
3508 else if (ASE_INTERVAL_UNION_P(tmp)) {
3509 ase_interval_union_item_t tra =
3510 XASE_INTERVAL_UNION_SER(tmp);
3512 Lisp_Object c = tra->current;
3513 u = u->next = _ase_make_interval_union_item(c);
3519 j = _ase_normalise_union_intr(ures);
3521 /* only return a union when there _is_ a union */
3522 ires = _ase_make_interval_union(ures->next);
3525 XSETASE_INTERVAL_UNION(result, ires);
3528 /* otherwise downgrade to a primitive interval */
3529 result = ures->next->current;
3530 _ase_interval_union_item_fini(ures->next);
3535 DEFUN("ase-interval-union", Fase_interval_union, 0, MANY, 0, /*
3536 Arguments: &rest intervals
3537 Return the union of all INTERVALS.
3539 (int nargs, Lisp_Object *args))
3545 return Qase_empty_interval;
3547 dim = ase_interval_check_dimensions(nargs, args);
3550 return Qase_empty_interval;
3552 return ase_interval_union_heapify(nargs, args);
3554 signal_error(Qembed_error, Qnil);
3557 return ase_interval_union_nsquare(nargs, args);
3562 ase_interval_intersection_maybe_empty(int nargs, Lisp_Object *args)
3564 /* check for empty intervals, return 1 if there are some */
3567 for (j = 0; j < nargs; j++) {
3568 if (ASE_INTERVAL_EMPTY_P(args[j])) {
3576 ase_interval_intersection_heapify(int nargs, Lisp_Object *args)
3581 return Qase_empty_interval;
3582 else if (nargs == 1)
3584 else if (ase_interval_intersection_maybe_empty(nargs, args))
3585 return Qase_empty_interval;
3587 _ase_heapsort(nargs, args, ase_interval_or_union_less_p);
3589 /* we start with the universe and intersect left-associatively from
3591 for (j = 1; j < nargs; j++) {
3592 ase_interval_type_t t1 = ase_interval_type(args[0]);
3593 ase_interval_type_t t2 = ase_interval_type(args[j]);
3594 ase_binary_operation_f opf = ase_optable_intersect[t1][t2];
3597 args[0] = opf(args[0], args[j]);
3605 ase_interval_intersection_nsquare(int nargs, Lisp_Object *args)
3610 return Qase_empty_interval;
3611 else if (nargs == 1)
3613 else if (ase_interval_intersection_maybe_empty(nargs, args))
3614 return Qase_empty_interval;
3616 /* we start with the universe and intersect left-associatively from
3618 for (j = 1; j < nargs; j++) {
3619 ase_interval_type_t t1 = ase_interval_type(args[0]);
3620 ase_interval_type_t t2 = ase_interval_type(args[j]);
3621 ase_binary_operation_f opf = ase_optable_intersect[t1][t2];
3624 args[0] = opf(args[0], args[j]);
3631 DEFUN("ase-interval-intersection", Fase_interval_intersection, 0, MANY, 0, /*
3632 Arguments: &rest intervals
3633 Return the intersection of all INTERVALS.
3635 (int nargs, Lisp_Object *args))
3639 return Qase_empty_interval;
3640 else if (nargs == 1)
3643 switch (ase_interval_check_dimensions(nargs, args)) {
3645 return Qase_empty_interval;
3647 return ase_interval_intersection_heapify(nargs, args);
3649 signal_error(Qembed_error, Qnil);
3652 return ase_interval_intersection_nsquare(nargs, args);
3656 static inline Lisp_Object
3657 ase_interval_difference_nsquare(int nargs, Lisp_Object *args)
3661 /* check for ASE_INTERVALs and sort empty intervals to the tail */
3662 for (j = 1; j < nargs; j++) {
3663 /* we can only resort empty intervals for j >= 1 */
3664 if (ASE_INTERVAL_EMPTY_P(args[j])) {
3665 _ase_swap(args, nargs-1, j);
3671 return Qase_empty_interval;
3675 /* we must not use heapsort here, since subtracting sets is
3676 * not commutative */
3678 /* we start with args[0] and subtract left-associatively from
3680 for (j = 1; j < nargs; j++) {
3681 ase_interval_type_t t1 = ase_interval_type(args[0]);
3682 ase_interval_type_t t2 = ase_interval_type(args[j]);
3683 ase_binary_operation_f opf = ase_optable_subtract[t1][t2];
3686 args[0] = opf(args[0], args[j]);
3693 DEFUN("ase-interval-difference", Fase_interval_difference, 0, MANY, 0, /*
3694 Arguments: &rest intervals
3695 Return the difference of all INTERVALS from left to right.
3697 (int nargs, Lisp_Object *args))
3699 /* Treat the case args[0] = ( ) specially */
3701 return Qase_empty_interval;
3702 else if (nargs == 1)
3705 switch (ase_interval_check_dimensions(nargs, args)) {
3707 return Qase_empty_interval;
3709 signal_error(Qembed_error, Qnil);
3712 return ase_interval_difference_nsquare(nargs, args);
3716 DEFUN("ase-copy-interval", Fase_copy_interval, 1, 1, 0, /*
3717 Return a copy of INTERVAL.
3721 CHECK_ASE_INTERVAL(interval);
3723 return ase_copy_interval(interval);
3726 DEFUN("ase-interval-boundary", Fase_interval_boundary, 1, 1, 0, /*
3727 Return the boundary of INTERVAL, that is the interior of INTERVAL
3728 subtracted from the closure of INTERVAL.
3732 CHECK_ASE_UBERINTERVAL(interval);
3734 if (ASE_INTERVAL_EMPTY_P(interval))
3735 return Qase_empty_interval;
3736 else if (ASE_INTERVALP(interval))
3737 return ase_interval_boundary(interval);
3738 else if (ASE_INTERVAL_INTERIOR_P(interval))
3739 return ase_interval_interior_boundary(interval);
3740 else if (ASE_INTERVAL_UNION_P(interval))
3741 return ase_interval_union_boundary(interval);
3746 DEFUN("ase-interval-closure", Fase_interval_closure, 1, 1, 0, /*
3747 Return the closure of INTERVAL, that is the smallest closed set
3748 that contains INTERVAL.
3752 CHECK_ASE_UBERINTERVAL(interval);
3754 if (ASE_INTERVAL_EMPTY_P(interval))
3755 return Qase_empty_interval;
3756 else if (ASE_INTERVALP(interval))
3757 return ase_interval_closure(interval);
3758 else if (ASE_INTERVAL_INTERIOR_P(interval))
3759 return ase_interval_interior_closure(interval);
3760 else if (ASE_INTERVAL_UNION_P(interval))
3761 return ase_interval_union_closure(interval);
3766 DEFUN("ase-interval-interior", Fase_interval_interior, 1, 1, 0, /*
3767 Return the interior of INTERVAL, that is the largest open set that
3768 is contained in INTERVAL.
3772 CHECK_ASE_UBERINTERVAL(interval);
3774 if (ASE_INTERVAL_EMPTY_P(interval))
3775 return Qase_empty_interval;
3776 else if (ASE_INTERVALP(interval))
3777 return ase_interval_interior(interval);
3778 else if (ASE_INTERVAL_INTERIOR_P(interval))
3779 return ase_interval_interior_interior(interval);
3780 else if (ASE_INTERVAL_UNION_P(interval))
3781 return ase_interval_union_interior(interval);
3787 DEFUN("ase-interval-lower", Fase_interval_lower, 1, 1, 0, /*
3788 Return the lower bound of INTERVAL or `nil' if empty.
3789 Only the numerical value is returned.
3793 CHECK_ASE_INTERVAL(interval);
3795 if (ASE_INTERVAL_EMPTY_P(interval))
3798 return XASE_INTERVAL(interval)->lower;
3801 DEFUN("ase-interval-upper", Fase_interval_upper, 1, 1, 0, /*
3802 Return the upper bound of INTERVAL or `nil' if empty.
3803 Only the numerical value is returned.
3807 CHECK_ASE_INTERVAL(interval);
3809 if (ASE_INTERVAL_EMPTY_P(interval))
3812 return XASE_INTERVAL(interval)->upper;
3815 DEFUN("ase-interval-lower*", Fase_interval_lower_, 1, 1, 0, /*
3816 Return the lower bound of INTERVAL or `nil' if empty
3817 along with the boundary shape.
3823 CHECK_ASE_INTERVAL(interval);
3824 if (ASE_INTERVAL_EMPTY_P(interval))
3827 res = XASE_INTERVAL(interval)->lower;
3828 if (XASE_INTERVAL(interval)->lower_open_p)
3829 return Fcons(Q_open, res);
3831 return Fcons(Q_closed, res);
3834 DEFUN("ase-interval-upper*", Fase_interval_upper_, 1, 1, 0, /*
3835 Return the upper bound of INTERVAL or `nil' if empty
3836 along with the boundary shape.
3842 CHECK_ASE_INTERVAL(interval);
3843 if (ASE_INTERVAL_EMPTY_P(interval))
3846 res = XASE_INTERVAL(interval)->upper;
3847 if (XASE_INTERVAL(interval)->upper_open_p)
3848 return Fcons(Q_open, res);
3850 return Fcons(Q_closed, res);
3853 DEFUN("ase-interval-explode-union", Fase_interval_explode_union, 1, 1, 0, /*
3854 Return IUNION exploded into primitive intervals and listed in a dllist.
3858 Lisp_Object result = Qnil;
3859 dllist_t resdll = make_dllist();
3860 ase_interval_union_item_t u;
3862 CHECK_ASE_INTERVAL_UNION(iunion);
3863 u = XASE_INTERVAL_UNION_SER(iunion);
3865 dllist_append(resdll, (void*)u->current);
3869 XSETDLLIST(result, resdll);
3875 DEFUN("ase-interval-lebesgue-measure",
3876 Fase_interval_lebesgue_measure, 1, 1, 0, /*
3877 Return the Lebesgue measure of INTERVAL.
3881 CHECK_ASE_UBERINTERVAL(interval);
3883 if (ASE_INTERVALP(interval))
3884 return ase_interval_lebesgue_measure(XASE_INTERVAL(interval));
3885 else if (ASE_INTERVAL_INTERIOR_P(interval))
3886 return ase_interval_interior_lebesgue_measure(
3887 XASE_CARTESIAN(interval));
3888 else if (ASE_INTERVAL_UNION_P(interval))
3889 return ase_interval_union_lebesgue_measure(
3890 XASE_INTERVAL_UNION(interval));
3894 DEFUN("ase-interval-rational-measure",
3895 Fase_interval_rational_measure, 1, 1, 0, /*
3896 Return the number of rational integers in INTERVAL.
3900 CHECK_ASE_UBERINTERVAL(interval);
3902 if (ASE_INTERVALP(interval))
3903 return ase_interval_rational_measure(XASE_INTERVAL(interval));
3904 else if (ASE_INTERVAL_INTERIOR_P(interval))
3905 return ase_interval_interior_rational_measure(
3906 XASE_CARTESIAN(interval));
3907 else if (ASE_INTERVAL_UNION_P(interval))
3908 return ase_interval_union_rational_measure(
3909 XASE_INTERVAL_UNION(interval));
3913 DEFUN("ase-interval-dump", Fase_interval_dump, 1, 1, 0, /*
3917 CHECK_ASE_INTERVAL_OR_UNION(interval);
3919 if (ASE_INTERVALP(interval)) {
3920 ase_interval_prnt(interval, Qexternal_debugging_output, 0);
3921 write_c_string("\n", Qexternal_debugging_output);
3924 ase_interval_union_prnt(
3925 interval, Qexternal_debugging_output, 0);
3926 write_c_string("\n", Qexternal_debugging_output);
3932 static inline Lisp_Object
3933 ase_interval_add_i_obj(Lisp_Object intv, Lisp_Object number)
3935 int lopenp = XASE_INTERVAL(intv)->lower_open_p;
3936 int uopenp = XASE_INTERVAL(intv)->upper_open_p;
3937 int lequp = XASE_INTERVAL(intv)->lower_eq_upper_p;
3938 Lisp_Object args[2] = {Qnil, number};
3939 Lisp_Object newl, newu;
3941 args[0] = XASE_INTERVAL(intv)->lower;
3942 newl = ent_binop(ASE_BINARY_OP_SUM, args[0], args[1]);
3944 args[0] = XASE_INTERVAL(intv)->upper;
3945 newu = ent_binop(ASE_BINARY_OP_SUM, args[0], args[1]);
3946 return ase_make_interval(newl, newu, lopenp, uopenp);
3948 return ase_make_interval(newl, newl, lopenp, uopenp);
3952 static inline Lisp_Object
3953 ase_interval_add_obj_i(Lisp_Object number, Lisp_Object intv)
3955 return ase_interval_add_i_obj(intv, number);
3959 /* initialiser stuff */
3961 ase_interval_binary_optable_init(void)
3963 int idx = ase_optable_index_typesym(Qase_interval);
3964 ent_binop_register(ASE_BINARY_OP_SUM,
3965 idx, INT_T, ase_interval_add_i_obj);
3966 ent_binop_register(ASE_BINARY_OP_SUM,
3967 INT_T, idx, ase_interval_add_obj_i);
3968 ent_binop_register(ASE_BINARY_OP_SUM,
3969 idx, FLOAT_T, ase_interval_add_obj_i);
3970 ent_binop_register(ASE_BINARY_OP_SUM,
3971 FLOAT_T, idx, ase_interval_add_obj_i);
3978 DEFSUBR(Fase_empty_interval);
3979 DEFSUBR(Fase_universe_interval);
3980 DEFSUBR(Fase_interval);
3981 DEFSUBR(Fase_interval_union);
3982 DEFSUBR(Fase_interval_intersection);
3983 DEFSUBR(Fase_interval_difference);
3984 DEFSUBR(Fase_copy_interval);
3985 DEFSUBR(Fase_interval_boundary);
3986 DEFSUBR(Fase_interval_interior);
3987 DEFSUBR(Fase_interval_closure);
3989 DEFSUBR(Fase_intervalp);
3990 DEFSUBR(Fase_interval_union_p);
3991 DEFSUBR(Fase_interval_empty_p);
3992 DEFSUBR(Fase_interval_imprimitive_p);
3993 DEFSUBR(Fase_interval_open_p);
3994 DEFSUBR(Fase_interval_closed_p);
3995 DEFSUBR(Fase_interval_contains_p);
3996 DEFSUBR(Fase_interval_contains_where);
3997 DEFSUBR(Fase_interval_connected_p);
3998 DEFSUBR(Fase_interval_disjoint_p);
3999 DEFSUBR(Fase_interval_equal_p);
4001 DEFSUBR(Fase_interval_lower);
4002 DEFSUBR(Fase_interval_lower_);
4003 DEFSUBR(Fase_interval_upper);
4004 DEFSUBR(Fase_interval_upper_);
4005 DEFSUBR(Fase_interval_explode_union);
4007 DEFSUBR(Fase_interval_lebesgue_measure);
4008 DEFSUBR(Fase_interval_rational_measure);
4010 DEFASETYPE_WITH_OPS(Qase_interval, "ase:interval");
4011 defsymbol(&Qase_intervalp, "ase:intervalp");
4012 DEFASETYPE_WITH_OPS(Qase_interval_union, "ase:interval-union");
4013 defsymbol(&Qase_interval_union_p, "ase:interval-union-p");
4015 defsymbol(&Q_less, ":<");
4016 defsymbol(&Q_greater, ":>");
4017 defsymbol(&Q_eql, ":=");
4018 DEFKEYWORD(Q_unknown);
4020 DEFKEYWORD(Q_closed);
4021 DEFKEYWORD(Q_disjoint);
4022 DEFKEYWORD(Q_connected);
4025 DEFSUBR(Fase_interval_dump);
4027 ase_interval_binary_optable_init();
4031 DEFVAR_CONST_LISP("ase-empty-interval", &Qase_empty_interval /*
4032 The interval which contains no elements.
4034 DEFVAR_CONST_LISP("ase-universe-interval", &Qase_universe_interval /*
4035 The interval which contains all elements.
4038 Fprovide(intern("ase-interval"));
4043 EMOD_PUBREINIT(void)
4045 Qase_empty_interval = ase_empty_interval();
4046 Qase_universe_interval = ase_universe_interval();
4047 staticpro(&Qase_empty_interval);
4048 staticpro(&Qase_universe_interval);
4050 if (LIKELY(ase_empty_sets != NULL)) {
4051 dllist_append(ase_empty_sets, (void*)Qase_empty_interval);
4053 EMOD_ASE_CRITICAL("Cannot proclaim empty elements\n");
4059 EMOD_PUBDEINIT(void)
4061 Frevoke(intern("ase-interval"));
4065 /* ase-interval ends here */