pcb 4.1.1
An interactive printed circuit board layout editor.
|
00001 /* GTS - Library for the manipulation of triangulated surfaces 00002 * Copyright (C) 1999 Stéphane Popinet 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Library General Public 00006 * License as published by the Free Software Foundation; either 00007 * version 2 of the License, or (at your option) any later version. 00008 * 00009 * This library is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Library General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Library General Public 00015 * License along with this library; if not, write to the 00016 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00017 * Boston, MA 02111-1307, USA. 00018 */ 00019 00020 #include <stdlib.h> 00021 #include "gts.h" 00022 00023 #define PARENT(i) ((i) >= 2 ? (i)/2 : 0) 00024 #define LEFT_CHILD(i) (2*(i)) 00025 #define RIGHT_CHILD(i) (2*(i) + 1) 00026 00027 struct _GtsHeap { 00028 GPtrArray * elts; 00029 GCompareFunc func; 00030 gboolean frozen; 00031 }; 00032 00039 GtsHeap * gts_heap_new (GCompareFunc compare_func) 00040 { 00041 GtsHeap * heap; 00042 00043 g_return_val_if_fail (compare_func != NULL, NULL); 00044 00045 heap = g_malloc (sizeof(GtsHeap)); 00046 heap->elts = g_ptr_array_new (); 00047 heap->func = compare_func; 00048 heap->frozen = FALSE; 00049 return heap; 00050 } 00051 00052 static void sift_up (GtsHeap * heap, guint i) 00053 { 00054 gpointer parent, child; 00055 guint p; 00056 gpointer * pdata = heap->elts->pdata; 00057 GCompareFunc func = heap->func; 00058 00059 child = pdata[i - 1]; 00060 while ((p = PARENT (i))) { 00061 parent = pdata[p - 1]; 00062 if ((*func) (parent, child) > 0) { 00063 pdata[p - 1] = child; 00064 pdata[i - 1] = parent; 00065 i = p; 00066 } 00067 else 00068 i = 0; 00069 } 00070 } 00071 00079 void gts_heap_insert (GtsHeap * heap, gpointer p) 00080 { 00081 g_return_if_fail (heap != NULL); 00082 00083 g_ptr_array_add (heap->elts, p); 00084 if (!heap->frozen) 00085 sift_up (heap, heap->elts->len); 00086 } 00087 00088 static void sift_down (GtsHeap * heap, guint i) 00089 { 00090 gpointer left_child, right_child, child, parent; 00091 guint lc, rc, c; 00092 gpointer * pdata = heap->elts->pdata; 00093 guint len = heap->elts->len; 00094 GCompareFunc func = heap->func; 00095 00096 lc = LEFT_CHILD (i); 00097 rc = RIGHT_CHILD (i); 00098 left_child = lc <= len ? pdata[lc - 1] : NULL; 00099 right_child = rc <= len ? pdata[rc - 1] : NULL; 00100 00101 parent = pdata[i - 1]; 00102 while (left_child != NULL) { 00103 if (right_child == NULL || 00104 (*func) (left_child, right_child) < 0) { 00105 child = left_child; 00106 c = lc; 00107 } 00108 else { 00109 child = right_child; 00110 c = rc; 00111 } 00112 if ((*func) (parent, child) > 0) { 00113 pdata[i - 1] = child; 00114 pdata[c - 1] = parent; 00115 i = c; 00116 lc = LEFT_CHILD (i); 00117 rc = RIGHT_CHILD (i); 00118 left_child = lc <= len ? pdata[lc - 1] : NULL; 00119 right_child = rc <= len ? pdata[rc - 1] : NULL; 00120 } 00121 else 00122 left_child = NULL; 00123 } 00124 } 00125 00134 gpointer gts_heap_remove_top (GtsHeap * heap) 00135 { 00136 gpointer root; 00137 GPtrArray * elts; 00138 guint len; 00139 00140 g_return_val_if_fail (heap != NULL, NULL); 00141 00142 elts = heap->elts; len = elts->len; 00143 00144 if (len == 0) 00145 return NULL; 00146 if (len == 1) 00147 return g_ptr_array_remove_index (elts, 0); 00148 00149 root = elts->pdata[0]; 00150 elts->pdata[0] = g_ptr_array_remove_index (elts, len - 1); 00151 sift_down (heap, 1); 00152 return root; 00153 } 00154 00161 gpointer gts_heap_top (GtsHeap * heap) 00162 { 00163 GPtrArray * elts; 00164 guint len; 00165 00166 g_return_val_if_fail (heap != NULL, NULL); 00167 00168 elts = heap->elts; 00169 len = elts->len; 00170 if (len == 0) 00171 return NULL; 00172 return elts->pdata[0]; 00173 } 00174 00181 void gts_heap_destroy (GtsHeap * heap) 00182 { 00183 g_return_if_fail (heap != NULL); 00184 00185 g_ptr_array_free (heap->elts, TRUE); 00186 g_free (heap); 00187 } 00188 00196 void gts_heap_thaw (GtsHeap * heap) 00197 { 00198 guint i; 00199 00200 g_return_if_fail (heap != NULL); 00201 00202 if (!heap->frozen) 00203 return; 00204 00205 for (i = heap->elts->len/2; i > 0; i--) 00206 sift_down (heap, i); 00207 00208 heap->frozen = FALSE; 00209 } 00210 00217 void gts_heap_foreach (GtsHeap * heap, 00218 GFunc func, 00219 gpointer user_data) 00220 { 00221 guint i; 00222 GPtrArray * elts; 00223 00224 g_return_if_fail (heap != NULL); 00225 g_return_if_fail (func != NULL); 00226 00227 elts = heap->elts; 00228 for (i = 0; i < elts->len; i++) 00229 (*func) (elts->pdata[i], user_data); 00230 } 00231 00240 void gts_heap_freeze (GtsHeap * heap) 00241 { 00242 g_return_if_fail (heap != NULL); 00243 00244 heap->frozen = TRUE; 00245 } 00246 00253 guint gts_heap_size (GtsHeap * heap) 00254 { 00255 g_return_val_if_fail (heap != NULL, 0); 00256 00257 return heap->elts->len; 00258 }