comparison data/model/EditableDenseThreeDimensionalModel.cpp @ 535:3ccf48fb81d6

* make compression optional in editable dense 3d model, and some tweaks
author Chris Cannam
date Fri, 23 Jan 2009 14:00:29 +0000
parents 6038cb6fcd30
children beb51f558e9c
comparison
equal deleted inserted replaced
534:6038cb6fcd30 535:3ccf48fb81d6
26 #include <cassert> 26 #include <cassert>
27 27
28 EditableDenseThreeDimensionalModel::EditableDenseThreeDimensionalModel(size_t sampleRate, 28 EditableDenseThreeDimensionalModel::EditableDenseThreeDimensionalModel(size_t sampleRate,
29 size_t resolution, 29 size_t resolution,
30 size_t yBinCount, 30 size_t yBinCount,
31 CompressionType compression,
31 bool notifyOnAdd) : 32 bool notifyOnAdd) :
32 m_sampleRate(sampleRate), 33 m_sampleRate(sampleRate),
33 m_resolution(resolution), 34 m_resolution(resolution),
34 m_yBinCount(yBinCount), 35 m_yBinCount(yBinCount),
36 m_compression(compression),
35 m_minimum(0.0), 37 m_minimum(0.0),
36 m_maximum(0.0), 38 m_maximum(0.0),
37 m_haveExtents(false), 39 m_haveExtents(false),
38 m_notifyOnAdd(notifyOnAdd), 40 m_notifyOnAdd(notifyOnAdd),
39 m_sinceLastNotifyMin(-1), 41 m_sinceLastNotifyMin(-1),
71 { 73 {
72 QMutexLocker locker(&m_mutex); 74 QMutexLocker locker(&m_mutex);
73 75
74 EditableDenseThreeDimensionalModel *model = 76 EditableDenseThreeDimensionalModel *model =
75 new EditableDenseThreeDimensionalModel 77 new EditableDenseThreeDimensionalModel
76 (m_sampleRate, m_resolution, m_yBinCount); 78 (m_sampleRate, m_resolution, m_yBinCount, m_compression);
77 79
78 model->m_minimum = m_minimum; 80 model->m_minimum = m_minimum;
79 model->m_maximum = m_maximum; 81 model->m_maximum = m_maximum;
80 model->m_haveExtents = m_haveExtents; 82 model->m_haveExtents = m_haveExtents;
81 83
150 152
151 float 153 float
152 EditableDenseThreeDimensionalModel::getValueAt(size_t index, size_t n) const 154 EditableDenseThreeDimensionalModel::getValueAt(size_t index, size_t n) const
153 { 155 {
154 Column c = getColumn(index); 156 Column c = getColumn(index);
155 if (n < c.size()) return s.at(n); 157 if (n < c.size()) return c.at(n);
156 return m_minimum; 158 return m_minimum;
157 } 159 }
158 160
159 static int given = 0, stored = 0; 161 //static int given = 0, stored = 0;
160 162
161 void 163 void
162 EditableDenseThreeDimensionalModel::truncateAndStore(size_t index, 164 EditableDenseThreeDimensionalModel::truncateAndStore(size_t index,
163 const Column &values) 165 const Column &values)
164 { 166 {
165 assert(index < m_data.size()); 167 assert(index < m_data.size());
166 168
167 //std::cout << "truncateAndStore(" << index << ", " << values.size() << ")" << std::endl; 169 //std::cout << "truncateAndStore(" << index << ", " << values.size() << ")" << std::endl;
168 170
171 // The default case is to store the entire column at m_data[index]
172 // and place 0 at m_trunc[index] to indicate that it has not been
173 // truncated. We only do clever stuff if one of the clever-stuff
174 // tests works out.
175
169 m_trunc[index] = 0; 176 m_trunc[index] = 0;
170 if (index == 0 || values.size() != m_yBinCount) { 177 if (index == 0 ||
171 given += values.size(); 178 m_compression == NoCompression ||
172 stored += values.size(); 179 values.size() != m_yBinCount) {
180 // given += values.size();
181 // stored += values.size();
173 m_data[index] = values; 182 m_data[index] = values;
174 return; 183 return;
175 } 184 }
176 185
177 static int maxdist = 120; 186 // Maximum distance between a column and the one we refer to as
178 187 // the source of its truncated values. Limited by having to fit
179 bool known = false; 188 // in a signed char, but in any case small values are usually
180 bool top = false; 189 // better
181 190 static int maxdist = 6;
191
192 bool known = false; // do we know whether to truncate at top or bottom?
193 bool top = false; // if we do know, will we truncate at top?
194
195 // If the previous column is not truncated, then it is the only
196 // candidate for comparison. If it is truncated, then the column
197 // that it refers to is the only candidate. Either way, we only
198 // have one possible column to compare against here, and we are
199 // being careful to ensure it is not a truncated one (to avoid
200 // doing more work recursively when uncompressing).
182 int tdist = 1; 201 int tdist = 1;
183 int ptrunc = m_trunc[index-1]; 202 int ptrunc = m_trunc[index-1];
184 if (ptrunc < 0) { 203 if (ptrunc < 0) {
185 top = false; 204 top = false;
186 known = true; 205 known = true;
196 215
197 if (p.size() == h && tdist <= maxdist) { 216 if (p.size() == h && tdist <= maxdist) {
198 217
199 int bcount = 0, tcount = 0; 218 int bcount = 0, tcount = 0;
200 if (!known || !top) { 219 if (!known || !top) {
220 // count how many identical values there are at the bottom
201 for (int i = 0; i < h; ++i) { 221 for (int i = 0; i < h; ++i) {
202 if (values.at(i) == p.at(i)) ++bcount; 222 if (values.at(i) == p.at(i)) ++bcount;
203 else break; 223 else break;
204 } 224 }
205 } 225 }
206 if (!known || top) { 226 if (!known || top) {
227 // count how many identical values there are at the top
207 for (int i = h; i > 0; --i) { 228 for (int i = h; i > 0; --i) {
208 if (values.at(i-1) == p.at(i-1)) ++tcount; 229 if (values.at(i-1) == p.at(i-1)) ++tcount;
209 else break; 230 else break;
210 } 231 }
211 } 232 }
212 if (!known) top = (tcount > bcount); 233 if (!known) top = (tcount > bcount);
213 234
214 int limit = h / 4; 235 int limit = h / 4; // don't bother unless we have at least this many
215 if ((top ? tcount : bcount) > limit) { 236 if ((top ? tcount : bcount) > limit) {
216 237
217 if (!top) { 238 if (!top) {
239 // create a new column with h - bcount values from bcount up
218 Column tcol(h - bcount); 240 Column tcol(h - bcount);
219 given += values.size(); 241 // given += values.size();
220 stored += h - bcount; 242 // stored += h - bcount;
221 for (int i = bcount; i < h; ++i) { 243 for (int i = bcount; i < h; ++i) {
222 tcol[i - bcount] = values.at(i); 244 tcol[i - bcount] = values.at(i);
223 } 245 }
224 m_data[index] = tcol; 246 m_data[index] = tcol;
225 m_trunc[index] = -tdist; 247 m_trunc[index] = -tdist;
226 //std::cout << "bottom " << bcount << " as col at " << -tdist << std::endl;
227 return; 248 return;
228 } else { 249 } else {
250 // create a new column with h - tcount values from 0 up
229 Column tcol(h - tcount); 251 Column tcol(h - tcount);
230 given += values.size(); 252 // given += values.size();
231 stored += h - tcount; 253 // stored += h - tcount;
232 for (int i = 0; i < h - tcount; ++i) { 254 for (int i = 0; i < h - tcount; ++i) {
233 tcol[i] = values.at(i); 255 tcol[i] = values.at(i);
234 } 256 }
235 m_data[index] = tcol; 257 m_data[index] = tcol;
236 m_trunc[index] = tdist; 258 m_trunc[index] = tdist;
237 //std::cout << "top " << tcount << " as col at " << -tdist << std::endl;
238 return; 259 return;
239 } 260 }
240 } 261 }
241 } 262 }
242 263
243 given += values.size(); 264 // given += values.size();
244 stored += values.size(); 265 // stored += values.size();
245
246 // std::cout << "given: " << given << ", stored: " << stored << " (" 266 // std::cout << "given: " << given << ", stored: " << stored << " ("
247 // << ((float(stored) / float(given)) * 100.f) << "%)" << std::endl; 267 // << ((float(stored) / float(given)) * 100.f) << "%)" << std::endl;
248 268
269 // default case if nothing wacky worked out
249 m_data[index] = values; 270 m_data[index] = values;
250 return; 271 return;
251 } 272 }
252 273
253 EditableDenseThreeDimensionalModel::Column 274 EditableDenseThreeDimensionalModel::Column
254 EditableDenseThreeDimensionalModel::expandAndRetrieve(size_t index) const 275 EditableDenseThreeDimensionalModel::expandAndRetrieve(size_t index) const
255 { 276 {
277 // See comment above m_trunc declaration in header
278
256 assert(index < m_data.size()); 279 assert(index < m_data.size());
257 Column c = m_data.at(index); 280 Column c = m_data.at(index);
258 if (index == 0) { 281 if (index == 0) {
259 return c; 282 return c;
260 } 283 }