comparison accumulator.h @ 416:6e6f4c1cc14d api-inversion

Initial implementation of accumulators for forthcoming audiodb_query(). Minimally tested using a temporary test harness; do not use as food. As well as the necessary C++ magic, doodle in API header files aiming vaguely for a sane API.
author mas01cr
date Wed, 24 Dec 2008 10:54:40 +0000
parents
children 580f696c817c
comparison
equal deleted inserted replaced
415:447f1cf2c276 416:6e6f4c1cc14d
1 #include <string>
2 #include <set>
3 #include <queue>
4 #include <map>
5 #include <functional>
6 #include "audioDB.h"
7 extern "C" {
8 #include "audioDB_API.h"
9 }
10 #include "audioDB-internals.h"
11
12 #ifndef ACCUMULATOR_H
13 #define ACCUMULATOR_H
14
15 class Accumulator {
16 public:
17 virtual ~Accumulator() {};
18 virtual void add_point(adb_result_t *r) = 0;
19 virtual adb_query_results_t *get_points() = 0;
20 };
21
22 template <class T> class DBAccumulator : public Accumulator {
23 public:
24 DBAccumulator(unsigned int pointNN);
25 ~DBAccumulator();
26 void add_point(adb_result_t *r);
27 adb_query_results_t *get_points();
28 private:
29 unsigned int pointNN;
30 std::priority_queue< adb_result_t, std::vector<adb_result_t>, T > *queue;
31 std::set< adb_result_t, adb_result_triple_lt > *set;
32 };
33
34 template <class T> DBAccumulator<T>::DBAccumulator(unsigned int pointNN)
35 : pointNN(pointNN), queue(0), set(0) {
36 queue = new std::priority_queue< adb_result_t, std::vector<adb_result_t>, T>;
37 set = new std::set<adb_result_t, adb_result_triple_lt>;
38 }
39
40 template <class T> DBAccumulator<T>::~DBAccumulator() {
41 if(queue) {
42 delete queue;
43 }
44 if(set) {
45 delete set;
46 }
47 }
48
49 template <class T> void DBAccumulator<T>::add_point(adb_result_t *r) {
50 if(!isnan(r->dist)) {
51 if(set->find(*r) == set->end()) {
52 set->insert(*r);
53 queue->push(*r);
54 if(queue->size() > pointNN) {
55 queue->pop();
56 }
57 }
58 }
59 }
60
61 template <class T> adb_query_results_t *DBAccumulator<T>::get_points() {
62 unsigned int size = queue->size();
63 adb_query_results_t *r = (adb_query_results_t *) malloc(sizeof(adb_query_results_t));
64 adb_result_t *rs = (adb_result_t *) calloc(size, sizeof(adb_result_t));
65 r->nresults = size;
66 r->results = rs;
67
68 for(unsigned int k = 0; k < size; k++) {
69 rs[k] = queue->top();
70 queue->pop();
71 }
72 return r;
73 }
74
75 template <class T> class PerTrackAccumulator : public Accumulator {
76 public:
77 PerTrackAccumulator(unsigned int pointNN, unsigned int trackNN);
78 ~PerTrackAccumulator();
79 void add_point(adb_result_t *r);
80 adb_query_results_t *get_points();
81 private:
82 unsigned int pointNN;
83 unsigned int trackNN;
84 std::map<adb_result_t, std::priority_queue< adb_result_t, std::vector<adb_result_t>, T > *, adb_result_key_lt> *queues;
85 std::set< adb_result_t, adb_result_triple_lt > *set;
86 };
87
88 template <class T> PerTrackAccumulator<T>::PerTrackAccumulator(unsigned int pointNN, unsigned int trackNN)
89 : pointNN(pointNN), trackNN(trackNN), queues(0), set(0) {
90 queues = new std::map<adb_result_t, std::priority_queue< adb_result_t, std::vector<adb_result_t>, T > *, adb_result_key_lt>;
91 set = new std::set< adb_result_t, adb_result_triple_lt >;
92 }
93
94 template <class T> PerTrackAccumulator<T>::~PerTrackAccumulator() {
95 if(queues) {
96 typename std::map< adb_result_t, std::priority_queue< adb_result_t, std::vector< adb_result_t >, T > *, adb_result_key_lt>::iterator it;
97 for(it = queues->begin(); it != queues->end(); it++) {
98 delete (*it).second;
99 }
100 delete queues;
101 }
102 if(set) {
103 delete set;
104 }
105 }
106
107 template <class T> void PerTrackAccumulator<T>::add_point(adb_result_t *r) {
108 if(!isnan(r->dist)) {
109 if(set->find(*r) == set->end()) {
110 set->insert(*r);
111
112 typename std::map< adb_result_t, std::priority_queue< adb_result_t, std::vector< adb_result_t >, T > *, adb_result_key_lt>::iterator it;
113 std::priority_queue< adb_result_t, std::vector< adb_result_t >, T > *queue;
114 it = queues->find(*r);
115 if(it == queues->end()) {
116 queue = new std::priority_queue< adb_result_t, std::vector< adb_result_t >, T >;
117 (*queues)[*r] = queue;
118 } else {
119 queue = (*it).second;
120 }
121
122 queue->push(*r);
123 if(queue->size() > pointNN) {
124 queue->pop();
125 }
126 }
127 }
128 }
129
130 template <class T> adb_query_results_t *PerTrackAccumulator<T>::get_points() {
131 typename std::map< adb_result_t, std::vector< adb_result_t >, adb_result_key_lt> points;
132 typename std::priority_queue< adb_result_t, std::vector< adb_result_t >, T> queue;
133 typename std::map< adb_result_t, std::priority_queue< adb_result_t, std::vector< adb_result_t >, T > *, adb_result_key_lt>::iterator it;
134
135 unsigned int size = 0;
136 for(it = queues->begin(); it != queues->end(); it++) {
137 unsigned int n = ((*it).second)->size();
138 std::vector<adb_result_t> v;
139 adb_result_t r;
140 double dist = 0;
141 for(unsigned int k = 0; k < n; k++) {
142 r = ((*it).second)->top();
143 dist += r.dist;
144 v.push_back(r);
145 ((*it).second)->pop();
146 }
147 points[r] = v;
148 dist /= n;
149 size += n;
150 r.dist = dist;
151 /* I will burn in hell */
152 r.ipos = n;
153 queue.push(r);
154 if(queue.size() > trackNN) {
155 size -= queue.top().ipos;
156 queue.pop();
157 }
158 }
159
160 adb_query_results_t *r = (adb_query_results_t *) malloc(sizeof(adb_query_results_t));
161 adb_result_t *rs = (adb_result_t *) calloc(size, sizeof(adb_result_t));
162 r->nresults = size;
163 r->results = rs;
164
165 unsigned int k = 0;
166 while(queue.size() > 0) {
167 std::vector<adb_result_t> v = points[queue.top()];
168 queue.pop();
169 while(v.size() > 0) {
170 rs[k++] = v.back();
171 v.pop_back();
172 }
173 }
174 return r;
175 }
176
177 template <class T> class NearestAccumulator : public Accumulator {
178 public:
179 NearestAccumulator();
180 ~NearestAccumulator();
181 void add_point(adb_result_t *r);
182 adb_query_results_t *get_points();
183 private:
184 std::set< adb_result_t, adb_result_triple_lt > *set;
185 std::set< adb_result_t, adb_result_qpos_lt > *points;
186 };
187
188 template <class T> NearestAccumulator<T>::NearestAccumulator()
189 : set(0), points(0) {
190 set = new std::set< adb_result_t, adb_result_triple_lt >;
191 points = new std::set< adb_result_t, adb_result_qpos_lt >;
192 }
193
194 template <class T> NearestAccumulator<T>::~NearestAccumulator() {
195 if(set) {
196 delete set;
197 }
198 if(points) {
199 delete points;
200 }
201 }
202
203 template <class T> void NearestAccumulator<T>::add_point(adb_result_t *r) {
204 if(!isnan(r->dist)) {
205 if(set->find(*r) == set->end()) {
206 set->insert(*r);
207
208 std::set< adb_result_t, adb_result_qpos_lt >::iterator it;
209 it = points->find(*r);
210 if(it == points->end()) {
211 points->insert(*r);
212 } else if(T()(*(const adb_result_t *)r,(*it))) {
213 points->erase(it);
214 points->insert(*r);
215 }
216 }
217 }
218 }
219
220 template <class T> adb_query_results_t *NearestAccumulator<T>::get_points() {
221 unsigned int nresults = points->size();
222 adb_query_results_t *r = (adb_query_results_t *) malloc(sizeof(adb_query_results_t));
223 adb_result_t *rs = (adb_result_t *) calloc(nresults, sizeof(adb_result_t));
224 r->nresults = nresults;
225 r->results = rs;
226 std::set< adb_result_t, adb_result_qpos_lt >::iterator it;
227 unsigned int k = 0;
228 for(it = points->begin(); it != points->end(); it++) {
229 rs[k++] = *it;
230 }
231 return r;
232 }
233
234 #endif