Mercurial > hg > svcore
diff data/model/EditableDenseThreeDimensionalModel.cpp @ 1777:d484490cdf69
Split EditableDenseThreeDimensionalModel into explicitly compressed and uncompressed variants. Simplifies the uncompressed version, and we may want to consider whether we need the compressed one at all.
author | Chris Cannam |
---|---|
date | Tue, 10 Sep 2019 16:34:47 +0100 |
parents | 6d09d68165a4 |
children | c546429d4c2f |
line wrap: on
line diff
--- a/data/model/EditableDenseThreeDimensionalModel.cpp Mon Sep 09 10:25:16 2019 +0100 +++ b/data/model/EditableDenseThreeDimensionalModel.cpp Tue Sep 10 16:34:47 2019 +0100 @@ -19,8 +19,7 @@ #include <QTextStream> #include <QStringList> -#include <QReadLocker> -#include <QWriteLocker> +#include <QMutexLocker> #include <iostream> @@ -34,13 +33,11 @@ EditableDenseThreeDimensionalModel::EditableDenseThreeDimensionalModel(sv_samplerate_t sampleRate, int resolution, int yBinCount, - CompressionType compression, bool notifyOnAdd) : m_startFrame(0), m_sampleRate(sampleRate), m_resolution(resolution), m_yBinCount(yBinCount), - m_compression(compression), m_minimum(0.0), m_maximum(0.0), m_haveExtents(false), @@ -145,218 +142,82 @@ EditableDenseThreeDimensionalModel::Column EditableDenseThreeDimensionalModel::getColumn(int index) const { - QReadLocker locker(&m_lock); - if (in_range_for(m_data, index)) return expandAndRetrieve(index); - else return Column(); -} - -float -EditableDenseThreeDimensionalModel::getValueAt(int index, int n) const -{ - Column c = getColumn(index); - if (in_range_for(c, n)) return c.at(n); - return m_minimum; -} - -//static int given = 0, stored = 0; - -void -EditableDenseThreeDimensionalModel::truncateAndStore(int index, - const Column &values) -{ - assert(in_range_for(m_data, index)); - - //cout << "truncateAndStore(" << index << ", " << values.size() << ")" << endl; - - // The default case is to store the entire column at m_data[index] - // and place 0 at m_trunc[index] to indicate that it has not been - // truncated. We only do clever stuff if one of the clever-stuff - // tests works out. - - m_trunc[index] = 0; - if (index == 0 || - m_compression == NoCompression || - int(values.size()) != m_yBinCount) { -// given += values.size(); -// stored += values.size(); - m_data[index] = values; - return; + QMutexLocker locker(&m_mutex); + if (!in_range_for(m_data, index)) { + return {}; } - - // Maximum distance between a column and the one we refer to as - // the source of its truncated values. Limited by having to fit - // in a signed char, but in any case small values are usually - // better - static int maxdist = 6; - - bool known = false; // do we know whether to truncate at top or bottom? - bool top = false; // if we do know, will we truncate at top? - - // If the previous column is not truncated, then it is the only - // candidate for comparison. If it is truncated, then the column - // that it refers to is the only candidate. Either way, we only - // have one possible column to compare against here, and we are - // being careful to ensure it is not a truncated one (to avoid - // doing more work recursively when uncompressing). - int tdist = 1; - int ptrunc = m_trunc[index-1]; - if (ptrunc < 0) { - top = false; - known = true; - tdist = -ptrunc + 1; - } else if (ptrunc > 0) { - top = true; - known = true; - tdist = ptrunc + 1; - } - - Column p = expandAndRetrieve(index - tdist); - int h = m_yBinCount; - - if (int(p.size()) == h && tdist <= maxdist) { - - int bcount = 0, tcount = 0; - if (!known || !top) { - // count how many identical values there are at the bottom - for (int i = 0; i < h; ++i) { - if (values.at(i) == p.at(i)) ++bcount; - else break; - } - } - if (!known || top) { - // count how many identical values there are at the top - for (int i = h; i > 0; --i) { - if (values.at(i-1) == p.at(i-1)) ++tcount; - else break; - } - } - if (!known) top = (tcount > bcount); - - int limit = h / 4; // don't bother unless we have at least this many - if ((top ? tcount : bcount) > limit) { - - if (!top) { - // create a new column with h - bcount values from bcount up - Column tcol(h - bcount); -// given += values.size(); -// stored += h - bcount; - for (int i = bcount; i < h; ++i) { - tcol[i - bcount] = values.at(i); - } - m_data[index] = tcol; - m_trunc[index] = (signed char)(-tdist); - return; - } else { - // create a new column with h - tcount values from 0 up - Column tcol(h - tcount); -// given += values.size(); -// stored += h - tcount; - for (int i = 0; i < h - tcount; ++i) { - tcol[i] = values.at(i); - } - m_data[index] = tcol; - m_trunc[index] = (signed char)(tdist); - return; - } - } - } - -// given += values.size(); -// stored += values.size(); -// cout << "given: " << given << ", stored: " << stored << " (" -// << ((float(stored) / float(given)) * 100.f) << "%)" << endl; - - // default case if nothing wacky worked out - m_data[index] = values; - return; -} - -EditableDenseThreeDimensionalModel::Column -EditableDenseThreeDimensionalModel::rightHeight(const Column &c) const -{ - if (int(c.size()) == m_yBinCount) return c; - else { + Column c = m_data.at(index); + if (int(c.size()) == m_yBinCount) { + return c; + } else { Column cc(c); cc.resize(m_yBinCount, 0.0); return cc; } } -EditableDenseThreeDimensionalModel::Column -EditableDenseThreeDimensionalModel::expandAndRetrieve(int index) const +float +EditableDenseThreeDimensionalModel::getValueAt(int index, int n) const { - // See comment above m_trunc declaration in header - - assert(index >= 0 && index < int(m_data.size())); - Column c = m_data.at(index); - if (index == 0) { - return rightHeight(c); + QMutexLocker locker(&m_mutex); + if (!in_range_for(m_data, index)) { + return m_minimum; } - int trunc = (int)m_trunc[index]; - if (trunc == 0) { - return rightHeight(c); + const Column &c = m_data.at(index); + if (!in_range_for(c, n)) { + return m_minimum; } - bool top = true; - int tdist = trunc; - if (trunc < 0) { top = false; tdist = -trunc; } - Column p = expandAndRetrieve(index - tdist); - int psize = int(p.size()), csize = int(c.size()); - if (psize != m_yBinCount) { - cerr << "WARNING: EditableDenseThreeDimensionalModel::expandAndRetrieve: Trying to expand from incorrectly sized column" << endl; - } - if (top) { - for (int i = csize; i < psize; ++i) { - c.push_back(p.at(i)); - } - } else { - Column cc(psize); - for (int i = 0; i < psize - csize; ++i) { - cc[i] = p.at(i); - } - for (int i = 0; i < csize; ++i) { - cc[i + (psize - csize)] = c.at(i); - } - return cc; - } - return c; + return c.at(n); } void EditableDenseThreeDimensionalModel::setColumn(int index, const Column &values) { - QWriteLocker locker(&m_lock); - - while (index >= int(m_data.size())) { - m_data.push_back(Column()); - m_trunc.push_back(0); - } - bool allChange = false; - - for (int i = 0; in_range_for(values, i); ++i) { - float value = values[i]; - if (ISNAN(value) || ISINF(value)) { - continue; - } - if (!m_haveExtents || value < m_minimum) { - m_minimum = value; - allChange = true; - } - if (!m_haveExtents || value > m_maximum) { - m_maximum = value; - allChange = true; - } - m_haveExtents = true; - } - - truncateAndStore(index, values); - -// assert(values == expandAndRetrieve(index)); - sv_frame_t windowStart = index; windowStart *= m_resolution; + { + QMutexLocker locker(&m_mutex); + + while (index >= int(m_data.size())) { + m_data.push_back(Column()); + } + + for (int i = 0; in_range_for(values, i); ++i) { + float value = values[i]; + if (ISNAN(value) || ISINF(value)) { + continue; + } + if (!m_haveExtents || value < m_minimum) { + m_minimum = value; + allChange = true; + } + if (!m_haveExtents || value > m_maximum) { + m_maximum = value; + allChange = true; + } + m_haveExtents = true; + } + + m_data[index] = values; + + if (allChange) { + m_sinceLastNotifyMin = -1; + m_sinceLastNotifyMax = -1; + } else { + if (m_sinceLastNotifyMin == -1 || + windowStart < m_sinceLastNotifyMin) { + m_sinceLastNotifyMin = windowStart; + } + if (m_sinceLastNotifyMax == -1 || + windowStart > m_sinceLastNotifyMax) { + m_sinceLastNotifyMax = windowStart; + } + } + } + if (m_notifyOnAdd) { if (allChange) { emit modelChanged(getId()); @@ -366,18 +227,7 @@ } } else { if (allChange) { - m_sinceLastNotifyMin = -1; - m_sinceLastNotifyMax = -1; emit modelChanged(getId()); - } else { - if (m_sinceLastNotifyMin == -1 || - windowStart < m_sinceLastNotifyMin) { - m_sinceLastNotifyMin = windowStart; - } - if (m_sinceLastNotifyMax == -1 || - windowStart > m_sinceLastNotifyMax) { - m_sinceLastNotifyMax = windowStart; - } } } } @@ -438,7 +288,7 @@ bool EditableDenseThreeDimensionalModel::shouldUseLogValueScale() const { - QReadLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); vector<double> sample; vector<int> n; @@ -507,7 +357,7 @@ sv_frame_t startFrame, sv_frame_t duration) const { - QReadLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); QString s; for (int i = 0; in_range_for(m_data, i); ++i) { sv_frame_t fr = m_startFrame + i * m_resolution; @@ -527,7 +377,7 @@ QString indent, QString extraAttributes) const { - QReadLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); // For historical reasons we read and write "resolution" as "windowSize". @@ -552,7 +402,7 @@ out << QString("<dataset id=\"%1\" dimensions=\"3\" separator=\" \">\n") .arg(getExportId()); - for (int i = 0; i < (int)m_binNames.size(); ++i) { + for (int i = 0; in_range_for(m_binNames, i); ++i) { if (m_binNames[i] != "") { out << indent + " "; out << QString("<bin number=\"%1\" name=\"%2\"/>\n") @@ -560,12 +410,13 @@ } } - for (int i = 0; i < (int)m_data.size(); ++i) { + for (int i = 0; in_range_for(m_data, i); ++i) { + Column c = getColumn(i); out << indent + " "; out << QString("<row n=\"%1\">").arg(i); - for (int j = 0; j < (int)m_data.at(i).size(); ++j) { + for (int j = 0; in_range_for(c, j); ++j) { if (j > 0) out << " "; - out << m_data.at(i).at(j); + out << c.at(j); } out << QString("</row>\n"); out.flush();