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))
65 static inline ase_yheap_t _ase_make_yheap(ase_heap_options_t opts);
66 static inline Lisp_Object _ase_wrap_yheap(ase_yheap_t);
67 static inline ase_dheap_t _ase_make_dheap(ase_heap_options_t opts);
68 static inline Lisp_Object _ase_wrap_dheap(ase_dheap_t);
69 static inline ase_wheap_t _ase_make_wheap(ase_heap_options_t opts);
70 static inline Lisp_Object _ase_wrap_wheap(ase_wheap_t);
73 struct ase_heap_ops_s ase_heap_ops[NUMBER_OF_ASE_HEAP_KINDS] =
74 {{(ase_heap_constr_f)_ase_make_yheap, (ase_heap_wrap_f)_ase_wrap_yheap,
75 (ase_heap_add_f)ase_add_yheap, (ase_heap_pop_f)ase_pop_yheap},
76 {(ase_heap_constr_f)_ase_make_dheap, (ase_heap_wrap_f)_ase_wrap_dheap,
77 (ase_heap_add_f)ase_add_dheap, (ase_heap_pop_f)ase_pop_dheap},
78 {(ase_heap_constr_f)_ase_make_wheap, (ase_heap_wrap_f)_ase_wrap_wheap,
79 (ase_heap_add_f)ase_add_wheap, (ase_heap_pop_f)ase_pop_wheap}};
82 struct ase_yheap_cell_s {
86 ase_yheap_cell_t left;
87 ase_yheap_cell_t right;
89 ase_yheap_cell_t mother;
92 ase_yheap_cell_t prev;
93 ase_yheap_cell_t next;
99 __ase_array_swap(Lisp_Object *d, int idx1, int idx2)
100 __attribute__((always_inline));
102 __ase_array_swap(Lisp_Object *d, int idx1, int idx2)
104 Lisp_Object tmp = d[idx1];
111 _ase_dheap_swap(ase_dheap_t h, int idx1, int idx2)
112 __attribute__((always_inline));
114 _ase_dheap_swap(ase_dheap_t h, int idx1, int idx2)
118 /* swap priority data */
119 d = ase_dheap_cells(h);
120 __ase_array_swap(d, idx1, idx2);
122 if (!ase_heap_opts_coloured(h))
125 /* swap colours too */
126 d = ase_dheap_colours(h);
127 __ase_array_swap(d, idx1, idx2);
132 _ase_wheap_swap(ase_wheap_t h, int idx1, int idx2)
133 __attribute__((always_inline));
135 _ase_wheap_swap(ase_wheap_t h, int idx1, int idx2)
139 /* swap priority data */
140 d = ase_wheap_cells(h);
141 __ase_array_swap(d, idx1, idx2);
143 if (!ase_heap_opts_coloured(h))
146 /* swap colours too */
147 d = ase_wheap_colours(h);
148 __ase_array_swap(d, idx1, idx2);
153 _ase_yheap_cell_swap_data(ase_yheap_cell_t c1, ase_yheap_cell_t c2)
154 __attribute__((always_inline));
156 _ase_yheap_cell_swap_data(ase_yheap_cell_t c1, ase_yheap_cell_t c2)
158 Lisp_Object l1 = ase_yheap_cell_data(c1);
159 Lisp_Object l2 = ase_yheap_cell_data(c2);
161 ase_yheap_cell_data(c1) = l2;
162 ase_yheap_cell_data(c2) = l1;
164 /* for coloured heaps */
165 l1 = ase_yheap_cell_colour(c1);
166 l2 = ase_yheap_cell_colour(c2);
167 ase_yheap_cell_colour(c1) = l2;
168 ase_yheap_cell_colour(c2) = l1;
172 /* stuff for the dynacat, printers */
174 _ase_yheap_prnt_cell(ase_yheap_cell_t c, Lisp_Object pcf)
176 write_c_string(" ", pcf);
177 print_internal(ase_yheap_cell_data(c), pcf, 0);
181 _ase_yheap_prnt(ase_yheap_t a, Lisp_Object pcf)
183 ase_yheap_cell_t c = ase_yheap_root(a);
186 write_c_string(" empty", pcf);
190 while (c && ase_yheap_cell_data(c) != Qnull_pointer) {
191 _ase_yheap_prnt_cell(c, pcf);
192 c = ase_yheap_cell_next(c);
198 ase_yheap_prnt(Lisp_Object obj, Lisp_Object pcf, int SXE_UNUSED(foo))
200 ase_yheap_t h = XASE_YHEAP(obj);
202 EMOD_ASE_DEBUG_HEAP("h:0x%08lx@0x%08lx shall be printed...\n",
203 (long unsigned int)h, (long unsigned int)obj);
204 write_c_string("#<ase:heap :dynamic", pcf);
206 write_c_string(" :size ", pcf);
207 write_fmt_str(pcf, "%u", (unsigned int)ase_yheap_size(h));
209 if (ase_yheap_root(h) != NULL &&
210 ase_yheap_cell_data(ase_yheap_root(h)) != Qnull_pointer) {
211 write_c_string(" :elements", pcf);
212 _ase_yheap_prnt(h, pcf);
214 write_c_string(" :empty>", pcf);
217 write_c_string(">", pcf);
221 _ase_dheap_prnt(ase_dheap_t h, Lisp_Object pcf)
223 size_t size = ase_dheap_size(h);
224 Lisp_Object *d = ase_dheap_cells(h);
227 for (i = 0; i < size; i++) {
228 write_c_string(" ", pcf);
229 print_internal(d[i], pcf, 0);
235 ase_dheap_prnt(Lisp_Object obj, Lisp_Object pcf, int SXE_UNUSED(foo))
237 ase_dheap_t h = XASE_DHEAP(obj);
239 EMOD_ASE_DEBUG_HEAP("d:0x%08lx@0x%08lx shall be printed...\n",
240 (long unsigned int)h, (long unsigned int)obj);
242 write_fmt_str(pcf, "#<ase:heap :dense :size %u",
243 (unsigned int)ase_dheap_size(h));
245 if (ase_heap_opts_coloured(h)) {
246 write_c_string(" :coloured", pcf);
249 if (ase_dheap_size(h)) {
250 write_c_string(" :elements", pcf);
251 _ase_dheap_prnt(h, pcf);
253 write_c_string(" :empty>", pcf);
256 write_c_string(">", pcf);
260 _ase_wheap_prnt(ase_wheap_t h, Lisp_Object pcf)
262 size_t size = ase_wheap_size(h);
263 Lisp_Object *d = ase_wheap_cells(h);
266 for (i = 0; i < size; i++) {
267 write_c_string(" ", pcf);
268 print_internal(d[i], pcf, 0);
274 ase_wheap_prnt(Lisp_Object obj, Lisp_Object pcf, int SXE_UNUSED(foo))
276 ase_wheap_t h = XASE_WHEAP(obj);
278 EMOD_ASE_DEBUG_HEAP("w:0x%08lx@0x%08lx shall be printed...\n",
279 (long unsigned int)h, (long unsigned int)obj);
280 write_fmt_string(pcf, "#<ase:heap :weak :size %u",
281 (unsigned int)ase_wheap_size(h));
283 if (ase_heap_opts_coloured(h)) {
284 write_c_string(" :coloured", pcf);
287 if (ase_wheap_size(h)) {
288 write_c_string(" :elements", pcf);
289 _ase_wheap_prnt(h, pcf);
291 write_c_string(" :empty>", pcf);
294 write_c_string(">", pcf);
298 _ase_yheap_cell_fini(ase_yheap_cell_t c)
299 __attribute__((always_inline));
301 _ase_yheap_cell_fini(ase_yheap_cell_t c)
303 EMOD_ASE_DEBUG_HEAP("c:0x%08lx shall be freed...\n",
304 (long unsigned int)c);
306 memset(c, 0, sizeof(struct ase_yheap_cell_s));
312 _ase_yheap_fini(ase_yheap_t h)
313 __attribute__((always_inline));
315 _ase_yheap_fini(ase_yheap_t h)
319 EMOD_ASE_DEBUG_HEAP("h:0x%08lx freeing used/free cells...\n",
320 (long unsigned int)h);
321 c = ase_yheap_root(h);
323 ase_yheap_cell_t tmp = ase_yheap_cell_next(c);
324 _ase_yheap_cell_fini(c);
329 ase_heap_fini_mutex(h);
330 xfree(ase_heap_options(h));
335 ase_yheap_fini(Lisp_Object obj, int SXE_UNUSED(foo))
337 ase_yheap_t h = XASE_YHEAP(obj);
339 EMOD_ASE_DEBUG_HEAP("h:0x%08lx@0x%08lx shall be freed...\n",
340 (long unsigned int)h, (long unsigned int)obj);
343 memset(h, 0, sizeof(struct ase_yheap_s));
349 _ase_dheap_fini(ase_dheap_t h)
350 __attribute__((always_inline));
352 _ase_dheap_fini(ase_dheap_t h)
355 xfree(ase_dheap_cells(h));
356 if (ase_dheap_colours(h)) {
357 xfree(ase_dheap_colours(h));
360 ase_heap_fini_mutex(h);
361 xfree(ase_heap_options(h));
366 ase_dheap_fini(Lisp_Object obj, int SXE_UNUSED(foo))
368 ase_dheap_t h = XASE_DHEAP(obj);
370 EMOD_ASE_DEBUG_HEAP("d:0x%08lx@0x%08lx shall be freed...\n",
371 (long unsigned int)h, (long unsigned int)obj);
374 memset(h, 0, sizeof(struct ase_dheap_s));
380 _ase_wheap_fini(ase_wheap_t h)
381 __attribute__((always_inline));
383 _ase_wheap_fini(ase_wheap_t h)
386 xfree(ase_wheap_cells(h));
387 xfree(ase_wheap_rbits(h));
388 if (ase_dheap_colours(h)) {
389 xfree(ase_wheap_colours(h));
392 ase_heap_fini_mutex(h);
393 xfree(ase_heap_options(h));
398 ase_wheap_fini(Lisp_Object obj, int SXE_UNUSED(foo))
400 ase_wheap_t h = XASE_WHEAP(obj);
402 EMOD_ASE_DEBUG_HEAP("w:0x%08lx@0x%08lx shall be freed...\n",
403 (long unsigned int)h, (long unsigned int)obj);
406 memset(h, 0, sizeof(struct ase_wheap_s));
412 _ase_yheap_mark_cell(ase_yheap_cell_t c)
414 if (c == NULL || ase_yheap_cell_data(c) == Qnull_pointer)
416 mark_object(ase_yheap_cell_data(c));
417 mark_object(ase_yheap_cell_colour(c));
421 ase_yheap_mark(Lisp_Object obj)
423 ase_yheap_t h = XASE_YHEAP(obj);
424 ase_yheap_cell_t c = ase_yheap_root(h);
426 EMOD_ASE_DEBUG_HEAP("h:0x%08lx@0x%08lx shall be marked...\n",
427 (long unsigned int)h, (long unsigned int)obj);
430 while (c && ase_yheap_cell_data(c) != Qnull_pointer) {
431 _ase_yheap_mark_cell(c);
432 c = ase_yheap_cell_next(c);
439 ase_dheap_mark(Lisp_Object obj)
441 ase_dheap_t h = XASE_DHEAP(obj);
446 EMOD_ASE_DEBUG_HEAP("d:0x%08lx@0x%08lx shall be marked...\n",
447 (long unsigned int)h, (long unsigned int)obj);
450 d = ase_dheap_cells(h);
451 c = ase_dheap_colours(h);
452 size = ase_dheap_size(h);
453 for (i = 0; i < size; i++) {
457 for (i = 0; i < size; i++) {
466 ase_wheap_mark(Lisp_Object obj)
468 ase_wheap_t h = XASE_WHEAP(obj);
473 EMOD_ASE_DEBUG_HEAP("w:0x%08lx@0x%08lx shall be marked...\n",
474 (long unsigned int)h, (long unsigned int)obj);
477 d = ase_wheap_cells(h);
478 c = ase_wheap_colours(h);
479 size = ase_wheap_size(h);
480 for (i = 0; i < size; i++) {
484 for (i = 0; i < size; i++) {
493 static inline ase_yheap_cell_t
494 _ase_make_initial_heap_cell(void)
495 __attribute__((always_inline));
496 static inline ase_yheap_cell_t
497 _ase_make_initial_heap_cell(void)
499 ase_yheap_cell_t c = xnew(struct ase_yheap_cell_s);
501 ase_yheap_cell_data(c) = Qnull_pointer;
502 ase_yheap_cell_colour(c) = Qnil;
503 ase_yheap_cell_left(c) = NULL;
504 ase_yheap_cell_right(c) = NULL;
505 ase_yheap_cell_mother(c) = NULL;
506 ase_yheap_cell_father(c) = NULL;
507 ase_yheap_cell_prev(c) = NULL;
508 ase_yheap_cell_next(c) = NULL;
510 EMOD_ASE_DEBUG_HEAP("c:0x%08lx shall be created...\n",
511 (long unsigned int)c);
515 static inline ase_yheap_cell_t
516 _ase_make_heap_cell(ase_yheap_cell_t mother)
517 __attribute__((always_inline));
518 static inline ase_yheap_cell_t
519 _ase_make_heap_cell(ase_yheap_cell_t mother)
521 ase_yheap_cell_t c = xnew(struct ase_yheap_cell_s);
523 ase_yheap_cell_data(c) = Qnull_pointer;
524 ase_yheap_cell_colour(c) = Qnil;
525 ase_yheap_cell_left(c) = NULL;
526 ase_yheap_cell_right(c) = NULL;
527 ase_yheap_cell_mother(c) = mother;
528 ase_yheap_cell_father(c) = ase_yheap_cell_father(mother);
529 ase_yheap_cell_prev(c) = NULL;
530 ase_yheap_cell_next(c) = NULL;
532 EMOD_ASE_DEBUG_HEAP("c:0x%08lx shall be created...\n",
533 (long unsigned int)c);
537 static inline Lisp_Object
538 _ase_wrap_yheap(ase_yheap_t h)
542 result = make_dynacat(h);
543 XDYNACAT(result)->type = Qase_yheap;
545 set_dynacat_printer(result, ase_yheap_prnt);
546 set_dynacat_marker(result, ase_yheap_mark);
547 set_dynacat_finaliser(result, ase_yheap_fini);
548 set_dynacat_intprinter(
549 result, (dynacat_intprinter_f)_ase_yheap_prnt);
551 EMOD_ASE_DEBUG_HEAP("h:0x%08lx shall be wrapped to 0x%08lx...\n",
552 (long unsigned int)h, (long unsigned int)result);
557 static inline Lisp_Object
558 _ase_wrap_dheap(ase_dheap_t h)
562 result = make_dynacat(h);
563 XDYNACAT(result)->type = Qase_dheap;
565 set_dynacat_printer(result, ase_dheap_prnt);
566 set_dynacat_marker(result, ase_dheap_mark);
567 set_dynacat_finaliser(result, ase_dheap_fini);
568 set_dynacat_intprinter(
569 result, (dynacat_intprinter_f)_ase_dheap_prnt);
571 EMOD_ASE_DEBUG_HEAP("d:0x%08lx shall be wrapped to 0x%08lx...\n",
572 (long unsigned int)h, (long unsigned int)result);
577 static inline ase_dheap_t
578 _ase_make_dheap(ase_heap_options_t opts)
580 ase_dheap_t h = xnew(struct ase_dheap_s);
581 size_t all = ase_heap_options_min_size(opts);
585 ase_dheap_size(h) = 0;
586 ase_heap_init_mutex(h);
587 ase_dheap_heapp(h) = 1;
590 ase_heap_options(h) = opts;
592 d = xnew_array_and_zero(Lisp_Object, all);
593 ase_dheap_cells(h) = d;
594 ase_dheap_colours(h) = NULL;
595 ase_dheap_alloc(h) = all;
597 if (ase_heap_options_coloured(opts))
598 ase_dheap_colours(h) = xnew_array_and_zero(Lisp_Object, all);
600 EMOD_ASE_DEBUG_HEAP("d:0x%08lx shall be created...\n",
601 (long unsigned int)h);
606 Lisp_Object ase_make_dheap(ase_heap_options_t opts)
608 ase_dheap_t h = NULL;
610 h = _ase_make_dheap(opts);
611 return _ase_wrap_dheap(h);
614 static inline Lisp_Object
615 _ase_wrap_wheap(ase_wheap_t h)
619 result = make_dynacat(h);
620 XDYNACAT(result)->type = Qase_wheap;
622 set_dynacat_printer(result, ase_wheap_prnt);
623 set_dynacat_marker(result, ase_wheap_mark);
624 set_dynacat_finaliser(result, ase_wheap_fini);
625 set_dynacat_intprinter(
626 result, (dynacat_intprinter_f)_ase_wheap_prnt);
628 EMOD_ASE_DEBUG_HEAP("w:0x%08lx shall be wrapped to 0x%08lx...\n",
629 (long unsigned int)h, (long unsigned int)result);
634 static inline ase_wheap_t
635 _ase_make_wheap(ase_heap_options_t opts)
637 ase_wheap_t h = xnew(struct ase_wheap_s);
638 size_t all = ase_heap_options_min_size(opts);
643 ase_wheap_size(h) = 0;
644 ase_heap_init_mutex(h);
645 ase_wheap_heapp(h) = 1;
648 ase_heap_options(h) = opts;
650 d = xnew_array_and_zero(Lisp_Object, all);
651 r = xnew_array_and_zero(int, all / sizeof(int) / 8);
652 ase_wheap_cells(h) = d;
653 ase_wheap_rbits(h) = r;
654 ase_wheap_colours(h) = NULL;
655 ase_wheap_alloc(h) = all;
657 if (ase_heap_options_coloured(opts))
658 ase_dheap_colours(h) = xnew_array_and_zero(Lisp_Object, all);
660 EMOD_ASE_DEBUG_HEAP("w:0x%08lx shall be created...\n",
661 (long unsigned int)h);
666 Lisp_Object ase_make_wheap(ase_heap_options_t opts)
668 ase_wheap_t h = NULL;
670 h = _ase_make_wheap(opts);
671 return _ase_wrap_wheap(h);
674 static inline ase_yheap_t
675 _ase_make_yheap(ase_heap_options_t opts)
677 ase_yheap_t h = xnew(struct ase_yheap_s);
681 ase_heap_init_mutex(h);
682 ase_yheap_heapp(h) = 1;
685 ase_heap_options(h) = opts;
687 /* create one empty cell */
688 c = _ase_make_initial_heap_cell();
689 ase_yheap_cell_father(c) = h;
690 ase_yheap_root(h) = NULL;
691 ase_yheap_first_free(h) = ase_yheap_last_free(h) = c;
692 ase_yheap_size(h) = 0;
693 ase_yheap_alloc(h) = 1;
695 EMOD_ASE_DEBUG_HEAP("h:0x%08lx shall be created...\n",
696 (long unsigned int)h);
700 Lisp_Object ase_make_yheap(ase_heap_options_t opts)
702 ase_yheap_t h = NULL;
704 h = _ase_make_yheap(opts);
705 return _ase_wrap_yheap(h);
710 _ase_fixup_heap_cell(ase_yheap_t h, ase_yheap_cell_t c)
711 __attribute__((always_inline));
713 _ase_fixup_heap_cell(ase_yheap_t h, ase_yheap_cell_t c)
715 /* create new free cells */
716 if (ase_yheap_cell_left(c) == NULL &&
717 ase_yheap_cell_right(c) == NULL) {
718 ase_yheap_cell_t l = ase_yheap_last_free(h);
719 ase_yheap_cell_t n = _ase_make_heap_cell(c);
721 ase_yheap_cell_left(c) = n;
723 ase_yheap_cell_prev(n) = l;
724 ase_yheap_cell_next(l) = n;
725 l = ase_yheap_last_free(h) = n;
726 ase_yheap_alloc(h)++;
728 n = _ase_make_heap_cell(c);
729 ase_yheap_cell_right(c) = n;
731 ase_yheap_cell_prev(n) = l;
732 ase_yheap_cell_next(l) = n;
733 ase_yheap_last_free(h) = n;
734 ase_yheap_alloc(h)++;
739 _ase_dheap_realloc(ase_dheap_t h, size_t new_alloc)
740 __attribute__((always_inline));
742 _ase_dheap_realloc(ase_dheap_t h, size_t new_alloc)
744 Lisp_Object *oldd = ase_dheap_cells(h);
745 Lisp_Object *newd = NULL;
746 size_t s = ase_dheap_size(h);
748 newd = xnew_array_and_zero(Lisp_Object, new_alloc);
749 memcpy(newd, oldd, sizeof(Lisp_Object)*s);
751 ase_dheap_cells(h) = newd;
752 ase_dheap_alloc(h) = new_alloc;
754 if (!ase_heap_opts_coloured(h))
757 oldd = ase_dheap_colours(h);
758 newd = xnew_array_and_zero(Lisp_Object, new_alloc);
759 memcpy(newd, oldd, sizeof(Lisp_Object)*s);
761 ase_dheap_colours(h) = newd;
766 _ase_dheap_check_resize(ase_dheap_t h)
767 __attribute__((always_inline));
769 _ase_dheap_check_resize(ase_dheap_t h)
771 size_t s = ase_dheap_size(h), all = ase_dheap_alloc(h);
773 if (s < ase_heap_opts_min_size(h))
777 EMOD_ASE_DEBUG_HEAP("d:0x%08lx upsize from %d to %d\n",
778 (long unsigned int)h,
779 (int)all, (int)(all*2));
780 _ase_dheap_realloc(h, 2*all);
784 EMOD_ASE_DEBUG_HEAP("d:0x%08lx downsize from %d to %d\n",
785 (long unsigned int)h,
786 (int)all, (int)(all/2));
787 _ase_dheap_realloc(h, all/2);
793 _ase_wheap_realloc(ase_wheap_t h, size_t new_alloc)
794 __attribute__((always_inline));
796 _ase_wheap_realloc(ase_wheap_t h, size_t new_alloc)
798 Lisp_Object *oldd = ase_wheap_cells(h);
799 Lisp_Object *newd = NULL;
800 int *oldr = ase_wheap_rbits(h);
802 size_t s = ase_wheap_size(h);
804 newd = xnew_array_and_zero(Lisp_Object, new_alloc);
805 newr = xnew_array_and_zero(int, new_alloc/sizeof(int)/8);
806 memcpy(newd, oldd, sizeof(Lisp_Object)*s);
807 memcpy(newr, oldr, s/8);
810 ase_wheap_cells(h) = newd;
811 ase_wheap_rbits(h) = newr;
812 ase_wheap_alloc(h) = new_alloc;
814 if (!ase_heap_opts_coloured(h))
817 oldd = ase_wheap_colours(h);
818 newd = xnew_array_and_zero(Lisp_Object, new_alloc);
819 memcpy(newd, oldd, sizeof(Lisp_Object)*s);
821 ase_wheap_colours(h) = newd;
826 _ase_wheap_check_resize(ase_wheap_t h)
827 __attribute__((always_inline));
829 _ase_wheap_check_resize(ase_wheap_t h)
831 size_t s = ase_wheap_size(h), all = ase_wheap_alloc(h);
833 if (s < ase_heap_opts_min_size(h))
837 EMOD_ASE_DEBUG_HEAP("w:0x%08lx upsize from %d to %d\n",
838 (long unsigned int)h,
839 (int)all, (int)(all*2));
840 _ase_wheap_realloc(h, 2*all);
844 EMOD_ASE_DEBUG_HEAP("w:0x%08lx downsize from %d to %d\n",
845 (long unsigned int)h,
846 (int)all, (int)(all/2));
847 _ase_wheap_realloc(h, all/2);
852 /* dense heap navigation */
854 ase_dheap_cell_mother(int c)
855 __attribute__((always_inline));
857 ase_dheap_cell_mother(int c)
863 ase_dheap_cell_left(int c)
864 __attribute__((always_inline));
866 ase_dheap_cell_left(int c)
872 ase_dheap_cell_right(int c)
873 __attribute__((always_inline));
875 ase_dheap_cell_right(int c)
880 /* weak heap navigation */
882 ase_wheap_cell_rbit(ase_wheap_t h, int c)
883 __attribute__((always_inline));
885 ase_wheap_cell_rbit(ase_wheap_t h, int c)
887 int *r = ase_wheap_rbits(h);
888 int w = sizeof(int) * 8;
889 int cell = c / w, bit = c % w;
899 ase_wheap_cell_rbit_neg(ase_wheap_t h, int c)
900 __attribute__((always_inline));
902 ase_wheap_cell_rbit_neg(ase_wheap_t h, int c)
904 int *r = ase_wheap_rbits(h);
905 int w = sizeof(int) * 8;
906 int cell = c / w, bit = c % w;
909 return r[cell] ^= bit2;
913 ase_wheap_cell_mother(ase_wheap_t SXE_UNUSED(h), int c)
914 __attribute__((always_inline));
916 ase_wheap_cell_mother(ase_wheap_t SXE_UNUSED(h), int c)
922 ase_wheap_cell_nana(ase_wheap_t h, int c)
923 __attribute__((always_inline));
925 ase_wheap_cell_nana(ase_wheap_t h, int c)
927 /* used to use odd(c), but simpler is odd(c) := c & 1 */
928 while ((c&1) == ase_wheap_cell_rbit(h, (c>>1)))
929 c = ase_wheap_cell_mother(h, c);
930 return ase_wheap_cell_mother(h, c);
934 ase_wheap_cell_left(ase_wheap_t h, int c)
935 __attribute__((always_inline));
937 ase_wheap_cell_left(ase_wheap_t h, int c)
939 return 2*c + ase_wheap_cell_rbit(h, c);
943 ase_wheap_cell_right(ase_wheap_t h, int c)
944 __attribute__((always_inline));
946 ase_wheap_cell_right(ase_wheap_t h, int c)
948 return 2*c + 1 - ase_wheap_cell_rbit(h, c);
953 _ase_yheapify_sink(ase_yheap_cell_t c)
955 /* iterative approach */
956 Lisp_Object cdata = ase_yheap_cell_data(c);
957 ase_yheap_cell_t l, r;
958 ase_binary_relation_t rel = ase_heap_opts_po(ase_yheap_cell_father(c));
960 if (cdata == Qnull_pointer) {
963 while ((l = ase_yheap_cell_left(c))) {
964 Lisp_Object ldata = 0, rdata = 0;
965 ase_yheap_cell_t chosen = l;
968 (ldata = ase_yheap_cell_data(l)) == Qnull_pointer) {
972 if ((r = ase_yheap_cell_right(c)) &&
973 (rdata = ase_yheap_cell_data(r)) &&
974 ent_binrel(rel, rdata, ldata)) {
979 if (ent_binrel(rel, ldata, cdata)) {
980 _ase_yheap_cell_swap_data(c, chosen);
990 _ase_dheapify_sink(ase_dheap_t h, int c)
991 __attribute__((always_inline));
993 _ase_dheapify_sink(ase_dheap_t h, int c)
995 /* iterative approach */
996 size_t size = ase_dheap_size(h);
997 Lisp_Object *d = ase_dheap_cells(h);
998 Lisp_Object cdata = d[c];
999 ase_binary_relation_t rel = ase_heap_opts_po(h);
1002 if (cdata == Qnull_pointer) {
1005 while ((l = ase_dheap_cell_left(c)) && l < size && d[l]) {
1008 if ((r = l+1) && r < size && d[r] &&
1009 ent_binrel(rel, d[r], d[l])) {
1013 if (ent_binrel(rel, d[chosen], cdata)) {
1014 _ase_dheap_swap(h, c, chosen);
1024 _ase_yheapify(ase_yheap_cell_t c)
1026 Lisp_Object cdata = ase_yheap_cell_data(c);
1027 ase_yheap_cell_t l = ase_yheap_cell_left(c);
1028 ase_yheap_cell_t r = ase_yheap_cell_right(c);
1030 if (cdata == Qnull_pointer || (l == NULL && r == NULL))
1040 _ase_yheapify_sink(c);
1044 ase_yheapify(ase_yheap_t h)
1046 _ase_yheapify(ase_yheap_root(h));
1047 ase_yheap_heapp(h) = 1;
1052 _ase_dheap_sift(ase_dheap_t h, int start, int count)
1053 __attribute__((always_inline));
1055 _ase_dheap_sift(ase_dheap_t h, int start, int count)
1057 int root = start, child;
1058 ase_binary_relation_t po = ase_heap_opts_po(h);
1059 Lisp_Object *d = ase_dheap_cells(h);
1061 while ((child = ase_dheap_cell_left(root)) < count) {
1062 if (child < count-1 &&
1063 ent_binrel(po, d[child], d[child+1])) {
1064 child++; /* choose the right child */
1066 if (ent_binrel(po, d[root], d[child])) {
1067 _ase_dheap_swap(h, root, child);
1077 __ase_wheapify_sink(ase_wheap_t h, int i, int j)
1078 __attribute__((always_inline));
1080 __ase_wheapify_sink(ase_wheap_t h, int i, int j)
1082 /* aka Merge(i, j) in Edelkamp/Wegener's paper */
1083 Lisp_Object *d = ase_wheap_cells(h);
1084 ase_binary_relation_t po = ase_heap_opts_po(h);
1087 EMOD_ASE_DEBUG_HEAP("Merge(%d, %d)\n", i, j);
1088 if ((res = ent_binrel(po, d[j], d[i]))) {
1089 /* swap(nana(idx), idx) */
1090 _ase_wheap_swap(h, i, j);
1091 /* update bit field */
1092 ase_wheap_cell_rbit_neg(h, j);
1098 _ase_wheapify_sink(ase_wheap_t h, int idx)
1099 __attribute__((always_inline));
1101 _ase_wheapify_sink(ase_wheap_t h, int m)
1103 /* aka MergeForest(m) in Edelkamp/Wegener's paper */
1106 EMOD_ASE_DEBUG_HEAP("MergeForest(%d)\n", m);
1110 while ((l = ase_wheap_cell_left(h, x)) < m) {
1115 __ase_wheapify_sink(h, m, x);
1116 /* move on to mother cell */
1117 x = ase_wheap_cell_mother(h, x);
1123 _ase_wheapify(ase_wheap_t h)
1126 for (i = ase_wheap_size(h)-1; i >= 1; i--) {
1127 __ase_wheapify_sink(h, ase_wheap_cell_nana(h, i), i);
1132 ase_wheap_sort(ase_wheap_t h)
1134 int s = ase_wheap_size(h), i, j;
1136 /* normally WeakHeapify is called first
1137 * howbeit, our wheaps always suffice the weak property */
1138 for (--s; s >= 2; s--) {
1139 _ase_wheapify_sink(h, s);
1141 /* now the i-th most extreme value is at index ase_wheap_size-i */
1142 s = (ase_wheap_size(h)+1)>>1;
1143 for (i = 1, j = ase_wheap_size(h)-1; i < s; i++, j--) {
1144 _ase_wheap_swap(h, i, j);
1149 ase_dheap_sort(ase_dheap_t h)
1151 size_t size = ase_dheap_size(h);
1152 int start = size/2 - 1, end = size-1;
1154 while (start >= 0) {
1155 _ase_dheap_sift(h, start, size);
1159 _ase_dheap_swap(h, end, 0);
1160 _ase_dheap_sift(h, 0, end);
1166 #if defined __GNUC__
1168 ase_add_yheap_unwind_protect(Lisp_Object unwind_obj)
1169 __attribute__((unused));
1172 ase_add_yheap_unwind_protect(Lisp_Object unwind_obj)
1174 ase_yheap_t h = get_opaque_ptr(unwind_obj);
1176 free_opaque_ptr(unwind_obj);
1181 ase_add_yheap(ase_yheap_t h, Lisp_Object o, Lisp_Object colour)
1183 ase_yheap_cell_t c, mother;
1185 int speccount = specpdl_depth();
1188 EMOD_ASE_DEBUG_HEAP("c:0x%08lx shall be populated...\n",
1189 (long unsigned int)c);
1192 record_unwind_protect(ase_add_yheap_unwind_protect,
1193 make_opaque_ptr(h));
1197 c = ase_yheap_first_free(h);
1199 EMOD_ASE_CRITICAL("broken heap 0x%08lx\n",
1200 (long unsigned int)h);
1205 ase_yheap_cell_data(c) = o;
1206 ase_yheap_cell_colour(c) = colour;
1208 /* it may violate the heap property now */
1209 ase_yheap_heapp(h) = 0;
1211 if (ase_yheap_cell_left(c) == NULL) {
1212 _ase_fixup_heap_cell(h, c);
1214 ase_yheap_first_free(h) = ase_yheap_cell_next(c);
1215 ase_yheap_size(h)++;
1217 if (ase_yheap_root(h) == NULL) {
1218 ase_yheap_root(h) = c;
1221 /* bottom-up heapify now */
1223 while ((mother = ase_yheap_cell_mother(mother))) {
1224 _ase_yheapify_sink(mother);
1230 #if defined __GNUC__
1232 ase_add_dheap_unwind_protect(Lisp_Object unwind_obj)
1233 __attribute__((unused));
1236 ase_add_dheap_unwind_protect(Lisp_Object unwind_obj)
1238 ase_dheap_t h = get_opaque_ptr(unwind_obj);
1240 free_opaque_ptr(unwind_obj);
1245 ase_add_dheap(ase_dheap_t h, Lisp_Object o, Lisp_Object colour)
1249 int speccount = specpdl_depth();
1253 EMOD_ASE_DEBUG_HEAP("c:%d shall be populated...\n", idx);
1256 record_unwind_protect(ase_add_dheap_unwind_protect,
1257 make_opaque_ptr(h));
1262 mother = idx = ase_dheap_size(h)++;
1263 d = ase_dheap_cells(h);
1264 c = ase_dheap_colours(h);
1271 /* it may violate the heap property now */
1272 ase_dheap_heapp(h) = 0;
1274 /* bottom-up heapify now */
1276 while ((mother = ase_dheap_cell_mother(mother)) != -1) {
1277 _ase_dheapify_sink(h, mother);
1280 _ase_dheap_check_resize(h);
1285 #if defined __GNUC__
1287 ase_add_wheap_unwind_protect(Lisp_Object unwind_obj)
1288 __attribute__((unused));
1291 ase_add_wheap_unwind_protect(Lisp_Object unwind_obj)
1293 ase_wheap_t h = get_opaque_ptr(unwind_obj);
1295 free_opaque_ptr(unwind_obj);
1300 ase_add_wheap(ase_wheap_t h, Lisp_Object o, Lisp_Object colour)
1304 int speccount = specpdl_depth();
1308 EMOD_ASE_DEBUG_HEAP("c:%d shall be populated...\n", idx);
1311 record_unwind_protect(ase_add_wheap_unwind_protect,
1312 make_opaque_ptr(h));
1317 idx = ase_wheap_size(h)++;
1318 d = ase_wheap_cells(h);
1321 if (ase_heap_opts_coloured(h)) {
1322 ase_wheap_colours(h)[idx] = colour;
1325 /* it may violate the heap property now */
1326 ase_wheap_heapp(h) = 0;
1328 /* bottom-up wheapify now */
1330 int nana = ase_wheap_cell_nana(h, idx);
1331 if (!__ase_wheapify_sink(h, nana, idx))
1336 _ase_wheap_check_resize(h);
1341 /* popping (dequeue operation) */
1343 ase_pop_yheap(ase_yheap_t h)
1345 ase_yheap_cell_t rc, c;
1346 Lisp_Object result = Qnil, swap;
1350 rc = ase_yheap_root(h);
1351 if (rc == NULL || ase_yheap_cell_data(rc) == Qnull_pointer) {
1356 if (!ase_heap_opts_coloured(h)) {
1357 result = ase_yheap_cell_data(rc);
1359 result = ase_yheap_cell_colour(rc);
1361 c = ase_yheap_cell_prev(ase_yheap_first_free(h));
1362 swap = ase_yheap_cell_data(c);
1363 ase_yheap_first_free(h) = c;
1364 ase_yheap_size(h)--;
1366 ase_yheap_cell_data(rc) = swap;
1367 ase_yheap_cell_data(c) = Qnull_pointer;
1368 ase_yheap_cell_colour(c) = Qnull_pointer;
1369 _ase_yheapify_sink(rc);
1376 ase_pop_dheap(ase_dheap_t h)
1378 Lisp_Object *d, result;
1383 d = ase_dheap_cells(h);
1385 if (d[0] == Qnull_pointer) {
1390 /* pop off the most extreme element */
1391 if (!ase_heap_opts_coloured(h)) {
1394 result = ase_dheap_colours(h)[0];
1395 ase_dheap_colours(h)[0] = Qnull_pointer;
1398 end_idx = --ase_dheap_size(h);
1399 _ase_dheap_swap(h, 0, end_idx);
1400 d[end_idx] = Qnull_pointer;
1402 /* reestablish heap property */
1403 _ase_dheapify_sink(h, 0);
1404 _ase_dheap_check_resize(h);
1411 ase_pop_wheap(ase_wheap_t h)
1413 Lisp_Object *d, *c, result;
1418 d = ase_wheap_cells(h);
1419 c = ase_wheap_colours(h);
1421 if (d[0] == Qnull_pointer) {
1426 /* pop off the most extreme element */
1427 if (!ase_heap_opts_coloured(h)) {
1433 /* MergeForest(end_idx) */
1434 end_idx = --ase_wheap_size(h);
1435 _ase_wheapify_sink(h, end_idx);
1438 d[end_idx] = Qnull_pointer;
1440 if (ase_heap_opts_coloured(h)) {
1442 c[end_idx] = Qnull_pointer;
1446 _ase_wheap_check_resize(h);
1453 ase_yheap_top(ase_yheap_t h)
1455 ase_yheap_cell_t rc;
1456 Lisp_Object result = Qnil;
1460 rc = ase_yheap_root(h);
1461 if (rc == NULL || ase_yheap_cell_data(rc) == Qnull_pointer) {
1466 /* grab the most extreme element */
1467 if (!ase_heap_opts_coloured(h)) {
1468 result = ase_yheap_cell_data(rc);
1470 result = ase_yheap_cell_colour(rc);
1478 ase_dheap_top(ase_dheap_t h)
1480 Lisp_Object *d, *c, result;
1484 d = ase_dheap_cells(h);
1485 c = ase_dheap_colours(h);
1487 if (d[0] == Qnull_pointer) {
1492 /* grab the most extreme element */
1493 if (!ase_heap_opts_coloured(h)) {
1504 ase_wheap_top(ase_wheap_t h)
1506 Lisp_Object *d, *c, result;
1510 d = ase_wheap_cells(h);
1511 c = ase_wheap_colours(h);
1513 if (d[0] == Qnull_pointer) {
1518 /* grab the most extreme element */
1519 if (!ase_heap_opts_coloured(h)) {
1530 ase_yheap_top_rank(ase_yheap_t h)
1532 ase_yheap_cell_t rc;
1533 Lisp_Object result = Qnil;
1537 rc = ase_yheap_root(h);
1539 result = ase_yheap_cell_data(rc);
1541 if (result != Qnull_pointer) {
1548 ase_dheap_top_rank(ase_dheap_t h)
1550 Lisp_Object *d, result;
1554 d = ase_dheap_cells(h);
1559 if (result != Qnull_pointer) {
1566 ase_wheap_top_rank(ase_wheap_t h)
1568 Lisp_Object *d, result;
1572 d = ase_wheap_cells(h);
1577 if (result != Qnull_pointer) {
1584 static inline Lisp_Object
1585 _ase_heap_to_listX(void *h, ase_heap_pop_f popfun)
1586 __attribute__((always_inline));
1587 static inline Lisp_Object
1588 _ase_heap_to_listX(void *h, ase_heap_pop_f popfun)
1590 Lisp_Object result = Qnil, tmp, trv;
1592 result = trv = Fcons(Qnil, Qnil);
1593 while (!NILP(tmp = popfun(h))) {
1594 trv = (XCDR(trv) = Fcons(tmp, Qnil));
1596 return XCDR(result);
1600 ase_yheap_to_listX(ase_yheap_t h)
1602 return _ase_heap_to_listX(h, (ase_heap_pop_f)ase_pop_yheap);
1606 ase_dheap_to_listX(ase_dheap_t h)
1608 return _ase_heap_to_listX(h, (ase_heap_pop_f)ase_pop_dheap);
1612 ase_wheap_to_listX(ase_wheap_t h)
1614 return _ase_heap_to_listX(h, (ase_heap_pop_f)ase_pop_wheap);
1618 ase_yheap_to_list(ase_yheap_t h)
1620 Lisp_Object res, tmp;
1622 res = tmp = ase_yheap_to_listX(h);
1623 /* now add them all back to the heap */
1624 while (!NILP(tmp)) {
1625 ase_add_yheap(h, XCAR(tmp), Qnil);
1632 ase_dheap_to_list(ase_dheap_t h)
1634 size_t size = ase_yheap_size(h);
1635 Lisp_Object *d = ase_dheap_cells(h);
1636 Lisp_Object result = Qnil;
1640 for (i = size-1; i >= 0; i--) {
1641 result = Fcons(d[i], result);
1647 ase_wheap_to_list(ase_wheap_t h)
1649 size_t size = ase_wheap_size(h);
1650 Lisp_Object *d = ase_wheap_cells(h);
1651 Lisp_Object result = Qnil;
1655 for (i = size-1; i >= 0; i--) {
1656 result = Fcons(d[i], result);
1661 static inline Lisp_Object
1662 _ase_heap_to_vectorX(void *h, ase_heap_pop_f popfun, size_t size)
1663 __attribute__((always_inline));
1664 static inline Lisp_Object
1665 _ase_heap_to_vectorX(void *h, ase_heap_pop_f popfun, size_t size)
1668 Lisp_Object result = make_vector(size, Qnil), tmp;
1670 while (!NILP(tmp = popfun(h))) {
1671 XVECTOR_DATA(result)[i++] = tmp;
1677 ase_yheap_to_vectorX(ase_yheap_t h)
1679 size_t s = ase_yheap_size(h);
1680 return _ase_heap_to_vectorX(h, (ase_heap_pop_f)ase_pop_yheap, s);
1684 ase_dheap_to_vectorX(ase_dheap_t h)
1686 size_t s = ase_dheap_size(h);
1687 return _ase_heap_to_vectorX(h, (ase_heap_pop_f)ase_pop_dheap, s);
1691 ase_wheap_to_vectorX(ase_wheap_t h)
1693 size_t s = ase_wheap_size(h);
1694 return _ase_heap_to_vectorX(h, (ase_heap_pop_f)ase_pop_wheap, s);
1698 ase_yheap_to_vector(ase_yheap_t h)
1703 res = ase_yheap_to_vectorX(h);
1704 /* now add them all back to the heap */
1705 i = XVECTOR_LENGTH(res);
1707 ase_add_yheap(h, XVECTOR_DATA(res)[i], Qnil);
1713 ase_dheap_to_vector(ase_dheap_t h)
1715 size_t size = ase_dheap_size(h);
1716 Lisp_Object *d = ase_dheap_cells(h);
1717 Lisp_Object result = make_vector(size, Qnil);
1721 for (i = 0; i < size; i++) {
1722 XVECTOR_DATA(result)[i] = d[i];
1728 ase_wheap_to_vector(ase_wheap_t h)
1730 size_t size = ase_wheap_size(h);
1731 Lisp_Object *d = ase_wheap_cells(h);
1732 Lisp_Object result = make_vector(size, Qnil);
1736 for (i = 0; i < size; i++) {
1737 XVECTOR_DATA(result)[i] = d[i];
1742 static inline Lisp_Object
1743 _ase_heap_to_dllistX(void *h, ase_heap_pop_f popfun)
1744 __attribute__((always_inline));
1745 static inline Lisp_Object
1746 _ase_heap_to_dllistX(void *h, ase_heap_pop_f popfun)
1748 dllist_t resdll = make_dllist();
1749 Lisp_Object result = Qnil, tmp;
1751 while (!NILP(tmp = popfun(h))) {
1752 dllist_append(resdll, (void*)tmp);
1755 XSETDLLIST(result, resdll);
1760 ase_yheap_to_dllistX(ase_yheap_t h)
1762 return _ase_heap_to_dllistX(h, (ase_heap_pop_f)ase_pop_yheap);
1766 ase_dheap_to_dllistX(ase_dheap_t h)
1768 return _ase_heap_to_dllistX(h, (ase_heap_pop_f)ase_pop_dheap);
1772 ase_wheap_to_dllistX(ase_wheap_t h)
1774 return _ase_heap_to_dllistX(h, (ase_heap_pop_f)ase_pop_wheap);
1778 ase_yheap_to_dllist(ase_yheap_t h)
1782 res = ase_yheap_to_dllistX(h);
1783 /* now add them all back to the heap */
1784 WITH_DLLIST_TRAVERSE(
1786 ase_add_yheap(h, (Lisp_Object)dllist_item, Qnil));
1791 ase_dheap_to_dllist(ase_dheap_t h)
1793 size_t size = ase_dheap_size(h);
1794 Lisp_Object *d = ase_dheap_cells(h);
1795 Lisp_Object result = Qnil;
1796 dllist_t resdll = make_dllist();
1800 for (i = 0; i < size; i++) {
1801 dllist_append(resdll, (void*)d[i]);
1804 XSETDLLIST(result, resdll);
1809 ase_wheap_to_dllist(ase_wheap_t h)
1811 size_t size = ase_wheap_size(h);
1812 Lisp_Object *d = ase_wheap_cells(h);
1813 Lisp_Object result = Qnil;
1814 dllist_t resdll = make_dllist();
1818 for (i = 0; i < size; i++) {
1819 dllist_append(resdll, (void*)d[i]);
1822 XSETDLLIST(result, resdll);
1826 static inline ase_heap_kind_t
1827 ase_determine_heap_kind(Lisp_Object o)
1828 __attribute__((always_inline));
1829 static inline ase_heap_kind_t
1830 ase_determine_heap_kind(Lisp_Object o)
1833 return ASE_HEAP_WEAK;
1834 } else if (EQ(o, Qdense)) {
1835 return ASE_HEAP_DENSE;
1836 } else if (EQ(o, Qdynamic)) {
1837 return ASE_HEAP_DYNAMIC;
1840 return ASE_HEAP_WEAK;
1845 DEFUN("ase-heap", Fase_heap, 0, MANY, 0, /*
1846 Return a new heap object.
1848 Arguments: &rest keys
1849 :kind kind of the heap, can be one of 'weak (default), 'dense, or 'dynamic
1852 (int nargs, Lisp_Object *args))
1854 ase_heap_options_t opts = xnew(struct ase_heap_options_s);
1855 ase_heap_constr_f constrf;
1856 ase_heap_wrap_f wrapf;
1857 ase_heap_kind_t kind;
1860 /* standard options */
1861 ase_heap_options_po(opts) = ASE_BINARY_REL_GREATERP;
1862 ase_heap_options_pof(opts) = NULL;
1863 kind = ase_heap_options_kind(opts) =
1864 ase_determine_heap_kind(Qase_heap_default_kind);
1865 ase_heap_options_min_size(opts) = ASE_HEAP_MIN_SIZE;
1866 ase_heap_options_coloured(opts) = 0;
1868 for (i = 0; i < nargs-1; i++) {
1869 if (EQ(args[i], Q_kind)) {
1870 kind = ase_heap_options_kind(opts) =
1871 ase_determine_heap_kind(args[++i]);
1873 if (EQ(args[i], Q_relation)) {
1875 if (EQ(args[i], Q_coloured)) {
1876 if (!NILP(args[++i]))
1877 ase_heap_options_coloured(opts) = 1;
1881 constrf = ase_heap_ops[kind].constrf;
1882 wrapf = ase_heap_ops[kind].wrapf;
1883 return wrapf(constrf(opts));
1886 DEFUN("ase-add-heap", Fase_add_heap, 2, 3, 0, /*
1887 Add OBJECT to HEAP and (optionally) COLOUR it.
1889 (heap, object, colour))
1892 ase_heap_add_f addfun = NULL;
1894 CHECK_ASE_HEAP(heap);
1896 if (ASE_WHEAPP(heap)) {
1897 addfun = ase_heap_ops[ASE_HEAP_WEAK].addf;
1898 h = XASE_WHEAP(heap);
1899 } else if (ASE_DHEAPP(heap)) {
1900 addfun = ase_heap_ops[ASE_HEAP_DENSE].addf;
1901 h = XASE_DHEAP(heap);
1902 } else if (ASE_YHEAPP(heap)) {
1903 addfun = ase_heap_ops[ASE_HEAP_DYNAMIC].addf;
1904 h = XASE_YHEAP(heap);
1906 addfun(h, object, colour);
1910 DEFUN("ase-pop-heap", Fase_pop_heap, 1, 1, 0, /*
1911 Pop off and return the most extreme element of HEAP.
1916 ase_heap_pop_f popfun = NULL;
1918 CHECK_ASE_HEAP(heap);
1920 if (ASE_WHEAPP(heap)) {
1921 popfun = ase_heap_ops[ASE_HEAP_WEAK].popf;
1922 h = XASE_WHEAP(heap);
1923 } else if (ASE_DHEAPP(heap)) {
1924 popfun = ase_heap_ops[ASE_HEAP_DENSE].popf;
1925 h = XASE_DHEAP(heap);
1926 } else if (ASE_YHEAPP(heap)) {
1927 popfun = ase_heap_ops[ASE_HEAP_DYNAMIC].popf;
1928 h = XASE_YHEAP(heap);
1934 /* convenience funs */
1935 DEFUN("ase-heap-size", Fase_heap_size, 1, 1, 0, /*
1936 Return the number of elements inside HEAP.
1940 CHECK_ASE_HEAP(heap);
1942 if (ASE_WHEAPP(heap)) {
1943 return make_int(ase_wheap_size(XASE_WHEAP(heap)));
1944 } else if (ASE_DHEAPP(heap)) {
1945 return make_int(ase_dheap_size(XASE_DHEAP(heap)));
1946 } else if (ASE_YHEAPP(heap)) {
1947 return make_int(ase_yheap_size(XASE_YHEAP(heap)));
1949 return Qnull_pointer;
1952 DEFUN("ase-heap-top", Fase_heap_top, 1, 1, 0, /*
1953 Return the topmost element of HEAP.
1957 CHECK_ASE_HEAP(heap);
1959 if (ASE_WHEAPP(heap)) {
1960 return ase_wheap_top(XASE_WHEAP(heap));
1961 } else if (ASE_DHEAPP(heap)) {
1962 return ase_dheap_top(XASE_DHEAP(heap));
1963 } else if (ASE_YHEAPP(heap)) {
1964 return ase_yheap_top(XASE_YHEAP(heap));
1966 return Qnull_pointer;
1969 DEFUN("ase-heap-top-rank", Fase_heap_top_rank, 1, 1, 0, /*
1970 Return the rank (priority) of the topmost element of HEAP.
1974 CHECK_ASE_HEAP(heap);
1976 if (ASE_WHEAPP(heap)) {
1977 return ase_wheap_top_rank(XASE_WHEAP(heap));
1978 } else if (ASE_DHEAPP(heap)) {
1979 return ase_dheap_top_rank(XASE_DHEAP(heap));
1980 } else if (ASE_YHEAPP(heap)) {
1981 return ase_yheap_top_rank(XASE_YHEAP(heap));
1983 return Qnull_pointer;
1986 DEFUN("ase-heap-to-list", Fase_heap_to_list, 1, 1, 0, /*
1987 Return a (sorted) list with the elements of HEAP.
1988 HEAP is kept alive. See also `ase-heap-to-list*'
1992 CHECK_ASE_HEAP(heap);
1993 if (ASE_WHEAPP(heap)) {
1994 return ase_wheap_to_list(XASE_WHEAP(heap));
1995 } else if (ASE_DHEAPP(heap)) {
1996 return ase_dheap_to_list(XASE_DHEAP(heap));
1997 } else if (ASE_YHEAPP(heap)) {
1998 return ase_yheap_to_list(XASE_YHEAP(heap));
2000 return Qnull_pointer;
2003 DEFUN("ase-heap-to-list*", Fase_heap_to_listX, 1, 1, 0, /*
2004 Return a (sorted) list with the elements of HEAP.
2005 HEAP is destroyed by side-effect, each element from HEAP is
2006 popped off and consed to the result list.
2010 CHECK_ASE_HEAP(heap);
2011 if (ASE_WHEAPP(heap)) {
2012 return ase_wheap_to_listX(XASE_WHEAP(heap));
2013 } else if (ASE_DHEAPP(heap)) {
2014 return ase_dheap_to_listX(XASE_DHEAP(heap));
2015 } else if (ASE_YHEAPP(heap)) {
2016 return ase_yheap_to_listX(XASE_YHEAP(heap));
2018 return Qnull_pointer;
2021 DEFUN("ase-heap-to-vector", Fase_heap_to_vector, 1, 1, 0, /*
2022 Return a (sorted) vector with the elements of HEAP.
2023 HEAP is kept alive hereby. See also `ase-heap-to-vector*'.
2027 CHECK_ASE_HEAP(heap);
2028 if (ASE_WHEAPP(heap)) {
2029 return ase_wheap_to_vector(XASE_WHEAP(heap));
2030 } else if (ASE_DHEAPP(heap)) {
2031 return ase_dheap_to_vector(XASE_DHEAP(heap));
2032 } else if (ASE_YHEAPP(heap)) {
2033 return ase_yheap_to_vector(XASE_YHEAP(heap));
2035 return Qnull_pointer;
2038 DEFUN("ase-heap-to-vector*", Fase_heap_to_vectorX, 1, 1, 0, /*
2039 Return a (sorted) vector with the elements of HEAP.
2040 HEAP is destroyed by side-effect, each element from HEAP is
2041 popped off and written into the result vector.
2045 CHECK_ASE_HEAP(heap);
2046 if (ASE_WHEAPP(heap)) {
2047 return ase_wheap_to_vectorX(XASE_WHEAP(heap));
2048 } else if (ASE_DHEAPP(heap)) {
2049 return ase_dheap_to_vectorX(XASE_DHEAP(heap));
2050 } else if (ASE_YHEAPP(heap)) {
2051 return ase_yheap_to_vectorX(XASE_YHEAP(heap));
2053 return Qnull_pointer;
2056 DEFUN("ase-heap-to-dllist", Fase_heap_to_dllist, 1, 1, 0, /*
2057 Return a (sorted) list with the elements of HEAP.
2058 HEAP is kept intact. See also `ase-heap-to-dllist*'.
2062 CHECK_ASE_HEAP(heap);
2063 if (ASE_WHEAPP(heap)) {
2064 return ase_wheap_to_dllist(XASE_WHEAP(heap));
2065 } else if (ASE_DHEAPP(heap)) {
2066 return ase_dheap_to_dllist(XASE_DHEAP(heap));
2067 } else if (ASE_YHEAPP(heap)) {
2068 return ase_yheap_to_dllist(XASE_YHEAP(heap));
2070 return Qnull_pointer;
2073 DEFUN("ase-heap-to-dllist*", Fase_heap_to_dllistX, 1, 1, 0, /*
2074 Return a (sorted) list with the elements of HEAP.
2075 HEAP is destroyed by side-effect, each element from HEAP is
2076 popped off and appended to the result dllist.
2080 CHECK_ASE_HEAP(heap);
2081 if (ASE_WHEAPP(heap)) {
2082 return ase_wheap_to_dllistX(XASE_WHEAP(heap));
2083 } else if (ASE_DHEAPP(heap)) {
2084 return ase_dheap_to_dllistX(XASE_DHEAP(heap));
2085 } else if (ASE_YHEAPP(heap)) {
2086 return ase_yheap_to_dllistX(XASE_YHEAP(heap));
2088 return Qnull_pointer;
2092 /* initialiser code */
2093 #define EMODNAME ase_heap
2099 DEFSUBR(Fase_add_heap);
2100 DEFSUBR(Fase_pop_heap);
2102 DEFSUBR(Fase_heap_to_list);
2103 DEFSUBR(Fase_heap_to_listX);
2104 DEFSUBR(Fase_heap_to_vector);
2105 DEFSUBR(Fase_heap_to_vectorX);
2106 DEFSUBR(Fase_heap_to_dllist);
2107 DEFSUBR(Fase_heap_to_dllistX);
2109 DEFSUBR(Fase_heap_size);
2110 DEFSUBR(Fase_heap_top);
2111 DEFSUBR(Fase_heap_top_rank);
2113 DEFASETYPE_WITH_OPS(Qase_heap, "ase:heap");
2114 defsymbol(&Qase_heapp, "ase:heapp");
2115 defsymbol(&Qase_yheap, "ase:yheap");
2116 defsymbol(&Qase_yheapp, "ase:yheapp");
2117 defsymbol(&Qase_dheap, "ase:dheap");
2118 defsymbol(&Qase_dheapp, "ase:dheapp");
2119 defsymbol(&Qase_wheap, "ase:wheap");
2120 defsymbol(&Qase_wheapp, "ase:wheapp");
2124 DEFSYMBOL(Qdynamic);
2127 DEFKEYWORD(Q_relation);
2128 DEFKEYWORD(Q_coloured);
2130 Fprovide(intern("ase-heap"));
2132 DEFVAR_LISP("ase:heap-default-kind", &Qase_heap_default_kind /*
2133 *Default kind of newly created heaps.
2137 Qase_heap_default_kind = Qweak;
2141 EMOD_PUBREINIT(void)
2146 EMOD_PUBDEINIT(void)
2148 Frevoke(intern("ase-heap"));
2152 /* ase-heap.c ends here */