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);
2051 ase_subtract_intr_union(Lisp_Object c, Lisp_Object iu)
2053 /* A \ (B u C) = (A \ B) \ C */
2054 ase_interval_union_item_t nu =
2055 _ase_subtract_intr_union(
2057 XASE_INTERVAL_UNION_SER(iu));
2060 return _ase_wrap_interval_union(
2061 _ase_make_interval_union(nu));
2063 Lisp_Object na = nu->current;
2064 _ase_interval_union_item_fini(nu);
2067 return Qase_empty_interval;
2070 static ase_interval_union_item_t
2071 _ase_subtract_union_union(ase_interval_union_t iu1, ase_interval_union_t iu2)
2073 /* (A u B) \ (C u D) = ((A u B) \ C) \ D */
2074 ase_interval_union_item_t na = ase_interval_union(iu1);
2075 ase_interval_union_item_t u = ase_interval_union(iu2);
2078 if (ASE_INTERVALP(u->current)) {
2079 ase_interval_t a = XASE_INTERVAL(u->current);
2080 na = _ase_subtract_union_intv(na, a);
2081 } else if (ASE_INTERVAL_INTERIOR_P(u->current)) {
2082 ase_cartesian_t c = XASE_CARTESIAN(u->current);
2083 na = _ase_subtract_union_intr(na, c);
2095 ase_subtract_union_union(Lisp_Object iu1, Lisp_Object iu2)
2097 /* (A u B) \ (C u D) = ((A u B) \ C) \ D */
2098 ase_interval_union_item_t nu =
2099 _ase_subtract_union_union(
2100 XASE_INTERVAL_UNION(iu1), XASE_INTERVAL_UNION(iu2));
2103 return _ase_wrap_interval_union(
2104 _ase_make_interval_union(nu));
2106 Lisp_Object na = nu->current;
2107 _ase_interval_union_item_fini(nu);
2110 return Qase_empty_interval;
2115 _ase_copy_interval(ase_interval_t a)
2117 Lisp_Object result = Qnil;
2119 XSETASE_INTERVAL(result, a);
2123 Lisp_Object ase_copy_interval(Lisp_Object intv)
2125 return _ase_copy_interval(XASE_INTERVAL(intv));
2129 _ase_interval_union_explode_array(int nargs, Lisp_Object *args, int add)
2131 ase_interval_union_item_t u;
2132 Lisp_Object *newargs = args;
2135 for (j = 0; j < nargs+add; ) {
2136 if (ASE_INTERVAL_UNION_P(args[j])) {
2137 u = ase_interval_union(XASE_INTERVAL_UNION(args[j]));
2138 newargs[j] = u->current;
2141 newargs[nargs+mov] = u->current;
2152 _ase_normalise_union(ase_interval_union_item_t u)
2154 /* assumes first item of u is sorta head, we cant change that */
2155 ase_interval_union_item_t u1 = u->next, u2 = NULL, pu = u;
2156 Lisp_Object a1, a2, atmp;
2159 while ((u2 = u1->next)) {
2163 /* connectivity can solely occur at upper-lower */
2164 atmp = ase_unite_intervals(a1, a2);
2166 ase_interval_union_item_t tmp;
2168 tmp = _ase_make_interval_union_item(atmp);
2169 tmp->next = u2->next;
2171 _ase_interval_union_item_fini(u1);
2172 _ase_interval_union_item_fini(u2);
2174 pu->next = u1 = tmp;
2185 _ase_normalise_union_intr(ase_interval_union_item_t u)
2187 /* assumes first item of u is sorta head, we cant change that */
2188 ase_interval_union_item_t u1 = u->next, u2 = NULL, pu1 = u, pu2;
2189 Lisp_Object a1, a2, atmp;
2199 /* connectivity can occur everywhere! */
2200 atmp = ase_unite_intervals(a1, a2);
2202 ase_interval_union_item_t tmp, u2n;
2204 tmp = _ase_make_interval_union_item(atmp);
2205 if (u1->next == u2) {
2206 tmp->next = u2->next;
2208 tmp->next = u1->next;
2214 _ase_interval_union_item_fini(u1);
2215 _ase_interval_union_item_fini(u2);
2217 /* we start over from the very beginning
2218 * there might be new merge opportunities now
2219 * if speed is important, we should allow
2220 * a merge depth of 1, settint u1 to tmp
2221 * would be the equivalent action for this */
2236 static ase_interval_union_item_t
2237 _ase_interval_boundary(ase_interval_t a)
2239 Lisp_Object blo = Qnil, bup = Qnil;
2240 ase_interval_union_item_t ures = NULL;
2242 if (a == NULL || a->lower_eq_upper_p)
2245 blo = _ase_wrap_interval(
2246 _ase_make_interval(a->lower, a->lower, 0, 0));
2247 if (!_ase_equal_p(a->lower, a->upper)) {
2248 bup = _ase_wrap_interval(
2249 _ase_make_interval(a->upper, a->upper, 0, 0));
2252 ures = _ase_make_interval_union_item(blo);
2254 ures->next = _ase_make_interval_union_item(bup);
2259 Lisp_Object ase_interval_boundary(Lisp_Object intv)
2261 ase_interval_union_item_t u =
2262 _ase_interval_boundary(XASE_INTERVAL(intv));
2265 return Qase_empty_interval;
2267 return _ase_wrap_interval_union(
2268 _ase_make_interval_union(u));
2271 static ase_interval_union_item_t
2272 _ase_interval_interior_boundary(ase_cartesian_t c)
2274 struct ase_interval_union_item_s ures, *ur = &ures;
2275 int i, dim = ase_cartesian_dimension(c);
2277 ur->current = Qase_empty_interval;
2279 for (i = 0; i < dim; i++) {
2280 ase_interval_union_item_t tmp =
2281 _ase_interval_boundary(
2282 XASE_INTERVAL(ase_cartesian_objects(c)[i]));
2283 Lisp_Object *newos = alloca_array(Lisp_Object, dim);
2289 for (j = 0; j < dim; j++) {
2290 newos[j] = ase_cartesian_objects(c)[j];
2292 /* replace i-th component with one boundary point */
2293 newos[i] = tmp->current;
2294 /* replace with the new interior product */
2296 _ase_wrap_cartesian_interior(
2297 _ase_make_cartesian(dim, newos, 1));
2298 /* replace i-th component with the other boundary point */
2299 newos[i] = tmp->next->current;
2300 /* and replace again with new interior product */
2301 tmp->next->current =
2302 _ase_wrap_cartesian_interior(
2303 _ase_make_cartesian(dim, newos, 1));
2305 /* pump the stuff into ur */
2313 static ase_interval_union_item_t
2314 _ase_interval_union_boundary(ase_interval_union_item_t u)
2316 struct ase_interval_union_item_s ures, *ur = &ures;
2319 lastiv = ur->current = Qase_empty_interval;
2322 ase_interval_union_item_t tmp = NULL;
2325 if (ASE_INTERVALP(u->current)) {
2326 tmp = _ase_interval_boundary(
2327 XASE_INTERVAL(u->current));
2328 } else if (ASE_INTERVAL_INTERIOR_P(u->current)) {
2329 tmp = _ase_interval_interior_boundary(
2330 XASE_CARTESIAN(u->current));
2337 /* disjoint intervals may have equal boundary points */
2338 curiv = tmp->current;
2339 if (!ase_interval_equal_p(lastiv, curiv)) {
2342 ur->next = tmp->next;
2346 lastiv = ur->current;
2349 if (ASE_INTERVAL_INTERIOR_P(lastiv)) {
2350 _ase_normalise_union_intr(&ures);
2356 Lisp_Object ase_interval_interior_boundary(Lisp_Object intv_intr_prod)
2358 ase_interval_union_item_t u =
2359 _ase_interval_interior_boundary(
2360 XASE_CARTESIAN(intv_intr_prod));
2363 return Qase_empty_interval;
2365 return _ase_wrap_interval_union(
2366 _ase_make_interval_union(u));
2369 Lisp_Object ase_interval_union_boundary(Lisp_Object intv_union)
2371 ase_interval_union_item_t u =
2372 _ase_interval_union_boundary(
2373 XASE_INTERVAL_UNION_SER(intv_union));
2376 return Qase_empty_interval;
2378 return _ase_wrap_interval_union(
2379 _ase_make_interval_union(u));
2382 static ase_interval_t
2383 _ase_interval_closure(ase_interval_t a)
2387 if (_ase_interval_closed_p(a))
2390 return _ase_make_interval(a->lower, a->upper, 0, 0);
2393 Lisp_Object ase_interval_closure(Lisp_Object intv)
2396 _ase_interval_closure(XASE_INTERVAL(intv));
2399 return Qase_empty_interval;
2401 return _ase_wrap_interval(u);
2404 static ase_cartesian_t
2405 _ase_interval_interior_closure(ase_cartesian_t c)
2407 int i, dim = ase_cartesian_dimension(c);
2408 Lisp_Object *os = ase_cartesian_objects(c);
2409 Lisp_Object *newos = alloca_array(Lisp_Object, dim);
2411 for (i = 0; i < dim; i++) {
2412 newos[i] = ase_interval_closure(os[i]);
2415 return _ase_make_cartesian(dim, newos, 1);
2418 Lisp_Object ase_interval_interior_closure(Lisp_Object intv_intr_prod)
2421 _ase_interval_interior_closure(
2422 XASE_CARTESIAN(intv_intr_prod));
2425 return Qase_empty_interval;
2427 return _ase_wrap_cartesian_interior(c);
2430 static ase_interval_union_item_t
2431 _ase_interval_union_closure(ase_interval_union_item_t u)
2433 struct ase_interval_union_item_s ures, *ur = &ures;
2435 if (_ase_interval_union_closed_p(u))
2438 ur->current = Qase_empty_interval;
2441 Lisp_Object ltmp = Qnil;
2442 if (ASE_INTERVALP(u->current)) {
2443 ase_interval_t tmp =
2444 _ase_interval_closure(
2445 XASE_INTERVAL(u->current));
2449 ltmp = _ase_wrap_interval(tmp);
2450 } else if (ASE_INTERVAL_INTERIOR_P(u->current)) {
2451 ase_cartesian_t tmp =
2452 _ase_interval_interior_closure(
2453 XASE_CARTESIAN(u->current));
2457 ltmp = _ase_wrap_cartesian_interior(tmp);
2459 ur = ur->next = _ase_make_interval_union_item(ltmp);
2462 _ase_normalise_union(&ures);
2467 Lisp_Object ase_interval_union_closure(Lisp_Object intv_union)
2469 ase_interval_union_item_t u =
2470 _ase_interval_union_closure(
2471 XASE_INTERVAL_UNION_SER(intv_union));
2474 return Qase_empty_interval;
2477 return _ase_wrap_interval_union(
2478 _ase_make_interval_union(u));
2483 static ase_interval_t
2484 _ase_interval_interior(ase_interval_t a)
2486 if (a == NULL || _ase_equal_p(a->lower, a->upper))
2489 if (_ase_interval_open_p(a))
2492 return _ase_make_interval(a->lower, a->upper, 1, 1);
2495 Lisp_Object ase_interval_interior(Lisp_Object intv)
2498 _ase_interval_interior(XASE_INTERVAL(intv));
2501 return Qase_empty_interval;
2503 return _ase_wrap_interval(u);
2506 static ase_cartesian_t
2507 _ase_interval_interior_interior(ase_cartesian_t c)
2509 int i, dim = ase_cartesian_dimension(c);
2510 Lisp_Object *os = ase_cartesian_objects(c);
2511 Lisp_Object *newos = alloca_array(Lisp_Object, dim);
2513 for (i = 0; i < dim; i++) {
2514 newos[i] = ase_interval_interior(os[i]);
2517 return _ase_make_cartesian(dim, newos, 1);
2520 Lisp_Object ase_interval_interior_interior(Lisp_Object intv_intr_prod)
2523 _ase_interval_interior_interior(
2524 XASE_CARTESIAN(intv_intr_prod));
2527 return Qase_empty_interval;
2529 return _ase_wrap_cartesian_interior(c);
2532 static ase_interval_union_item_t
2533 _ase_interval_union_interior(ase_interval_union_item_t u)
2535 struct ase_interval_union_item_s ures, *ur = &ures;
2537 if (_ase_interval_union_open_p(u))
2540 ur->current = Qase_empty_interval;
2543 Lisp_Object ltmp = Qnil;
2544 if (ASE_INTERVALP(u->current)) {
2545 ase_interval_t tmp =
2546 _ase_interval_interior(
2547 XASE_INTERVAL(u->current));
2551 ltmp = _ase_wrap_interval(tmp);
2552 } else if (ASE_INTERVAL_INTERIOR_P(u->current)) {
2553 ase_cartesian_t tmp =
2554 _ase_interval_interior_interior(
2555 XASE_CARTESIAN(u->current));
2559 ltmp = _ase_wrap_cartesian_interior(tmp);
2561 ur = ur->next = _ase_make_interval_union_item(ltmp);
2567 Lisp_Object ase_interval_union_interior(Lisp_Object intv_union)
2569 ase_interval_union_item_t u =
2570 _ase_interval_union_interior(
2571 XASE_INTERVAL_UNION_SER(intv_union));
2574 return Qase_empty_interval;
2577 return _ase_wrap_interval_union(
2578 _ase_make_interval_union(u));
2583 static ase_interval_type_t
2584 ase_interval_type(Lisp_Object o)
2586 if (ASE_INTERVALP(o)) {
2587 return ASE_ITYPE_INTERVAL;
2588 } else if (ASE_INTERVAL_UNION_P(o)) {
2589 return ASE_ITYPE_UNION;
2590 } else if (ASE_INTERVAL_INTERIOR_P(o)) {
2591 return ASE_ITYPE_INTERIOR;
2593 return ASE_ITYPE_OBJECT;
2598 _ase_heapsort_sift(Lisp_Object *args, int start, int count,
2599 ase_order_relation_f lessp)
2601 int root = start, child;
2603 while (2*root + 1 < count) {
2606 if (child < count-1 && lessp(args[child], args[child+1]))
2608 if (lessp(args[root], args[child])) {
2609 _ase_swap(args, root, child);
2619 _ase_heapsort(int nargs, Lisp_Object *args, ase_order_relation_f lessp)
2621 int start = nargs/2 - 1, end = nargs-1;
2623 while (start >= 0) {
2624 _ase_heapsort_sift(args, start, nargs, lessp);
2628 _ase_swap(args, end, 0);
2629 _ase_heapsort_sift(args, 0, end, lessp);
2636 ase_interval_connected_p_heapify(int nargs, Lisp_Object *args)
2638 /* special case for flat intervals,
2639 * uses a heapsort to ease the connectivity question */
2640 Lisp_Object *newargs;
2643 /* check for ASE_INTERVALs and sort empty intervals to the tail */
2644 for (j = 0; j < nargs; ) {
2645 if (ASE_INTERVAL_UNION_P(args[j])) {
2646 /* remember the number of additional elements we need */
2647 add += XASE_INTERVAL_UNION(args[j])->no_intv-1;
2649 } else if (!ASE_INTERVAL_EMPTY_P(args[j])) {
2652 _ase_swap(args, nargs-1, j);
2659 else if (nargs == 1) /* reflexivity! */
2660 return (ASE_INTERVAL_UNION_P(args[0]) ? Qnil : Qt);
2663 EMOD_ASE_DEBUG_INTV("exploding %d union items\n", add);
2664 newargs = alloca_array(Lisp_Object, nargs+add);
2665 /* move the first nargs args here */
2666 memmove(newargs, args, nargs*sizeof(Lisp_Object));
2667 /* now explode the whole story */
2668 args = _ase_interval_union_explode_array(nargs, newargs, add);
2672 /* sort intervals in less-p metric */
2673 _ase_heapsort(nargs, args, ase_interval_less_p);
2675 for (j = 1; j < nargs; j++) {
2676 Lisp_Object o1 = args[j-1], o2 = args[j];
2677 if (!ase_interval_connected_p(o1, o2))
2685 ase_interval_connected_p_nsquare(int nargs, Lisp_Object *args)
2688 ase_interval_type_t t1, t2;
2689 ase_st_relation_f relf = NULL;
2693 else if (nargs == 1 && !ASE_INTERVAL_UNION_P(args[0]))
2695 else if (nargs == 1 &&
2696 ASE_INTERVAL_INTERIOR_P(XASE_INTERVAL_UNION_FIRST(args[0]))) {
2697 ase_interval_union_item_t u1, u2;
2698 u1 = XASE_INTERVAL_UNION_SER(args[0]);
2699 t1 = t2 = ASE_ITYPE_INTERIOR;
2700 relf = ase_optable_connected[t1][t2];
2701 while ((u2 = u1->next)) {
2702 Lisp_Object o1 = u1->current;
2703 Lisp_Object o2 = u2->current;
2709 } else if (nargs == 1)
2712 /* the slow approach */
2713 /* connectivity itself is an intransitive relation,
2714 * but if any two are (locally) connected then all items are
2715 * globally connected */
2716 for (i = 0; i < nargs-1; i++) {
2717 Lisp_Object o1 = args[i];
2719 t1 = ase_interval_type(o1);
2720 for (j = i+1; j < nargs && !foundp; j++) {
2721 Lisp_Object o2 = args[j];
2722 t2 = ase_interval_type(o2);
2723 relf = ase_optable_connected[t1][t2];
2724 if (relf && relf(o1, o2))
2735 ase_interval_disjoint_p_nsquare(int nargs, Lisp_Object *args)
2738 ase_interval_type_t t1, t2;
2739 ase_st_relation_f relf = NULL;
2743 else if (nargs == 1) /* irreflexivity! */
2746 /* don't think that sorting helps here, but i'll profile this one day */
2747 /* pairwise (local) disjunction implies global disjunction */
2748 for (i = 0; i < nargs-1; i++) {
2749 Lisp_Object o1 = args[i];
2750 t1 = ase_interval_type(o1);
2751 for (j = i+1; j < nargs; j++) {
2752 Lisp_Object o2 = args[j];
2753 t2 = ase_interval_type(o2);
2754 relf = ase_optable_disjoint[t1][t2];
2755 if (relf && !relf(o1, o2))
2764 ase_interval_dimension(Lisp_Object o)
2766 switch (ase_interval_type(o)) {
2767 case ASE_ITYPE_INTERVAL:
2769 case ASE_ITYPE_INTERIOR:
2770 return XASE_CARTESIAN_DIMENSION(o);
2771 case ASE_ITYPE_UNION:
2772 return ase_interval_dimension(XASE_INTERVAL_UNION_FIRST(o));
2774 case ASE_ITYPE_OBJECT:
2775 case NUMBER_OF_ASE_ITYPES:
2782 ase_interval_check_dimensions(int nargs, Lisp_Object *args)
2784 int i, predicdim = 0;
2789 /* partial loop unrolling */
2790 for (i = 0; i < nargs; i++) {
2791 CHECK_ASE_UBERINTERVAL(args[i]);
2792 if (!ASE_INTERVAL_EMPTY_P(args[i])) {
2793 predicdim = ase_interval_dimension(args[i]);
2797 for (i++; i < nargs; i++) {
2798 CHECK_ASE_UBERINTERVAL(args[i]);
2799 if (!ASE_INTERVAL_EMPTY_P(args[i]) &&
2800 predicdim != ase_interval_dimension(args[i]))
2810 _ase_interval_compute_lebesgue(ase_interval_t a)
2815 return ent_binop(ASE_BINARY_OP_DIFF, a->upper, a->lower);
2819 _ase_interval_update_lebesgue(ase_interval_t a)
2821 if (a && NILP(a->lebesgue_measure))
2822 a->lebesgue_measure = _ase_interval_compute_lebesgue(a);
2826 static inline Lisp_Object
2827 _ase_interval_lebesgue(ase_interval_t a)
2830 return a->lebesgue_measure;
2836 _ase_interval_compute_rational(ase_interval_t a)
2838 Lisp_Object args[2];
2844 if (a->lower == a->upper) {
2845 /* special case of 1 point intervals */
2846 if (INTEGERP(a->lower))
2852 if (_ase_equal_p((args[0] = Ftruncate(a->upper)), a->upper))
2853 args[0] = Fsub1(a->upper);
2854 args[1] = Ftruncate(a->lower);
2856 /* care for alternation of the signum */
2857 if (!NILP(Fnonnegativep(a->upper)) &&
2858 NILP(Fnonnegativep(a->lower)) &&
2859 !_ase_equal_p(args[1], a->lower))
2860 args[1] = Fsub1(args[1]);
2862 result = ent_binop_many(ASE_BINARY_OP_DIFF, countof(args), args);
2864 if (INTEGERP(a->upper) && !a->upper_open_p)
2865 result = Fadd1(result);
2866 if (INTEGERP(a->lower) && !a->lower_open_p)
2867 result = Fadd1(result);
2873 _ase_interval_update_rational(ase_interval_t a)
2875 if (a && NILP(a->rational_measure))
2876 a->rational_measure = _ase_interval_compute_rational(a);
2880 static inline Lisp_Object
2881 _ase_interval_rational(ase_interval_t a)
2884 return a->rational_measure;
2890 __ase_interval_interior_update_lebesgue(ase_cartesian_t c)
2892 int i = 0, dim = ase_cartesian_dimension(c);
2893 for (i = 0; i < dim; i++) {
2894 _ase_interval_update_lebesgue(
2895 XASE_INTERVAL(ase_cartesian_objects(c)[i]));
2901 __ase_interval_interior_lebesgue(ase_cartesian_t c)
2904 int i = 0, dim = __ase_interval_interior_update_lebesgue(c);
2909 args = alloca_array(Lisp_Object, dim);
2910 for (i = 0; i < dim; i++) {
2911 args[i] = _ase_interval_lebesgue(
2912 XASE_INTERVAL(ase_cartesian_objects(c)[i]));
2914 return ent_binop_many(ASE_BINARY_OP_PROD, dim, args);
2918 __ase_interval_interior_update_rational(ase_cartesian_t c)
2920 int i = 0, dim = ase_cartesian_dimension(c);
2921 for (i = 0; i < dim; i++) {
2922 _ase_interval_update_rational(
2923 XASE_INTERVAL(ase_cartesian_objects(c)[i]));
2929 __ase_interval_interior_rational(ase_cartesian_t c)
2932 int i = 0, dim = __ase_interval_interior_update_rational(c);
2937 args = alloca_array(Lisp_Object, dim);
2938 for (i = 0; i < dim; i++) {
2939 args[i] = _ase_interval_rational(
2940 XASE_INTERVAL(ase_cartesian_objects(c)[i]));
2942 return ent_binop_many(ASE_BINARY_OP_PROD, dim, args);
2946 _ase_interval_interior_update_lebesgue(ase_cartesian_t c)
2947 __attribute__((always_inline));
2949 _ase_interval_interior_update_lebesgue(ase_cartesian_t c)
2951 if (NILP(c->lebesgue_measure))
2952 c->lebesgue_measure =
2953 __ase_interval_interior_lebesgue(c);
2958 _ase_interval_interior_lebesgue(ase_cartesian_t c)
2960 return c->lebesgue_measure;
2964 _ase_interval_interior_update_rational(ase_cartesian_t c)
2966 if (NILP(c->rational_measure))
2967 c->rational_measure =
2968 __ase_interval_interior_rational(c);
2972 static inline Lisp_Object
2973 _ase_interval_interior_rational(ase_cartesian_t c)
2975 return c->rational_measure;
2979 __ase_interval_union_update_lebesgue(ase_interval_union_item_t u)
2980 __attribute__((always_inline));
2982 __ase_interval_union_update_lebesgue(ase_interval_union_item_t u)
2986 if (ASE_INTERVALP(u->current)) {
2987 _ase_interval_update_lebesgue(
2988 XASE_INTERVAL(u->current));
2989 } else if (ASE_INTERVAL_INTERIOR_P(u->current)) {
2990 _ase_interval_interior_update_lebesgue(
2991 XASE_CARTESIAN(u->current));
3000 __ase_interval_union_lebesgue(ase_interval_union_item_t u)
3003 int i = 0, nargs = __ase_interval_union_update_lebesgue(u);
3008 args = alloca_array(Lisp_Object, nargs);
3010 if (ASE_INTERVALP(u->current)) {
3011 args[i] = _ase_interval_lebesgue(
3012 XASE_INTERVAL(u->current));
3013 } else if (ASE_INTERVAL_INTERIOR_P(u->current)) {
3014 args[i] = _ase_interval_interior_lebesgue(
3015 XASE_CARTESIAN(u->current));
3020 return ent_binop_many(ASE_BINARY_OP_SUM, nargs, args);
3024 __ase_interval_union_update_rational(ase_interval_union_item_t u)
3028 if (ASE_INTERVALP(u->current)) {
3029 _ase_interval_update_rational(
3030 XASE_INTERVAL(u->current));
3031 } else if (ASE_INTERVAL_INTERIOR_P(u->current)) {
3032 _ase_interval_interior_update_rational(
3033 XASE_CARTESIAN(u->current));
3042 __ase_interval_union_rational(ase_interval_union_item_t u)
3044 int i = 0, nargs = __ase_interval_union_update_rational(u);
3045 Lisp_Object args[nargs];
3051 if (ASE_INTERVALP(u->current)) {
3052 args[i] = _ase_interval_rational(
3053 XASE_INTERVAL(u->current));
3054 } else if (ASE_INTERVAL_INTERIOR_P(u->current)) {
3055 args[i] = _ase_interval_interior_rational(
3056 XASE_CARTESIAN(u->current));
3061 return ent_binop_many(ASE_BINARY_OP_SUM, nargs, args);
3065 _ase_interval_union_update_lebesgue(ase_interval_union_t iu)
3067 if (NILP(iu->lebesgue_measure))
3068 iu->lebesgue_measure =
3069 __ase_interval_union_lebesgue(ase_interval_union(iu));
3073 static inline Lisp_Object
3074 _ase_interval_union_lebesgue(ase_interval_union_t iu)
3076 return iu->lebesgue_measure;
3080 _ase_interval_union_update_rational(ase_interval_union_t iu)
3082 if (NILP(iu->rational_measure))
3083 iu->rational_measure =
3084 __ase_interval_union_rational(ase_interval_union(iu));
3088 static inline Lisp_Object
3089 _ase_interval_union_rational(ase_interval_union_t iu)
3091 return iu->rational_measure;
3095 ase_interval_lebesgue_measure(ase_interval_t a)
3097 _ase_interval_update_lebesgue(a);
3098 return _ase_interval_lebesgue(a);
3102 ase_interval_rational_measure(ase_interval_t a)
3104 _ase_interval_update_rational(a);
3105 return _ase_interval_rational(a);
3109 ase_interval_interior_lebesgue_measure(ase_cartesian_t c)
3111 _ase_interval_interior_update_lebesgue(c);
3112 return _ase_interval_interior_lebesgue(c);
3116 ase_interval_interior_rational_measure(ase_cartesian_t c)
3118 _ase_interval_interior_update_rational(c);
3119 return _ase_interval_interior_rational(c);
3123 ase_interval_union_lebesgue_measure(ase_interval_union_t iu)
3125 _ase_interval_union_update_lebesgue(iu);
3126 return _ase_interval_union_lebesgue(iu);
3130 ase_interval_union_rational_measure(ase_interval_union_t iu)
3132 _ase_interval_union_update_rational(iu);
3133 return _ase_interval_union_rational(iu);
3136 /* arithmetical operations */
3137 /* I x Q -> I : (a, b) + x -> (a+x, b+x) */
3138 /* I x I -> I : (a, b) + (c, d) -> (a+c, b+d) */
3139 /* U x Q -> U : (a, b) u (c, d) + x -> (a, b) + x u (c, d) + x */
3140 /* U x I -> U : (a, b) u (c, d) + (e, f) -> (a, b) + (e, f) u (c, d) + (e, f) */
3141 /* 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 */
3145 DEFUN("ase-intervalp", Fase_intervalp, 1, 1, 0, /*
3146 Return non-`nil' iff OBJECT is an ase interval.
3150 if (ASE_INTERVALP(object))
3156 DEFUN("ase-interval-union-p", Fase_interval_union_p, 1, 1, 0, /*
3157 Return non-`nil' iff OBJECT is an ase interval or union thereof.
3161 if (ASE_INTERVAL_OR_UNION_P(object))
3167 DEFUN("ase-interval-empty-p", Fase_interval_empty_p, 1, 1, 0, /*
3168 Return non-`nil' iff INTERVAL is the empty interval.
3172 CHECK_ASE_INTERVAL(interval);
3174 if (ASE_INTERVAL_EMPTY_P(interval))
3180 DEFUN("ase-interval-imprimitive-p", Fase_interval_imprimitive_p, 1, 1, 0, /*
3181 Return non-`nil' iff INTERVAL is not a primitive interval.
3185 CHECK_ASE_UBERINTERVAL(interval);
3187 if (ASE_INTERVALP(interval))
3193 DEFUN("ase-interval-open-p", Fase_interval_open_p, 1, 1, 0, /*
3194 Return non-`nil' iff INTERVAL (or a union thereof) is an open set
3195 with respect to the standard topology.
3199 CHECK_ASE_UBERINTERVAL(interval);
3201 if (ASE_INTERVALP(interval)) {
3202 if (ASE_INTERVAL_EMPTY_P(interval))
3204 if (ase_interval_open_p(interval))
3206 } else if (ASE_INTERVAL_UNION_P(interval)) {
3207 if (ase_interval_union_open_p(interval))
3209 } else if (ASE_INTERVAL_INTERIOR_P(interval)) {
3210 if (ase_interval_interior_open_p(interval))
3216 DEFUN("ase-interval-closed-p", Fase_interval_closed_p, 1, 1, 0, /*
3217 Return non-`nil' iff INTERVAL (or a union thereof) is a closed set
3218 with respect to the standard metric.
3220 An interval is said to be closed iff the complement is open.
3224 CHECK_ASE_UBERINTERVAL(interval);
3226 if (ASE_INTERVALP(interval)) {
3227 if (ASE_INTERVAL_EMPTY_P(interval))
3229 if (ase_interval_closed_p(interval))
3231 } else if (ASE_INTERVAL_UNION_P(interval)) {
3232 if (ase_interval_union_closed_p(interval))
3234 } else if (ASE_INTERVAL_INTERIOR_P(interval)) {
3235 if (ase_interval_interior_closed_p(interval))
3244 DEFUN("ase-empty-interval", Fase_empty_interval, 0, 0, 0, /*
3245 Return the empty interval.
3249 return Qase_empty_interval;
3253 DEFUN("ase-universe-interval", Fase_universe_interval, 0, 0, 0, /*
3254 Return the universe interval.
3258 return Qase_universe_interval;
3262 DEFUN("ase-interval", Fase_interval, 1, 4, 0, /*
3263 Return a (primitive) interval with lower bound LOWER and upper bound UPPER.
3264 To construct a (degenerated) one point interval, leave out the UPPER part.
3266 ASE's definition of an interval:
3267 With respect to a (strict) partial order, an interval is a connected
3270 If no special partial order is given, it defaults to less-equal-p (<=).
3271 If no special topology is given, it defaults to the po topology.
3273 (lower, upper, lower_open_p, upper_open_p))
3275 Lisp_Object result = Qnil;
3276 Lisp_Object args[2] = {lower, upper};
3278 CHECK_COMPARABLE(lower);
3280 args[1] = upper = lower;
3282 CHECK_COMPARABLE(upper);
3284 if (_ase_less_p(lower, upper))
3285 result = ase_make_interval(
3286 lower, upper, !NILP(lower_open_p), !NILP(upper_open_p));
3288 result = ase_make_interval(
3289 upper, lower, !NILP(upper_open_p), !NILP(lower_open_p));
3294 DEFUN("ase-interval-contains-p", Fase_interval_contains_p, 2, 2, 0, /*
3295 Return non-`nil' iff INTERVAL (or a union thereof) contains OBJECT
3296 as one of its elements. OBJECT can also be another interval or
3297 interval union to obtain the subset relation.
3301 ase_interval_type_t sup, sub;
3302 ase_element_relation_f relf = NULL;
3304 CHECK_ASE_UBERINTERVAL(interval);
3306 sup = ase_interval_type(interval);
3307 sub = ase_interval_type(object);
3309 if ((relf = ase_optable_superset[sup][sub]) &&
3310 (!NILP(relf(interval, object))))
3316 DEFUN("ase-interval-contains-where", Fase_interval_contains_where, 2, 2, 0, /*
3317 Return non-`nil' iff INTERVAL contains OBJECT as one of its elements.
3318 ELEMENT can also be another interval to obtain the subset relation.
3320 The non-`nil' value returned is the primitive interval which
3325 ase_interval_type_t sup, sub;
3326 ase_element_relation_f relf = NULL;
3328 CHECK_ASE_UBERINTERVAL(interval);
3330 sup = ase_interval_type(interval);
3331 sub = ase_interval_type(object);
3333 if ((relf = ase_optable_superset[sup][sub]))
3334 return relf(interval, object);
3339 DEFUN("ase-interval-connected-p", Fase_interval_connected_p, 0, MANY, 0, /*
3340 Return non-`nil' iff INTERVALS are connected.
3341 Arguments: &rest intervals
3343 Zero intervals are trivially connected, as is one interval.
3345 (int nargs, Lisp_Object *args))
3351 switch (ase_interval_check_dimensions(nargs, args)) {
3355 return ase_interval_connected_p_heapify(nargs, args);
3357 signal_error(Qembed_error, Qnil);
3360 return ase_interval_connected_p_nsquare(nargs, args);
3364 DEFUN("ase-interval-disjoint-p", Fase_interval_disjoint_p, 0, MANY, 0, /*
3365 Arguments: &rest intervals
3366 Return non-`nil' iff INTERVALS are (pairwise) disjoint.
3368 Zero intervals are trivially disjoint, while one interval is
3369 trivially not disjoint.
3371 (int nargs, Lisp_Object *args))
3377 switch (ase_interval_check_dimensions(nargs, args)) {
3381 signal_error(Qembed_error, Qnil);
3384 return ase_interval_disjoint_p_nsquare(nargs, args);
3388 DEFUN("ase-interval-equal-p", Fase_interval_equal_p, 2, 2, 0, /*
3389 Return non-`nil' if I1 and I2 are equal in some sense, equality
3390 hereby means that I1 and I2 contain each other.
3392 In fact, this is just a convenience function and totally equivalent
3394 (and (ase-interval-contains-p i1 i2) (ase-interval-contains-p i2 i1))
3398 Lisp_Object i1in2, i2in1;
3400 CHECK_ASE_UBERINTERVAL(i1);
3401 CHECK_ASE_UBERINTERVAL(i2);
3403 i1in2 = Fase_interval_contains_p(i1, i2);
3404 i2in1 = Fase_interval_contains_p(i2, i1);
3406 if (!NILP(i1in2) && !NILP(i2in1))
3412 /* more constructors */
3414 ase_interval_union_heapify(int nargs, Lisp_Object *args)
3416 Lisp_Object result = Qnil, *newargs;
3418 struct ase_interval_union_item_s _ures, *ures = &_ures, *u;
3419 ase_interval_union_t ires;
3421 /* check for ASE_INTERVALs and sort empty intervals to the tail */
3422 for (j = 0; j < nargs; ) {
3423 if (ASE_INTERVAL_UNION_P(args[j])) {
3424 /* remember the number of additional elements we need */
3425 add += XASE_INTERVAL_UNION(args[j])->no_intv-1;
3427 } else if (!ASE_INTERVAL_EMPTY_P(args[j])) {
3430 _ase_swap(args, nargs-1, j);
3436 return Qase_empty_interval;
3441 EMOD_ASE_DEBUG_INTV("exploding %d union items\n", add);
3442 newargs = alloca_array(Lisp_Object, nargs+add);
3443 /* move the first nargs args here */
3444 memmove(newargs, args, nargs*sizeof(Lisp_Object));
3445 /* now explode the whole story */
3446 args = _ase_interval_union_explode_array(nargs, newargs, add);
3450 /* sort intervals in less-p metric */
3451 _ase_heapsort(nargs, args, ase_interval_less_p);
3453 /* we start with the empty union and unite left-associatively from
3455 ures->current = Qase_empty_interval;
3456 u = ures->next = _ase_make_interval_union_item(args[0]);
3457 for (j = 1; j < nargs; j++) {
3458 u = u->next = _ase_make_interval_union_item(args[j]);
3461 j = _ase_normalise_union(ures);
3463 /* only return a union when there _is_ a union */
3464 ires = _ase_make_interval_union(ures->next);
3467 XSETASE_INTERVAL_UNION(result, ires);
3470 /* otherwise downgrade to a primitive interval */
3471 result = ures->next->current;
3472 _ase_interval_union_item_fini(ures->next);
3477 static inline Lisp_Object
3478 ase_interval_union_nsquare(int nargs, Lisp_Object *args)
3481 struct ase_interval_union_item_s _ures, *ures = &_ures, *u;
3482 ase_interval_union_t ires;
3483 Lisp_Object result = Qnil;
3486 return Qase_empty_interval;
3487 else if (nargs == 1)
3490 /* the slow approach */
3491 /* we start with the empty union and unite left-associatively from
3493 ures->current = Qase_empty_interval;
3495 for (i = 0; i < nargs; i++) {
3496 Lisp_Object tmp = args[i];
3497 if (ASE_INTERVAL_INTERIOR_P(tmp))
3498 u = u->next = _ase_make_interval_union_item(tmp);
3499 else if (ASE_INTERVAL_UNION_P(tmp)) {
3500 ase_interval_union_item_t tra =
3501 XASE_INTERVAL_UNION_SER(tmp);
3503 Lisp_Object c = tra->current;
3504 u = u->next = _ase_make_interval_union_item(c);
3510 j = _ase_normalise_union_intr(ures);
3512 /* only return a union when there _is_ a union */
3513 ires = _ase_make_interval_union(ures->next);
3516 XSETASE_INTERVAL_UNION(result, ires);
3519 /* otherwise downgrade to a primitive interval */
3520 result = ures->next->current;
3521 _ase_interval_union_item_fini(ures->next);
3526 DEFUN("ase-interval-union", Fase_interval_union, 0, MANY, 0, /*
3527 Arguments: &rest intervals
3528 Return the union of all INTERVALS.
3530 (int nargs, Lisp_Object *args))
3536 return Qase_empty_interval;
3538 dim = ase_interval_check_dimensions(nargs, args);
3541 return Qase_empty_interval;
3543 return ase_interval_union_heapify(nargs, args);
3545 signal_error(Qembed_error, Qnil);
3548 return ase_interval_union_nsquare(nargs, args);
3553 ase_interval_intersection_maybe_empty(int nargs, Lisp_Object *args)
3555 /* check for empty intervals, return 1 if there are some */
3558 for (j = 0; j < nargs; j++) {
3559 if (ASE_INTERVAL_EMPTY_P(args[j])) {
3567 ase_interval_intersection_heapify(int nargs, Lisp_Object *args)
3572 return Qase_empty_interval;
3573 else if (nargs == 1)
3575 else if (ase_interval_intersection_maybe_empty(nargs, args))
3576 return Qase_empty_interval;
3578 _ase_heapsort(nargs, args, ase_interval_or_union_less_p);
3580 /* we start with the universe and intersect left-associatively from
3582 for (j = 1; j < nargs; j++) {
3583 ase_interval_type_t t1 = ase_interval_type(args[0]);
3584 ase_interval_type_t t2 = ase_interval_type(args[j]);
3585 ase_binary_operation_f opf = ase_optable_intersect[t1][t2];
3588 args[0] = opf(args[0], args[j]);
3596 ase_interval_intersection_nsquare(int nargs, Lisp_Object *args)
3601 return Qase_empty_interval;
3602 else if (nargs == 1)
3604 else if (ase_interval_intersection_maybe_empty(nargs, args))
3605 return Qase_empty_interval;
3607 /* we start with the universe and intersect left-associatively from
3609 for (j = 1; j < nargs; j++) {
3610 ase_interval_type_t t1 = ase_interval_type(args[0]);
3611 ase_interval_type_t t2 = ase_interval_type(args[j]);
3612 ase_binary_operation_f opf = ase_optable_intersect[t1][t2];
3615 args[0] = opf(args[0], args[j]);
3622 DEFUN("ase-interval-intersection", Fase_interval_intersection, 0, MANY, 0, /*
3623 Arguments: &rest intervals
3624 Return the intersection of all INTERVALS.
3626 (int nargs, Lisp_Object *args))
3630 return Qase_empty_interval;
3631 else if (nargs == 1)
3634 switch (ase_interval_check_dimensions(nargs, args)) {
3636 return Qase_empty_interval;
3638 return ase_interval_intersection_heapify(nargs, args);
3640 signal_error(Qembed_error, Qnil);
3643 return ase_interval_intersection_nsquare(nargs, args);
3647 static inline Lisp_Object
3648 ase_interval_difference_nsquare(int nargs, Lisp_Object *args)
3652 /* check for ASE_INTERVALs and sort empty intervals to the tail */
3653 for (j = 1; j < nargs; j++) {
3654 /* we can only resort empty intervals for j >= 1 */
3655 if (ASE_INTERVAL_EMPTY_P(args[j])) {
3656 _ase_swap(args, nargs-1, j);
3662 return Qase_empty_interval;
3666 /* we must not use heapsort here, since subtracting sets is
3667 * not commutative */
3669 /* we start with args[0] and subtract left-associatively from
3671 for (j = 1; j < nargs; j++) {
3672 ase_interval_type_t t1 = ase_interval_type(args[0]);
3673 ase_interval_type_t t2 = ase_interval_type(args[j]);
3674 ase_binary_operation_f opf = ase_optable_subtract[t1][t2];
3677 args[0] = opf(args[0], args[j]);
3684 DEFUN("ase-interval-difference", Fase_interval_difference, 0, MANY, 0, /*
3685 Arguments: &rest intervals
3686 Return the difference of all INTERVALS from left to right.
3688 (int nargs, Lisp_Object *args))
3690 /* Treat the case args[0] = ( ) specially */
3692 return Qase_empty_interval;
3693 else if (nargs == 1)
3696 switch (ase_interval_check_dimensions(nargs, args)) {
3698 return Qase_empty_interval;
3700 signal_error(Qembed_error, Qnil);
3703 return ase_interval_difference_nsquare(nargs, args);
3707 DEFUN("ase-copy-interval", Fase_copy_interval, 1, 1, 0, /*
3708 Return a copy of INTERVAL.
3712 CHECK_ASE_INTERVAL(interval);
3714 return ase_copy_interval(interval);
3717 DEFUN("ase-interval-boundary", Fase_interval_boundary, 1, 1, 0, /*
3718 Return the boundary of INTERVAL, that is the interior of INTERVAL
3719 subtracted from the closure of INTERVAL.
3723 CHECK_ASE_UBERINTERVAL(interval);
3725 if (ASE_INTERVAL_EMPTY_P(interval))
3726 return Qase_empty_interval;
3727 else if (ASE_INTERVALP(interval))
3728 return ase_interval_boundary(interval);
3729 else if (ASE_INTERVAL_INTERIOR_P(interval))
3730 return ase_interval_interior_boundary(interval);
3731 else if (ASE_INTERVAL_UNION_P(interval))
3732 return ase_interval_union_boundary(interval);
3737 DEFUN("ase-interval-closure", Fase_interval_closure, 1, 1, 0, /*
3738 Return the closure of INTERVAL, that is the smallest closed set
3739 that contains INTERVAL.
3743 CHECK_ASE_UBERINTERVAL(interval);
3745 if (ASE_INTERVAL_EMPTY_P(interval))
3746 return Qase_empty_interval;
3747 else if (ASE_INTERVALP(interval))
3748 return ase_interval_closure(interval);
3749 else if (ASE_INTERVAL_INTERIOR_P(interval))
3750 return ase_interval_interior_closure(interval);
3751 else if (ASE_INTERVAL_UNION_P(interval))
3752 return ase_interval_union_closure(interval);
3757 DEFUN("ase-interval-interior", Fase_interval_interior, 1, 1, 0, /*
3758 Return the interior of INTERVAL, that is the largest open set that
3759 is contained in INTERVAL.
3763 CHECK_ASE_UBERINTERVAL(interval);
3765 if (ASE_INTERVAL_EMPTY_P(interval))
3766 return Qase_empty_interval;
3767 else if (ASE_INTERVALP(interval))
3768 return ase_interval_interior(interval);
3769 else if (ASE_INTERVAL_INTERIOR_P(interval))
3770 return ase_interval_interior_interior(interval);
3771 else if (ASE_INTERVAL_UNION_P(interval))
3772 return ase_interval_union_interior(interval);
3778 DEFUN("ase-interval-lower", Fase_interval_lower, 1, 1, 0, /*
3779 Return the lower bound of INTERVAL or `nil' if empty.
3780 Only the numerical value is returned.
3784 CHECK_ASE_INTERVAL(interval);
3786 if (ASE_INTERVAL_EMPTY_P(interval))
3789 return XASE_INTERVAL(interval)->lower;
3792 DEFUN("ase-interval-upper", Fase_interval_upper, 1, 1, 0, /*
3793 Return the upper bound of INTERVAL or `nil' if empty.
3794 Only the numerical value is returned.
3798 CHECK_ASE_INTERVAL(interval);
3800 if (ASE_INTERVAL_EMPTY_P(interval))
3803 return XASE_INTERVAL(interval)->upper;
3806 DEFUN("ase-interval-lower*", Fase_interval_lower_, 1, 1, 0, /*
3807 Return the lower bound of INTERVAL or `nil' if empty
3808 along with the boundary shape.
3814 CHECK_ASE_INTERVAL(interval);
3815 if (ASE_INTERVAL_EMPTY_P(interval))
3818 res = XASE_INTERVAL(interval)->lower;
3819 if (XASE_INTERVAL(interval)->lower_open_p)
3820 return Fcons(Q_open, res);
3822 return Fcons(Q_closed, res);
3825 DEFUN("ase-interval-upper*", Fase_interval_upper_, 1, 1, 0, /*
3826 Return the upper bound of INTERVAL or `nil' if empty
3827 along with the boundary shape.
3833 CHECK_ASE_INTERVAL(interval);
3834 if (ASE_INTERVAL_EMPTY_P(interval))
3837 res = XASE_INTERVAL(interval)->upper;
3838 if (XASE_INTERVAL(interval)->upper_open_p)
3839 return Fcons(Q_open, res);
3841 return Fcons(Q_closed, res);
3844 DEFUN("ase-interval-explode-union", Fase_interval_explode_union, 1, 1, 0, /*
3845 Return IUNION exploded into primitive intervals and listed in a dllist.
3849 Lisp_Object result = Qnil;
3850 dllist_t resdll = make_dllist();
3851 ase_interval_union_item_t u;
3853 CHECK_ASE_INTERVAL_UNION(iunion);
3854 u = XASE_INTERVAL_UNION_SER(iunion);
3856 dllist_append(resdll, (void*)u->current);
3860 XSETDLLIST(result, resdll);
3866 DEFUN("ase-interval-lebesgue-measure",
3867 Fase_interval_lebesgue_measure, 1, 1, 0, /*
3868 Return the Lebesgue measure of INTERVAL.
3872 CHECK_ASE_UBERINTERVAL(interval);
3874 if (ASE_INTERVALP(interval))
3875 return ase_interval_lebesgue_measure(XASE_INTERVAL(interval));
3876 else if (ASE_INTERVAL_INTERIOR_P(interval))
3877 return ase_interval_interior_lebesgue_measure(
3878 XASE_CARTESIAN(interval));
3879 else if (ASE_INTERVAL_UNION_P(interval))
3880 return ase_interval_union_lebesgue_measure(
3881 XASE_INTERVAL_UNION(interval));
3885 DEFUN("ase-interval-rational-measure",
3886 Fase_interval_rational_measure, 1, 1, 0, /*
3887 Return the number of rational integers in INTERVAL.
3891 CHECK_ASE_UBERINTERVAL(interval);
3893 if (ASE_INTERVALP(interval))
3894 return ase_interval_rational_measure(XASE_INTERVAL(interval));
3895 else if (ASE_INTERVAL_INTERIOR_P(interval))
3896 return ase_interval_interior_rational_measure(
3897 XASE_CARTESIAN(interval));
3898 else if (ASE_INTERVAL_UNION_P(interval))
3899 return ase_interval_union_rational_measure(
3900 XASE_INTERVAL_UNION(interval));
3904 DEFUN("ase-interval-dump", Fase_interval_dump, 1, 1, 0, /*
3908 CHECK_ASE_INTERVAL_OR_UNION(interval);
3910 if (ASE_INTERVALP(interval)) {
3911 ase_interval_prnt(interval, Qexternal_debugging_output, 0);
3912 write_c_string("\n", Qexternal_debugging_output);
3915 ase_interval_union_prnt(
3916 interval, Qexternal_debugging_output, 0);
3917 write_c_string("\n", Qexternal_debugging_output);
3923 static inline Lisp_Object
3924 ase_interval_add_i_obj(Lisp_Object intv, Lisp_Object number)
3926 int lopenp = XASE_INTERVAL(intv)->lower_open_p;
3927 int uopenp = XASE_INTERVAL(intv)->upper_open_p;
3928 int lequp = XASE_INTERVAL(intv)->lower_eq_upper_p;
3929 Lisp_Object args[2] = {Qnil, number};
3930 Lisp_Object newl, newu;
3932 args[0] = XASE_INTERVAL(intv)->lower;
3933 newl = ent_binop(ASE_BINARY_OP_SUM, args[0], args[1]);
3935 args[0] = XASE_INTERVAL(intv)->upper;
3936 newu = ent_binop(ASE_BINARY_OP_SUM, args[0], args[1]);
3937 return ase_make_interval(newl, newu, lopenp, uopenp);
3939 return ase_make_interval(newl, newl, lopenp, uopenp);
3943 static inline Lisp_Object
3944 ase_interval_add_obj_i(Lisp_Object number, Lisp_Object intv)
3946 return ase_interval_add_i_obj(intv, number);
3950 /* initialiser stuff */
3952 ase_interval_binary_optable_init(void)
3954 int idx = ase_optable_index_typesym(Qase_interval);
3955 ent_binop_register(ASE_BINARY_OP_SUM,
3956 idx, INT_T, ase_interval_add_i_obj);
3957 ent_binop_register(ASE_BINARY_OP_SUM,
3958 INT_T, idx, ase_interval_add_obj_i);
3959 ent_binop_register(ASE_BINARY_OP_SUM,
3960 idx, FLOAT_T, ase_interval_add_obj_i);
3961 ent_binop_register(ASE_BINARY_OP_SUM,
3962 FLOAT_T, idx, ase_interval_add_obj_i);
3969 DEFSUBR(Fase_empty_interval);
3970 DEFSUBR(Fase_universe_interval);
3971 DEFSUBR(Fase_interval);
3972 DEFSUBR(Fase_interval_union);
3973 DEFSUBR(Fase_interval_intersection);
3974 DEFSUBR(Fase_interval_difference);
3975 DEFSUBR(Fase_copy_interval);
3976 DEFSUBR(Fase_interval_boundary);
3977 DEFSUBR(Fase_interval_interior);
3978 DEFSUBR(Fase_interval_closure);
3980 DEFSUBR(Fase_intervalp);
3981 DEFSUBR(Fase_interval_union_p);
3982 DEFSUBR(Fase_interval_empty_p);
3983 DEFSUBR(Fase_interval_imprimitive_p);
3984 DEFSUBR(Fase_interval_open_p);
3985 DEFSUBR(Fase_interval_closed_p);
3986 DEFSUBR(Fase_interval_contains_p);
3987 DEFSUBR(Fase_interval_contains_where);
3988 DEFSUBR(Fase_interval_connected_p);
3989 DEFSUBR(Fase_interval_disjoint_p);
3990 DEFSUBR(Fase_interval_equal_p);
3992 DEFSUBR(Fase_interval_lower);
3993 DEFSUBR(Fase_interval_lower_);
3994 DEFSUBR(Fase_interval_upper);
3995 DEFSUBR(Fase_interval_upper_);
3996 DEFSUBR(Fase_interval_explode_union);
3998 DEFSUBR(Fase_interval_lebesgue_measure);
3999 DEFSUBR(Fase_interval_rational_measure);
4001 DEFASETYPE_WITH_OPS(Qase_interval, "ase:interval");
4002 defsymbol(&Qase_intervalp, "ase:intervalp");
4003 DEFASETYPE_WITH_OPS(Qase_interval_union, "ase:interval-union");
4004 defsymbol(&Qase_interval_union_p, "ase:interval-union-p");
4006 defsymbol(&Q_less, ":<");
4007 defsymbol(&Q_greater, ":>");
4008 defsymbol(&Q_eql, ":=");
4009 DEFKEYWORD(Q_unknown);
4011 DEFKEYWORD(Q_closed);
4012 DEFKEYWORD(Q_disjoint);
4013 DEFKEYWORD(Q_connected);
4016 DEFSUBR(Fase_interval_dump);
4018 ase_interval_binary_optable_init();
4022 DEFVAR_CONST_LISP("ase-empty-interval", &Qase_empty_interval /*
4023 The interval which contains no elements.
4025 DEFVAR_CONST_LISP("ase-universe-interval", &Qase_universe_interval /*
4026 The interval which contains all elements.
4029 Fprovide(intern("ase-interval"));
4034 EMOD_PUBREINIT(void)
4036 Qase_empty_interval = ase_empty_interval();
4037 Qase_universe_interval = ase_universe_interval();
4038 staticpro(&Qase_empty_interval);
4039 staticpro(&Qase_universe_interval);
4041 if (LIKELY(ase_empty_sets != NULL)) {
4042 dllist_append(ase_empty_sets, (void*)Qase_empty_interval);
4044 EMOD_ASE_CRITICAL("Cannot proclaim empty elements\n");
4050 EMOD_PUBDEINIT(void)
4052 Frevoke(intern("ase-interval"));
4056 /* ase-interval ends here */