3 Copyright (C) 2007 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.
37 /* Synched up with: Not in FSF. */
45 #ifdef ALL_DEBUG_FLAGS
46 #undef EMOD_ASE_DEBUG_FLAG
47 #define EMOD_ASE_DEBUG_FLAG
50 #define EMOD_ASE_DEBUG_HEAP(args...) EMOD_ASE_DEBUG("[HEAP]: " args)
54 Lisp_Object Qase_heap, Qase_heapp;
55 Lisp_Object Qase_yheap, Qase_yheapp;
56 Lisp_Object Qase_dheap, Qase_dheapp;
57 Lisp_Object Qase_wheap, Qase_wheapp;
58 Lisp_Object Qase_heap_default_kind;
60 Lisp_Object Qweak, Qdense, Qdynamic, Q_kind, Q_relation, Q_coloured;
62 #define ASE_HEAP_MIN_SIZE 4096 /* 65536 */
63 #define ALIGNED(n) __attribute__((aligned(n), packed))
66 struct ase_heap_ops_s ase_heap_ops[NUMBER_OF_ASE_HEAP_KINDS] =
67 {{(ase_heap_constr_f)_ase_make_yheap, (ase_heap_wrap_f)_ase_wrap_yheap,
68 (ase_heap_add_f)ase_add_yheap, (ase_heap_pop_f)ase_pop_yheap},
69 {(ase_heap_constr_f)_ase_make_dheap, (ase_heap_wrap_f)_ase_wrap_dheap,
70 (ase_heap_add_f)ase_add_dheap, (ase_heap_pop_f)ase_pop_dheap},
71 {(ase_heap_constr_f)_ase_make_wheap, (ase_heap_wrap_f)_ase_wrap_wheap,
72 (ase_heap_add_f)ase_add_wheap, (ase_heap_pop_f)ase_pop_wheap}};
75 struct ase_yheap_cell_s {
79 ase_yheap_cell_t left;
80 ase_yheap_cell_t right;
82 ase_yheap_cell_t mother;
85 ase_yheap_cell_t prev;
86 ase_yheap_cell_t next;
92 __ase_array_swap(Lisp_Object *d, int idx1, int idx2)
93 __attribute__((always_inline));
95 __ase_array_swap(Lisp_Object *d, int idx1, int idx2)
97 Lisp_Object tmp = d[idx1];
104 _ase_dheap_swap(ase_dheap_t h, int idx1, int idx2)
105 __attribute__((always_inline));
107 _ase_dheap_swap(ase_dheap_t h, int idx1, int idx2)
111 /* swap priority data */
112 d = ase_dheap_cells(h);
113 __ase_array_swap(d, idx1, idx2);
115 if (!ase_heap_opts_coloured(h))
118 /* swap colours too */
119 d = ase_dheap_colours(h);
120 __ase_array_swap(d, idx1, idx2);
125 _ase_wheap_swap(ase_wheap_t h, int idx1, int idx2)
126 __attribute__((always_inline));
128 _ase_wheap_swap(ase_wheap_t h, int idx1, int idx2)
132 /* swap priority data */
133 d = ase_wheap_cells(h);
134 __ase_array_swap(d, idx1, idx2);
136 if (!ase_heap_opts_coloured(h))
139 /* swap colours too */
140 d = ase_wheap_colours(h);
141 __ase_array_swap(d, idx1, idx2);
146 _ase_yheap_cell_swap_data(ase_yheap_cell_t c1, ase_yheap_cell_t c2)
147 __attribute__((always_inline));
149 _ase_yheap_cell_swap_data(ase_yheap_cell_t c1, ase_yheap_cell_t c2)
151 Lisp_Object l1 = ase_yheap_cell_data(c1);
152 Lisp_Object l2 = ase_yheap_cell_data(c2);
154 ase_yheap_cell_data(c1) = l2;
155 ase_yheap_cell_data(c2) = l1;
157 /* for coloured heaps */
158 l1 = ase_yheap_cell_colour(c1);
159 l2 = ase_yheap_cell_colour(c2);
160 ase_yheap_cell_colour(c1) = l2;
161 ase_yheap_cell_colour(c2) = l1;
165 /* stuff for the dynacat, printers */
167 _ase_yheap_prnt_cell(ase_yheap_cell_t c, Lisp_Object pcf)
169 write_c_string(" ", pcf);
170 print_internal(ase_yheap_cell_data(c), pcf, 0);
174 _ase_yheap_prnt(ase_yheap_t a, Lisp_Object pcf)
176 ase_yheap_cell_t c = ase_yheap_root(a);
179 write_c_string(" empty", pcf);
183 while (c && ase_yheap_cell_data(c) != Qnull_pointer) {
184 _ase_yheap_prnt_cell(c, pcf);
185 c = ase_yheap_cell_next(c);
191 ase_yheap_prnt(Lisp_Object obj, Lisp_Object pcf, int SXE_UNUSED(foo))
193 ase_yheap_t h = XASE_YHEAP(obj);
195 EMOD_ASE_DEBUG_HEAP("h:0x%08lx@0x%08lx shall be printed...\n",
196 (long unsigned int)h, (long unsigned int)obj);
197 write_c_string("#<ase:heap :dynamic", pcf);
199 write_c_string(" :size ", pcf);
200 write_fmt_str(pcf, "%u", (unsigned int)ase_yheap_size(h));
202 if (ase_yheap_root(h) != NULL &&
203 ase_yheap_cell_data(ase_yheap_root(h)) != Qnull_pointer) {
204 write_c_string(" :elements", pcf);
205 _ase_yheap_prnt(h, pcf);
207 write_c_string(" :empty>", pcf);
210 write_c_string(">", pcf);
214 _ase_dheap_prnt(ase_dheap_t h, Lisp_Object pcf)
216 size_t size = ase_dheap_size(h);
217 Lisp_Object *d = ase_dheap_cells(h);
220 for (i = 0; i < size; i++) {
221 write_c_string(" ", pcf);
222 print_internal(d[i], pcf, 0);
228 ase_dheap_prnt(Lisp_Object obj, Lisp_Object pcf, int SXE_UNUSED(foo))
230 ase_dheap_t h = XASE_DHEAP(obj);
232 EMOD_ASE_DEBUG_HEAP("d:0x%08lx@0x%08lx shall be printed...\n",
233 (long unsigned int)h, (long unsigned int)obj);
235 write_fmt_str(pcf, "#<ase:heap :dense :size %u",
236 (unsigned int)ase_dheap_size(h));
238 if (ase_heap_opts_coloured(h)) {
239 write_c_string(" :coloured", pcf);
242 if (ase_dheap_size(h)) {
243 write_c_string(" :elements", pcf);
244 _ase_dheap_prnt(h, pcf);
246 write_c_string(" :empty>", pcf);
249 write_c_string(">", pcf);
253 _ase_wheap_prnt(ase_wheap_t h, Lisp_Object pcf)
255 size_t size = ase_wheap_size(h);
256 Lisp_Object *d = ase_wheap_cells(h);
259 for (i = 0; i < size; i++) {
260 write_c_string(" ", pcf);
261 print_internal(d[i], pcf, 0);
267 ase_wheap_prnt(Lisp_Object obj, Lisp_Object pcf, int SXE_UNUSED(foo))
269 ase_wheap_t h = XASE_WHEAP(obj);
271 EMOD_ASE_DEBUG_HEAP("w:0x%08lx@0x%08lx shall be printed...\n",
272 (long unsigned int)h, (long unsigned int)obj);
273 write_fmt_string(pcf, "#<ase:heap :weak :size %u",
274 (unsigned int)ase_wheap_size(h));
276 if (ase_heap_opts_coloured(h)) {
277 write_c_string(" :coloured", pcf);
280 if (ase_wheap_size(h)) {
281 write_c_string(" :elements", pcf);
282 _ase_wheap_prnt(h, pcf);
284 write_c_string(" :empty>", pcf);
287 write_c_string(">", pcf);
291 _ase_yheap_cell_fini(ase_yheap_cell_t c)
292 __attribute__((always_inline));
294 _ase_yheap_cell_fini(ase_yheap_cell_t c)
296 EMOD_ASE_DEBUG_HEAP("c:0x%08lx shall be freed...\n",
297 (long unsigned int)c);
299 memset(c, 0, sizeof(struct ase_yheap_cell_s));
305 _ase_yheap_fini(ase_yheap_t h)
306 __attribute__((always_inline));
308 _ase_yheap_fini(ase_yheap_t h)
312 EMOD_ASE_DEBUG_HEAP("h:0x%08lx freeing used/free cells...\n",
313 (long unsigned int)h);
314 c = ase_yheap_root(h);
316 ase_yheap_cell_t tmp = ase_yheap_cell_next(c);
317 _ase_yheap_cell_fini(c);
322 ase_heap_fini_mutex(h);
323 xfree(ase_heap_options(h));
328 ase_yheap_fini(Lisp_Object obj, int SXE_UNUSED(foo))
330 ase_yheap_t h = XASE_YHEAP(obj);
332 EMOD_ASE_DEBUG_HEAP("h:0x%08lx@0x%08lx shall be freed...\n",
333 (long unsigned int)h, (long unsigned int)obj);
336 memset(h, 0, sizeof(struct ase_yheap_s));
342 _ase_dheap_fini(ase_dheap_t h)
343 __attribute__((always_inline));
345 _ase_dheap_fini(ase_dheap_t h)
348 xfree(ase_dheap_cells(h));
349 if (ase_dheap_colours(h)) {
350 xfree(ase_dheap_colours(h));
353 ase_heap_fini_mutex(h);
354 xfree(ase_heap_options(h));
359 ase_dheap_fini(Lisp_Object obj, int SXE_UNUSED(foo))
361 ase_dheap_t h = XASE_DHEAP(obj);
363 EMOD_ASE_DEBUG_HEAP("d:0x%08lx@0x%08lx shall be freed...\n",
364 (long unsigned int)h, (long unsigned int)obj);
367 memset(h, 0, sizeof(struct ase_dheap_s));
373 _ase_wheap_fini(ase_wheap_t h)
374 __attribute__((always_inline));
376 _ase_wheap_fini(ase_wheap_t h)
379 xfree(ase_wheap_cells(h));
380 xfree(ase_wheap_rbits(h));
381 if (ase_dheap_colours(h)) {
382 xfree(ase_wheap_colours(h));
385 ase_heap_fini_mutex(h);
386 xfree(ase_heap_options(h));
391 ase_wheap_fini(Lisp_Object obj, int SXE_UNUSED(foo))
393 ase_wheap_t h = XASE_WHEAP(obj);
395 EMOD_ASE_DEBUG_HEAP("w:0x%08lx@0x%08lx shall be freed...\n",
396 (long unsigned int)h, (long unsigned int)obj);
399 memset(h, 0, sizeof(struct ase_wheap_s));
405 _ase_yheap_mark_cell(ase_yheap_cell_t c)
407 if (c == NULL || ase_yheap_cell_data(c) == Qnull_pointer)
409 mark_object(ase_yheap_cell_data(c));
410 mark_object(ase_yheap_cell_colour(c));
414 ase_yheap_mark(Lisp_Object obj)
416 ase_yheap_t h = XASE_YHEAP(obj);
417 ase_yheap_cell_t c = ase_yheap_root(h);
419 EMOD_ASE_DEBUG_HEAP("h:0x%08lx@0x%08lx shall be marked...\n",
420 (long unsigned int)h, (long unsigned int)obj);
423 while (c && ase_yheap_cell_data(c) != Qnull_pointer) {
424 _ase_yheap_mark_cell(c);
425 c = ase_yheap_cell_next(c);
432 ase_dheap_mark(Lisp_Object obj)
434 ase_dheap_t h = XASE_DHEAP(obj);
439 EMOD_ASE_DEBUG_HEAP("d:0x%08lx@0x%08lx shall be marked...\n",
440 (long unsigned int)h, (long unsigned int)obj);
443 d = ase_dheap_cells(h);
444 c = ase_dheap_colours(h);
445 size = ase_dheap_size(h);
446 for (i = 0; i < size; i++) {
450 for (i = 0; i < size; i++) {
459 ase_wheap_mark(Lisp_Object obj)
461 ase_wheap_t h = XASE_WHEAP(obj);
466 EMOD_ASE_DEBUG_HEAP("w:0x%08lx@0x%08lx shall be marked...\n",
467 (long unsigned int)h, (long unsigned int)obj);
470 d = ase_wheap_cells(h);
471 c = ase_wheap_colours(h);
472 size = ase_wheap_size(h);
473 for (i = 0; i < size; i++) {
477 for (i = 0; i < size; i++) {
486 static inline ase_yheap_cell_t
487 _ase_make_initial_heap_cell(void)
488 __attribute__((always_inline));
489 static inline ase_yheap_cell_t
490 _ase_make_initial_heap_cell(void)
492 ase_yheap_cell_t c = xnew(struct ase_yheap_cell_s);
494 ase_yheap_cell_data(c) = Qnull_pointer;
495 ase_yheap_cell_colour(c) = Qnil;
496 ase_yheap_cell_left(c) = NULL;
497 ase_yheap_cell_right(c) = NULL;
498 ase_yheap_cell_mother(c) = NULL;
499 ase_yheap_cell_father(c) = NULL;
500 ase_yheap_cell_prev(c) = NULL;
501 ase_yheap_cell_next(c) = NULL;
503 EMOD_ASE_DEBUG_HEAP("c:0x%08lx shall be created...\n",
504 (long unsigned int)c);
508 static inline ase_yheap_cell_t
509 _ase_make_heap_cell(ase_yheap_cell_t mother)
510 __attribute__((always_inline));
511 static inline ase_yheap_cell_t
512 _ase_make_heap_cell(ase_yheap_cell_t mother)
514 ase_yheap_cell_t c = xnew(struct ase_yheap_cell_s);
516 ase_yheap_cell_data(c) = Qnull_pointer;
517 ase_yheap_cell_colour(c) = Qnil;
518 ase_yheap_cell_left(c) = NULL;
519 ase_yheap_cell_right(c) = NULL;
520 ase_yheap_cell_mother(c) = mother;
521 ase_yheap_cell_father(c) = ase_yheap_cell_father(mother);
522 ase_yheap_cell_prev(c) = NULL;
523 ase_yheap_cell_next(c) = NULL;
525 EMOD_ASE_DEBUG_HEAP("c:0x%08lx shall be created...\n",
526 (long unsigned int)c);
531 _ase_wrap_yheap(ase_yheap_t h)
535 result = make_dynacat(h);
536 XDYNACAT(result)->type = Qase_yheap;
538 set_dynacat_printer(result, ase_yheap_prnt);
539 set_dynacat_marker(result, ase_yheap_mark);
540 set_dynacat_finaliser(result, ase_yheap_fini);
541 set_dynacat_intprinter(
542 result, (dynacat_intprinter_f)_ase_yheap_prnt);
544 EMOD_ASE_DEBUG_HEAP("h:0x%08lx shall be wrapped to 0x%08lx...\n",
545 (long unsigned int)h, (long unsigned int)result);
551 _ase_wrap_dheap(ase_dheap_t h)
555 result = make_dynacat(h);
556 XDYNACAT(result)->type = Qase_dheap;
558 set_dynacat_printer(result, ase_dheap_prnt);
559 set_dynacat_marker(result, ase_dheap_mark);
560 set_dynacat_finaliser(result, ase_dheap_fini);
561 set_dynacat_intprinter(
562 result, (dynacat_intprinter_f)_ase_dheap_prnt);
564 EMOD_ASE_DEBUG_HEAP("d:0x%08lx shall be wrapped to 0x%08lx...\n",
565 (long unsigned int)h, (long unsigned int)result);
571 _ase_make_dheap(ase_heap_options_t opts)
573 ase_dheap_t h = xnew(struct ase_dheap_s);
574 size_t all = ase_heap_options_min_size(opts);
578 ase_dheap_size(h) = 0;
579 ase_heap_init_mutex(h);
580 ase_dheap_heapp(h) = 1;
583 ase_heap_options(h) = opts;
585 d = xnew_array_and_zero(Lisp_Object, all);
586 ase_dheap_cells(h) = d;
587 ase_dheap_colours(h) = NULL;
588 ase_dheap_alloc(h) = all;
590 if (ase_heap_options_coloured(opts))
591 ase_dheap_colours(h) = xnew_array_and_zero(Lisp_Object, all);
593 EMOD_ASE_DEBUG_HEAP("d:0x%08lx shall be created...\n",
594 (long unsigned int)h);
599 Lisp_Object ase_make_dheap(ase_heap_options_t opts)
601 ase_dheap_t h = NULL;
603 h = _ase_make_dheap(opts);
604 return _ase_wrap_dheap(h);
608 _ase_wrap_wheap(ase_wheap_t h)
612 result = make_dynacat(h);
613 XDYNACAT(result)->type = Qase_wheap;
615 set_dynacat_printer(result, ase_wheap_prnt);
616 set_dynacat_marker(result, ase_wheap_mark);
617 set_dynacat_finaliser(result, ase_wheap_fini);
618 set_dynacat_intprinter(
619 result, (dynacat_intprinter_f)_ase_wheap_prnt);
621 EMOD_ASE_DEBUG_HEAP("w:0x%08lx shall be wrapped to 0x%08lx...\n",
622 (long unsigned int)h, (long unsigned int)result);
628 _ase_make_wheap(ase_heap_options_t opts)
630 ase_wheap_t h = xnew(struct ase_wheap_s);
631 size_t all = ase_heap_options_min_size(opts);
636 ase_wheap_size(h) = 0;
637 ase_heap_init_mutex(h);
638 ase_wheap_heapp(h) = 1;
641 ase_heap_options(h) = opts;
643 d = xnew_array_and_zero(Lisp_Object, all);
644 r = xnew_array_and_zero(int, all / sizeof(int) / 8);
645 ase_wheap_cells(h) = d;
646 ase_wheap_rbits(h) = r;
647 ase_wheap_colours(h) = NULL;
648 ase_wheap_alloc(h) = all;
650 if (ase_heap_options_coloured(opts))
651 ase_dheap_colours(h) = xnew_array_and_zero(Lisp_Object, all);
653 EMOD_ASE_DEBUG_HEAP("w:0x%08lx shall be created...\n",
654 (long unsigned int)h);
659 Lisp_Object ase_make_wheap(ase_heap_options_t opts)
661 ase_wheap_t h = NULL;
663 h = _ase_make_wheap(opts);
664 return _ase_wrap_wheap(h);
668 _ase_make_yheap(ase_heap_options_t opts)
670 ase_yheap_t h = xnew(struct ase_yheap_s);
674 ase_heap_init_mutex(h);
675 ase_yheap_heapp(h) = 1;
678 ase_heap_options(h) = opts;
680 /* create one empty cell */
681 c = _ase_make_initial_heap_cell();
682 ase_yheap_cell_father(c) = h;
683 ase_yheap_root(h) = NULL;
684 ase_yheap_first_free(h) = ase_yheap_last_free(h) = c;
685 ase_yheap_size(h) = 0;
686 ase_yheap_alloc(h) = 1;
688 EMOD_ASE_DEBUG_HEAP("h:0x%08lx shall be created...\n",
689 (long unsigned int)h);
693 Lisp_Object ase_make_yheap(ase_heap_options_t opts)
695 ase_yheap_t h = NULL;
697 h = _ase_make_yheap(opts);
698 return _ase_wrap_yheap(h);
703 _ase_fixup_heap_cell(ase_yheap_t h, ase_yheap_cell_t c)
704 __attribute__((always_inline));
706 _ase_fixup_heap_cell(ase_yheap_t h, ase_yheap_cell_t c)
708 /* create new free cells */
709 if (ase_yheap_cell_left(c) == NULL &&
710 ase_yheap_cell_right(c) == NULL) {
711 ase_yheap_cell_t l = ase_yheap_last_free(h);
712 ase_yheap_cell_t n = _ase_make_heap_cell(c);
714 ase_yheap_cell_left(c) = n;
716 ase_yheap_cell_prev(n) = l;
717 ase_yheap_cell_next(l) = n;
718 l = ase_yheap_last_free(h) = n;
719 ase_yheap_alloc(h)++;
721 n = _ase_make_heap_cell(c);
722 ase_yheap_cell_right(c) = n;
724 ase_yheap_cell_prev(n) = l;
725 ase_yheap_cell_next(l) = n;
726 ase_yheap_last_free(h) = n;
727 ase_yheap_alloc(h)++;
732 _ase_dheap_realloc(ase_dheap_t h, size_t new_alloc)
733 __attribute__((always_inline));
735 _ase_dheap_realloc(ase_dheap_t h, size_t new_alloc)
737 Lisp_Object *oldd = ase_dheap_cells(h);
738 Lisp_Object *newd = NULL;
739 size_t s = ase_dheap_size(h);
741 newd = xnew_array_and_zero(Lisp_Object, new_alloc);
742 memcpy(newd, oldd, sizeof(Lisp_Object)*s);
744 ase_dheap_cells(h) = newd;
745 ase_dheap_alloc(h) = new_alloc;
747 if (!ase_heap_opts_coloured(h))
750 oldd = ase_dheap_colours(h);
751 newd = xnew_array_and_zero(Lisp_Object, new_alloc);
752 memcpy(newd, oldd, sizeof(Lisp_Object)*s);
754 ase_dheap_colours(h) = newd;
759 _ase_dheap_check_resize(ase_dheap_t h)
760 __attribute__((always_inline));
762 _ase_dheap_check_resize(ase_dheap_t h)
764 size_t s = ase_dheap_size(h), all = ase_dheap_alloc(h);
766 if (s < ase_heap_opts_min_size(h))
770 EMOD_ASE_DEBUG_HEAP("d:0x%08lx upsize from %d to %d\n",
771 (long unsigned int)h,
772 (int)all, (int)(all*2));
773 _ase_dheap_realloc(h, 2*all);
777 EMOD_ASE_DEBUG_HEAP("d:0x%08lx downsize from %d to %d\n",
778 (long unsigned int)h,
779 (int)all, (int)(all/2));
780 _ase_dheap_realloc(h, all/2);
786 _ase_wheap_realloc(ase_wheap_t h, size_t new_alloc)
787 __attribute__((always_inline));
789 _ase_wheap_realloc(ase_wheap_t h, size_t new_alloc)
791 Lisp_Object *oldd = ase_wheap_cells(h);
792 Lisp_Object *newd = NULL;
793 int *oldr = ase_wheap_rbits(h);
795 size_t s = ase_wheap_size(h);
797 newd = xnew_array_and_zero(Lisp_Object, new_alloc);
798 newr = xnew_array_and_zero(int, new_alloc/sizeof(int)/8);
799 memcpy(newd, oldd, sizeof(Lisp_Object)*s);
800 memcpy(newr, oldr, s/8);
803 ase_wheap_cells(h) = newd;
804 ase_wheap_rbits(h) = newr;
805 ase_wheap_alloc(h) = new_alloc;
807 if (!ase_heap_opts_coloured(h))
810 oldd = ase_wheap_colours(h);
811 newd = xnew_array_and_zero(Lisp_Object, new_alloc);
812 memcpy(newd, oldd, sizeof(Lisp_Object)*s);
814 ase_wheap_colours(h) = newd;
819 _ase_wheap_check_resize(ase_wheap_t h)
820 __attribute__((always_inline));
822 _ase_wheap_check_resize(ase_wheap_t h)
824 size_t s = ase_wheap_size(h), all = ase_wheap_alloc(h);
826 if (s < ase_heap_opts_min_size(h))
830 EMOD_ASE_DEBUG_HEAP("w:0x%08lx upsize from %d to %d\n",
831 (long unsigned int)h,
832 (int)all, (int)(all*2));
833 _ase_wheap_realloc(h, 2*all);
837 EMOD_ASE_DEBUG_HEAP("w:0x%08lx downsize from %d to %d\n",
838 (long unsigned int)h,
839 (int)all, (int)(all/2));
840 _ase_wheap_realloc(h, all/2);
845 /* dense heap navigation */
847 ase_dheap_cell_mother(int c)
848 __attribute__((always_inline));
850 ase_dheap_cell_mother(int c)
856 ase_dheap_cell_left(int c)
857 __attribute__((always_inline));
859 ase_dheap_cell_left(int c)
865 ase_dheap_cell_right(int c)
866 __attribute__((always_inline));
868 ase_dheap_cell_right(int c)
873 /* weak heap navigation */
875 ase_wheap_cell_rbit(ase_wheap_t h, int c)
876 __attribute__((always_inline));
878 ase_wheap_cell_rbit(ase_wheap_t h, int c)
880 int *r = ase_wheap_rbits(h);
881 int w = sizeof(int) * 8;
882 int cell = c / w, bit = c % w;
892 ase_wheap_cell_rbit_neg(ase_wheap_t h, int c)
893 __attribute__((always_inline));
895 ase_wheap_cell_rbit_neg(ase_wheap_t h, int c)
897 int *r = ase_wheap_rbits(h);
898 int w = sizeof(int) * 8;
899 int cell = c / w, bit = c % w;
902 return r[cell] ^= bit2;
906 ase_wheap_cell_mother(ase_wheap_t SXE_UNUSED(h), int c)
907 __attribute__((always_inline));
909 ase_wheap_cell_mother(ase_wheap_t SXE_UNUSED(h), int c)
915 ase_wheap_cell_nana(ase_wheap_t h, int c)
916 __attribute__((always_inline));
918 ase_wheap_cell_nana(ase_wheap_t h, int c)
920 /* used to use odd(c), but simpler is odd(c) := c & 1 */
921 while ((c&1) == ase_wheap_cell_rbit(h, (c>>1)))
922 c = ase_wheap_cell_mother(h, c);
923 return ase_wheap_cell_mother(h, c);
927 ase_wheap_cell_left(ase_wheap_t h, int c)
928 __attribute__((always_inline));
930 ase_wheap_cell_left(ase_wheap_t h, int c)
932 return 2*c + ase_wheap_cell_rbit(h, c);
936 ase_wheap_cell_right(ase_wheap_t h, int c)
937 __attribute__((always_inline));
939 ase_wheap_cell_right(ase_wheap_t h, int c)
941 return 2*c + 1 - ase_wheap_cell_rbit(h, c);
946 _ase_yheapify_sink(ase_yheap_cell_t c)
948 /* iterative approach */
949 Lisp_Object cdata = ase_yheap_cell_data(c);
950 ase_yheap_cell_t l, r;
951 ase_binary_relation_t rel = ase_heap_opts_po(ase_yheap_cell_father(c));
953 if (cdata == Qnull_pointer) {
956 while ((l = ase_yheap_cell_left(c))) {
957 Lisp_Object ldata = 0, rdata = 0;
958 ase_yheap_cell_t chosen = l;
961 (ldata = ase_yheap_cell_data(l)) == Qnull_pointer) {
965 if ((r = ase_yheap_cell_right(c)) &&
966 (rdata = ase_yheap_cell_data(r)) &&
967 ent_binrel(rel, rdata, ldata)) {
972 if (ent_binrel(rel, ldata, cdata)) {
973 _ase_yheap_cell_swap_data(c, chosen);
983 _ase_dheapify_sink(ase_dheap_t h, int c)
984 __attribute__((always_inline));
986 _ase_dheapify_sink(ase_dheap_t h, int c)
988 /* iterative approach */
989 size_t size = ase_dheap_size(h);
990 Lisp_Object *d = ase_dheap_cells(h);
991 Lisp_Object cdata = d[c];
992 ase_binary_relation_t rel = ase_heap_opts_po(h);
995 if (cdata == Qnull_pointer) {
998 while ((l = ase_dheap_cell_left(c)) && l < size && d[l]) {
1001 if ((r = l+1) && r < size && d[r] &&
1002 ent_binrel(rel, d[r], d[l])) {
1006 if (ent_binrel(rel, d[chosen], cdata)) {
1007 _ase_dheap_swap(h, c, chosen);
1017 _ase_yheapify(ase_yheap_cell_t c)
1019 Lisp_Object cdata = ase_yheap_cell_data(c);
1020 ase_yheap_cell_t l = ase_yheap_cell_left(c);
1021 ase_yheap_cell_t r = ase_yheap_cell_right(c);
1023 if (cdata == Qnull_pointer || (l == NULL && r == NULL))
1033 _ase_yheapify_sink(c);
1037 ase_yheapify(ase_yheap_t h)
1039 _ase_yheapify(ase_yheap_root(h));
1040 ase_yheap_heapp(h) = 1;
1045 _ase_dheap_sift(ase_dheap_t h, int start, int count)
1046 __attribute__((always_inline));
1048 _ase_dheap_sift(ase_dheap_t h, int start, int count)
1050 int root = start, child;
1051 ase_binary_relation_t po = ase_heap_opts_po(h);
1052 Lisp_Object *d = ase_dheap_cells(h);
1054 while ((child = ase_dheap_cell_left(root)) < count) {
1055 if (child < count-1 &&
1056 ent_binrel(po, d[child], d[child+1])) {
1057 child++; /* choose the right child */
1059 if (ent_binrel(po, d[root], d[child])) {
1060 _ase_dheap_swap(h, root, child);
1070 __ase_wheapify_sink(ase_wheap_t h, int i, int j)
1071 __attribute__((always_inline));
1073 __ase_wheapify_sink(ase_wheap_t h, int i, int j)
1075 /* aka Merge(i, j) in Edelkamp/Wegener's paper */
1076 Lisp_Object *d = ase_wheap_cells(h);
1077 ase_binary_relation_t po = ase_heap_opts_po(h);
1080 EMOD_ASE_DEBUG_HEAP("Merge(%d, %d)\n", i, j);
1081 if ((res = ent_binrel(po, d[j], d[i]))) {
1082 /* swap(nana(idx), idx) */
1083 _ase_wheap_swap(h, i, j);
1084 /* update bit field */
1085 ase_wheap_cell_rbit_neg(h, j);
1091 _ase_wheapify_sink(ase_wheap_t h, int idx)
1092 __attribute__((always_inline));
1094 _ase_wheapify_sink(ase_wheap_t h, int m)
1096 /* aka MergeForest(m) in Edelkamp/Wegener's paper */
1099 EMOD_ASE_DEBUG_HEAP("MergeForest(%d)\n", m);
1103 while ((l = ase_wheap_cell_left(h, x)) < m) {
1108 __ase_wheapify_sink(h, m, x);
1109 /* move on to mother cell */
1110 x = ase_wheap_cell_mother(h, x);
1116 _ase_wheapify(ase_wheap_t h)
1119 for (i = ase_wheap_size(h)-1; i >= 1; i--) {
1120 __ase_wheapify_sink(h, ase_wheap_cell_nana(h, i), i);
1125 ase_wheap_sort(ase_wheap_t h)
1127 int s = ase_wheap_size(h), i, j;
1129 /* normally WeakHeapify is called first
1130 * howbeit, our wheaps always suffice the weak property */
1131 for (--s; s >= 2; s--) {
1132 _ase_wheapify_sink(h, s);
1134 /* now the i-th most extreme value is at index ase_wheap_size-i */
1135 s = (ase_wheap_size(h)+1)>>1;
1136 for (i = 1, j = ase_wheap_size(h)-1; i < s; i++, j--) {
1137 _ase_wheap_swap(h, i, j);
1142 ase_dheap_sort(ase_dheap_t h)
1144 size_t size = ase_dheap_size(h);
1145 int start = size/2 - 1, end = size-1;
1147 while (start >= 0) {
1148 _ase_dheap_sift(h, start, size);
1152 _ase_dheap_swap(h, end, 0);
1153 _ase_dheap_sift(h, 0, end);
1159 #if defined __GNUC__
1161 ase_add_yheap_unwind_protect(Lisp_Object unwind_obj)
1162 __attribute__((unused));
1165 ase_add_yheap_unwind_protect(Lisp_Object unwind_obj)
1167 ase_yheap_t h = get_opaque_ptr(unwind_obj);
1169 free_opaque_ptr(unwind_obj);
1174 ase_add_yheap(ase_yheap_t h, Lisp_Object o, Lisp_Object colour)
1176 ase_yheap_cell_t c, mother;
1178 int speccount = specpdl_depth();
1181 EMOD_ASE_DEBUG_HEAP("c:0x%08lx shall be populated...\n",
1182 (long unsigned int)c);
1185 record_unwind_protect(ase_add_yheap_unwind_protect,
1186 make_opaque_ptr(h));
1190 c = ase_yheap_first_free(h);
1192 EMOD_ASE_CRITICAL("broken heap 0x%08lx\n",
1193 (long unsigned int)h);
1198 ase_yheap_cell_data(c) = o;
1199 ase_yheap_cell_colour(c) = colour;
1201 /* it may violate the heap property now */
1202 ase_yheap_heapp(h) = 0;
1204 if (ase_yheap_cell_left(c) == NULL) {
1205 _ase_fixup_heap_cell(h, c);
1207 ase_yheap_first_free(h) = ase_yheap_cell_next(c);
1208 ase_yheap_size(h)++;
1210 if (ase_yheap_root(h) == NULL) {
1211 ase_yheap_root(h) = c;
1214 /* bottom-up heapify now */
1216 while ((mother = ase_yheap_cell_mother(mother))) {
1217 _ase_yheapify_sink(mother);
1223 #if defined __GNUC__
1225 ase_add_dheap_unwind_protect(Lisp_Object unwind_obj)
1226 __attribute__((unused));
1229 ase_add_dheap_unwind_protect(Lisp_Object unwind_obj)
1231 ase_dheap_t h = get_opaque_ptr(unwind_obj);
1233 free_opaque_ptr(unwind_obj);
1238 ase_add_dheap(ase_dheap_t h, Lisp_Object o, Lisp_Object colour)
1242 int speccount = specpdl_depth();
1246 EMOD_ASE_DEBUG_HEAP("c:%d shall be populated...\n", idx);
1249 record_unwind_protect(ase_add_dheap_unwind_protect,
1250 make_opaque_ptr(h));
1255 mother = idx = ase_dheap_size(h)++;
1256 d = ase_dheap_cells(h);
1257 c = ase_dheap_colours(h);
1264 /* it may violate the heap property now */
1265 ase_dheap_heapp(h) = 0;
1267 /* bottom-up heapify now */
1269 while ((mother = ase_dheap_cell_mother(mother)) != -1) {
1270 _ase_dheapify_sink(h, mother);
1273 _ase_dheap_check_resize(h);
1278 #if defined __GNUC__
1280 ase_add_wheap_unwind_protect(Lisp_Object unwind_obj)
1281 __attribute__((unused));
1284 ase_add_wheap_unwind_protect(Lisp_Object unwind_obj)
1286 ase_wheap_t h = get_opaque_ptr(unwind_obj);
1288 free_opaque_ptr(unwind_obj);
1293 ase_add_wheap(ase_wheap_t h, Lisp_Object o, Lisp_Object colour)
1297 int speccount = specpdl_depth();
1301 EMOD_ASE_DEBUG_HEAP("c:%d shall be populated...\n", idx);
1304 record_unwind_protect(ase_add_wheap_unwind_protect,
1305 make_opaque_ptr(h));
1310 idx = ase_wheap_size(h)++;
1311 d = ase_wheap_cells(h);
1314 if (ase_heap_opts_coloured(h)) {
1315 ase_wheap_colours(h)[idx] = colour;
1318 /* it may violate the heap property now */
1319 ase_wheap_heapp(h) = 0;
1321 /* bottom-up wheapify now */
1323 int nana = ase_wheap_cell_nana(h, idx);
1324 if (!__ase_wheapify_sink(h, nana, idx))
1329 _ase_wheap_check_resize(h);
1334 /* popping (dequeue operation) */
1336 ase_pop_yheap(ase_yheap_t h)
1338 ase_yheap_cell_t rc, c;
1339 Lisp_Object result = Qnil, swap;
1343 rc = ase_yheap_root(h);
1344 if (rc == NULL || ase_yheap_cell_data(rc) == Qnull_pointer) {
1349 if (!ase_heap_opts_coloured(h)) {
1350 result = ase_yheap_cell_data(rc);
1352 result = ase_yheap_cell_colour(rc);
1354 c = ase_yheap_cell_prev(ase_yheap_first_free(h));
1355 swap = ase_yheap_cell_data(c);
1356 ase_yheap_first_free(h) = c;
1357 ase_yheap_size(h)--;
1359 ase_yheap_cell_data(rc) = swap;
1360 ase_yheap_cell_data(c) = Qnull_pointer;
1361 ase_yheap_cell_colour(c) = Qnull_pointer;
1362 _ase_yheapify_sink(rc);
1369 ase_pop_dheap(ase_dheap_t h)
1371 Lisp_Object *d, result;
1376 d = ase_dheap_cells(h);
1378 if (d[0] == Qnull_pointer) {
1383 /* pop off the most extreme element */
1384 if (!ase_heap_opts_coloured(h)) {
1387 result = ase_dheap_colours(h)[0];
1388 ase_dheap_colours(h)[0] = Qnull_pointer;
1391 end_idx = --ase_dheap_size(h);
1392 _ase_dheap_swap(h, 0, end_idx);
1393 d[end_idx] = Qnull_pointer;
1395 /* reestablish heap property */
1396 _ase_dheapify_sink(h, 0);
1397 _ase_dheap_check_resize(h);
1404 ase_pop_wheap(ase_wheap_t h)
1406 Lisp_Object *d, *c, result;
1411 d = ase_wheap_cells(h);
1412 c = ase_wheap_colours(h);
1414 if (d[0] == Qnull_pointer) {
1419 /* pop off the most extreme element */
1420 if (!ase_heap_opts_coloured(h)) {
1426 /* MergeForest(end_idx) */
1427 end_idx = --ase_wheap_size(h);
1428 _ase_wheapify_sink(h, end_idx);
1431 d[end_idx] = Qnull_pointer;
1433 if (ase_heap_opts_coloured(h)) {
1435 c[end_idx] = Qnull_pointer;
1439 _ase_wheap_check_resize(h);
1446 ase_yheap_top(ase_yheap_t h)
1448 ase_yheap_cell_t rc;
1449 Lisp_Object result = Qnil;
1453 rc = ase_yheap_root(h);
1454 if (rc == NULL || ase_yheap_cell_data(rc) == Qnull_pointer) {
1459 /* grab the most extreme element */
1460 if (!ase_heap_opts_coloured(h)) {
1461 result = ase_yheap_cell_data(rc);
1463 result = ase_yheap_cell_colour(rc);
1471 ase_dheap_top(ase_dheap_t h)
1473 Lisp_Object *d, *c, result;
1477 d = ase_dheap_cells(h);
1478 c = ase_dheap_colours(h);
1480 if (d[0] == Qnull_pointer) {
1485 /* grab the most extreme element */
1486 if (!ase_heap_opts_coloured(h)) {
1497 ase_wheap_top(ase_wheap_t h)
1499 Lisp_Object *d, *c, result;
1503 d = ase_wheap_cells(h);
1504 c = ase_wheap_colours(h);
1506 if (d[0] == Qnull_pointer) {
1511 /* grab the most extreme element */
1512 if (!ase_heap_opts_coloured(h)) {
1523 ase_yheap_top_rank(ase_yheap_t h)
1525 ase_yheap_cell_t rc;
1526 Lisp_Object result = Qnil;
1530 rc = ase_yheap_root(h);
1532 result = ase_yheap_cell_data(rc);
1534 if (result != Qnull_pointer) {
1541 ase_dheap_top_rank(ase_dheap_t h)
1543 Lisp_Object *d, result;
1547 d = ase_dheap_cells(h);
1552 if (result != Qnull_pointer) {
1559 ase_wheap_top_rank(ase_wheap_t h)
1561 Lisp_Object *d, result;
1565 d = ase_wheap_cells(h);
1570 if (result != Qnull_pointer) {
1577 static inline Lisp_Object
1578 _ase_heap_to_listX(void *h, ase_heap_pop_f popfun)
1579 __attribute__((always_inline));
1580 static inline Lisp_Object
1581 _ase_heap_to_listX(void *h, ase_heap_pop_f popfun)
1583 Lisp_Object result = Qnil, tmp, trv;
1585 result = trv = Fcons(Qnil, Qnil);
1586 while (!NILP(tmp = popfun(h))) {
1587 trv = (XCDR(trv) = Fcons(tmp, Qnil));
1589 return XCDR(result);
1593 ase_yheap_to_listX(ase_yheap_t h)
1595 return _ase_heap_to_listX(h, (ase_heap_pop_f)ase_pop_yheap);
1599 ase_dheap_to_listX(ase_dheap_t h)
1601 return _ase_heap_to_listX(h, (ase_heap_pop_f)ase_pop_dheap);
1605 ase_wheap_to_listX(ase_wheap_t h)
1607 return _ase_heap_to_listX(h, (ase_heap_pop_f)ase_pop_wheap);
1611 ase_yheap_to_list(ase_yheap_t h)
1613 Lisp_Object res, tmp;
1615 res = tmp = ase_yheap_to_listX(h);
1616 /* now add them all back to the heap */
1617 while (!NILP(tmp)) {
1618 ase_add_yheap(h, XCAR(tmp), Qnil);
1625 ase_dheap_to_list(ase_dheap_t h)
1627 size_t size = ase_yheap_size(h);
1628 Lisp_Object *d = ase_dheap_cells(h);
1629 Lisp_Object result = Qnil;
1633 for (i = size-1; i >= 0; i--) {
1634 result = Fcons(d[i], result);
1640 ase_wheap_to_list(ase_wheap_t h)
1642 size_t size = ase_wheap_size(h);
1643 Lisp_Object *d = ase_wheap_cells(h);
1644 Lisp_Object result = Qnil;
1648 for (i = size-1; i >= 0; i--) {
1649 result = Fcons(d[i], result);
1654 static inline Lisp_Object
1655 _ase_heap_to_vectorX(void *h, ase_heap_pop_f popfun, size_t size)
1656 __attribute__((always_inline));
1657 static inline Lisp_Object
1658 _ase_heap_to_vectorX(void *h, ase_heap_pop_f popfun, size_t size)
1661 Lisp_Object result = make_vector(size, Qnil), tmp;
1663 while (!NILP(tmp = popfun(h))) {
1664 XVECTOR_DATA(result)[i++] = tmp;
1670 ase_yheap_to_vectorX(ase_yheap_t h)
1672 size_t s = ase_yheap_size(h);
1673 return _ase_heap_to_vectorX(h, (ase_heap_pop_f)ase_pop_yheap, s);
1677 ase_dheap_to_vectorX(ase_dheap_t h)
1679 size_t s = ase_dheap_size(h);
1680 return _ase_heap_to_vectorX(h, (ase_heap_pop_f)ase_pop_dheap, s);
1684 ase_wheap_to_vectorX(ase_wheap_t h)
1686 size_t s = ase_wheap_size(h);
1687 return _ase_heap_to_vectorX(h, (ase_heap_pop_f)ase_pop_wheap, s);
1691 ase_yheap_to_vector(ase_yheap_t h)
1696 res = ase_yheap_to_vectorX(h);
1697 /* now add them all back to the heap */
1698 i = XVECTOR_LENGTH(res);
1700 ase_add_yheap(h, XVECTOR_DATA(res)[i], Qnil);
1706 ase_dheap_to_vector(ase_dheap_t h)
1708 size_t size = ase_dheap_size(h);
1709 Lisp_Object *d = ase_dheap_cells(h);
1710 Lisp_Object result = make_vector(size, Qnil);
1714 for (i = 0; i < size; i++) {
1715 XVECTOR_DATA(result)[i] = d[i];
1721 ase_wheap_to_vector(ase_wheap_t h)
1723 size_t size = ase_wheap_size(h);
1724 Lisp_Object *d = ase_wheap_cells(h);
1725 Lisp_Object result = make_vector(size, Qnil);
1729 for (i = 0; i < size; i++) {
1730 XVECTOR_DATA(result)[i] = d[i];
1735 static inline Lisp_Object
1736 _ase_heap_to_dllistX(void *h, ase_heap_pop_f popfun)
1737 __attribute__((always_inline));
1738 static inline Lisp_Object
1739 _ase_heap_to_dllistX(void *h, ase_heap_pop_f popfun)
1741 dllist_t resdll = make_dllist();
1742 Lisp_Object result = Qnil, tmp;
1744 while (!NILP(tmp = popfun(h))) {
1745 dllist_append(resdll, (void*)tmp);
1748 XSETDLLIST(result, resdll);
1753 ase_yheap_to_dllistX(ase_yheap_t h)
1755 return _ase_heap_to_dllistX(h, (ase_heap_pop_f)ase_pop_yheap);
1759 ase_dheap_to_dllistX(ase_dheap_t h)
1761 return _ase_heap_to_dllistX(h, (ase_heap_pop_f)ase_pop_dheap);
1765 ase_wheap_to_dllistX(ase_wheap_t h)
1767 return _ase_heap_to_dllistX(h, (ase_heap_pop_f)ase_pop_wheap);
1771 ase_yheap_to_dllist(ase_yheap_t h)
1775 res = ase_yheap_to_dllistX(h);
1776 /* now add them all back to the heap */
1777 WITH_DLLIST_TRAVERSE(
1779 ase_add_yheap(h, (Lisp_Object)dllist_item, Qnil));
1784 ase_dheap_to_dllist(ase_dheap_t h)
1786 size_t size = ase_dheap_size(h);
1787 Lisp_Object *d = ase_dheap_cells(h);
1788 Lisp_Object result = Qnil;
1789 dllist_t resdll = make_dllist();
1793 for (i = 0; i < size; i++) {
1794 dllist_append(resdll, (void*)d[i]);
1797 XSETDLLIST(result, resdll);
1802 ase_wheap_to_dllist(ase_wheap_t h)
1804 size_t size = ase_wheap_size(h);
1805 Lisp_Object *d = ase_wheap_cells(h);
1806 Lisp_Object result = Qnil;
1807 dllist_t resdll = make_dllist();
1811 for (i = 0; i < size; i++) {
1812 dllist_append(resdll, (void*)d[i]);
1815 XSETDLLIST(result, resdll);
1819 static inline ase_heap_kind_t
1820 ase_determine_heap_kind(Lisp_Object o)
1821 __attribute__((always_inline));
1822 static inline ase_heap_kind_t
1823 ase_determine_heap_kind(Lisp_Object o)
1826 return ASE_HEAP_WEAK;
1827 } else if (EQ(o, Qdense)) {
1828 return ASE_HEAP_DENSE;
1829 } else if (EQ(o, Qdynamic)) {
1830 return ASE_HEAP_DYNAMIC;
1833 return ASE_HEAP_WEAK;
1838 DEFUN("ase-heap", Fase_heap, 0, MANY, 0, /*
1839 Return a new heap object.
1841 Arguments: &rest keys
1842 :kind kind of the heap, can be one of 'weak (default), 'dense, or 'dynamic
1845 (int nargs, Lisp_Object *args))
1847 ase_heap_options_t opts = xnew(struct ase_heap_options_s);
1848 ase_heap_constr_f constrf;
1849 ase_heap_wrap_f wrapf;
1850 ase_heap_kind_t kind;
1853 /* standard options */
1854 ase_heap_options_po(opts) = ASE_BINARY_REL_GREATERP;
1855 ase_heap_options_pof(opts) = NULL;
1856 kind = ase_heap_options_kind(opts) =
1857 ase_determine_heap_kind(Qase_heap_default_kind);
1858 ase_heap_options_min_size(opts) = ASE_HEAP_MIN_SIZE;
1859 ase_heap_options_coloured(opts) = 0;
1861 for (i = 0; i < nargs-1; i++) {
1862 if (EQ(args[i], Q_kind)) {
1863 kind = ase_heap_options_kind(opts) =
1864 ase_determine_heap_kind(args[++i]);
1866 if (EQ(args[i], Q_relation)) {
1868 if (EQ(args[i], Q_coloured)) {
1869 if (!NILP(args[++i]))
1870 ase_heap_options_coloured(opts) = 1;
1874 constrf = ase_heap_ops[kind].constrf;
1875 wrapf = ase_heap_ops[kind].wrapf;
1876 return wrapf(constrf(opts));
1879 DEFUN("ase-add-heap", Fase_add_heap, 2, 3, 0, /*
1880 Add OBJECT to HEAP and (optionally) COLOUR it.
1882 (heap, object, colour))
1885 ase_heap_add_f addfun = NULL;
1887 CHECK_ASE_HEAP(heap);
1889 if (ASE_WHEAPP(heap)) {
1890 addfun = ase_heap_ops[ASE_HEAP_WEAK].addf;
1891 h = XASE_WHEAP(heap);
1892 } else if (ASE_DHEAPP(heap)) {
1893 addfun = ase_heap_ops[ASE_HEAP_DENSE].addf;
1894 h = XASE_DHEAP(heap);
1895 } else if (ASE_YHEAPP(heap)) {
1896 addfun = ase_heap_ops[ASE_HEAP_DYNAMIC].addf;
1897 h = XASE_YHEAP(heap);
1899 addfun(h, object, colour);
1903 DEFUN("ase-pop-heap", Fase_pop_heap, 1, 1, 0, /*
1904 Pop off and return the most extreme element of HEAP.
1909 ase_heap_pop_f popfun = NULL;
1911 CHECK_ASE_HEAP(heap);
1913 if (ASE_WHEAPP(heap)) {
1914 popfun = ase_heap_ops[ASE_HEAP_WEAK].popf;
1915 h = XASE_WHEAP(heap);
1916 } else if (ASE_DHEAPP(heap)) {
1917 popfun = ase_heap_ops[ASE_HEAP_DENSE].popf;
1918 h = XASE_DHEAP(heap);
1919 } else if (ASE_YHEAPP(heap)) {
1920 popfun = ase_heap_ops[ASE_HEAP_DYNAMIC].popf;
1921 h = XASE_YHEAP(heap);
1927 /* convenience funs */
1928 DEFUN("ase-heap-size", Fase_heap_size, 1, 1, 0, /*
1929 Return the number of elements inside HEAP.
1933 CHECK_ASE_HEAP(heap);
1935 if (ASE_WHEAPP(heap)) {
1936 return make_int(ase_wheap_size(XASE_WHEAP(heap)));
1937 } else if (ASE_DHEAPP(heap)) {
1938 return make_int(ase_dheap_size(XASE_DHEAP(heap)));
1939 } else if (ASE_YHEAPP(heap)) {
1940 return make_int(ase_yheap_size(XASE_YHEAP(heap)));
1942 return Qnull_pointer;
1945 DEFUN("ase-heap-top", Fase_heap_top, 1, 1, 0, /*
1946 Return the topmost element of HEAP.
1950 CHECK_ASE_HEAP(heap);
1952 if (ASE_WHEAPP(heap)) {
1953 return ase_wheap_top(XASE_WHEAP(heap));
1954 } else if (ASE_DHEAPP(heap)) {
1955 return ase_dheap_top(XASE_DHEAP(heap));
1956 } else if (ASE_YHEAPP(heap)) {
1957 return ase_yheap_top(XASE_YHEAP(heap));
1959 return Qnull_pointer;
1962 DEFUN("ase-heap-top-rank", Fase_heap_top_rank, 1, 1, 0, /*
1963 Return the rank (priority) of the topmost element of HEAP.
1967 CHECK_ASE_HEAP(heap);
1969 if (ASE_WHEAPP(heap)) {
1970 return ase_wheap_top_rank(XASE_WHEAP(heap));
1971 } else if (ASE_DHEAPP(heap)) {
1972 return ase_dheap_top_rank(XASE_DHEAP(heap));
1973 } else if (ASE_YHEAPP(heap)) {
1974 return ase_yheap_top_rank(XASE_YHEAP(heap));
1976 return Qnull_pointer;
1979 DEFUN("ase-heap-to-list", Fase_heap_to_list, 1, 1, 0, /*
1980 Return a (sorted) list with the elements of HEAP.
1981 HEAP is kept alive. See also `ase-heap-to-list*'
1985 CHECK_ASE_HEAP(heap);
1986 if (ASE_WHEAPP(heap)) {
1987 return ase_wheap_to_list(XASE_WHEAP(heap));
1988 } else if (ASE_DHEAPP(heap)) {
1989 return ase_dheap_to_list(XASE_DHEAP(heap));
1990 } else if (ASE_YHEAPP(heap)) {
1991 return ase_yheap_to_list(XASE_YHEAP(heap));
1993 return Qnull_pointer;
1996 DEFUN("ase-heap-to-list*", Fase_heap_to_listX, 1, 1, 0, /*
1997 Return a (sorted) list with the elements of HEAP.
1998 HEAP is destroyed by side-effect, each element from HEAP is
1999 popped off and consed to the result list.
2003 CHECK_ASE_HEAP(heap);
2004 if (ASE_WHEAPP(heap)) {
2005 return ase_wheap_to_listX(XASE_WHEAP(heap));
2006 } else if (ASE_DHEAPP(heap)) {
2007 return ase_dheap_to_listX(XASE_DHEAP(heap));
2008 } else if (ASE_YHEAPP(heap)) {
2009 return ase_yheap_to_listX(XASE_YHEAP(heap));
2011 return Qnull_pointer;
2014 DEFUN("ase-heap-to-vector", Fase_heap_to_vector, 1, 1, 0, /*
2015 Return a (sorted) vector with the elements of HEAP.
2016 HEAP is kept alive hereby. See also `ase-heap-to-vector*'.
2020 CHECK_ASE_HEAP(heap);
2021 if (ASE_WHEAPP(heap)) {
2022 return ase_wheap_to_vector(XASE_WHEAP(heap));
2023 } else if (ASE_DHEAPP(heap)) {
2024 return ase_dheap_to_vector(XASE_DHEAP(heap));
2025 } else if (ASE_YHEAPP(heap)) {
2026 return ase_yheap_to_vector(XASE_YHEAP(heap));
2028 return Qnull_pointer;
2031 DEFUN("ase-heap-to-vector*", Fase_heap_to_vectorX, 1, 1, 0, /*
2032 Return a (sorted) vector with the elements of HEAP.
2033 HEAP is destroyed by side-effect, each element from HEAP is
2034 popped off and written into the result vector.
2038 CHECK_ASE_HEAP(heap);
2039 if (ASE_WHEAPP(heap)) {
2040 return ase_wheap_to_vectorX(XASE_WHEAP(heap));
2041 } else if (ASE_DHEAPP(heap)) {
2042 return ase_dheap_to_vectorX(XASE_DHEAP(heap));
2043 } else if (ASE_YHEAPP(heap)) {
2044 return ase_yheap_to_vectorX(XASE_YHEAP(heap));
2046 return Qnull_pointer;
2049 DEFUN("ase-heap-to-dllist", Fase_heap_to_dllist, 1, 1, 0, /*
2050 Return a (sorted) list with the elements of HEAP.
2051 HEAP is kept intact. See also `ase-heap-to-dllist*'.
2055 CHECK_ASE_HEAP(heap);
2056 if (ASE_WHEAPP(heap)) {
2057 return ase_wheap_to_dllist(XASE_WHEAP(heap));
2058 } else if (ASE_DHEAPP(heap)) {
2059 return ase_dheap_to_dllist(XASE_DHEAP(heap));
2060 } else if (ASE_YHEAPP(heap)) {
2061 return ase_yheap_to_dllist(XASE_YHEAP(heap));
2063 return Qnull_pointer;
2066 DEFUN("ase-heap-to-dllist*", Fase_heap_to_dllistX, 1, 1, 0, /*
2067 Return a (sorted) list with the elements of HEAP.
2068 HEAP is destroyed by side-effect, each element from HEAP is
2069 popped off and appended to the result dllist.
2073 CHECK_ASE_HEAP(heap);
2074 if (ASE_WHEAPP(heap)) {
2075 return ase_wheap_to_dllistX(XASE_WHEAP(heap));
2076 } else if (ASE_DHEAPP(heap)) {
2077 return ase_dheap_to_dllistX(XASE_DHEAP(heap));
2078 } else if (ASE_YHEAPP(heap)) {
2079 return ase_yheap_to_dllistX(XASE_YHEAP(heap));
2081 return Qnull_pointer;
2085 /* initialiser code */
2086 #define EMODNAME ase_heap
2092 DEFSUBR(Fase_add_heap);
2093 DEFSUBR(Fase_pop_heap);
2095 DEFSUBR(Fase_heap_to_list);
2096 DEFSUBR(Fase_heap_to_listX);
2097 DEFSUBR(Fase_heap_to_vector);
2098 DEFSUBR(Fase_heap_to_vectorX);
2099 DEFSUBR(Fase_heap_to_dllist);
2100 DEFSUBR(Fase_heap_to_dllistX);
2102 DEFSUBR(Fase_heap_size);
2103 DEFSUBR(Fase_heap_top);
2104 DEFSUBR(Fase_heap_top_rank);
2106 DEFASETYPE_WITH_OPS(Qase_heap, "ase:heap");
2107 defsymbol(&Qase_heapp, "ase:heapp");
2108 defsymbol(&Qase_yheap, "ase:yheap");
2109 defsymbol(&Qase_yheapp, "ase:yheapp");
2110 defsymbol(&Qase_dheap, "ase:dheap");
2111 defsymbol(&Qase_dheapp, "ase:dheapp");
2112 defsymbol(&Qase_wheap, "ase:wheap");
2113 defsymbol(&Qase_wheapp, "ase:wheapp");
2117 DEFSYMBOL(Qdynamic);
2120 DEFKEYWORD(Q_relation);
2121 DEFKEYWORD(Q_coloured);
2123 Fprovide(intern("ase-heap"));
2125 DEFVAR_LISP("ase:heap-default-kind", &Qase_heap_default_kind /*
2126 *Default kind of newly created heaps.
2130 Qase_heap_default_kind = Qweak;
2134 EMOD_PUBREINIT(void)
2139 EMOD_PUBDEINIT(void)
2141 Frevoke(intern("ase-heap"));
2145 /* ase-heap.c ends here */