1 /*** ase-neighbourhood.c -- Neighbourhood of ASE objects
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-neighbourhood.h"
46 #define EMOD_ASE_DEBUG_NBH(args...) EMOD_ASE_DEBUG("[NBH]: " args)
48 #define EMODNAME ase_neighbourhood
50 PROVIDE(ase_neighbourhood);
51 REQUIRE(ase_neighbourhood, "ase", "ase-interval");
53 Lisp_Object Qase_neighbourhood, Qase_neighbourhoodp;
56 /* stuff for the dynacat */
58 _ase_neighbourhood_prnt(ase_neighbourhood_t n, Lisp_Object pcf)
60 write_c_string("{p : (< (d ", pcf);
61 print_internal(n->point, pcf, 0);
62 write_c_string(" p) ", pcf);
63 print_internal(n->radius, pcf, 0);
64 write_c_string("}", pcf);
68 ase_neighbourhood_prnt(Lisp_Object obj, Lisp_Object pcf, int unused)
70 EMOD_ASE_DEBUG_NBH("n:0x%08x@0x%08x (rc:%d)\n",
71 (unsigned int)(XASE_NEIGHBOURHOOD(obj)),
73 (XASE_NEIGHBOURHOOD(obj) ?
74 XASE_NEIGHBOURHOOD_REFVAL(obj) : 1));
75 write_c_string("#<ase:neighbourhood ", pcf);
76 _ase_neighbourhood_prnt(XASE_NEIGHBOURHOOD(obj), pcf);
77 write_c_string(" wrt supremum metric>", pcf);
81 ase_neighbourhood_fini(Lisp_Object obj, int unused)
83 ase_neighbourhood_t n = XASE_NEIGHBOURHOOD(obj);
85 EMOD_ASE_DEBUG_GC("n:0x%08x@0x%08x (rc:%d) shall be freed...\n",
86 (unsigned int)(n), (unsigned int)obj,
87 ase_neighbourhood_refval(n));
89 if (ase_neighbourhood_decref(n) <= 0) {
93 ase_neighbourhood_fini_refcnt(n);
96 EMOD_ASE_DEBUG_GC("VETO! References exist\n");
102 _ase_neighbourhood_mark(ase_neighbourhood_t n)
107 mark_object(n->point);
108 mark_object(n->radius);
109 mark_object(n->lebesgue_measure);
110 mark_object(n->rational_measure);
111 mark_object(n->colour);
114 mark_object(n->ldata);
121 ase_neighbourhood_mark(Lisp_Object obj)
123 EMOD_ASE_DEBUG_NBH("n:0x%08x@0x%08x (rc:%d) shall be marked...\n",
124 (unsigned int)(XASE_NEIGHBOURHOOD(obj)),
126 (XASE_NEIGHBOURHOOD(obj) ?
127 XASE_NEIGHBOURHOOD_REFVAL(obj) : 1));
128 _ase_neighbourhood_mark(XASE_NEIGHBOURHOOD(obj));
134 _ase_wrap_neighbourhood(ase_neighbourhood_t n)
138 result = make_dynacat(n);
139 XDYNACAT(result)->type = Qase_neighbourhood;
142 ase_neighbourhood_incref(n);
144 set_dynacat_printer(result, ase_neighbourhood_prnt);
145 set_dynacat_marker(result, ase_neighbourhood_mark);
146 set_dynacat_finaliser(result, ase_neighbourhood_fini);
148 EMOD_ASE_DEBUG_NBH("n:0x%08x (rc:%d) shall be wrapped to 0x%08x...\n",
150 (n ? ase_neighbourhood_refval(n) : 1),
151 (unsigned int)result);
156 static inline Lisp_Object
157 __ase_make_neighbourhood_intv(Lisp_Object p, Lisp_Object r)
160 Lisp_Object args[2] = {p, r};
162 /* special case r == 0 */
163 if (!NILP(Fzerop(r))) {
164 return ase_make_interval(p, p, 0, 0);
167 lo = Fent_binop_diff(countof(args), args);
168 up = Fent_binop_sum(countof(args), args);
170 return ase_make_interval(lo, up, 1, 1);
174 __ase_make_neighbourhood_intr(Lisp_Object p, Lisp_Object r)
176 Lisp_Object args[2] = {Qnil, r};
177 int i, dim = XASE_CARTESIAN_DIMENSION(p);
178 Lisp_Object *tmp = alloca_array(Lisp_Object, dim);
179 Lisp_Object *pobjs = XASE_CARTESIAN_OBJECTS(p);
181 /* special case r == 0 */
182 if (!NILP(Fzerop(r))) {
183 for (i = 0; i < dim; i++) {
184 tmp[i] = ase_make_interval(pobjs[i], pobjs[i], 0, 0);
186 return ase_make_cartesian(dim, tmp, 1);
189 for (i = 0; i < dim; i++) {
192 lo = Fent_binop_diff(countof(args), args);
193 up = Fent_binop_sum(countof(args), args);
194 tmp[i] = ase_make_interval(lo, up, 1, 1);
196 return ase_make_cartesian(dim, tmp, 1);
199 static ase_neighbourhood_t
200 _ase_make_neighbourhood(Lisp_Object p, Lisp_Object r, void *metric)
202 ase_neighbourhood_t n = NULL;
204 n = xnew(struct ase_neighbourhood_s);
210 n->lebesgue_measure = Qnil;
211 n->rational_measure = Qnil;
214 /* if it's the supremum metric (atm it always is) we use our
215 * fancy interval implementation */
217 n->ldata = __ase_make_neighbourhood_intv(p, r);
218 else if (ASE_CARTESIAN_INTERIOR_P(p))
219 n->ldata = __ase_make_neighbourhood_intr(p, r);
222 /* initialise the reference counter */
223 ase_neighbourhood_init_refcnt(n);
225 EMOD_ASE_DEBUG_NBH("n:%p (rc:0) shall be created...\n", n);
230 ase_make_neighbourhood(Lisp_Object pt, Lisp_Object rad, Lisp_Object metric)
232 ase_neighbourhood_t a = NULL;
233 Lisp_Object result = Qnil;
235 a = _ase_make_neighbourhood(pt, rad, NULL);
236 XSETASE_NEIGHBOURHOOD(result, a);
243 ase_neighbourhood_point(ase_neighbourhood_t n)
249 ase_neighbourhood_radius(ase_neighbourhood_t n)
256 _ase_neighbourhood_update_lebesgue(ase_neighbourhood_t n)
258 if (n && NILP(n->lebesgue_measure)) {
259 Lisp_Object i = n->ldata;
260 n->lebesgue_measure = Fase_interval_lebesgue_measure(i);
265 static inline Lisp_Object
266 _ase_neighbourhood_lebesgue(ase_neighbourhood_t n)
268 return n->lebesgue_measure;
272 ase_neighbourhood_lebesgue_measure(ase_neighbourhood_t n)
274 _ase_neighbourhood_update_lebesgue(n);
275 return _ase_neighbourhood_lebesgue(n);
279 _ase_neighbourhood_update_rational(ase_neighbourhood_t n)
281 if (n && NILP(n->rational_measure)) {
282 Lisp_Object i = n->ldata;
283 n->rational_measure = Fase_interval_rational_measure(i);
288 static inline Lisp_Object
289 _ase_neighbourhood_rational(ase_neighbourhood_t n)
291 return n->rational_measure;
295 ase_neighbourhood_rational_measure(ase_neighbourhood_t n)
297 _ase_neighbourhood_update_rational(n);
298 return _ase_neighbourhood_rational(n);
303 DEFUN("ase-neighbourhoodp", Fase_neighbourhoodp, 1, 1, 0, /*
304 Return non-`nil' iff OBJECT is an ase neighbourhood.
308 if (ASE_NEIGHBOURHOODP(object))
315 DEFUN("ase-neighbourhood", Fase_neighbourhood, 2, 3, 0, /*
316 Return a neighbourhood around with POINT of radius RADIUS
317 with respect to METRIC (optional).
319 If no special metric is given, the supremum metric is used.
321 (point, radius, metric))
323 if (!COMPARABLEP(point) &&
324 !(ASE_CARTESIAN_INTERIOR_P(point))) {
325 dead_wrong_type_argument(Qase_cartesian_interior_p, point);
327 CHECK_COMPARABLE(radius);
329 if (NILP(Fnonnegativep(radius)))
330 return wrong_type_argument(Qnonnegativep, radius);
332 return ase_make_neighbourhood(point, radius, metric);
335 DEFUN("ase-neighbourhood-open-p", Fase_neighbourhood_open_p, 1, 1, 0, /*
336 Return non-`nil' iff NEIGHBOURHOOD is open with respect to its metric.
340 CHECK_ASE_NEIGHBOURHOOD(neighbourhood);
342 if (ase_neighbourhood_open_p(XASE_NEIGHBOURHOOD(neighbourhood)))
348 DEFUN("ase-neighbourhood-closed-p", Fase_neighbourhood_closed_p, 1, 1, 0, /*
349 Return non-`nil' iff NEIGHBOURHOOD is closed with respect to its metric.
353 CHECK_ASE_NEIGHBOURHOOD(neighbourhood);
355 if (ase_neighbourhood_closed_p(XASE_NEIGHBOURHOOD(neighbourhood)))
361 DEFUN("ase-neighbourhood-contains-p", Fase_neighbourhood_contains_p, 2, 2, 0, /*
362 Return non-`nil' iff NEIGHBOURHOOD contains OBJECT.
363 OBJECT may also be another neighbourhood under the restriction that
364 both neighbourhoods must be defined over the same metric space.
366 (neighbourhood, object))
368 CHECK_ASE_NEIGHBOURHOOD(neighbourhood);
370 if (COMPARABLEP(object)) {
371 if (ase_neighbourhood_contains_obj_p(
372 XASE_NEIGHBOURHOOD(neighbourhood), object))
374 } else if (ASE_NEIGHBOURHOODP(object)) {
375 if (ase_neighbourhood_contains_nbh_p(
376 XASE_NEIGHBOURHOOD(neighbourhood),
377 XASE_NEIGHBOURHOOD(object)))
384 DEFUN("ase-neighbourhood-equal-p", Fase_neighbourhood_equal_p, 2, 2, 0, /*
385 Return non-`nil' if N1 and N2 are equal in some sense, equality
386 hereby means that N1 and N2 contain each other.
388 In fact, this is just a convenience function and totally equivalent
390 (and (ase-neighbourhood-contains-p n1 n2)
391 (ase-neighbourhood-contains-p n2 n1))
393 Both neighbourhoods must be defined over the same metric space.
397 Lisp_Object n1in2, n2in1;
399 CHECK_ASE_NEIGHBOURHOOD(n1);
400 CHECK_ASE_NEIGHBOURHOOD(n2);
402 n1in2 = Fase_neighbourhood_contains_p(n1, n2);
403 n2in1 = Fase_neighbourhood_contains_p(n2, n1);
405 if (!NILP(n1in2) && !NILP(n2in1))
411 /* just for now until we can overload <, > and = */
412 DEFUN("ase-neighbourhood-<", Fase_neighbourhood_lssp, 2, 2, 0, /*
419 CHECK_ASE_NEIGHBOURHOOD_OR_COMPARABLE(n1);
420 CHECK_ASE_NEIGHBOURHOOD_OR_COMPARABLE(n2);
422 if (COMPARABLEP(n1) && ASE_NEIGHBOURHOODP(n2)) {
423 cmp = ase_neighbourhood_greater_obj_p(
424 XASE_NEIGHBOURHOOD(n2), n1);
425 } else if (COMPARABLEP(n2) && ASE_NEIGHBOURHOODP(n1)) {
426 cmp = ase_neighbourhood_less_obj_p(
427 XASE_NEIGHBOURHOOD(n1), n2);
428 } else if (ASE_NEIGHBOURHOODP(n1) && ASE_NEIGHBOURHOODP(n2)) {
429 cmp = ase_neighbourhood_less_nbh_p(
430 XASE_NEIGHBOURHOOD(n1), XASE_NEIGHBOURHOOD(n2));
432 return _ase_less_p(n1, n2);
440 DEFUN("ase-neighbourhood->", Fase_neighbourhood_gtrp, 2, 2, 0, /*
447 CHECK_ASE_NEIGHBOURHOOD_OR_COMPARABLE(n1);
448 CHECK_ASE_NEIGHBOURHOOD_OR_COMPARABLE(n2);
450 if (COMPARABLEP(n1) && ASE_NEIGHBOURHOODP(n2)) {
451 cmp = ase_neighbourhood_less_obj_p(
452 XASE_NEIGHBOURHOOD(n2), n1);
453 } else if (COMPARABLEP(n2) && ASE_NEIGHBOURHOODP(n1)) {
454 cmp = ase_neighbourhood_greater_obj_p(
455 XASE_NEIGHBOURHOOD(n1), n2);
456 } else if (ASE_NEIGHBOURHOODP(n1) && ASE_NEIGHBOURHOODP(n2)) {
457 cmp = ase_neighbourhood_greater_nbh_p(
458 XASE_NEIGHBOURHOOD(n1), XASE_NEIGHBOURHOOD(n2));
460 return _ase_less_p(n2, n1);
469 DEFUN("ase-neighbourhood-point", Fase_neighbourhood_point, 1, 1, 0, /*
470 Return the point of NEIGHBOURHOOD which defined it.
474 CHECK_ASE_NEIGHBOURHOOD(neighbourhood);
476 return ase_neighbourhood_point(XASE_NEIGHBOURHOOD(neighbourhood));
479 DEFUN("ase-neighbourhood-radius", Fase_neighbourhood_radius, 1, 1, 0, /*
480 Return the radius of NEIGHBOURHOOD which defined it.
484 CHECK_ASE_NEIGHBOURHOOD(neighbourhood);
486 return ase_neighbourhood_radius(XASE_NEIGHBOURHOOD(neighbourhood));
490 DEFUN("ase-neighbourhood-lebesgue-measure", Fase_neighbourhood_lebesgue_measure, 1, 1, 0, /*
491 Return the Lebesgue measure of NEIGHBOURHOOD.
495 CHECK_ASE_NEIGHBOURHOOD(neighbourhood);
497 return ase_neighbourhood_lebesgue_measure(
498 XASE_NEIGHBOURHOOD(neighbourhood));
501 DEFUN("ase-neighbourhood-rational-measure", Fase_neighbourhood_rational_measure, 1, 1, 0, /*
502 Return the number of rational integers in NEIGHBOURHOOD.
506 CHECK_ASE_NEIGHBOURHOOD(neighbourhood);
508 return ase_neighbourhood_rational_measure(
509 XASE_NEIGHBOURHOOD(neighbourhood));
513 /* initialiser code */
518 DEFSUBR(Fase_neighbourhood);
520 DEFSUBR(Fase_neighbourhoodp);
521 DEFSUBR(Fase_neighbourhood_open_p);
522 DEFSUBR(Fase_neighbourhood_closed_p);
523 DEFSUBR(Fase_neighbourhood_contains_p);
524 DEFSUBR(Fase_neighbourhood_equal_p);
525 DEFSUBR(Fase_neighbourhood_lssp);
526 DEFSUBR(Fase_neighbourhood_gtrp);
528 DEFSUBR(Fase_neighbourhood_point);
529 DEFSUBR(Fase_neighbourhood_radius);
531 DEFSUBR(Fase_neighbourhood_lebesgue_measure);
532 DEFSUBR(Fase_neighbourhood_rational_measure);
534 defsymbol(&Qase_neighbourhood, "ase:neighbourhood");
535 defsymbol(&Qase_neighbourhoodp, "ase:neighbourhoodp");
537 Fprovide(intern("ase-neighbourhood"));
548 Frevoke(intern("ase-neighbourhood"));
551 /* ase-neighbourhood ends here */