mas01cr@408
|
1 typedef struct adb_datum_internal {
|
mas01cr@408
|
2 uint32_t nvectors;
|
mas01cr@408
|
3 uint32_t dim;
|
mas01cr@408
|
4 const char *key;
|
mas01cr@408
|
5 void *data;
|
mas01cr@408
|
6 void *times;
|
mas01cr@408
|
7 void *power;
|
mas01cr@408
|
8 } adb_datum_internal_t;
|
mas01cr@408
|
9
|
mas01cr@402
|
10 struct adb {
|
mas01cr@402
|
11 char *path;
|
mas01cr@402
|
12 int fd;
|
mas01cr@402
|
13 int flags;
|
mas01cr@402
|
14 adb_header_t *header;
|
mas01cr@430
|
15 std::map<std::string,uint32_t> *keys;
|
mas01cr@402
|
16 };
|
mas01cr@402
|
17
|
mas01cr@416
|
18 typedef struct {
|
mas01cr@416
|
19 bool operator() (const adb_result_t &r1, const adb_result_t &r2) {
|
mas01cr@416
|
20 return strcmp(r1.key, r2.key) < 0;
|
mas01cr@416
|
21 }
|
mas01cr@416
|
22 } adb_result_key_lt;
|
mas01cr@416
|
23
|
mas01cr@416
|
24 typedef struct {
|
mas01cr@416
|
25 bool operator() (const adb_result_t &r1, const adb_result_t &r2) {
|
mas01cr@416
|
26 return r1.qpos < r2.qpos;
|
mas01cr@416
|
27 }
|
mas01cr@416
|
28 } adb_result_qpos_lt;
|
mas01cr@416
|
29
|
mas01cr@416
|
30 typedef struct {
|
mas01cr@416
|
31 bool operator() (const adb_result_t &r1, const adb_result_t &r2) {
|
mas01cr@416
|
32 return r1.dist < r2.dist;
|
mas01cr@416
|
33 }
|
mas01cr@416
|
34 } adb_result_dist_lt;
|
mas01cr@416
|
35
|
mas01cr@416
|
36 typedef struct {
|
mas01cr@416
|
37 bool operator() (const adb_result_t &r1, const adb_result_t &r2) {
|
mas01cr@416
|
38 return r1.dist > r2.dist;
|
mas01cr@416
|
39 }
|
mas01cr@416
|
40 } adb_result_dist_gt;
|
mas01cr@416
|
41
|
mas01cr@416
|
42 typedef struct {
|
mas01cr@416
|
43 bool operator() (const adb_result_t &r1, const adb_result_t &r2) {
|
mas01cr@416
|
44 return ((r1.ipos < r2.ipos) ||
|
mas01cr@416
|
45 ((r1.ipos == r2.ipos) &&
|
mas01cr@416
|
46 ((r1.qpos < r2.qpos) ||
|
mas01cr@416
|
47 ((r1.qpos == r2.qpos) && (strcmp(r1.key, r2.key) < 0)))));
|
mas01cr@416
|
48 }
|
mas01cr@416
|
49 } adb_result_triple_lt;
|
mas01cr@416
|
50
|
mas01cr@401
|
51 /* We could go gcc-specific here and use typeof() instead of passing
|
mas01cr@401
|
52 * in an explicit type. Answers on a postcard as to whether that's a
|
mas01cr@401
|
53 * good plan or not. */
|
mas01cr@401
|
54 #define mmap_or_goto_error(type, var, start, length) \
|
mas01cr@401
|
55 { void *tmp = mmap(0, length, PROT_READ, MAP_SHARED, adb->fd, (start)); \
|
mas01cr@401
|
56 if(tmp == (void *) -1) { \
|
mas01cr@401
|
57 goto error; \
|
mas01cr@401
|
58 } \
|
mas01cr@401
|
59 var = (type) tmp; \
|
mas01cr@401
|
60 }
|
mas01cr@401
|
61
|
mas01cr@401
|
62 #define maybe_munmap(table, length) \
|
mas01cr@401
|
63 { if(table) { \
|
mas01cr@401
|
64 munmap(table, length); \
|
mas01cr@401
|
65 } \
|
mas01cr@401
|
66 }
|
mas01cr@401
|
67
|
mas01cr@410
|
68 #define write_or_goto_error(fd, buffer, size) \
|
mas01cr@410
|
69 { ssize_t tmp = size; \
|
mas01cr@410
|
70 if(write(fd, buffer, size) != tmp) { \
|
mas01cr@410
|
71 goto error; \
|
mas01cr@410
|
72 } \
|
mas01cr@410
|
73 }
|
mas01cr@410
|
74
|
mas01cr@410
|
75 #define read_or_goto_error(fd, buffer, size) \
|
mas01cr@410
|
76 { ssize_t tmp = size; \
|
mas01cr@410
|
77 if(read(fd, buffer, size) != tmp) { \
|
mas01cr@410
|
78 goto error; \
|
mas01cr@410
|
79 } \
|
mas01cr@410
|
80 }
|
mas01cr@410
|
81
|
mas01cr@401
|
82 static inline int audiodb_sync_header(adb_t *adb) {
|
mas01cr@401
|
83 off_t pos;
|
mas01cr@401
|
84 pos = lseek(adb->fd, (off_t) 0, SEEK_CUR);
|
mas01cr@401
|
85 if(pos == (off_t) -1) {
|
mas01cr@401
|
86 goto error;
|
mas01cr@401
|
87 }
|
mas01cr@401
|
88 if(lseek(adb->fd, (off_t) 0, SEEK_SET) == (off_t) -1) {
|
mas01cr@401
|
89 goto error;
|
mas01cr@401
|
90 }
|
mas01cr@401
|
91 if(write(adb->fd, adb->header, O2_HEADERSIZE) != O2_HEADERSIZE) {
|
mas01cr@401
|
92 goto error;
|
mas01cr@401
|
93 }
|
mas01cr@401
|
94
|
mas01cr@401
|
95 /* can be fsync() if fdatasync() is racily exciting and new */
|
mas01cr@401
|
96 fdatasync(adb->fd);
|
mas01cr@401
|
97 if(lseek(adb->fd, pos, SEEK_SET) == (off_t) -1) {
|
mas01cr@401
|
98 goto error;
|
mas01cr@401
|
99 }
|
mas01cr@401
|
100 return 0;
|
mas01cr@401
|
101
|
mas01cr@401
|
102 error:
|
mas01cr@401
|
103 return 1;
|
mas01cr@401
|
104 }
|
mas01cr@425
|
105
|
mas01cr@425
|
106 static inline double audiodb_dot_product(double *p, double *q, size_t count) {
|
mas01cr@425
|
107 double result = 0;
|
mas01cr@425
|
108 while(count--) {
|
mas01cr@425
|
109 result += *p++ * *q++;
|
mas01cr@425
|
110 }
|
mas01cr@425
|
111 return result;
|
mas01cr@425
|
112 }
|
mas01cr@426
|
113
|
mas01cr@426
|
114 static inline void audiodb_l2norm_buffer(double *d, size_t dim, size_t nvectors, double *l) {
|
mas01cr@426
|
115 while(nvectors--) {
|
mas01cr@426
|
116 double *d1 = d;
|
mas01cr@426
|
117 double *d2 = d;
|
mas01cr@426
|
118 *l++ = audiodb_dot_product(d1, d2, dim);
|
mas01cr@426
|
119 d += dim;
|
mas01cr@426
|
120 }
|
mas01cr@426
|
121 }
|
mas01cr@427
|
122
|
mas01cr@427
|
123 // This is a common pattern in sequence queries: what we are doing is
|
mas01cr@427
|
124 // taking a window of length seqlen over a buffer of length length,
|
mas01cr@427
|
125 // and placing the sum of the elements in that window in the first
|
mas01cr@427
|
126 // element of the window: thus replacing all but the last seqlen
|
mas01cr@427
|
127 // elements in the buffer with the corresponding windowed sum.
|
mas01cr@427
|
128 static inline void audiodb_sequence_sum(double *buffer, int length, int seqlen) {
|
mas01cr@427
|
129 double tmp1, tmp2, *ps;
|
mas01cr@427
|
130 int j, w;
|
mas01cr@427
|
131
|
mas01cr@427
|
132 tmp1 = *buffer;
|
mas01cr@427
|
133 j = 1;
|
mas01cr@427
|
134 w = seqlen - 1;
|
mas01cr@427
|
135 while(w--) {
|
mas01cr@427
|
136 *buffer += buffer[j++];
|
mas01cr@427
|
137 }
|
mas01cr@427
|
138 ps = buffer + 1;
|
mas01cr@427
|
139 w = length - seqlen; // +1 - 1
|
mas01cr@427
|
140 while(w--) {
|
mas01cr@427
|
141 tmp2 = *ps;
|
mas01cr@427
|
142 if(isfinite(tmp1)) {
|
mas01cr@427
|
143 *ps = *(ps - 1) - tmp1 + *(ps + seqlen - 1);
|
mas01cr@427
|
144 } else {
|
mas01cr@427
|
145 for(int i = 1; i < seqlen; i++) {
|
mas01cr@427
|
146 *ps += *(ps + i);
|
mas01cr@427
|
147 }
|
mas01cr@427
|
148 }
|
mas01cr@427
|
149 tmp1 = tmp2;
|
mas01cr@427
|
150 ps++;
|
mas01cr@427
|
151 }
|
mas01cr@427
|
152 }
|
mas01cr@427
|
153
|
mas01cr@427
|
154 // In contrast to audiodb_sequence_sum() above,
|
mas01cr@427
|
155 // audiodb_sequence_sqrt() and audiodb_sequence_average() below are
|
mas01cr@427
|
156 // simple mappers across the sequence.
|
mas01cr@427
|
157 static inline void audiodb_sequence_sqrt(double *buffer, int length, int seqlen) {
|
mas01cr@427
|
158 int w = length - seqlen + 1;
|
mas01cr@427
|
159 while(w--) {
|
mas01cr@427
|
160 *buffer = sqrt(*buffer);
|
mas01cr@427
|
161 buffer++;
|
mas01cr@427
|
162 }
|
mas01cr@427
|
163 }
|
mas01cr@427
|
164
|
mas01cr@427
|
165 static inline void audiodb_sequence_average(double *buffer, int length, int seqlen) {
|
mas01cr@427
|
166 int w = length - seqlen + 1;
|
mas01cr@427
|
167 while(w--) {
|
mas01cr@427
|
168 *buffer /= seqlen;
|
mas01cr@427
|
169 buffer++;
|
mas01cr@427
|
170 }
|
mas01cr@427
|
171 }
|
mas01cr@430
|
172
|
mas01cr@430
|
173 static inline uint32_t audiodb_key_index(adb_t *adb, const char *key) {
|
mas01cr@430
|
174 std::map<std::string,uint32_t>::iterator it;
|
mas01cr@430
|
175 it = adb->keys->find(key);
|
mas01cr@430
|
176 if(it == adb->keys->end()) {
|
mas01cr@430
|
177 return (uint32_t) -1;
|
mas01cr@430
|
178 } else {
|
mas01cr@430
|
179 return (*it).second;
|
mas01cr@430
|
180 }
|
mas01cr@430
|
181 }
|