diff pertrackaccumulator.h @ 498:342822c2d49a

Merge api-inversion branch (-r656:771, but I don't expect to return to that branch) into the trunk. I expect there to be minor performance regressions (e.g. in the SOAP server index cacheing, which I have forcibly removed) and minor unplugged memory leaks (e.g. in audioDB::query(), where I don't free up the datum). I hope that these leaks and performance regressions can be plugged in short order. I also expect that some (but maybe not all) of the issues currently addressed in the memory-leaks branch are superseded or fixed by this merge. There remains much work to be done; go forth and do it.
author mas01cr
date Sat, 10 Jan 2009 16:47:57 +0000
parents
children e21a3db643af
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pertrackaccumulator.h	Sat Jan 10 16:47:57 2009 +0000
@@ -0,0 +1,102 @@
+template <class T> class PerTrackAccumulator : public Accumulator {
+public:
+  PerTrackAccumulator(unsigned int pointNN, unsigned int trackNN);
+  ~PerTrackAccumulator();
+  void add_point(adb_result_t *r);
+  adb_query_results_t *get_points();
+private:
+  unsigned int pointNN;
+  unsigned int trackNN;
+  std::map<adb_result_t, std::priority_queue< adb_result_t, std::vector<adb_result_t>, T > *, adb_result_key_lt> *queues;
+  std::set< adb_result_t, adb_result_triple_lt > *set;
+};
+
+template <class T> PerTrackAccumulator<T>::PerTrackAccumulator(unsigned int pointNN, unsigned int trackNN)
+  : pointNN(pointNN), trackNN(trackNN), queues(0), set(0) {
+  queues = new std::map<adb_result_t, std::priority_queue< adb_result_t, std::vector<adb_result_t>, T > *, adb_result_key_lt>;
+  set = new std::set< adb_result_t, adb_result_triple_lt >;
+}
+
+template <class T> PerTrackAccumulator<T>::~PerTrackAccumulator() {
+  if(queues) {
+    typename std::map< adb_result_t, std::priority_queue< adb_result_t, std::vector< adb_result_t >, T > *, adb_result_key_lt>::iterator it;
+    for(it = queues->begin(); it != queues->end(); it++) {
+      delete (*it).second;
+    }
+    delete queues;
+  }
+  if(set) {
+    delete set;
+  }
+}
+
+template <class T> void PerTrackAccumulator<T>::add_point(adb_result_t *r) {
+  if(!isnan(r->dist)) {
+    if(set->find(*r) == set->end()) {
+      set->insert(*r);
+
+      typename std::map< adb_result_t, std::priority_queue< adb_result_t, std::vector< adb_result_t >, T > *, adb_result_key_lt>::iterator it;
+      std::priority_queue< adb_result_t, std::vector< adb_result_t >, T > *queue;
+      it = queues->find(*r);
+      if(it == queues->end()) {
+        queue = new std::priority_queue< adb_result_t, std::vector< adb_result_t >, T >;
+        (*queues)[*r] = queue;
+      } else {
+        queue = (*it).second;
+      }
+
+      queue->push(*r);
+      if(queue->size() > pointNN) {
+        queue->pop();
+      }
+    }
+  }
+}
+
+template <class T> adb_query_results_t *PerTrackAccumulator<T>::get_points() {
+  typename std::map< adb_result_t, std::vector< adb_result_t >, adb_result_key_lt> points;
+  typename std::priority_queue< adb_result_t, std::vector< adb_result_t >, T> queue;
+  typename std::map< adb_result_t, std::priority_queue< adb_result_t, std::vector< adb_result_t >, T > *, adb_result_key_lt>::iterator it;
+
+  unsigned int size = 0;
+  for(it = queues->begin(); it != queues->end(); it++) {
+    unsigned int n = ((*it).second)->size();
+    std::vector<adb_result_t> v;
+    adb_result_t r;
+    double dist = 0;
+    for(unsigned int k = 0; k < n; k++) {
+      r = ((*it).second)->top();
+      dist += r.dist;
+      v.push_back(r);
+      ((*it).second)->pop();
+    }
+    points[r] = v;
+    dist /= n;
+    size += n;
+    r.dist = dist;
+    /* I will burn in hell */
+    r.ipos = n;
+    queue.push(r);
+    if(queue.size() > trackNN) {
+      size -= queue.top().ipos;
+      queue.pop();
+    }
+  }
+
+  adb_query_results_t *r = (adb_query_results_t *) malloc(sizeof(adb_query_results_t));
+  adb_result_t *rs = (adb_result_t *) calloc(size, sizeof(adb_result_t));
+  r->nresults = size;
+  r->results = rs;
+  
+  unsigned int k = 0;
+  while(queue.size() > 0) {
+    std::vector<adb_result_t> v = points[queue.top()];
+    queue.pop();
+    while(v.size() > 0) {
+      rs[k++] = v.back();
+      v.pop_back();
+    }
+  }
+  return r;
+}
+