annotate tree.c @ 727:98b64f65be0d libavutil

Reorganise intreadwrite.h This changes intreadwrite.h to support per-arch implementations of the various macros allowing us to take advantage of special instructions or other properties the compiler does not know about.
author mru
date Sat, 18 Apr 2009 00:00:22 +0000
parents 5d344280a1f8
children f0e08dd7d583
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
136
4ae092965c27 AVL tree
michael
parents:
diff changeset
1 /*
4ae092965c27 AVL tree
michael
parents:
diff changeset
2 * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
4ae092965c27 AVL tree
michael
parents:
diff changeset
3 *
4ae092965c27 AVL tree
michael
parents:
diff changeset
4 * This file is part of FFmpeg.
4ae092965c27 AVL tree
michael
parents:
diff changeset
5 *
4ae092965c27 AVL tree
michael
parents:
diff changeset
6 * FFmpeg is free software; you can redistribute it and/or
4ae092965c27 AVL tree
michael
parents:
diff changeset
7 * modify it under the terms of the GNU Lesser General Public
4ae092965c27 AVL tree
michael
parents:
diff changeset
8 * License as published by the Free Software Foundation; either
4ae092965c27 AVL tree
michael
parents:
diff changeset
9 * version 2.1 of the License, or (at your option) any later version.
4ae092965c27 AVL tree
michael
parents:
diff changeset
10 *
4ae092965c27 AVL tree
michael
parents:
diff changeset
11 * FFmpeg is distributed in the hope that it will be useful,
4ae092965c27 AVL tree
michael
parents:
diff changeset
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
4ae092965c27 AVL tree
michael
parents:
diff changeset
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
4ae092965c27 AVL tree
michael
parents:
diff changeset
14 * Lesser General Public License for more details.
4ae092965c27 AVL tree
michael
parents:
diff changeset
15 *
4ae092965c27 AVL tree
michael
parents:
diff changeset
16 * You should have received a copy of the GNU Lesser General Public
4ae092965c27 AVL tree
michael
parents:
diff changeset
17 * License along with FFmpeg; if not, write to the Free Software
4ae092965c27 AVL tree
michael
parents:
diff changeset
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
4ae092965c27 AVL tree
michael
parents:
diff changeset
19 */
4ae092965c27 AVL tree
michael
parents:
diff changeset
20
4ae092965c27 AVL tree
michael
parents:
diff changeset
21 #include "common.h"
4ae092965c27 AVL tree
michael
parents:
diff changeset
22 #include "log.h"
4ae092965c27 AVL tree
michael
parents:
diff changeset
23 #include "tree.h"
4ae092965c27 AVL tree
michael
parents:
diff changeset
24
4ae092965c27 AVL tree
michael
parents:
diff changeset
25 typedef struct AVTreeNode{
4ae092965c27 AVL tree
michael
parents:
diff changeset
26 struct AVTreeNode *child[2];
4ae092965c27 AVL tree
michael
parents:
diff changeset
27 void *elem;
4ae092965c27 AVL tree
michael
parents:
diff changeset
28 int state;
4ae092965c27 AVL tree
michael
parents:
diff changeset
29 }AVTreeNode;
4ae092965c27 AVL tree
michael
parents:
diff changeset
30
413
a54e20281de9 Move *malloc() out of tree.c, that way the code can be used with
michael
parents: 412
diff changeset
31 const int av_tree_node_size = sizeof(AVTreeNode);
a54e20281de9 Move *malloc() out of tree.c, that way the code can be used with
michael
parents: 412
diff changeset
32
136
4ae092965c27 AVL tree
michael
parents:
diff changeset
33 void *av_tree_find(const AVTreeNode *t, void *key, int (*cmp)(void *key, const void *b), void *next[2]){
4ae092965c27 AVL tree
michael
parents:
diff changeset
34 if(t){
418
9f2461caf179 Flip key and element so types match, not that it matters for any code
michael
parents: 415
diff changeset
35 unsigned int v= cmp(key, t->elem);
136
4ae092965c27 AVL tree
michael
parents:
diff changeset
36 if(v){
418
9f2461caf179 Flip key and element so types match, not that it matters for any code
michael
parents: 415
diff changeset
37 if(next) next[v>>31]= t->elem;
9f2461caf179 Flip key and element so types match, not that it matters for any code
michael
parents: 415
diff changeset
38 return av_tree_find(t->child[(v>>31)^1], key, cmp, next);
136
4ae092965c27 AVL tree
michael
parents:
diff changeset
39 }else{
412
357ac44f4720 Always set next correctly, even if a matching element is found (that is
michael
parents: 404
diff changeset
40 if(next){
357ac44f4720 Always set next correctly, even if a matching element is found (that is
michael
parents: 404
diff changeset
41 av_tree_find(t->child[0], key, cmp, next);
357ac44f4720 Always set next correctly, even if a matching element is found (that is
michael
parents: 404
diff changeset
42 av_tree_find(t->child[1], key, cmp, next);
357ac44f4720 Always set next correctly, even if a matching element is found (that is
michael
parents: 404
diff changeset
43 }
136
4ae092965c27 AVL tree
michael
parents:
diff changeset
44 return t->elem;
4ae092965c27 AVL tree
michael
parents:
diff changeset
45 }
4ae092965c27 AVL tree
michael
parents:
diff changeset
46 }
4ae092965c27 AVL tree
michael
parents:
diff changeset
47 return NULL;
4ae092965c27 AVL tree
michael
parents:
diff changeset
48 }
4ae092965c27 AVL tree
michael
parents:
diff changeset
49
413
a54e20281de9 Move *malloc() out of tree.c, that way the code can be used with
michael
parents: 412
diff changeset
50 void *av_tree_insert(AVTreeNode **tp, void *key, int (*cmp)(void *key, const void *b), AVTreeNode **next){
136
4ae092965c27 AVL tree
michael
parents:
diff changeset
51 AVTreeNode *t= *tp;
4ae092965c27 AVL tree
michael
parents:
diff changeset
52 if(t){
4ae092965c27 AVL tree
michael
parents:
diff changeset
53 unsigned int v= cmp(t->elem, key);
414
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
54 void *ret;
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
55 if(!v){
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
56 if(*next)
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
57 return t->elem;
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
58 else if(t->child[0]||t->child[1]){
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
59 int i= !t->child[0];
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
60 void *next_elem[2];
429
3be382cb92ba simplify
michael
parents: 425
diff changeset
61 av_tree_find(t->child[i], key, cmp, next_elem);
414
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
62 key= t->elem= next_elem[i];
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
63 v= -i;
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
64 }else{
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
65 *next= t;
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
66 *tp=NULL;
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
67 return NULL;
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
68 }
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
69 }
419
michael
parents: 418
diff changeset
70 ret= av_tree_insert(&t->child[v>>31], key, cmp, next);
michael
parents: 418
diff changeset
71 if(!ret){
michael
parents: 418
diff changeset
72 int i= (v>>31) ^ !!*next;
michael
parents: 418
diff changeset
73 AVTreeNode **child= &t->child[i];
michael
parents: 418
diff changeset
74 t->state += 2*i - 1;
414
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
75
419
michael
parents: 418
diff changeset
76 if(!(t->state&1)){
michael
parents: 418
diff changeset
77 if(t->state){
433
0839746f3fcf Comment to explain how the add/remove core works.
michael
parents: 430
diff changeset
78 /* The following code is equivalent to
0839746f3fcf Comment to explain how the add/remove core works.
michael
parents: 430
diff changeset
79 if((*child)->state*2 == -t->state)
0839746f3fcf Comment to explain how the add/remove core works.
michael
parents: 430
diff changeset
80 rotate(child, i^1);
0839746f3fcf Comment to explain how the add/remove core works.
michael
parents: 430
diff changeset
81 rotate(tp, i);
0839746f3fcf Comment to explain how the add/remove core works.
michael
parents: 430
diff changeset
82
0839746f3fcf Comment to explain how the add/remove core works.
michael
parents: 430
diff changeset
83 with rotate():
0839746f3fcf Comment to explain how the add/remove core works.
michael
parents: 430
diff changeset
84 static void rotate(AVTreeNode **tp, int i){
0839746f3fcf Comment to explain how the add/remove core works.
michael
parents: 430
diff changeset
85 AVTreeNode *t= *tp;
0839746f3fcf Comment to explain how the add/remove core works.
michael
parents: 430
diff changeset
86
0839746f3fcf Comment to explain how the add/remove core works.
michael
parents: 430
diff changeset
87 *tp= t->child[i];
0839746f3fcf Comment to explain how the add/remove core works.
michael
parents: 430
diff changeset
88 t->child[i]= t->child[i]->child[i^1];
0839746f3fcf Comment to explain how the add/remove core works.
michael
parents: 430
diff changeset
89 (*tp)->child[i^1]= t;
0839746f3fcf Comment to explain how the add/remove core works.
michael
parents: 430
diff changeset
90 i= 4*t->state + 2*(*tp)->state + 12;
0839746f3fcf Comment to explain how the add/remove core works.
michael
parents: 430
diff changeset
91 t ->state= ((0x614586 >> i) & 3)-1;
0839746f3fcf Comment to explain how the add/remove core works.
michael
parents: 430
diff changeset
92 (*tp)->state= ((*tp)->state>>1) + ((0x400EEA >> i) & 3)-1;
0839746f3fcf Comment to explain how the add/remove core works.
michael
parents: 430
diff changeset
93 }
0839746f3fcf Comment to explain how the add/remove core works.
michael
parents: 430
diff changeset
94 but such a rotate function is both bigger and slower
0839746f3fcf Comment to explain how the add/remove core works.
michael
parents: 430
diff changeset
95 */
419
michael
parents: 418
diff changeset
96 if((*child)->state*2 == -t->state){
michael
parents: 418
diff changeset
97 *tp= (*child)->child[i^1];
michael
parents: 418
diff changeset
98 (*child)->child[i^1]= (*tp)->child[i];
michael
parents: 418
diff changeset
99 (*tp)->child[i]= *child;
michael
parents: 418
diff changeset
100 *child= (*tp)->child[i^1];
michael
parents: 418
diff changeset
101 (*tp)->child[i^1]= t;
136
4ae092965c27 AVL tree
michael
parents:
diff changeset
102
419
michael
parents: 418
diff changeset
103 (*tp)->child[0]->state= -((*tp)->state>0);
michael
parents: 418
diff changeset
104 (*tp)->child[1]->state= (*tp)->state<0 ;
michael
parents: 418
diff changeset
105 (*tp)->state=0;
michael
parents: 418
diff changeset
106 }else{
michael
parents: 418
diff changeset
107 *tp= *child;
michael
parents: 418
diff changeset
108 *child= (*child)->child[i^1];
michael
parents: 418
diff changeset
109 (*tp)->child[i^1]= t;
michael
parents: 418
diff changeset
110 if((*tp)->state) t->state = 0;
michael
parents: 418
diff changeset
111 else t->state>>= 1;
michael
parents: 418
diff changeset
112 (*tp)->state= -t->state;
136
4ae092965c27 AVL tree
michael
parents:
diff changeset
113 }
414
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
114 }
136
4ae092965c27 AVL tree
michael
parents:
diff changeset
115 }
419
michael
parents: 418
diff changeset
116 if(!(*tp)->state ^ !!*next)
michael
parents: 418
diff changeset
117 return key;
michael
parents: 418
diff changeset
118 }
michael
parents: 418
diff changeset
119 return ret;
136
4ae092965c27 AVL tree
michael
parents:
diff changeset
120 }else{
413
a54e20281de9 Move *malloc() out of tree.c, that way the code can be used with
michael
parents: 412
diff changeset
121 *tp= *next; *next= NULL;
572
5877edf05eb7 Avoid undefined behavior for removing elements that were not in the tree.
michael
parents: 433
diff changeset
122 if(*tp){
5877edf05eb7 Avoid undefined behavior for removing elements that were not in the tree.
michael
parents: 433
diff changeset
123 (*tp)->elem= key;
5877edf05eb7 Avoid undefined behavior for removing elements that were not in the tree.
michael
parents: 433
diff changeset
124 return NULL;
5877edf05eb7 Avoid undefined behavior for removing elements that were not in the tree.
michael
parents: 433
diff changeset
125 }else
5877edf05eb7 Avoid undefined behavior for removing elements that were not in the tree.
michael
parents: 433
diff changeset
126 return key;
136
4ae092965c27 AVL tree
michael
parents:
diff changeset
127 }
4ae092965c27 AVL tree
michael
parents:
diff changeset
128 }
4ae092965c27 AVL tree
michael
parents:
diff changeset
129
4ae092965c27 AVL tree
michael
parents:
diff changeset
130 void av_tree_destroy(AVTreeNode *t){
593
6fabc7908537 add a termination condition
aurel
parents: 572
diff changeset
131 if(t){
594
1f3b92c985eb cosmetic: indent
aurel
parents: 593
diff changeset
132 av_tree_destroy(t->child[0]);
1f3b92c985eb cosmetic: indent
aurel
parents: 593
diff changeset
133 av_tree_destroy(t->child[1]);
1f3b92c985eb cosmetic: indent
aurel
parents: 593
diff changeset
134 av_free(t);
593
6fabc7908537 add a termination condition
aurel
parents: 572
diff changeset
135 }
136
4ae092965c27 AVL tree
michael
parents:
diff changeset
136 }
4ae092965c27 AVL tree
michael
parents:
diff changeset
137
4ae092965c27 AVL tree
michael
parents:
diff changeset
138 #if 0
4ae092965c27 AVL tree
michael
parents:
diff changeset
139 void av_tree_enumerate(AVTreeNode *t, void *opaque, int (*f)(void *opaque, void *elem)){
137
dbcf66639764 improve enumerate so arbitrary ranges can be enumerated quickly
michael
parents: 136
diff changeset
140 int v= f(opaque, t->elem);
dbcf66639764 improve enumerate so arbitrary ranges can be enumerated quickly
michael
parents: 136
diff changeset
141 if(v>=0) av_tree_enumerate(t->child[0], opaque, f);
dbcf66639764 improve enumerate so arbitrary ranges can be enumerated quickly
michael
parents: 136
diff changeset
142 if(v<=0) av_tree_enumerate(t->child[1], opaque, f);
136
4ae092965c27 AVL tree
michael
parents:
diff changeset
143 }
4ae092965c27 AVL tree
michael
parents:
diff changeset
144 #endif
4ae092965c27 AVL tree
michael
parents:
diff changeset
145
4ae092965c27 AVL tree
michael
parents:
diff changeset
146 #ifdef TEST
701
ae6e96434bec Replace random() usage in test programs by av_lfg_*().
diego
parents: 633
diff changeset
147
ae6e96434bec Replace random() usage in test programs by av_lfg_*().
diego
parents: 633
diff changeset
148 #include "lfg.h"
ae6e96434bec Replace random() usage in test programs by av_lfg_*().
diego
parents: 633
diff changeset
149
136
4ae092965c27 AVL tree
michael
parents:
diff changeset
150 static int check(AVTreeNode *t){
4ae092965c27 AVL tree
michael
parents:
diff changeset
151 if(t){
4ae092965c27 AVL tree
michael
parents:
diff changeset
152 int left= check(t->child[0]);
4ae092965c27 AVL tree
michael
parents:
diff changeset
153 int right= check(t->child[1]);
4ae092965c27 AVL tree
michael
parents:
diff changeset
154
4ae092965c27 AVL tree
michael
parents:
diff changeset
155 if(left>999 || right>999)
4ae092965c27 AVL tree
michael
parents:
diff changeset
156 return 1000;
4ae092965c27 AVL tree
michael
parents:
diff changeset
157 if(right - left != t->state)
4ae092965c27 AVL tree
michael
parents:
diff changeset
158 return 1000;
4ae092965c27 AVL tree
michael
parents:
diff changeset
159 if(t->state>1 || t->state<-1)
4ae092965c27 AVL tree
michael
parents:
diff changeset
160 return 1000;
4ae092965c27 AVL tree
michael
parents:
diff changeset
161 return FFMAX(left, right)+1;
4ae092965c27 AVL tree
michael
parents:
diff changeset
162 }
4ae092965c27 AVL tree
michael
parents:
diff changeset
163 return 0;
4ae092965c27 AVL tree
michael
parents:
diff changeset
164 }
4ae092965c27 AVL tree
michael
parents:
diff changeset
165
4ae092965c27 AVL tree
michael
parents:
diff changeset
166 static void print(AVTreeNode *t, int depth){
4ae092965c27 AVL tree
michael
parents:
diff changeset
167 int i;
4ae092965c27 AVL tree
michael
parents:
diff changeset
168 for(i=0; i<depth*4; i++) av_log(NULL, AV_LOG_ERROR, " ");
4ae092965c27 AVL tree
michael
parents:
diff changeset
169 if(t){
717
01f68e5fb9af Fix warnings in tree.c test code.
benoit
parents: 716
diff changeset
170 av_log(NULL, AV_LOG_ERROR, "Node %p %2d %p\n", t, t->state, t->elem);
136
4ae092965c27 AVL tree
michael
parents:
diff changeset
171 print(t->child[0], depth+1);
4ae092965c27 AVL tree
michael
parents:
diff changeset
172 print(t->child[1], depth+1);
4ae092965c27 AVL tree
michael
parents:
diff changeset
173 }else
4ae092965c27 AVL tree
michael
parents:
diff changeset
174 av_log(NULL, AV_LOG_ERROR, "NULL\n");
4ae092965c27 AVL tree
michael
parents:
diff changeset
175 }
4ae092965c27 AVL tree
michael
parents:
diff changeset
176
717
01f68e5fb9af Fix warnings in tree.c test code.
benoit
parents: 716
diff changeset
177 static int cmp(void *a, const void *b){
01f68e5fb9af Fix warnings in tree.c test code.
benoit
parents: 716
diff changeset
178 return (uint8_t*)a-(const uint8_t*)b;
136
4ae092965c27 AVL tree
michael
parents:
diff changeset
179 }
4ae092965c27 AVL tree
michael
parents:
diff changeset
180
404
f9a4c04ebb0e main() --> main(void)
diego
parents: 141
diff changeset
181 int main(void){
717
01f68e5fb9af Fix warnings in tree.c test code.
benoit
parents: 716
diff changeset
182 int i;
01f68e5fb9af Fix warnings in tree.c test code.
benoit
parents: 716
diff changeset
183 void *k;
414
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
184 AVTreeNode *root= NULL, *node=NULL;
726
5d344280a1f8 cosmetics: Rename prn variable to prng (Pseudo Random Number Generator).
diego
parents: 717
diff changeset
185 AVLFG prng;
701
ae6e96434bec Replace random() usage in test programs by av_lfg_*().
diego
parents: 633
diff changeset
186
726
5d344280a1f8 cosmetics: Rename prn variable to prng (Pseudo Random Number Generator).
diego
parents: 717
diff changeset
187 av_lfg_init(&prng, 1);
136
4ae092965c27 AVL tree
michael
parents:
diff changeset
188
4ae092965c27 AVL tree
michael
parents:
diff changeset
189 for(i=0; i<10000; i++){
726
5d344280a1f8 cosmetics: Rename prn variable to prng (Pseudo Random Number Generator).
diego
parents: 717
diff changeset
190 int j = av_lfg_get(&prng) % 86294;
136
4ae092965c27 AVL tree
michael
parents:
diff changeset
191 if(check(root) > 999){
4ae092965c27 AVL tree
michael
parents:
diff changeset
192 av_log(NULL, AV_LOG_ERROR, "FATAL error %d\n", i);
4ae092965c27 AVL tree
michael
parents:
diff changeset
193 print(root, 0);
4ae092965c27 AVL tree
michael
parents:
diff changeset
194 return -1;
4ae092965c27 AVL tree
michael
parents:
diff changeset
195 }
4ae092965c27 AVL tree
michael
parents:
diff changeset
196 av_log(NULL, AV_LOG_ERROR, "inserting %4d\n", j);
414
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
197 if(!node)
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
198 node= av_mallocz(av_tree_node_size);
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
199 av_tree_insert(&root, (void*)(j+1), cmp, &node);
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
200
726
5d344280a1f8 cosmetics: Rename prn variable to prng (Pseudo Random Number Generator).
diego
parents: 717
diff changeset
201 j = av_lfg_get(&prng) % 86294;
572
5877edf05eb7 Avoid undefined behavior for removing elements that were not in the tree.
michael
parents: 433
diff changeset
202 {
414
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
203 AVTreeNode *node2=NULL;
430
42011b593830 Print removing of nodes in the test code.
michael
parents: 429
diff changeset
204 av_log(NULL, AV_LOG_ERROR, "removing %4d\n", j);
414
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
205 av_tree_insert(&root, (void*)(j+1), cmp, &node2);
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
206 k= av_tree_find(root, (void*)(j+1), cmp, NULL);
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
207 if(k)
633
8c48a1b999a3 spelling/grammar/consistency review part I
diego
parents: 594
diff changeset
208 av_log(NULL, AV_LOG_ERROR, "removal failure %d\n", i);
414
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
209 }
136
4ae092965c27 AVL tree
michael
parents:
diff changeset
210 }
4ae092965c27 AVL tree
michael
parents:
diff changeset
211 return 0;
4ae092965c27 AVL tree
michael
parents:
diff changeset
212 }
4ae092965c27 AVL tree
michael
parents:
diff changeset
213 #endif