[apps] Multiple data series in FloatPairStore

This commit is contained in:
Léa Saviot
2018-05-21 12:21:57 +02:00
parent 600f5307c4
commit 33fa32d55f
4 changed files with 137 additions and 137 deletions

View File

@@ -6,64 +6,55 @@
namespace Shared {
FloatPairStore::FloatPairStore() :
m_numberOfPairs(0),
m_data{}
{
}
double FloatPairStore::get(int i, int j) {
assert(j < m_numberOfPairs);
return m_data[i][j];
}
void FloatPairStore::set(double f, int i, int j) {
void FloatPairStore::set(double f, int series, int i, int j) {
assert(series >= 0 && series < k_numberOfSeries);
if (j >= k_maxNumberOfPairs) {
return;
}
m_data[i][j] = f;
m_data[series][i][j] = f;
if (j >= m_numberOfPairs) {
int otherI = i == 0 ? 1 : 0;
m_data[otherI][j] = defaultValue(otherI, j);
m_numberOfPairs++;
m_data[series][otherI][j] = defaultValue(otherI, j);
m_numberOfPairs[series]++;
}
}
int FloatPairStore::numberOfPairs() {
return m_numberOfPairs;
}
void FloatPairStore::deletePairAtIndex(int i) {
m_numberOfPairs--;
for (int k = i; k < m_numberOfPairs; k++) {
m_data[0][k] = m_data[0][k+1];
m_data[1][k] = m_data[1][k+1];
void FloatPairStore::deletePairAtIndex(int series, int j) {
m_numberOfPairs[series]--;
for (int k = j; k < m_numberOfPairs[series]; k++) {
m_data[series][0][k] = m_data[series][0][k+1];
m_data[series][1][k] = m_data[series][1][k+1];
}
/* We reset the values of the empty row to ensure the correctness of the
* checksum. */
m_data[0][m_numberOfPairs] = 0;
m_data[1][m_numberOfPairs] = 0;
m_data[series][0][m_numberOfPairs] = 0;
m_data[series][1][m_numberOfPairs] = 0;
}
void FloatPairStore::deleteAllPairs() {
void FloatPairStore::deleteAllPairs(int series) {
assert(series >= 0 && series < k_numberOfSeries);
/* We reset all values to 0 to ensure the correctness of the checksum.*/
for (int k = 0; k < m_numberOfPairs; k++) {
m_data[0][k] = 0;
m_data[1][k] = 0;
for (int k = 0; k < m_numberOfPairs[series]; k++) {
m_data[series][0][k] = 0;
m_data[series][1][k] = 0;
}
m_numberOfPairs = 0;
m_numberOfPairs[series] = 0;
}
void FloatPairStore::resetColumn(int i) {
for (int k = 0; k < m_numberOfPairs; k++) {
m_data[i][k] = defaultValue(i, k);
void FloatPairStore::resetColumn(int series, int i) {
assert(series >= 0 && series < k_numberOfSeries);
assert(i == 0 || i == 1);
for (int k = 0; k < m_numberOfPairs[series]; k++) {
m_data[series][i][k] = defaultValue(i, k);
}
}
double FloatPairStore::sumOfColumn(int i) {
double FloatPairStore::sumOfColumn(int series, int i) {
assert(series >= 0 && series < k_numberOfSeries);
assert(i == 0 || i == 1);
double result = 0;
for (int k = 0; k < m_numberOfPairs; k++) {
result += m_data[i][k];
for (int k = 0; k < m_numberOfPairs[series]; k++) {
result += m_data[series][i][k];
}
return result;
}
@@ -73,14 +64,15 @@ uint32_t FloatPairStore::storeChecksum() {
* pairs. However, the two values of a pair are not stored consecutively. We
* thus compute the checksum on all pairs and ensure to set the pair at 0
* when removing them. */
size_t dataLengthInBytes = k_maxNumberOfPairs*2*sizeof(double);
size_t dataLengthInBytes = k_numberOfSeries*k_maxNumberOfPairs*2*sizeof(double);
assert((dataLengthInBytes & 0x3) == 0); // Assert that dataLengthInBytes is a multiple of 4
return Ion::crc32((uint32_t *)m_data, dataLengthInBytes/sizeof(uint32_t));
}
double FloatPairStore::defaultValue(int i, int j) {
double FloatPairStore::defaultValue(int series, int i, int j) {
assert(series >= 0 && series < k_numberOfSeries);
if(i == 0 && j > 1) {
return 2*m_data[i][j-1]-m_data[i][j-2];
return 2*m_data[series][i][j-1]-m_data[i][j-2];
} else {
return 0.0;
}

View File

@@ -2,27 +2,35 @@
#define SHARED_FLOAT_PAIR_STORE_H
#include <stdint.h>
#include <assert.h>
namespace Shared {
class FloatPairStore {
public:
FloatPairStore();
constexpr static int k_numberOfSeries = 3;
constexpr static int k_maxNumberOfPairs = 100;
FloatPairStore() :
m_numberOfPairs{},
m_data{}
{}
// Delete the implicit copy constructor: the object is heavy
FloatPairStore(const FloatPairStore&) = delete;
double get(int i, int j);
void set(double f, int i, int j);
int numberOfPairs();
void deletePairAtIndex(int j);
void deleteAllPairs();
void resetColumn(int i);
double sumOfColumn(int i);
double get(int series, int i, int j) const {
assert(j < m_numberOfPairs[series]);
return m_data[series][i][j];
}
void set(double f, int series, int i, int j);
int numberOfPairsOfSeries(int series) const { return m_numberOfPairs[series]; }
void deletePairAtIndex(int series, int j);
void deleteAllPairs(int series);
void resetColumn(int series, int i);
double sumOfColumn(int series, int i);
uint32_t storeChecksum();
constexpr static int k_maxNumberOfPairs = 100;
protected:
virtual double defaultValue(int i, int j);
int m_numberOfPairs;
double m_data[2][k_maxNumberOfPairs];
virtual double defaultValue(int series, int i, int j);
int m_numberOfPairs[k_numberOfSeries];
double m_data[k_numberOfSeries][2][k_maxNumberOfPairs];
};
}

View File

@@ -32,34 +32,34 @@ void Store::setBarWidth(double barWidth) {
}
}
double Store::heightOfBarAtIndex(int index) {
return sumOfValuesBetween(startOfBarAtIndex(index), endOfBarAtIndex(index));
double Store::heightOfBarAtIndex(int series, int index) {
return sumOfValuesBetween(startOfBarAtIndex(series, index), endOfBarAtIndex(series, index));
}
double Store::heightOfBarAtValue(double value) {
double Store::heightOfBarAtValue(int series, double value) {
double width = barWidth();
int barNumber = std::floor((value - m_firstDrawnBarAbscissa)/width);
double lowerBound = m_firstDrawnBarAbscissa + barNumber*width;
double upperBound = m_firstDrawnBarAbscissa + (barNumber+1)*width;
return sumOfValuesBetween(lowerBound, upperBound);
return sumOfValuesBetween(series, lowerBound, upperBound);
}
double Store::startOfBarAtIndex(int index) {
double firstBarAbscissa = m_firstDrawnBarAbscissa + m_barWidth*std::floor((minValue()- m_firstDrawnBarAbscissa)/m_barWidth);
double Store::startOfBarAtIndex(int series, int index) {
double firstBarAbscissa = m_firstDrawnBarAbscissa + m_barWidth*std::floor((minValue(series)- m_firstDrawnBarAbscissa)/m_barWidth);
return firstBarAbscissa + index * m_barWidth;
}
double Store::endOfBarAtIndex(int index) {
return startOfBarAtIndex(index+1);
double Store::endOfBarAtIndex(int series, int index) {
return startOfBarAtIndex(series, index+1);
}
double Store::numberOfBars() {
double firstBarAbscissa = m_firstDrawnBarAbscissa + m_barWidth*std::floor((minValue()- m_firstDrawnBarAbscissa)/m_barWidth);
return std::ceil((maxValue() - firstBarAbscissa)/m_barWidth)+1;
double Store::numberOfBars(int series) {
double firstBarAbscissa = m_firstDrawnBarAbscissa + m_barWidth*std::floor((minValue(series)- m_firstDrawnBarAbscissa)/m_barWidth);
return std::ceil((maxValue(series) - firstBarAbscissa)/m_barWidth)+1;
}
bool Store::scrollToSelectedBarIndex(int index) {
float startSelectedBar = startOfBarAtIndex(index);
bool Store::scrollToSelectedBarIndex(int series, int index) {
float startSelectedBar = startOfBarAtIndex(series, index);
float windowRange = m_xMax - m_xMin;
float range = windowRange/(1+k_displayLeftMarginRatio+k_displayRightMarginRatio);
if (m_xMin + k_displayLeftMarginRatio*range > startSelectedBar) {
@@ -67,7 +67,7 @@ bool Store::scrollToSelectedBarIndex(int index) {
m_xMax = m_xMin + windowRange;
return true;
}
float endSelectedBar = endOfBarAtIndex(index);
float endSelectedBar = endOfBarAtIndex(series, index);
if (endSelectedBar > m_xMax - k_displayRightMarginRatio*range) {
m_xMax = endSelectedBar + k_displayRightMarginRatio*range;
m_xMin = m_xMax - windowRange;
@@ -78,124 +78,124 @@ bool Store::scrollToSelectedBarIndex(int index) {
/* Calculation */
double Store::sumOfOccurrences() {
return sumOfColumn(1);
double Store::sumOfOccurrences(int series) {
return sumOfColumn(series, 1);
}
double Store::maxValue() {
double Store::maxValue(int series) {
double max = -DBL_MAX;
for (int k = 0; k < m_numberOfPairs; k++) {
if (m_data[0][k] > max && m_data[1][k] > 0) {
max = m_data[0][k];
if (m_data[series][0][k] > max && m_data[series][1][k] > 0) {
max = m_data[series][0][k];
}
}
return max;
}
double Store::minValue() {
double Store::minValue(int series) {
double min = DBL_MAX;
for (int k = 0; k < m_numberOfPairs; k++) {
if (m_data[0][k] < min && m_data[1][k] > 0) {
min = m_data[0][k];
if (m_data[series][0][k] < min && m_data[series][1][k] > 0) {
min = m_data[series][0][k];
}
}
return min;
}
double Store::range() {
return maxValue()-minValue();
double Store::range(int series) {
return maxValue(series)-minValue(series);
}
double Store::mean() {
return sum()/sumOfOccurrences();
double Store::mean(int series) {
return sum(series)/sumOfOccurrences(series);
}
double Store::variance() {
double m = mean();
return squaredValueSum()/sumOfOccurrences() - m*m;
double Store::variance(int series) {
double m = mean(series);
return squaredValueSum(series)/sumOfOccurrences(series) - m*m;
}
double Store::standardDeviation() {
return std::sqrt(variance());
double Store::standardDeviation(int series) {
return std::sqrt(variance(series));
}
double Store::sampleStandardDeviation() {
double n = sumOfOccurrences();
double Store::sampleStandardDeviation(int series) {
double n = sumOfOccurrences(series);
double s = std::sqrt(n/(n-1.0));
return s*standardDeviation();
return s*standardDeviation(series);
}
double Store::firstQuartile() {
int firstQuartileIndex = std::ceil(sumOfOccurrences()/4);
return sortedElementNumber(firstQuartileIndex);
double Store::firstQuartile(int series) {
int firstQuartileIndex = std::ceil(sumOfOccurrences(series)/4);
return sortedElementNumber(series, firstQuartileIndex);
}
double Store::thirdQuartile() {
int thirdQuartileIndex = std::ceil(3*sumOfOccurrences()/4);
return sortedElementNumber(thirdQuartileIndex);
double Store::thirdQuartile(int series) {
int thirdQuartileIndex = std::ceil(3*sumOfOccurrences(series)/4);
return sortedElementNumber(series, thirdQuartileIndex);
}
double Store::quartileRange() {
double Store::quartileRange(int series) {
return thirdQuartile()-firstQuartile();
}
double Store::median() {
int total = sumOfOccurrences();
double Store::median(int series) {
int total = sumOfOccurrences(series);
int halfTotal = total/2;
int totalMod2 = total - 2*halfTotal;
if (totalMod2 == 0) {
double minusMedian = sortedElementNumber(halfTotal);
double maxMedian = sortedElementNumber(halfTotal+1);
double minusMedian = sortedElementNumber(series, halfTotal);
double maxMedian = sortedElementNumber(series, halfTotal+1);
return (minusMedian+maxMedian)/2.0;
} else {
return sortedElementNumber(halfTotal+1);
return sortedElementNumber(series, halfTotal+1);
}
}
double Store::sum() {
double Store::sum(int series) {
double result = 0;
for (int k = 0; k < m_numberOfPairs; k++) {
result += m_data[0][k]*m_data[1][k];
result += m_data[series][0][k]*m_data[series][1][k];
}
return result;
}
double Store::squaredValueSum() {
double Store::squaredValueSum(int series) {
double result = 0;
for (int k = 0; k < m_numberOfPairs; k++) {
result += m_data[0][k]*m_data[0][k]*m_data[1][k];
result += m_data[series][0][k]*m_data[series][0][k]*m_data[series][1][k];
}
return result;
}
/* private methods */
/* Private methods */
double Store::defaultValue(int i, int j) {
return i == 0 ? FloatPairStore::defaultValue(i, j) : 1.0;
double Store::defaultValue(int series, int i, int j) {
return i == 0 ? FloatPairStore::defaultValue(series, i, j) : 1.0;
}
double Store::sumOfValuesBetween(double x1, double x2) {
double result = 0;
for (int k = 0; k < m_numberOfPairs; k++) {
if (m_data[0][k] < x2 && x1 <= m_data[0][k]) {
result += m_data[1][k];
for (int k = 0; k < m_numberOfPairs[series]; k++) {
if (m_data[series][0][k] < x2 && x1 <= m_data[series][0][k]) {
result += m_data[series][1][k];
}
}
return result;
}
double Store::sortedElementNumber(int k) {
double Store::sortedElementNumber(int series, int k) {
// TODO: use an other algorithm (ex quickselect) to avoid quadratic complexity
double bufferValues[m_numberOfPairs];
memcpy(bufferValues, m_data[0], m_numberOfPairs*sizeof(double));
double bufferValues[m_numberOfPairs[series]];
memcpy(bufferValues, m_data[series][0], m_numberOfPairs[series]*sizeof(double));
int sortedElementIndex = 0;
double cumulatedSize = 0.0;
while (cumulatedSize < k) {
sortedElementIndex = minIndex(bufferValues, m_numberOfPairs);
sortedElementIndex = minIndex(bufferValues, m_numberOfPairs[series]);
bufferValues[sortedElementIndex] = DBL_MAX;
cumulatedSize += m_data[1][sortedElementIndex];
cumulatedSize += m_data[series][1][sortedElementIndex];
}
return m_data[0][sortedElementIndex];
return m_data[series][0][sortedElementIndex];
}
int Store::minIndex(double * bufferValues, int bufferLength) {

View File

@@ -15,38 +15,38 @@ public:
void setBarWidth(double barWidth);
double firstDrawnBarAbscissa() const { return m_firstDrawnBarAbscissa; }
void setFirstDrawnBarAbscissa(double firstDrawnBarAbscissa) { m_firstDrawnBarAbscissa = firstBarAbscissa;}
double heightOfBarAtIndex(int index);
double heightOfBarAtValue(double value);
double startOfBarAtIndex(int index);
double endOfBarAtIndex(int index);
double numberOfBars();
double heightOfBarAtIndex(int series, int index);
double heightOfBarAtValue(int series, double value);
double startOfBarAtIndex(int series, int index);
double endOfBarAtIndex(int series, int index);
double numberOfBars(int series);
// return true if the window has scrolled
bool scrollToSelectedBarIndex(int index);
bool scrollToSelectedBarIndex(int series, int index);
// Calculation
double sumOfOccurrences();
double maxValue();
double minValue();
double range();
double mean();
double variance();
double standardDeviation();
double sampleStandardDeviation();
double firstQuartile();
double thirdQuartile();
double quartileRange();
double median();
double sum();
double squaredValueSum();
double sumOfOccurrences(int series);
double maxValue(int series);
double minValue(int series);
double range(int series);
double mean(int series);
double variance(int series);
double standardDeviation(int series);
double sampleStandardDeviation(int series);
double firstQuartile(int series);
double thirdQuartile(int series);
double quartileRange(int series);
double median(int series);
double sum(int series);
double squaredValueSum(int series);
constexpr static double k_maxNumberOfBars = 10000.0;
constexpr static float k_displayTopMarginRatio = 0.1f;
constexpr static float k_displayRightMarginRatio = 0.04f;
constexpr static float k_displayBottomMarginRatio = 0.4f;
constexpr static float k_displayLeftMarginRatio = 0.04f;
private:
double defaultValue(int i, int j) override;
double sumOfValuesBetween(double x1, double x2);
double sortedElementNumber(int k);
double defaultValue(int series, int i, int j) override;
double sumOfValuesBetween(int series, double x1, double x2);
double sortedElementNumber(int series, int k);
int minIndex(double * bufferValues, int bufferLength);
// Histogram bars
double m_barWidth;